From cdad289a0803babecd30cbc0a95be99c5caadeb5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 15 May 2013 01:24:56 -0700 Subject: altos: Add flash-loader for telescience-v0.2 Signed-off-by: Keith Packard --- src/Makefile | 2 +- src/telescience-v0.2/flash-loader/Makefile | 8 +++++++ src/telescience-v0.2/flash-loader/ao_pins.h | 34 +++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 src/telescience-v0.2/flash-loader/Makefile create mode 100644 src/telescience-v0.2/flash-loader/ao_pins.h (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 11f149dd..c3596498 100644 --- a/src/Makefile +++ b/src/Makefile @@ -35,7 +35,7 @@ ARMDIRS=\ telegps-v0.1 telegps-v0.1/flash-loader \ stm-bringup stm-demo \ telelco-v0.2 telelco-v0.2/flash-loader \ - telescience-v0.2 + telescience-v0.2 telescience-v0.2/flash-loader ifneq ($(shell which sdcc),) SUBDIRS += $(SDCCDIRS) diff --git a/src/telescience-v0.2/flash-loader/Makefile b/src/telescience-v0.2/flash-loader/Makefile new file mode 100644 index 00000000..7a2ceb77 --- /dev/null +++ b/src/telescience-v0.2/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telescience-v0.2 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telescience-v0.2/flash-loader/ao_pins.h b/src/telescience-v0.2/flash-loader/ao_pins.h new file mode 100644 index 00000000..907ff341 --- /dev/null +++ b/src/telescience-v0.2/flash-loader/ao_pins.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +/* External crystal at 8MHz */ +#define AO_HSE 8000000 + +#include + +/* Companion port SS PA4 */ + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO stm_gpioa +#define AO_BOOT_APPLICATION_PIN 4 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +#endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 5e9193f6375be27e5f7a0321fd34b6acfe81247f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 14 May 2013 09:12:29 -0700 Subject: altos: Add 'g' command to ublox GPS code. Take the gps_dump function from ao_gps_skytraq.c and move it to a new file so it can be shared with the u-blox driver. That affects every skytraq and u-blox user as they need to include the new file. Signed-off-by: Keith Packard --- src/core/ao.h | 3 +++ src/core/ao_gps_show.c | 39 +++++++++++++++++++++++++++++++++++++++ src/drivers/ao_gps_skytraq.c | 21 +-------------------- src/drivers/ao_gps_ublox.c | 6 ++++++ src/telegps-v0.1/Makefile | 1 + src/telemega-v0.1/Makefile | 1 + src/telemega-v0.3/Makefile | 1 + src/telemetrum-v0.1-sky/Makefile | 1 + src/telemetrum-v1.0/Makefile | 1 + src/telemetrum-v1.1/Makefile | 1 + src/telemetrum-v1.2/Makefile | 1 + src/teleterra-v0.2/Makefile | 3 ++- src/test/Makefile | 4 ++-- src/test/ao_gps_test_skytraq.c | 12 +++++++----- src/test/ao_gps_test_ublox.c | 11 +++++++---- 15 files changed, 74 insertions(+), 32 deletions(-) create mode 100644 src/core/ao_gps_show.c (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 0ad3e4aa..71bfb6a1 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -379,6 +379,9 @@ ao_gps_print(__xdata struct ao_gps_orig *gps_data); void ao_gps_tracking_print(__xdata struct ao_gps_tracking_orig *gps_tracking_data); +void +ao_gps_show(void) __reentrant; + void ao_gps_init(void); diff --git a/src/core/ao_gps_show.c b/src/core/ao_gps_show.c new file mode 100644 index 00000000..3a05e35a --- /dev/null +++ b/src/core/ao_gps_show.c @@ -0,0 +1,39 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_GPS_TEST +#include +#endif + +void +ao_gps_show(void) __reentrant +{ + uint8_t i; + ao_mutex_get(&ao_gps_mutex); + printf ("Date: %02d/%02d/%02d\n", ao_gps_data.year, ao_gps_data.month, ao_gps_data.day); + printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second); + printf ("Lat/Lon: %ld %ld\n", (long) ao_gps_data.latitude, (long) ao_gps_data.longitude); + printf ("Alt: %d\n", ao_gps_data.altitude); + printf ("Flags: 0x%x\n", ao_gps_data.flags); + printf ("Sats: %d", ao_gps_tracking_data.channels); + for (i = 0; i < ao_gps_tracking_data.channels; i++) + printf (" %d %d", + ao_gps_tracking_data.sats[i].svid, + ao_gps_tracking_data.sats[i].c_n_1); + printf ("\ndone\n"); + ao_mutex_put(&ao_gps_mutex); +} diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index d2f67e6b..9a9dff75 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -483,25 +483,6 @@ ao_gps(void) __reentrant __xdata struct ao_task ao_gps_task; -static void -gps_dump(void) __reentrant -{ - uint8_t i; - ao_mutex_get(&ao_gps_mutex); - printf ("Date: %02d/%02d/%02d\n", ao_gps_data.year, ao_gps_data.month, ao_gps_data.day); - printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second); - printf ("Lat/Lon: %ld %ld\n", (long) ao_gps_data.latitude, (long) ao_gps_data.longitude); - printf ("Alt: %d\n", ao_gps_data.altitude); - printf ("Flags: 0x%x\n", ao_gps_data.flags); - printf ("Sats: %d", ao_gps_tracking_data.channels); - for (i = 0; i < ao_gps_tracking_data.channels; i++) - printf (" %d %d", - ao_gps_tracking_data.sats[i].svid, - ao_gps_tracking_data.sats[i].c_n_1); - printf ("\ndone\n"); - ao_mutex_put(&ao_gps_mutex); -} - static __code uint8_t ao_gps_115200[] = { SKYTRAQ_MSG_3(5,0,5,0) /* Set to 115200 baud */ }; @@ -532,7 +513,7 @@ gps_update(void) __reentrant } __code struct ao_cmds ao_gps_cmds[] = { - { gps_dump, "g\0Display GPS" }, + { ao_gps_show, "g\0Display GPS" }, { gps_update, "U\0Update GPS firmware" }, { 0, NULL }, }; diff --git a/src/drivers/ao_gps_ublox.c b/src/drivers/ao_gps_ublox.c index 22300df3..24e70ee3 100644 --- a/src/drivers/ao_gps_ublox.c +++ b/src/drivers/ao_gps_ublox.c @@ -695,10 +695,16 @@ ao_gps(void) __reentrant } } +__code struct ao_cmds ao_gps_cmds[] = { + { ao_gps_show, "g\0Display GPS" }, + { 0, NULL }, +}; + __xdata struct ao_task ao_gps_task; void ao_gps_init(void) { + ao_cmd_register(&ao_gps_cmds[0]); ao_add_task(&ao_gps_task, ao_gps, "gps"); } diff --git a/src/telegps-v0.1/Makefile b/src/telegps-v0.1/Makefile index 2c41235b..64deddc6 100644 --- a/src/telegps-v0.1/Makefile +++ b/src/telegps-v0.1/Makefile @@ -52,6 +52,7 @@ ALTOS_SRC = \ ao_exti_stm.c \ ao_serial_stm.c \ ao_gps_skytraq.c \ + ao_gps_show.c \ ao_cc115l.c \ ao_fec_tx.c \ ao_rfpa0133.c \ diff --git a/src/telemega-v0.1/Makefile b/src/telemega-v0.1/Makefile index a72d08f2..bf756e96 100644 --- a/src/telemega-v0.1/Makefile +++ b/src/telemega-v0.1/Makefile @@ -59,6 +59,7 @@ ALTOS_SRC = \ ao_mutex.c \ ao_serial_stm.c \ ao_gps_skytraq.c \ + ao_gps_show.c \ ao_gps_report_mega.c \ ao_ignite.c \ ao_freq.c \ diff --git a/src/telemega-v0.3/Makefile b/src/telemega-v0.3/Makefile index 398c7dab..f2c0625f 100644 --- a/src/telemega-v0.3/Makefile +++ b/src/telemega-v0.3/Makefile @@ -59,6 +59,7 @@ ALTOS_SRC = \ ao_mutex.c \ ao_serial_stm.c \ ao_gps_ublox.c \ + ao_gps_show.c \ ao_gps_report_mega.c \ ao_ignite.c \ ao_freq.c \ diff --git a/src/telemetrum-v0.1-sky/Makefile b/src/telemetrum-v0.1-sky/Makefile index 69cd3461..a6634c29 100644 --- a/src/telemetrum-v0.1-sky/Makefile +++ b/src/telemetrum-v0.1-sky/Makefile @@ -11,6 +11,7 @@ TM_INC = \ TM_SRC = \ ao_gps_skytraq.c \ + ao_gps_show.c \ ao_25lc1024.c include ../product/Makefile.telemetrum diff --git a/src/telemetrum-v1.0/Makefile b/src/telemetrum-v1.0/Makefile index 4aae84c8..476a3b0a 100644 --- a/src/telemetrum-v1.0/Makefile +++ b/src/telemetrum-v1.0/Makefile @@ -11,6 +11,7 @@ TM_INC = \ TM_SRC = \ ao_companion.c \ ao_gps_skytraq.c \ + ao_gps_show.c \ ao_at45db161d.c include ../product/Makefile.telemetrum diff --git a/src/telemetrum-v1.1/Makefile b/src/telemetrum-v1.1/Makefile index 4bea03db..e44be7f9 100644 --- a/src/telemetrum-v1.1/Makefile +++ b/src/telemetrum-v1.1/Makefile @@ -11,6 +11,7 @@ TM_INC = TM_SRC = \ ao_companion.c \ ao_gps_skytraq.c \ + ao_gps_show.c \ ao_m25.c include ../product/Makefile.telemetrum diff --git a/src/telemetrum-v1.2/Makefile b/src/telemetrum-v1.2/Makefile index 4b650adf..f2285fbe 100644 --- a/src/telemetrum-v1.2/Makefile +++ b/src/telemetrum-v1.2/Makefile @@ -11,6 +11,7 @@ TM_INC = TM_SRC = \ ao_companion.c \ ao_gps_skytraq.c \ + ao_gps_show.c \ ao_m25.c include ../product/Makefile.telemetrum diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile index 65db57ce..68a8d1b6 100644 --- a/src/teleterra-v0.2/Makefile +++ b/src/teleterra-v0.2/Makefile @@ -52,7 +52,8 @@ CC1111_SRC = \ DRIVER_SRC = \ ao_m25.c \ ao_lcd.c \ - ao_gps_skytraq.c + ao_gps_skytraq.c \ + ao_gps_show.c PRODUCT_SRC = \ ao_teleterra_0_2.c \ diff --git a/src/test/Makefile b/src/test/Makefile index 169c1dc6..8032a163 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -35,10 +35,10 @@ ao_flight_test_mm: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman. ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h cc $(CFLAGS) -o $@ $< -ao_gps_test_skytraq: ao_gps_test_skytraq.c ao_gps_skytraq.c ao_gps_print.c ao_host.h +ao_gps_test_skytraq: ao_gps_test_skytraq.c ao_gps_skytraq.c ao_gps_print.c ao_gps_show.c ao_host.h cc $(CFLAGS) -o $@ $< -ao_gps_test_ublox: ao_gps_test_ublox.c ao_gps_ublox.c ao_gps_print.c ao_host.h ao_gps_ublox.h +ao_gps_test_ublox: ao_gps_test_ublox.c ao_gps_ublox.c ao_gps_print.c ao_gps_show.c ao_host.h ao_gps_ublox.h cc $(CFLAGS) -o $@ $< ao_convert_test: ao_convert_test.c ao_convert.c altitude.h diff --git a/src/test/ao_gps_test_skytraq.c b/src/test/ao_gps_test_skytraq.c index 81008b39..89cbd767 100644 --- a/src/test/ao_gps_test_skytraq.c +++ b/src/test/ao_gps_test_skytraq.c @@ -75,6 +75,11 @@ struct ao_gps_tracking_orig { #define ao_telemetry_satellite ao_gps_tracking_orig #define ao_telemetry_satellite_info ao_gps_sat_orig +extern __xdata struct ao_telemetry_location ao_gps_data; +extern __xdata struct ao_telemetry_satellite ao_gps_tracking_data; + +uint8_t ao_gps_mutex; + void ao_mutex_get(uint8_t *mutex) { @@ -432,17 +437,14 @@ uint8_t ao_task_minimize_latency; #define ao_usb_getchar() 0 #include "ao_gps_print.c" +#include "ao_gps_show.c" #include "ao_gps_skytraq.c" void ao_dump_state(void *wchan) { if (wchan == &ao_gps_data) - ao_gps_print(&ao_gps_data); - else - ao_gps_tracking_print(&ao_gps_tracking_data); - putchar('\n'); - return; + ao_gps_show(); } int diff --git a/src/test/ao_gps_test_ublox.c b/src/test/ao_gps_test_ublox.c index 80671735..afd4dba4 100644 --- a/src/test/ao_gps_test_ublox.c +++ b/src/test/ao_gps_test_ublox.c @@ -77,6 +77,11 @@ struct ao_telemetry_satellite { #define ao_gps_tracking_orig ao_telemetry_satellite #define ao_gps_sat_orig ao_telemetry_satellite_info +extern __xdata struct ao_telemetry_location ao_gps_data; +extern __xdata struct ao_telemetry_satellite ao_gps_tracking_data; + +uint8_t ao_gps_mutex; + void ao_mutex_get(uint8_t *mutex) { @@ -224,6 +229,7 @@ uint8_t ao_task_minimize_latency; #define ao_usb_getchar() 0 #include "ao_gps_print.c" +#include "ao_gps_show.c" #include "ao_gps_ublox.c" static void @@ -342,10 +348,7 @@ void ao_dump_state(void *wchan) { if (wchan == &ao_gps_data) - ao_gps_print(&ao_gps_data); - else - ao_gps_tracking_print(&ao_gps_tracking_data); - putchar('\n'); + ao_gps_show(); return; } -- cgit v1.2.3 From 461215eea72ff9d64748304e76b08da37ee3dfe9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 14 May 2013 09:21:54 -0700 Subject: altos: Give u-blox 3 seconds after boot before we bug it Signed-off-by: Keith Packard --- src/drivers/ao_gps_ublox.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/drivers/ao_gps_ublox.c b/src/drivers/ao_gps_ublox.c index 24e70ee3..56a4da16 100644 --- a/src/drivers/ao_gps_ublox.c +++ b/src/drivers/ao_gps_ublox.c @@ -405,6 +405,9 @@ static void ao_gps_setup(void) { uint8_t i, k; + + ao_delay(AO_SEC_TO_TICKS(3)); + ao_ublox_set_speed(AO_SERIAL_SPEED_9600); /* -- cgit v1.2.3 From a4e4eec827d61a05fda52ddb68b55f17b6028d5e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 14 May 2013 09:25:08 -0700 Subject: altos: gps serial routines are called ao_gps_*, not ao_ublox_* This caused the u-blox driver to use serial port 1 instead of the project-specified serial port. Signed-off-by: Keith Packard --- src/drivers/ao_gps_ublox.c | 28 +++++++++++----------------- src/test/ao_gps_test_ublox.c | 6 +++--- 2 files changed, 14 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_gps_ublox.c b/src/drivers/ao_gps_ublox.c index 56a4da16..80869561 100644 --- a/src/drivers/ao_gps_ublox.c +++ b/src/drivers/ao_gps_ublox.c @@ -39,13 +39,7 @@ struct ao_ublox_cksum { static __pdata struct ao_ublox_cksum ao_ublox_cksum; static __pdata uint16_t ao_ublox_len; -#ifndef ao_ublox_getchar -#define ao_ublox_getchar ao_serial1_getchar -#define ao_ublox_putchar ao_serial1_putchar -#define ao_ublox_set_speed ao_serial1_set_speed -#endif - -#define ao_ublox_byte() ((uint8_t) ao_ublox_getchar()) +#define ao_ublox_byte() ((uint8_t) ao_gps_getchar()) static inline void add_cksum(struct ao_ublox_cksum *cksum, uint8_t c) { @@ -61,7 +55,7 @@ static void ao_ublox_init_cksum(void) static void ao_ublox_put_u8(uint8_t c) { add_cksum(&ao_ublox_cksum, c); - ao_ublox_putchar(c); + ao_gps_putchar(c); } static void ao_ublox_put_i8(int8_t c) @@ -408,14 +402,14 @@ ao_gps_setup(void) ao_delay(AO_SEC_TO_TICKS(3)); - ao_ublox_set_speed(AO_SERIAL_SPEED_9600); + ao_gps_set_speed(AO_SERIAL_SPEED_9600); /* * A bunch of nulls so the start bit * is clear */ for (i = 0; i < 64; i++) - ao_ublox_putchar(0x00); + ao_gps_putchar(0x00); /* * Send the baud-rate setting and protocol-setting @@ -423,27 +417,27 @@ ao_gps_setup(void) */ for (k = 0; k < 3; k++) for (i = 0; i < sizeof (ao_gps_set_nmea); i++) - ao_ublox_putchar(ao_gps_set_nmea[i]); + ao_gps_putchar(ao_gps_set_nmea[i]); /* * Increase the baud rate */ - ao_ublox_set_speed(AO_SERIAL_SPEED_57600); + ao_gps_set_speed(AO_SERIAL_SPEED_57600); /* * Pad with nulls to give the chip * time to see the baud rate switch */ for (i = 0; i < 64; i++) - ao_ublox_putchar(0x00); + ao_gps_putchar(0x00); } static void ao_ublox_putstart(uint8_t class, uint8_t id, uint16_t len) { ao_ublox_init_cksum(); - ao_ublox_putchar(0xb5); - ao_ublox_putchar(0x62); + ao_gps_putchar(0xb5); + ao_gps_putchar(0x62); ao_ublox_put_u8(class); ao_ublox_put_u8(id); ao_ublox_put_u8(len); @@ -453,8 +447,8 @@ ao_ublox_putstart(uint8_t class, uint8_t id, uint16_t len) static void ao_ublox_putend(void) { - ao_ublox_putchar(ao_ublox_cksum.a); - ao_ublox_putchar(ao_ublox_cksum.b); + ao_gps_putchar(ao_ublox_cksum.a); + ao_gps_putchar(ao_ublox_cksum.b); } static void diff --git a/src/test/ao_gps_test_ublox.c b/src/test/ao_gps_test_ublox.c index afd4dba4..a0e04cb6 100644 --- a/src/test/ao_gps_test_ublox.c +++ b/src/test/ao_gps_test_ublox.c @@ -130,7 +130,7 @@ static uint16_t recv_len; static void check_ublox_message(char *which, uint8_t *msg); char -ao_serial1_getchar(void) +ao_gps_getchar(void) { char c; uint8_t uc; @@ -163,7 +163,7 @@ static int message_len; static uint16_t send_len; void -ao_serial1_putchar(char c) +ao_gps_putchar(char c) { int i; uint8_t uc = (uint8_t) c; @@ -196,7 +196,7 @@ ao_serial1_putchar(char c) #define AO_SERIAL_SPEED_115200 3 static void -ao_serial1_set_speed(uint8_t speed) +ao_gps_set_speed(uint8_t speed) { int fd = ao_gps_fd; struct termios termios; -- cgit v1.2.3 From 6d553230903ddd0ec522c07be0df975b38ef23d3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 14 May 2013 09:56:16 -0700 Subject: altos: Fix telemega v0.3 igniter order (drogue/main moved). Label ADC dump telemega moves the igniters around so that E/F are now drogue/main. Add custom labels for ADC values to make parsing possible Signed-off-by: Keith Packard --- src/stm/ao_adc_stm.c | 4 +++ src/telemega-v0.3/ao_pins.h | 65 +++++++++++++++++++++++++++------------------ 2 files changed, 43 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index 48fc4262..53f19b40 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -113,11 +113,15 @@ ao_adc_dump(void) __reentrant uint8_t i; ao_data_get(&packet); +#ifdef AO_ADC_DUMP + AO_ADC_DUMP(&packet); +#else printf("tick: %5u", packet.tick); d = (int16_t *) (&packet.adc); for (i = 0; i < AO_NUM_ADC; i++) printf (" %2d: %5d", i, d[i]); printf("\n"); +#endif } __code struct ao_cmds ao_adc_cmds[] = { diff --git a/src/telemega-v0.3/ao_pins.h b/src/telemega-v0.3/ao_pins.h index b1504d28..88b473cc 100644 --- a/src/telemega-v0.3/ao_pins.h +++ b/src/telemega-v0.3/ao_pins.h @@ -121,28 +121,34 @@ #define HAS_IGNITE 1 #define HAS_IGNITE_REPORT 1 -#define AO_SENSE_DROGUE(p) ((p)->adc.sense[0]) -#define AO_SENSE_MAIN(p) ((p)->adc.sense[1]) +#define AO_SENSE_DROGUE(p) ((p)->adc.sense[4]) +#define AO_SENSE_MAIN(p) ((p)->adc.sense[5]) #define AO_IGNITER_CLOSED 400 #define AO_IGNITER_OPEN 60 -#define AO_IGNITER_DROGUE_PORT (&stm_gpiod) -#define AO_IGNITER_DROGUE_PIN 6 +/* Pyro A */ +#define AO_PYRO_PORT_0 (&stm_gpiod) +#define AO_PYRO_PIN_0 6 -#define AO_IGNITER_MAIN_PORT (&stm_gpiod) -#define AO_IGNITER_MAIN_PIN 7 +/* Pyro B */ +#define AO_PYRO_PORT_1 (&stm_gpiod) +#define AO_PYRO_PIN_1 7 -#define AO_PYRO_PORT_0 (&stm_gpiob) -#define AO_PYRO_PIN_0 5 +/* Pyro C */ +#define AO_PYRO_PORT_2 (&stm_gpiob) +#define AO_PYRO_PIN_2 5 -#define AO_PYRO_PORT_1 (&stm_gpioe) -#define AO_PYRO_PIN_1 4 +/* Pyro D */ +#define AO_PYRO_PORT_3 (&stm_gpioe) +#define AO_PYRO_PIN_3 4 -#define AO_PYRO_PORT_2 (&stm_gpioe) -#define AO_PYRO_PIN_2 6 +/* Drogue */ +#define AO_IGNITER_DROGUE_PORT (&stm_gpioe) +#define AO_IGNITER_DROGUE_PIN 6 -#define AO_PYRO_PORT_3 (&stm_gpioe) -#define AO_PYRO_PIN_3 5 +/* Main */ +#define AO_IGNITER_MAIN_PORT (&stm_gpioe) +#define AO_IGNITER_MAIN_PIN 5 /* Number of general purpose pyro channels available */ #define AO_PYRO_NUM 4 @@ -163,6 +169,13 @@ struct ao_adc { int16_t temp; }; +#define AO_ADC_DUMP(p) \ + printf("tick: %5u A: %5d B: %5d C: %5d D: %5d drogue: %5d main: %5d batt: %5d pbatt: %5d temp: %5d\n", \ + (p)->tick, \ + (p)->adc.sense[0], (p)->adc.sense[1], (p)->adc.sense[2], \ + (p)->adc.sense[3], (p)->adc.sense[4], (p)->adc.sense[5], \ + (p)->adc.v_batt, (p)->adc.v_pbatt, (p)->adc.temp) + #define AO_ADC_SENSE_A 0 #define AO_ADC_SENSE_A_PORT (&stm_gpioa) #define AO_ADC_SENSE_A_PIN 0 @@ -179,13 +192,13 @@ struct ao_adc { #define AO_ADC_SENSE_D_PORT (&stm_gpioa) #define AO_ADC_SENSE_D_PIN 3 -#define AO_ADC_SENSE_E 4 -#define AO_ADC_SENSE_E_PORT (&stm_gpioa) -#define AO_ADC_SENSE_E_PIN 4 +#define AO_ADC_SENSE_DROGUE 4 +#define AO_ADC_SENSE_DROGUE_PORT (&stm_gpioa) +#define AO_ADC_SENSE_DROGUE_PIN 4 -#define AO_ADC_SENSE_F 22 -#define AO_ADC_SENSE_F_PORT (&stm_gpioe) -#define AO_ADC_SENSE_F_PIN 7 +#define AO_ADC_SENSE_MAIN 22 +#define AO_ADC_SENSE_MAIN_PORT (&stm_gpioe) +#define AO_ADC_SENSE_MAIN_PIN 7 #define AO_ADC_V_BATT 8 #define AO_ADC_V_BATT_PORT (&stm_gpiob) @@ -211,10 +224,10 @@ struct ao_adc { #define AO_ADC_PIN2_PIN AO_ADC_SENSE_C_PIN #define AO_ADC_PIN3_PORT AO_ADC_SENSE_D_PORT #define AO_ADC_PIN3_PIN AO_ADC_SENSE_D_PIN -#define AO_ADC_PIN4_PORT AO_ADC_SENSE_E_PORT -#define AO_ADC_PIN4_PIN AO_ADC_SENSE_E_PIN -#define AO_ADC_PIN5_PORT AO_ADC_SENSE_F_PORT -#define AO_ADC_PIN5_PIN AO_ADC_SENSE_F_PIN +#define AO_ADC_PIN4_PORT AO_ADC_SENSE_DROGUE_PORT +#define AO_ADC_PIN4_PIN AO_ADC_SENSE_DROGUE_PIN +#define AO_ADC_PIN5_PORT AO_ADC_SENSE_MAIN_PORT +#define AO_ADC_PIN5_PIN AO_ADC_SENSE_MAIN_PIN #define AO_ADC_PIN6_PORT AO_ADC_V_BATT_PORT #define AO_ADC_PIN6_PIN AO_ADC_V_BATT_PIN #define AO_ADC_PIN7_PORT AO_ADC_V_PBATT_PORT @@ -226,8 +239,8 @@ struct ao_adc { #define AO_ADC_SQ2 AO_ADC_SENSE_B #define AO_ADC_SQ3 AO_ADC_SENSE_C #define AO_ADC_SQ4 AO_ADC_SENSE_D -#define AO_ADC_SQ5 AO_ADC_SENSE_E -#define AO_ADC_SQ6 AO_ADC_SENSE_F +#define AO_ADC_SQ5 AO_ADC_SENSE_DROGUE +#define AO_ADC_SQ6 AO_ADC_SENSE_MAIN #define AO_ADC_SQ7 AO_ADC_V_BATT #define AO_ADC_SQ8 AO_ADC_V_PBATT #define AO_ADC_SQ9 AO_ADC_TEMP -- cgit v1.2.3 From 9beacd77b3e8106e036e50a67312dfee414fbc51 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 14 May 2013 09:01:49 -0700 Subject: altos: Initialize MPU6000 CS pin for SPI mode Without this, we can't talk to the chip very well Signed-off-by: Keith Packard --- src/drivers/ao_mpu6000.c | 6 ++++++ src/telemega-v0.3/ao_pins.h | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index c65aecbc..fc768cc9 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -19,6 +19,8 @@ #include #include +#if HAS_MPU6000 + static uint8_t ao_mpu6000_wake; static uint8_t ao_mpu6000_configured; @@ -326,5 +328,9 @@ ao_mpu6000_init(void) ao_mpu6000_configured = 0; ao_add_task(&ao_mpu6000_task, ao_mpu6000, "mpu6000"); +#ifndef AO_MPU6000_I2C_INDEX + ao_spi_init_cs(AO_MPU6000_SPI_CS_PORT, (1 << AO_MPU6000_SPI_CS_PIN)); +#endif ao_cmd_register(&ao_mpu6000_cmds[0]); } +#endif diff --git a/src/telemega-v0.3/ao_pins.h b/src/telemega-v0.3/ao_pins.h index 88b473cc..bace5853 100644 --- a/src/telemega-v0.3/ao_pins.h +++ b/src/telemega-v0.3/ao_pins.h @@ -308,7 +308,7 @@ struct ao_adc { * mpu6000 */ -#define HAS_MPU6000 1 +#define HAS_MPU6000 1 #define AO_MPU6000_INT_PORT (&stm_gpioe) #define AO_MPU6000_INT_PIN 0 #define AO_MPU6000_SPI_BUS AO_SPI_1_PE13_PE14_PE15 -- cgit v1.2.3 From 0571531066918fdefe9447f3b4192d0c6c477afa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 14 May 2013 10:48:24 -0700 Subject: altos: Grab SPI mutex until MPU6000 I2C mode is disabled If other drivers use the SPI bus, the MPU6000 gets confused as its sitting on the bus looking for I2C messages. Just grab the mutex before the OS is running and hold onto it until the MPU6000 has been initialized. Signed-off-by: Keith Packard --- src/drivers/ao_mpu6000.c | 265 ++++++++++++++++++++++++++++------------------- src/drivers/ao_mpu6000.h | 14 +-- src/stm/ao_arch_funcs.h | 7 +- 3 files changed, 168 insertions(+), 118 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index fc768cc9..73057820 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -24,81 +24,89 @@ static uint8_t ao_mpu6000_wake; static uint8_t ao_mpu6000_configured; -#define ao_mpu6000_spi_get() ao_spi_get_bit(AO_MPU6000_SPI_CS_PORT, \ - AO_MPU6000_SPI_CS_PIN, \ - AO_MPU6000_SPI_CS, \ - AO_MPU6000_SPI_BUS, \ - AO_SPI_SPEED_1MHz) +#ifndef AO_MPU6000_I2C_INDEX +#define AO_MPU6000_SPI 1 +#else +#define AO_MPU6000_SPI 0 +#endif + +#if AO_MPU6000_SPI -#define ao_mpu6000_spi_put() ao_spi_put_bit(AO_MPU6000_SPI_CS_PORT, \ - AO_MPU6000_SPI_CS_PIN, \ - AO_MPU6000_SPI_CS, \ - AO_MPU6000_SPI_BUS) +#define ao_mpu6000_spi_get() ao_spi_get(AO_MPU6000_SPI_BUS, AO_SPI_SPEED_1MHz) +#define ao_mpu6000_spi_put() ao_spi_put(AO_MPU6000_SPI_BUS) + +#define ao_mpu6000_spi_start() ao_spi_set_cs(AO_MPU6000_SPI_CS_PORT, \ + (1 << AO_MPU6000_SPI_CS_PIN)) + +#define ao_mpu6000_spi_end() ao_spi_clr_cs(AO_MPU6000_SPI_CS_PORT, \ + (1 << AO_MPU6000_SPI_CS_PIN)) + +#endif static void -ao_mpu6000_reg_write(uint8_t addr, uint8_t value) +_ao_mpu6000_reg_write(uint8_t addr, uint8_t value) { uint8_t d[2] = { addr, value }; -#ifdef AO_MPU6000_I2C_INDEX +#if AO_MPU6000_SPI + ao_mpu6000_spi_start(); + ao_spi_send(d, 2, AO_MPU6000_SPI_BUS); + ao_mpu6000_spi_end(); +#else ao_i2c_get(AO_MPU6000_I2C_INDEX); ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); ao_i2c_send(d, 2, AO_MPU6000_I2C_INDEX, TRUE); ao_i2c_put(AO_MPU6000_I2C_INDEX); -#else - ao_mpu6000_spi_get(); - ao_spi_send(d, 2, AO_MPU6000_SPI_BUS); - ao_mpu6000_spi_put(); #endif } static void -ao_mpu6000_read(uint8_t addr, void *data, uint8_t len) +_ao_mpu6000_read(uint8_t addr, void *data, uint8_t len) { -#ifdef AO_MPU6000_I2C_INDEX +#if AO_MPU6000_SPI + addr |= 0x80; + ao_mpu6000_spi_start(); + ao_spi_send(&addr, 1, AO_MPU6000_SPI_BUS); + ao_spi_recv(data, len, AO_MPU6000_SPI_BUS); + ao_mpu6000_spi_end(); +#else ao_i2c_get(AO_MPU6000_I2C_INDEX); ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX, FALSE); ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_READ); ao_i2c_recv(data, len, AO_MPU6000_I2C_INDEX, TRUE); ao_i2c_put(AO_MPU6000_I2C_INDEX); -#else - addr |= 0x80; - ao_mpu6000_spi_get(); - ao_spi_send(&addr, 1, AO_MPU6000_SPI_BUS); - ao_spi_recv(data, len, AO_MPU6000_SPI_BUS); - ao_mpu6000_spi_put(); #endif } static uint8_t -ao_mpu6000_reg_read(uint8_t addr) +_ao_mpu6000_reg_read(uint8_t addr) { uint8_t value; -#ifdef AO_MPU6000_I2C_INDEX +#if AO_MPU6000_SPI + addr |= 0x80; + ao_mpu6000_spi_start(); + ao_spi_send(&addr, 1, AO_MPU6000_SPI_BUS); + ao_spi_recv(&value, 1, AO_MPU6000_SPI_BUS); + ao_mpu6000_spi_end(); +#else ao_i2c_get(AO_MPU6000_I2C_INDEX); ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX, FALSE); ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_READ); ao_i2c_recv(&value, 1, AO_MPU6000_I2C_INDEX, TRUE); ao_i2c_put(AO_MPU6000_I2C_INDEX); -#else - addr |= 0x80; - ao_mpu6000_spi_get(); - ao_spi_send(&addr, 1, AO_MPU6000_SPI_BUS); - ao_spi_recv(&value, 1, AO_MPU6000_SPI_BUS); - ao_mpu6000_spi_put(); #endif return value; } static void -ao_mpu6000_sample(struct ao_mpu6000_sample *sample) +_ao_mpu6000_sample(struct ao_mpu6000_sample *sample) { uint16_t *d = (uint16_t *) sample; int i = sizeof (*sample) / 2; - ao_mpu6000_read(MPU6000_ACCEL_XOUT_H, sample, sizeof (*sample)); + _ao_mpu6000_read(MPU6000_ACCEL_XOUT_H, sample, sizeof (*sample)); #if __BYTE_ORDER == __LITTLE_ENDIAN /* byte swap */ while (i--) { @@ -153,7 +161,22 @@ ao_mpu6000_gyro_check(int16_t normal, int16_t test, char *which) } static void -ao_mpu6000_setup(void) +_ao_mpu6000_wait_alive(void) +{ + uint8_t i; + + /* Wait for the chip to wake up */ + for (i = 0; i < 30; i++) { + ao_delay(AO_MS_TO_TICKS(100)); + if (_ao_mpu6000_reg_read(MPU6000_WHO_AM_I) == 0x68) + break; + } + if (i == 30) + ao_panic(AO_PANIC_SELF_TEST_MPU6000); +} + +static void +_ao_mpu6000_setup(void) { struct ao_mpu6000_sample normal_mode, test_mode; int errors =0; @@ -161,104 +184,107 @@ ao_mpu6000_setup(void) if (ao_mpu6000_configured) return; + _ao_mpu6000_wait_alive(); + /* Reset the whole chip */ - ao_mpu6000_reg_write(MPU6000_PWR_MGMT_1, - (1 << MPU6000_PWR_MGMT_1_DEVICE_RESET)); + _ao_mpu6000_reg_write(MPU6000_PWR_MGMT_1, + (1 << MPU6000_PWR_MGMT_1_DEVICE_RESET)); /* Wait for it to reset. If we talk too quickly, it appears to get confused */ - ao_delay(AO_MS_TO_TICKS(100)); - /* Reset signal conditioning */ - ao_mpu6000_reg_write(MPU6000_USER_CONTROL, - (0 << MPU6000_USER_CONTROL_FIFO_EN) | - (0 << MPU6000_USER_CONTROL_I2C_MST_EN) | - (0 << MPU6000_USER_CONTROL_I2C_IF_DIS) | - (0 << MPU6000_USER_CONTROL_FIFO_RESET) | - (0 << MPU6000_USER_CONTROL_I2C_MST_RESET) | - (1 << MPU6000_USER_CONTROL_SIG_COND_RESET)); + _ao_mpu6000_wait_alive(); + + /* Reset signal conditioning, disabling I2C on SPI systems */ + _ao_mpu6000_reg_write(MPU6000_USER_CTRL, + (0 << MPU6000_USER_CTRL_FIFO_EN) | + (0 << MPU6000_USER_CTRL_I2C_MST_EN) | + (AO_MPU6000_SPI << MPU6000_USER_CTRL_I2C_IF_DIS) | + (0 << MPU6000_USER_CTRL_FIFO_RESET) | + (0 << MPU6000_USER_CTRL_I2C_MST_RESET) | + (1 << MPU6000_USER_CTRL_SIG_COND_RESET)); - while (ao_mpu6000_reg_read(MPU6000_USER_CONTROL) & (1 << MPU6000_USER_CONTROL_SIG_COND_RESET)) - ao_yield(); + while (_ao_mpu6000_reg_read(MPU6000_USER_CTRL) & (1 << MPU6000_USER_CTRL_SIG_COND_RESET)) + ao_delay(AO_MS_TO_TICKS(10)); /* Reset signal paths */ - ao_mpu6000_reg_write(MPU6000_SIGNAL_PATH_RESET, - (1 << MPU6000_SIGNAL_PATH_RESET_GYRO_RESET) | - (1 << MPU6000_SIGNAL_PATH_RESET_ACCEL_RESET) | - (1 << MPU6000_SIGNAL_PATH_RESET_TEMP_RESET)); + _ao_mpu6000_reg_write(MPU6000_SIGNAL_PATH_RESET, + (1 << MPU6000_SIGNAL_PATH_RESET_GYRO_RESET) | + (1 << MPU6000_SIGNAL_PATH_RESET_ACCEL_RESET) | + (1 << MPU6000_SIGNAL_PATH_RESET_TEMP_RESET)); - ao_mpu6000_reg_write(MPU6000_SIGNAL_PATH_RESET, - (0 << MPU6000_SIGNAL_PATH_RESET_GYRO_RESET) | - (0 << MPU6000_SIGNAL_PATH_RESET_ACCEL_RESET) | - (0 << MPU6000_SIGNAL_PATH_RESET_TEMP_RESET)); + _ao_mpu6000_reg_write(MPU6000_SIGNAL_PATH_RESET, + (0 << MPU6000_SIGNAL_PATH_RESET_GYRO_RESET) | + (0 << MPU6000_SIGNAL_PATH_RESET_ACCEL_RESET) | + (0 << MPU6000_SIGNAL_PATH_RESET_TEMP_RESET)); /* Select clocks, disable sleep */ - ao_mpu6000_reg_write(MPU6000_PWR_MGMT_1, - (0 << MPU6000_PWR_MGMT_1_DEVICE_RESET) | - (0 << MPU6000_PWR_MGMT_1_SLEEP) | - (0 << MPU6000_PWR_MGMT_1_CYCLE) | - (0 << MPU6000_PWR_MGMT_1_TEMP_DIS) | - (MPU6000_PWR_MGMT_1_CLKSEL_PLL_X_AXIS << MPU6000_PWR_MGMT_1_CLKSEL)); + _ao_mpu6000_reg_write(MPU6000_PWR_MGMT_1, + (0 << MPU6000_PWR_MGMT_1_DEVICE_RESET) | + (0 << MPU6000_PWR_MGMT_1_SLEEP) | + (0 << MPU6000_PWR_MGMT_1_CYCLE) | + (0 << MPU6000_PWR_MGMT_1_TEMP_DIS) | + (MPU6000_PWR_MGMT_1_CLKSEL_PLL_X_AXIS << MPU6000_PWR_MGMT_1_CLKSEL)); - /* Set sample rate divider to sample at full speed - ao_mpu6000_reg_write(MPU6000_SMPRT_DIV, 0); + /* Set sample rate divider to sample at full speed */ + _ao_mpu6000_reg_write(MPU6000_SMPRT_DIV, 0); /* Disable filtering */ - ao_mpu6000_reg_write(MPU6000_CONFIG, - (MPU6000_CONFIG_EXT_SYNC_SET_DISABLED << MPU6000_CONFIG_EXT_SYNC_SET) | - (MPU6000_CONFIG_DLPF_CFG_260_256 << MPU6000_CONFIG_DLPF_CFG)); + _ao_mpu6000_reg_write(MPU6000_CONFIG, + (MPU6000_CONFIG_EXT_SYNC_SET_DISABLED << MPU6000_CONFIG_EXT_SYNC_SET) | + (MPU6000_CONFIG_DLPF_CFG_260_256 << MPU6000_CONFIG_DLPF_CFG)); /* Configure accelerometer to +/-16G in self-test mode */ - ao_mpu6000_reg_write(MPU6000_ACCEL_CONFIG, - (1 << MPU600_ACCEL_CONFIG_XA_ST) | - (1 << MPU600_ACCEL_CONFIG_YA_ST) | - (1 << MPU600_ACCEL_CONFIG_ZA_ST) | - (MPU600_ACCEL_CONFIG_AFS_SEL_16G << MPU600_ACCEL_CONFIG_AFS_SEL)); + _ao_mpu6000_reg_write(MPU6000_ACCEL_CONFIG, + (1 << MPU600_ACCEL_CONFIG_XA_ST) | + (1 << MPU600_ACCEL_CONFIG_YA_ST) | + (1 << MPU600_ACCEL_CONFIG_ZA_ST) | + (MPU600_ACCEL_CONFIG_AFS_SEL_16G << MPU600_ACCEL_CONFIG_AFS_SEL)); /* Configure gyro to +/- 2000°/s in self-test mode */ - ao_mpu6000_reg_write(MPU6000_GYRO_CONFIG, - (1 << MPU600_GYRO_CONFIG_XG_ST) | - (1 << MPU600_GYRO_CONFIG_YG_ST) | - (1 << MPU600_GYRO_CONFIG_ZG_ST) | - (MPU600_GYRO_CONFIG_FS_SEL_2000 << MPU600_GYRO_CONFIG_FS_SEL)); + _ao_mpu6000_reg_write(MPU6000_GYRO_CONFIG, + (1 << MPU600_GYRO_CONFIG_XG_ST) | + (1 << MPU600_GYRO_CONFIG_YG_ST) | + (1 << MPU600_GYRO_CONFIG_ZG_ST) | + (MPU600_GYRO_CONFIG_FS_SEL_2000 << MPU600_GYRO_CONFIG_FS_SEL)); ao_delay(AO_MS_TO_TICKS(200)); - ao_mpu6000_sample(&test_mode); + _ao_mpu6000_sample(&test_mode); #if TRIDGE // read the product ID rev c has 1/2 the sensitivity of rev d - _mpu6000_product_id = _register_read(MPUREG_PRODUCT_ID); - //Serial.printf("Product_ID= 0x%x\n", (unsigned) _mpu6000_product_id); - - if ((_mpu6000_product_id == MPU6000ES_REV_C4) || (_mpu6000_product_id == MPU6000ES_REV_C5) || - (_mpu6000_product_id == MPU6000_REV_C4) || (_mpu6000_product_id == MPU6000_REV_C5)) { - // Accel scale 8g (4096 LSB/g) - // Rev C has different scaling than rev D - register_write(MPUREG_ACCEL_CONFIG,1<<3); - } else { - // Accel scale 8g (4096 LSB/g) - register_write(MPUREG_ACCEL_CONFIG,2<<3); - } - hal.scheduler->delay(1); + _mpu6000_product_id = _register_read(MPUREG_PRODUCT_ID); + //Serial.printf("Product_ID= 0x%x\n", (unsigned) _mpu6000_product_id); + + if ((_mpu6000_product_id == MPU6000ES_REV_C4) || (_mpu6000_product_id == MPU6000ES_REV_C5) || + (_mpu6000_product_id == MPU6000_REV_C4) || (_mpu6000_product_id == MPU6000_REV_C5)) { + // Accel scale 8g (4096 LSB/g) + // Rev C has different scaling than rev D + register_write(MPUREG_ACCEL_CONFIG,1<<3); + } else { + // Accel scale 8g (4096 LSB/g) + register_write(MPUREG_ACCEL_CONFIG,2<<3); + } + hal.scheduler->delay(1); #endif /* Configure accelerometer to +/-16G */ - ao_mpu6000_reg_write(MPU6000_ACCEL_CONFIG, - (0 << MPU600_ACCEL_CONFIG_XA_ST) | - (0 << MPU600_ACCEL_CONFIG_YA_ST) | - (0 << MPU600_ACCEL_CONFIG_ZA_ST) | - (MPU600_ACCEL_CONFIG_AFS_SEL_16G << MPU600_ACCEL_CONFIG_AFS_SEL)); + _ao_mpu6000_reg_write(MPU6000_ACCEL_CONFIG, + (0 << MPU600_ACCEL_CONFIG_XA_ST) | + (0 << MPU600_ACCEL_CONFIG_YA_ST) | + (0 << MPU600_ACCEL_CONFIG_ZA_ST) | + (MPU600_ACCEL_CONFIG_AFS_SEL_16G << MPU600_ACCEL_CONFIG_AFS_SEL)); /* Configure gyro to +/- 2000°/s */ - ao_mpu6000_reg_write(MPU6000_GYRO_CONFIG, - (0 << MPU600_GYRO_CONFIG_XG_ST) | - (0 << MPU600_GYRO_CONFIG_YG_ST) | - (0 << MPU600_GYRO_CONFIG_ZG_ST) | - (MPU600_GYRO_CONFIG_FS_SEL_2000 << MPU600_GYRO_CONFIG_FS_SEL)); + _ao_mpu6000_reg_write(MPU6000_GYRO_CONFIG, + (0 << MPU600_GYRO_CONFIG_XG_ST) | + (0 << MPU600_GYRO_CONFIG_YG_ST) | + (0 << MPU600_GYRO_CONFIG_ZG_ST) | + (MPU600_GYRO_CONFIG_FS_SEL_2000 << MPU600_GYRO_CONFIG_FS_SEL)); ao_delay(AO_MS_TO_TICKS(10)); - ao_mpu6000_sample(&normal_mode); + _ao_mpu6000_sample(&normal_mode); errors += ao_mpu6000_accel_check(normal_mode.accel_x, test_mode.accel_x, "x"); errors += ao_mpu6000_accel_check(normal_mode.accel_y, test_mode.accel_y, "y"); @@ -272,13 +298,13 @@ ao_mpu6000_setup(void) ao_panic(AO_PANIC_SELF_TEST_MPU6000); /* Filter to about 100Hz, which also sets the gyro rate to 1000Hz */ - ao_mpu6000_reg_write(MPU6000_CONFIG, - (MPU6000_CONFIG_EXT_SYNC_SET_DISABLED << MPU6000_CONFIG_EXT_SYNC_SET) | - (MPU6000_CONFIG_DLPF_CFG_94_98 << MPU6000_CONFIG_DLPF_CFG)); + _ao_mpu6000_reg_write(MPU6000_CONFIG, + (MPU6000_CONFIG_EXT_SYNC_SET_DISABLED << MPU6000_CONFIG_EXT_SYNC_SET) | + (MPU6000_CONFIG_DLPF_CFG_94_98 << MPU6000_CONFIG_DLPF_CFG)); /* Set sample rate divider to sample at 200Hz (v = gyro/rate - 1) */ - ao_mpu6000_reg_write(MPU6000_SMPRT_DIV, - 1000 / 200 - 1); + _ao_mpu6000_reg_write(MPU6000_SMPRT_DIV, + 1000 / 200 - 1); ao_delay(AO_MS_TO_TICKS(100)); ao_mpu6000_configured = 1; @@ -289,10 +315,20 @@ struct ao_mpu6000_sample ao_mpu6000_current; static void ao_mpu6000(void) { - ao_mpu6000_setup(); + /* ao_mpu6000_init already grabbed the SPI bus and mutex */ + _ao_mpu6000_setup(); +#if AO_MPU6000_SPI + ao_mpu6000_spi_put(); +#endif for (;;) { - ao_mpu6000_sample(&ao_mpu6000_current); +#if AO_MPU6000_SPI + ao_mpu6000_spi_get(); +#endif + _ao_mpu6000_sample(&ao_mpu6000_current); +#if AO_MPU6000_SPI + ao_mpu6000_spi_put(); +#endif ao_arch_critical( AO_DATA_PRESENT(AO_DATA_MPU6000); AO_DATA_WAIT(); @@ -328,9 +364,20 @@ ao_mpu6000_init(void) ao_mpu6000_configured = 0; ao_add_task(&ao_mpu6000_task, ao_mpu6000, "mpu6000"); -#ifndef AO_MPU6000_I2C_INDEX + +#if AO_MPU6000_SPI ao_spi_init_cs(AO_MPU6000_SPI_CS_PORT, (1 << AO_MPU6000_SPI_CS_PIN)); + + /* Pretend to be the mpu6000 task. Grab the SPI bus right away and + * hold it for the task so that nothing else uses the SPI bus before + * we get the I2C mode disabled in the chip + */ + + ao_cur_task = &ao_mpu6000_task; + ao_spi_get(AO_MPU6000_SPI_BUS, AO_SPI_SPEED_1MHz); + ao_cur_task = NULL; #endif + ao_cmd_register(&ao_mpu6000_cmds[0]); } #endif diff --git a/src/drivers/ao_mpu6000.h b/src/drivers/ao_mpu6000.h index f01e9e83..a42f69c4 100644 --- a/src/drivers/ao_mpu6000.h +++ b/src/drivers/ao_mpu6000.h @@ -133,13 +133,13 @@ #define MPU6000_SIGNAL_PATH_RESET_ACCEL_RESET 1 #define MPU6000_SIGNAL_PATH_RESET_TEMP_RESET 0 -#define MPU6000_USER_CONTROL 0x6a -#define MPU6000_USER_CONTROL_FIFO_EN 6 -#define MPU6000_USER_CONTROL_I2C_MST_EN 5 -#define MPU6000_USER_CONTROL_I2C_IF_DIS 4 -#define MPU6000_USER_CONTROL_FIFO_RESET 2 -#define MPU6000_USER_CONTROL_I2C_MST_RESET 1 -#define MPU6000_USER_CONTROL_SIG_COND_RESET 0 +#define MPU6000_USER_CTRL 0x6a +#define MPU6000_USER_CTRL_FIFO_EN 6 +#define MPU6000_USER_CTRL_I2C_MST_EN 5 +#define MPU6000_USER_CTRL_I2C_IF_DIS 4 +#define MPU6000_USER_CTRL_FIFO_RESET 2 +#define MPU6000_USER_CTRL_I2C_MST_RESET 1 +#define MPU6000_USER_CTRL_SIG_COND_RESET 0 #define MPU6000_PWR_MGMT_1 0x6b #define MPU6000_PWR_MGMT_1_DEVICE_RESET 7 diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 1e78cabc..6fe86e62 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -87,13 +87,16 @@ extern uint16_t ao_spi_speed[STM_NUM_SPI]; void ao_spi_init(void); +#define ao_spi_set_cs(reg,mask) ((reg)->bsrr = ((uint32_t) (mask)) << 16) +#define ao_spi_clr_cs(reg,mask) ((reg)->bsrr = (mask)) + #define ao_spi_get_mask(reg,mask,bus, speed) do { \ ao_spi_get(bus, speed); \ - (reg)->bsrr = ((uint32_t) mask) << 16; \ + ao_spi_set_cs(reg,mask); \ } while (0) #define ao_spi_put_mask(reg,mask,bus) do { \ - (reg)->bsrr = mask; \ + ao_spi_clr_cs(reg,mask); \ ao_spi_put(bus); \ } while (0) -- cgit v1.2.3 From 69b9f613ad36b8039f223ed30f8c75913916d82c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 14 May 2013 22:19:07 -0700 Subject: altos: Remove some MMA655x debugging printfs Signed-off-by: Keith Packard --- src/drivers/ao_mma655x.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_mma655x.c b/src/drivers/ao_mma655x.c index 28fe1e08..ce83a5a3 100644 --- a/src/drivers/ao_mma655x.c +++ b/src/drivers/ao_mma655x.c @@ -206,10 +206,7 @@ ao_mma655x_setup(void) ao_mma655x_reg_write(AO_MMA655X_AXISCFG, AXISCFG_VALUE | (1 << AO_MMA655X_AXISCFG_ST)); - for (i = 0; i < 10; i++) { - a_st = ao_mma655x_value(); - printf ("SELF-TEST %2d = %6d\n", i, a_st); - } + a_st = ao_mma655x_value(); stdefl = ao_mma655x_reg_read(AO_MMA655X_STDEFL); @@ -218,11 +215,6 @@ ao_mma655x_setup(void) (0 << AO_MMA655X_AXISCFG_ST)); a = ao_mma655x_value(); - for (i = 0; i < 10; i++) { - a = ao_mma655x_value(); - printf("NORMAL %2d = %6d\n", i, a); - } - ao_mma655x_reg_write(AO_MMA655X_DEVCFG, DEVCFG_VALUE | (1 << AO_MMA655X_DEVCFG_ENDINIT)); s0 = ao_mma655x_reg_read(AO_MMA655X_SN0); @@ -234,8 +226,6 @@ ao_mma655x_setup(void) serial = lot & 0x1fff; lot >>= 12; pn = ao_mma655x_reg_read(AO_MMA655X_PN); - printf ("MMA655X lot %d serial %d number %d\n", lot, serial, pn); - } uint16_t ao_mma655x_current; -- cgit v1.2.3 From 1931e028bebc3cd8df9392e30eb0e888d0799768 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 14 May 2013 22:29:06 -0700 Subject: altos: Move MS5607 info from 'v' to 'c s' Makes more sense there. Signed-off-by: Keith Packard --- src/core/ao_cmd.c | 3 --- src/core/ao_config.c | 3 +++ 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 188b8bb4..5113548b 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -290,9 +290,6 @@ version(void) , ao_log_format #endif ); -#if HAS_MS5607 - ao_ms5607_info(); -#endif printf("software-version %s\n", ao_version); } #endif diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 73608a55..1a500c79 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -693,6 +693,9 @@ ao_config_show(void) __reentrant for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) if (ao_config_vars[cmd].show) (*ao_config_vars[cmd].show)(); +#if HAS_MS5607 + ao_ms5607_info(); +#endif } #if HAS_EEPROM -- cgit v1.2.3 From 4ef0136c27e8f47a1eb38f9cbcd2c61288732d78 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 15 May 2013 15:32:59 -0700 Subject: altos: Generate unmodulated carrier for CC1120 test mode This sets the deviation to 0, enables the preamble and turns on the transmitter. It will sit there happily sending a bare carrier forever Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 42 ++++++++++++++++++++++++++++++++++++++++-- src/drivers/ao_cc1120.h | 2 ++ 2 files changed, 42 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 772014ee..37d04927 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -326,6 +326,8 @@ static const uint16_t packet_setup[] = { (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | (0 << CC1120_PKT_CFG0_UART_MODE_EN) | (0 << CC1120_PKT_CFG0_UART_SWAP_EN)), + CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) | + (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)), AO_CC1120_MARC_GPIO_IOCFG, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP, }; @@ -389,6 +391,8 @@ static const uint16_t rdf_setup[] = { (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | (0 << CC1120_PKT_CFG0_UART_MODE_EN) | (0 << CC1120_PKT_CFG0_UART_SWAP_EN)), + CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) | + (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)), }; /* @@ -433,6 +437,33 @@ static const uint16_t aprs_setup[] = { (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) | (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) | (0 << CC1120_PKT_CFG1_APPEND_STATUS)), + CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) | + (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)), +}; + +/* + * For Test mode, we want an unmodulated carrier. To do that, we + * set the deviation to zero and enable a preamble so that the radio + * turns on before we send any data + */ + +static const uint16_t test_setup[] = { + CC1120_DEVIATION_M, 0, + CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) | + (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) | + (0 << CC1120_MODCFG_DEV_E_DEV_E)), + CC1120_DRATE2, ((APRS_DRATE_E << CC1120_DRATE2_DATARATE_E) | + (((APRS_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)), + CC1120_DRATE1, ((APRS_DRATE_M >> 8) & 0xff), + CC1120_DRATE0, ((APRS_DRATE_M >> 0) & 0xff), + CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | + (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)), + CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) | + (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) | + (0 << CC1120_PKT_CFG1_APPEND_STATUS)), + CC1120_PREAMBLE_CFG1, ((CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) | + (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD)), }; #define AO_PKT_CFG0_INFINITE ((0 << CC1120_PKT_CFG0_RESERVED7) | \ @@ -456,8 +487,9 @@ static uint16_t ao_radio_mode; #define AO_RADIO_MODE_BITS_PACKET_RX 16 #define AO_RADIO_MODE_BITS_RDF 32 #define AO_RADIO_MODE_BITS_APRS 64 -#define AO_RADIO_MODE_BITS_INFINITE 128 -#define AO_RADIO_MODE_BITS_FIXED 256 +#define AO_RADIO_MODE_BITS_TEST 128 +#define AO_RADIO_MODE_BITS_INFINITE 256 +#define AO_RADIO_MODE_BITS_FIXED 512 #define AO_RADIO_MODE_NONE 0 #define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF) @@ -467,6 +499,7 @@ static uint16_t ao_radio_mode; #define AO_RADIO_MODE_APRS_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF) #define AO_RADIO_MODE_APRS_LAST_BUF (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_BUF) #define AO_RADIO_MODE_APRS_FINISH (AO_RADIO_MODE_BITS_APRS | AO_RADIO_MODE_BITS_FIXED | AO_RADIO_MODE_BITS_TX_FINISH) +#define AO_RADIO_MODE_TEST (AO_RADIO_MODE_BITS_TEST | AO_RADIO_MODE_BITS_INFINITE | AO_RADIO_MODE_BITS_TX_BUF) static void ao_radio_set_mode(uint16_t new_mode) @@ -504,6 +537,10 @@ ao_radio_set_mode(uint16_t new_mode) for (i = 0; i < sizeof (aprs_setup) / sizeof (aprs_setup[0]); i += 2) ao_radio_reg_write(aprs_setup[i], aprs_setup[i+1]); + if (changes & AO_RADIO_MODE_BITS_TEST) + for (i = 0; i < sizeof (test_setup) / sizeof (test_setup[0]); i += 2) + ao_radio_reg_write(test_setup[i], test_setup[i+1]); + if (changes & AO_RADIO_MODE_BITS_INFINITE) ao_radio_reg_write(CC1120_PKT_CFG0, AO_PKT_CFG0_INFINITE); @@ -652,6 +689,7 @@ ao_radio_test_cmd(void) ao_packet_slave_stop(); #endif ao_radio_get(0xff); + ao_radio_set_mode(AO_RADIO_MODE_TEST); ao_radio_strobe(CC1120_STX); #if CC1120_TRACE { int t; diff --git a/src/drivers/ao_cc1120.h b/src/drivers/ao_cc1120.h index 5d226b64..a1d78c01 100644 --- a/src/drivers/ao_cc1120.h +++ b/src/drivers/ao_cc1120.h @@ -404,6 +404,8 @@ #define CC1120_MARC_SPARE (CC1120_EXTENDED_BIT | 0x03) #define CC1120_ECG_CFG (CC1120_EXTENDED_BIT | 0x04) #define CC1120_SOFT_TX_DATA_CFG (CC1120_EXTENDED_BIT | 0x05) +#define CC1120_SOFT_TX_DATA_CFG_SYMBOL_MAP_CFG 5 +#define CC1120_SOFT_TX_DATA_CFG_SOFT_TX_DATA_EN 0 #define CC1120_EXT_CTRL (CC1120_EXTENDED_BIT | 0x06) #define CC1120_RCCAL_FINE (CC1120_EXTENDED_BIT | 0x07) #define CC1120_RCCAL_COARSE (CC1120_EXTENDED_BIT | 0x08) -- cgit v1.2.3 From 8a19805a6b079450b5afd5fa2334cede8495ae4a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 17 May 2013 03:21:08 -0700 Subject: altos/cc1111: Hack on USB driver to make Windows happy The Windows modem driver is quite chatty at startup time, getting and setting the comm parameters each time the device is opened. Sometimes, when setting the parameters, the cc1111 would STALL EP0. Most of the time, Windows would happily pass this as an error back to AltosUI which would then re-try the open (and succeed, most of the time). Sometimes, Windows would stall for 30 seconds before passing the error back. This made the whole UI freeze, and I suspect most people assumed our app had died. A bit of analysis with the beagle USB sniffer and I discovered the STALL settings, but there wasn't any correlation between the data on the wire and when the STALL would be generated. So, I found a couple of other cc1111 USB stacks on the net and just looked to see how our driver differed. There wasn't anything clearly related, but there were a list of small differences: 1) Other drivers didn't bother waiting for the hardware to ack the USBADDR setting; doing it this way means we can set the address *before* acking the setup packet. It'll get set eventually, at which point the device will start responding to packets again. Easy to fix, and saves a bit of code space too. 2) The other drivers set the STALL bit for setup packets which aren't understood. This shouldn't have any effect on 'good' systems as those shouldn't ever be generating bogus setup packets anyways. The driver already handled the STALL state in the interrupt handler, the only requirement was to figure out when to explicitly set the STALL bit. That required moving the state updating code from the start of the ep0 setup handling to the end, after the setup packet had been examined and data queued in or out as appropriate. 3) Our driver explicitly queued an IN packet for any setup request that wasn't waiting for an OUT pack. This appears to tie in with the USBADDR change above as before I made that change, this change caused the driver to fail to respond to most setup packets. This was simple once the above change was made, just move the generation of the IN packet inside the code that switched to the IN state. Signed-off-by: Keith Packard --- src/cc1111/ao_usb.c | 68 ++++++++++++++++++++++++++++++----------------------- src/core/ao_usb.h | 1 + 2 files changed, 39 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_usb.c b/src/cc1111/ao_usb.c index 8bd2efdf..a655d1be 100644 --- a/src/cc1111/ao_usb.c +++ b/src/cc1111/ao_usb.c @@ -152,19 +152,17 @@ ao_usb_ep0_fill(void) *ao_usb_ep0_out_data++ = USBFIFO[0]; } -void +static void ao_usb_ep0_queue_byte(uint8_t a) { ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a; } -void +static void ao_usb_set_address(uint8_t address) { ao_usb_running = 1; - USBADDR = address | 0x80; - while (USBADDR & 0x80) - ; + USBADDR = address; } static void @@ -191,24 +189,6 @@ ao_usb_ep0_setup(void) if (ao_usb_ep0_out_len != 0) return; - /* Figure out how to ACK the setup packet */ - if (ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) { - if (ao_usb_setup.length) - ao_usb_ep0_state = AO_USB_EP0_DATA_IN; - else - ao_usb_ep0_state = AO_USB_EP0_IDLE; - } else { - if (ao_usb_setup.length) - ao_usb_ep0_state = AO_USB_EP0_DATA_OUT; - else - ao_usb_ep0_state = AO_USB_EP0_IDLE; - } - USBINDEX = 0; - if (ao_usb_ep0_state == AO_USB_EP0_IDLE) - USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END; - else - USBCS0 = USBCS0_CLR_OUTPKT_RDY; - ao_usb_ep0_in_data = ao_usb_ep0_in_buf; ao_usb_ep0_in_len = 0; switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_TYPE_MASK) { @@ -274,10 +254,39 @@ ao_usb_ep0_setup(void) } break; } - if (ao_usb_ep0_state != AO_USB_EP0_DATA_OUT) { + + /* Figure out how to ACK the setup packet and the + * next state + */ + USBINDEX = 0; + if (ao_usb_ep0_in_len) { + + /* Sending data back to the host + */ + ao_usb_ep0_state = AO_USB_EP0_DATA_IN; + USBCS0 = USBCS0_CLR_OUTPKT_RDY; if (ao_usb_setup.length < ao_usb_ep0_in_len) ao_usb_ep0_in_len = ao_usb_setup.length; ao_usb_ep0_flush(); + } else if (ao_usb_ep0_out_len) { + + /* Receiving data from the host + */ + ao_usb_ep0_state = AO_USB_EP0_DATA_OUT; + USBCS0 = USBCS0_CLR_OUTPKT_RDY; + } else if (ao_usb_setup.length) { + + /* Uh-oh, the host expected to send or receive data + * and we don't know what to do. + */ + ao_usb_ep0_state = AO_USB_EP0_STALL; + USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_SEND_STALL; + } else { + + /* Simple setup packet with no data + */ + ao_usb_ep0_state = AO_USB_EP0_IDLE; + USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END; } } @@ -299,12 +308,12 @@ ao_usb_ep0(void) USBINDEX = 0; cs0 = USBCS0; if (cs0 & USBCS0_SETUP_END) { - ao_usb_ep0_state = AO_USB_EP0_IDLE; USBCS0 = USBCS0_CLR_SETUP_END; + ao_usb_ep0_state = AO_USB_EP0_IDLE; } if (cs0 & USBCS0_SENT_STALL) { + USBCS0 = 0; ao_usb_ep0_state = AO_USB_EP0_IDLE; - USBCS0 &= ~USBCS0_SENT_STALL; } if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN && (cs0 & USBCS0_INPKT_RDY) == 0) @@ -318,12 +327,11 @@ ao_usb_ep0(void) break; case AO_USB_EP0_DATA_OUT: ao_usb_ep0_fill(); - if (ao_usb_ep0_out_len == 0) - ao_usb_ep0_state = AO_USB_EP0_IDLE; USBINDEX = 0; - if (ao_usb_ep0_state == AO_USB_EP0_IDLE) + if (ao_usb_ep0_out_len == 0) { + ao_usb_ep0_state = AO_USB_EP0_IDLE; USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END; - else + } else USBCS0 = USBCS0_CLR_OUTPKT_RDY; break; } diff --git a/src/core/ao_usb.h b/src/core/ao_usb.h index 4476ee6b..6bc77608 100644 --- a/src/core/ao_usb.h +++ b/src/core/ao_usb.h @@ -114,6 +114,7 @@ extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; #define AO_USB_EP0_IDLE 0 #define AO_USB_EP0_DATA_IN 1 #define AO_USB_EP0_DATA_OUT 2 +#define AO_USB_EP0_STALL 3 #define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) -- cgit v1.2.3 From bcc65597d3d20f1d58df784100af766cee5f0f20 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 18 Apr 2013 15:54:13 -0500 Subject: lpc: Initial lpcxpresso bits This gets the LPC11U14 clock set to the PLL and blinks the LED. Signed-off-by: Keith Packard --- src/lpc/Makefile.defs | 42 +++ src/lpc/altos.ld | 72 +++++ src/lpc/ao_arch.h | 122 ++++++++ src/lpc/ao_arch_funcs.h | 147 ++++++++++ src/lpc/ao_interrupt.c | 155 ++++++++++ src/lpc/ao_led_lpc.c | 65 +++++ src/lpc/ao_romconfig.c | 25 ++ src/lpc/ao_serial_lpc.c | 154 ++++++++++ src/lpc/ao_timer_lpc.c | 165 +++++++++++ src/lpc/baud_rate | 131 +++++++++ src/lpc/figure-checksum | 39 +++ src/lpc/lpc.h | 723 +++++++++++++++++++++++++++++++++++++++++++++++ src/lpc/registers.ld | 9 + src/lpcxpresso/Makefile | 64 +++++ src/lpcxpresso/ao_pins.h | 47 +++ 15 files changed, 1960 insertions(+) create mode 100644 src/lpc/Makefile.defs create mode 100644 src/lpc/altos.ld create mode 100644 src/lpc/ao_arch.h create mode 100644 src/lpc/ao_arch_funcs.h create mode 100644 src/lpc/ao_interrupt.c create mode 100644 src/lpc/ao_led_lpc.c create mode 100644 src/lpc/ao_romconfig.c create mode 100644 src/lpc/ao_serial_lpc.c create mode 100644 src/lpc/ao_timer_lpc.c create mode 100644 src/lpc/baud_rate create mode 100755 src/lpc/figure-checksum create mode 100644 src/lpc/lpc.h create mode 100644 src/lpc/registers.ld create mode 100644 src/lpcxpresso/Makefile create mode 100644 src/lpcxpresso/ao_pins.h (limited to 'src') diff --git a/src/lpc/Makefile.defs b/src/lpc/Makefile.defs new file mode 100644 index 00000000..c18284d2 --- /dev/null +++ b/src/lpc/Makefile.defs @@ -0,0 +1,42 @@ +vpath % ../lpc:../product:../drivers:../core:../util:../kalman:../aes:.. +vpath make-altitude ../util +vpath make-kalman ../util +vpath kalman.5c ../kalman +vpath kalman_filter.5c ../kalman +vpath load_csv.5c ../kalman +vpath matrix.5c ../kalman +vpath ao-make-product.5c ../util + +CC=arm-none-eabi-gcc +SAT=/opt/cortex +SAT_CLIB=$(SAT)/lib/pdclib-cortex-m0.a +SAT_CFLAGS=-I$(SAT)/include + +ifndef VERSION +include ../Version +endif + +AO_CFLAGS=-I. -I../lpc -I../core -I../drivers -I.. +LPC_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) + +LDFLAGS=-L../stm -Wl,-Taltos.ld + +NICKLE=nickle + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +.c.o: + $(call quiet,CC) -c $(CFLAGS) -o $@ $< + +ao_serial_lpc.h: ../lpc/baud_rate ao_pins.h + nickle ../lpc/baud_rate `awk '/AO_LPC_CLKOUT/{print $$3}' ao_pins.h` > $@ + +ao_serial_lpc.o: ao_serial_lpc.h + +.DEFAULT_GOAL=all diff --git a/src/lpc/altos.ld b/src/lpc/altos.ld new file mode 100644 index 00000000..7a99e66b --- /dev/null +++ b/src/lpc/altos.ld @@ -0,0 +1,72 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +MEMORY { + rom (rx) : ORIGIN = 0x00000000, LENGTH = 32K + ram (!w) : ORIGIN = 0x10000000, LENGTH = 4K +} + +INCLUDE registers.ld + +EXTERN (lpc_interrupt_vector) + +SECTIONS { + /* + * Rom contents + */ + + .text ORIGIN(rom) : { + __text_start__ = .; + *(.interrupt) /* Interrupt vectors */ + + . = ORIGIN(rom) + 0x100; + + ao_romconfig.o(.romconfig*) + ao_product.o(.romconfig*) + + *(.text*) /* Executable code */ + *(.rodata*) /* Constants */ + + } > rom + + .ARM.exidx : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __text_end__ = .; + } > rom + + /* Data -- relocated to RAM, but written to ROM + */ + .data ORIGIN(ram) : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + __data_start__ = .; + *(.data) /* initialized data */ + __data_end__ = .; + __bss_start__ = .; + } >ram + + .bss : { + *(.bss) + *(COMMON) + __bss_end__ = .; + } >ram + + PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram)); + PROVIDE(end = .); +} + +ENTRY(start); + + diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h new file mode 100644 index 00000000..61182160 --- /dev/null +++ b/src/lpc/ao_arch.h @@ -0,0 +1,122 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_ARCH_H_ +#define _AO_ARCH_H_ + +#include + +/* + * LPC11U14 definitions and code fragments for AltOS + */ + +#define AO_STACK_SIZE 512 + +#define AO_LED_TYPE uint16_t + +#ifndef AO_TICK_TYPE +#define AO_TICK_TYPE uint16_t +#define AO_TICK_SIGNED int16_t +#endif + +/* Various definitions to make GCC look more like SDCC */ + +#define ao_arch_naked_declare __attribute__((naked)) +#define ao_arch_naked_define +#define __pdata +#define __data +#define __xdata +#define __code const +#define __reentrant +#define __interrupt(n) +#define __at(n) + +#define ao_arch_reboot() + +#define ao_arch_nop() asm("nop") + +#define ao_arch_interrupt(n) /* nothing */ + +#undef putchar +#undef getchar +#define putchar(c) ao_putchar(c) +#define getchar ao_getchar + +extern void putchar(char c); +extern char getchar(void); + +/* + * ao_romconfig.c + */ + +#define AO_ROMCONFIG_VERSION 2 + +#define AO_ROMCONFIG_SYMBOL(a) __attribute__((section(".romconfig"))) const + +extern const uint16_t ao_romconfig_version; +extern const uint16_t ao_romconfig_check; +extern const uint16_t ao_serial_number; +extern const uint32_t ao_radio_cal; + +#define ao_arch_task_members\ + uint32_t *sp; /* saved stack pointer */ + +#define ao_arch_block_interrupts() asm("cpsid i") +#define ao_arch_release_interrupts() asm("cpsie i") + +/* + * For now, we're running at a weird frequency + */ + +#if AO_HSE +#define AO_PLLSRC AO_HSE +#else +#define AO_PLLSRC STM_HSI_FREQ +#endif + +#define AO_PLLVCO (AO_PLLSRC * AO_PLLMUL) +#define AO_SYSCLK (AO_PLLVCO / AO_PLLDIV) +#define AO_HCLK (AO_SYSCLK / AO_AHB_PRESCALER) +#define AO_PCLK1 (AO_HCLK / AO_APB1_PRESCALER) +#define AO_PCLK2 (AO_HCLK / AO_APB2_PRESCALER) + +#if AO_APB1_PRESCALER == 1 +#define AO_TIM23467_CLK AO_PCLK1 +#else +#define AO_TIM23467_CLK (2 * AO_PCLK1) +#endif + +#if AO_APB2_PRESCALER == 1 +#define AO_TIM91011_CLK AO_PCLK2 +#else +#define AO_TIM91011_CLK (2 * AO_PCLK2) +#endif + +#define AO_STM_NVIC_HIGH_PRIORITY 4 +#define AO_STM_NVIC_CLOCK_PRIORITY 6 +#define AO_STM_NVIC_MED_PRIORITY 8 +#define AO_STM_NVIC_LOW_PRIORITY 10 + +void +ao_adc_init(void); + + + +void +ao_serial_init(void); + +#endif /* _AO_ARCH_H_ */ diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h new file mode 100644 index 00000000..39222b9d --- /dev/null +++ b/src/lpc/ao_arch_funcs.h @@ -0,0 +1,147 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_ARCH_FUNCS_H_ +#define _AO_ARCH_FUNCS_H_ + +#define ao_spi_get_bit(reg,bit,pin,bus,speed) ao_spi_get_mask(reg,(1<stack + AO_STACK_SIZE); + uint32_t a = (uint32_t) start; + int i; + + /* Return address (goes into LR) */ + ARM_PUSH32(sp, a); + + /* Clear register values r0-r7 */ + i = 8; + while (i--) + ARM_PUSH32(sp, 0); + + /* APSR */ + ARM_PUSH32(sp, 0); + + /* PRIMASK with interrupts enabled */ + ARM_PUSH32(sp, 0); + + task->sp = sp; +} + +static inline void ao_arch_save_regs(void) { + /* Save general registers */ + asm("push {r0-r7,lr}\n"); + + /* Save APSR */ + asm("mrs r0,apsr"); + asm("push {r0}"); + + /* Save PRIMASK */ + asm("mrs r0,primask"); + asm("push {r0}"); +} + +static inline void ao_arch_save_stack(void) { + uint32_t *sp; + asm("mov %0,sp" : "=&r" (sp) ); + ao_cur_task->sp = (sp); + if ((uint8_t *) sp < &ao_cur_task->stack[0]) + ao_panic (AO_PANIC_STACK); +} + +static inline void ao_arch_restore_stack(void) { + uint32_t sp; + sp = (uint32_t) ao_cur_task->sp; + + /* Switch stacks */ + asm("mov sp, %0" : : "r" (sp) ); + + /* Restore PRIMASK */ + asm("pop {r0}"); + asm("msr primask,r0"); + + /* Restore APSR */ + asm("pop {r0}"); + asm("msr apsr,r0"); + + /* Restore general registers and return */ + asm("pop {r0-r7,pc}\n"); +} + +#define ao_arch_isr_stack() + +#define ao_arch_wait_interrupt() do { \ + asm(".global ao_idle_loc\n\twfi\nao_idle_loc:"); \ + ao_arch_release_interrupts(); \ + ao_arch_block_interrupts(); \ + } while (0) + +#define ao_arch_critical(b) do { \ + ao_arch_block_interrupts(); \ + do { b } while (0); \ + ao_arch_release_interrupts(); \ + } while (0) + +#endif /* _AO_ARCH_FUNCS_H_ */ diff --git a/src/lpc/ao_interrupt.c b/src/lpc/ao_interrupt.c new file mode 100644 index 00000000..b5e67007 --- /dev/null +++ b/src/lpc/ao_interrupt.c @@ -0,0 +1,155 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +extern void main(void); +extern char __stack__; +extern char __text_start__, __text_end__; +extern char __data_start__, __data_end__; +extern char __bss_start__, __bss_end__; + +/* Interrupt functions */ + +void lpc_halt_isr(void) +{ + ao_panic(AO_PANIC_CRASH); +} + +void lpc_ignore_isr(void) +{ +} + +int x; + +void start(void) { + x = 0; + memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__); + memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__); + main(); +} + +#define STRINGIFY(x) #x + +#define isr(name) \ + void __attribute__ ((weak)) lpc_ ## name ## _isr(void); \ + _Pragma(STRINGIFY(weak lpc_ ## name ## _isr = lpc_ignore_isr)) + +#define isr_halt(name) \ + void __attribute__ ((weak)) lpc_ ## name ## _isr(void); \ + _Pragma(STRINGIFY(weak lpc_ ## name ## _isr = lpc_halt_isr)) + +isr(nmi) +isr_halt(hardfault) +isr_halt(memmanage) +isr_halt(busfault) +isr_halt(usagefault) +isr(svc) +isr(debugmon) +isr(pendsv) +isr(systick) + +isr(pin_int0) /* IRQ0 */ +isr(pin_int1) +isr(pin_int2) +isr(pin_int3) +isr(pin_int4) /* IRQ4 */ +isr(pin_int5) +isr(pin_int6) +isr(pin_int7) + +isr(gint0) /* IRQ8 */ +isr(gint1) +isr(ssp1) +isr(i2c) + +isr(ct16b0) /* IRQ16 */ +isr(ct16b1) +isr(ct32b0) +isr(ct32b1) +isr(ssp0) /* IRQ20 */ +isr(usart) +isr(usb_irq) +isr(usb_fiq) + +isr(adc) /* IRQ24 */ +isr(wwdt) +isr(bod) +isr(flash) + +isr(usb_wakeup) + +#define i(addr,name) [(addr)/4] = lpc_ ## name ## _isr +#define c(addr,value) [(addr)/4] = (value) + +__attribute__ ((section(".interrupt"))) +const void *lpc_interrupt_vector[] = { + [0] = &__stack__, + [1] = start, + i(0x08, nmi), + i(0x0c, hardfault), + c(0x10, 0), + c(0x14, 0), + c(0x18, 0), + c(0x1c, 0), + c(0x20, 0), + c(0x24, 0), + c(0x28, 0), + i(0x2c, svc), + i(0x30, hardfault), + i(0x34, hardfault), + i(0x38, pendsv), + i(0x3c, systick), + + i(0x40, pin_int0), /* IRQ0 */ + i(0x44, pin_int1), + i(0x48, pin_int2), + i(0x4c, pin_int3), + i(0x50, pin_int4), /* IRQ4 */ + i(0x54, pin_int5), + i(0x58, pin_int6), + i(0x5c, pin_int7), + + i(0x60, gint0), /* IRQ8 */ + i(0x64, gint1), + i(0x68, hardfault), + i(0x6c, hardfault), + i(0x70, hardfault), /* IRQ12 */ + i(0x74, hardfault), + i(0x78, ssp1), + i(0x7c, i2c), + + i(0x80, ct16b0), /* IRQ16 */ + i(0x84, ct16b1), + i(0x88, ct32b0), + i(0x8c, ct32b1), + i(0x90, ssp0), /* IRQ20 */ + i(0x94, usart), + i(0x98, usb_irq), + i(0x9c, usb_fiq), + + i(0xa0, adc), /* IRQ24 */ + i(0xa4, wwdt), + i(0xa8, bod), + i(0xac, flash), + + i(0xb0, hardfault), /* IRQ28 */ + i(0xb4, hardfault), + i(0xb8, usb_wakeup), + i(0xbc, hardfault), +}; diff --git a/src/lpc/ao_led_lpc.c b/src/lpc/ao_led_lpc.c new file mode 100644 index 00000000..098dad6b --- /dev/null +++ b/src/lpc/ao_led_lpc.c @@ -0,0 +1,65 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include + +__pdata uint16_t ao_led_enable; + +void +ao_led_on(uint16_t colors) +{ + lpc_gpio.pin[LED_PORT] = 0xffffffff; +} + +void +ao_led_off(uint16_t colors) +{ + lpc_gpio.pin[LED_PORT] = 0; +} + +void +ao_led_set(uint16_t colors) +{ + uint16_t on = colors & ao_led_enable; + uint16_t off = ~colors & ao_led_enable; + + ao_led_off(off); + ao_led_on(on); +} + +void +ao_led_toggle(uint16_t colors) +{ +} + +void +ao_led_for(uint16_t colors, uint16_t ticks) __reentrant +{ + ao_led_on(colors); + ao_delay(ticks); + ao_led_off(colors); +} + +void +ao_led_init(uint16_t enable) +{ + int bit; + + ao_led_enable = enable; + lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_GPIO); + lpc_gpio.dir[LED_PORT] |= enable; +} diff --git a/src/lpc/ao_romconfig.c b/src/lpc/ao_romconfig.c new file mode 100644 index 00000000..cbb922ec --- /dev/null +++ b/src/lpc/ao_romconfig.c @@ -0,0 +1,25 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +AO_ROMCONFIG_SYMBOL (0) uint16_t ao_romconfig_version = AO_ROMCONFIG_VERSION; +AO_ROMCONFIG_SYMBOL (0) uint16_t ao_romconfig_check = ~AO_ROMCONFIG_VERSION; +AO_ROMCONFIG_SYMBOL (0) uint16_t ao_serial_number = 0; +#ifdef AO_RADIO_CAL_DEFAULT +AO_ROMCONFIG_SYMBOL (0) uint32_t ao_radio_cal = AO_RADIO_CAL_DEFAULT; +#endif diff --git a/src/lpc/ao_serial_lpc.c b/src/lpc/ao_serial_lpc.c new file mode 100644 index 00000000..e47f743e --- /dev/null +++ b/src/lpc/ao_serial_lpc.c @@ -0,0 +1,154 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +struct ao_fifo ao_usart_rx_fifo; +struct ao_fifo ao_usart_tx_fifo; +uint8_t ao_usart_tx_started; + +void +ao_debug_out(char c) +{ + if (c == '\n') + ao_debug_out('\r'); +#if 0 + while (!(stm_usart1.sr & (1 << STM_USART_SR_TXE))); + stm_usart1.dr = c; +#endif +} + +static void +_ao_serial_tx_start(void) +{ + if (!ao_fifo_empty(ao_usart_tx_fifo) & !ao_usart_tx_started) + { + ao_usart_tx_started = 1; +#if 0 + ao_fifo_remove(ao_usart_tx_fifo, usart->reg->dr); +#endif + } +} + +void +lpc_usart_isr(void) +{ +#if 0 + uint32_t sr; + + sr = usart->reg->sr; + usart->reg->sr = 0; + + if (sr & (1 << STM_USART_SR_RXNE)) { + char c = usart->reg->dr; + if (!ao_fifo_full(ao_usart_rx_fifo)) + ao_fifo_insert(ao_usart_rx_fifo, c); + ao_wakeup(ao_usart_rx_fifo); + if (stdin) + ao_wakeup(&ao_stdin_ready); + } + if (sr & (1 << STM_USART_SR_TC)) { + ao_usart_tx_started = 0; + _ao_usart_tx_start(usart); + ao_wakeup(ao_usart_tx_fifo); + } +#endif +} + +int +_ao_serial_pollchar(void) +{ + int c; + + if (ao_fifo_empty(ao_usart_rx_fifo)) + c = AO_READ_AGAIN; + else { + uint8_t u; + ao_fifo_remove(ao_usart_rx_fifo,u); + c = u; + } + return c; +} + +char +ao_serial_getchar(void) +{ + int c; + ao_arch_block_interrupts(); + while ((c = _ao_serial_pollchar()) == AO_READ_AGAIN) + ao_sleep(&ao_usart_rx_fifo); + ao_arch_release_interrupts(); + return (char) c; +} + +void +ao_serial_putchar(char c) +{ + ao_arch_block_interrupts(); + while (ao_fifo_full(ao_usart_tx_fifo)) + ao_sleep(&ao_usart_tx_fifo); + ao_fifo_insert(ao_usart_tx_fifo, c); + _ao_serial_tx_start(); + ao_arch_release_interrupts(); +} + +void +ao_serial_drain(void) +{ + ao_arch_block_interrupts(); + while (!ao_fifo_empty(ao_usart_tx_fifo)) + ao_sleep(&ao_usart_tx_fifo); + ao_arch_release_interrupts(); +} + +void +ao_serial_set_speed(uint8_t speed) +{ + if (speed > AO_SERIAL_SPEED_115200) + return; +#if 0 + usart->reg->brr = ao_usart_speeds[speed].brr; +#endif +} + +#include "ao_serial_lpc.h" + +void +ao_serial_init(void) +{ + /* Turn on the USART clock */ + lpc_scb.uartclkdiv = 1; + +#if SERIAL_0_18_19 + lpc_ioconf.pio0_18 = ((LPC_IOCONF_FUNC_PIO0_18_RXD << LPC_IOCONF_FUNC) | + (LPC_IOCONF_MODE_INACTIVE << LPC_IOCONF_MODE) | + (0 << LPC_IOCONF_HYS) | + (0 << LPC_IOCONF_INV) | + (0 << LPC_IOCONF_OD)); + lpc_ioconf.pio0_19 = ((LPC_IOCONF_FUNC_PIO0_19_TXD << LPC_IOCONF_FUNC) | + (LPC_IOCONF_MODE_INACTIVE << LPC_IOCONF_MODE) | + (0 << LPC_IOCONF_HYS) | + (0 << LPC_IOCONF_INV) | + (0 << LPC_IOCONF_OD)); +#endif + + /* Turn on the USART */ + lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_USART); +} + + diff --git a/src/lpc/ao_timer_lpc.c b/src/lpc/ao_timer_lpc.c new file mode 100644 index 00000000..aa796acf --- /dev/null +++ b/src/lpc/ao_timer_lpc.c @@ -0,0 +1,165 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include + +volatile __data AO_TICK_TYPE ao_tick_count; + +uint16_t +ao_time(void) +{ + return ao_tick_count; +} + +#if AO_DATA_ALL +volatile __data uint8_t ao_data_interval = 1; +volatile __data uint8_t ao_data_count; +#endif + +void lpc_systick_isr(void) +{ + if (lpc_systick.csr & (1 << LPC_SYSTICK_CSR_COUNTFLAG)) { + ++ao_tick_count; +#if HAS_TASK_QUEUE + if (ao_task_alarm_tick && (int16_t) (ao_tick_count - ao_task_alarm_tick) >= 0) + ao_task_check_alarm((uint16_t) ao_tick_count); +#endif +#if AO_DATA_ALL + if (++ao_data_count == ao_data_interval) { + ao_data_count = 0; + ao_adc_poll(); +#if (AO_DATA_ALL & ~(AO_DATA_ADC)) + ao_wakeup((void *) &ao_data_count); +#endif + } +#endif + } +} + +#if HAS_ADC +void +ao_timer_set_adc_interval(uint8_t interval) +{ + ao_arch_critical( + ao_data_interval = interval; + ao_data_count = 0; + ); +} +#endif + +#define SYSTICK_RELOAD ((AO_LPC_CLKOUT / 2) / 100 - 1) + +/* Initialize our 100Hz clock */ +void +ao_timer_init(void) +{ + lpc_systick.rvr = SYSTICK_RELOAD; + lpc_systick.cvr = 0; + lpc_systick.csr = ((1 << LPC_SYSTICK_CSR_ENABLE) | + (1 << LPC_SYSTICK_CSR_TICKINT) | + (LPC_SYSTICK_CSR_CLKSOURCE_CPU_OVER_2 << LPC_SYSTICK_CSR_CLKSOURCE)); +} + +#define AO_LPC_M ((AO_LPC_CLKOUT / AO_LPC_CLKIN) - 1) + +#define AO_LPC_FCCO_MIN 156000000 + +void +ao_clock_init(void) +{ + uint8_t p; + uint32_t i; + + /* Turn off all perhipherals except for GPIO configuration */ + lpc_scb.sysahbclkctrl = ((1 << LPC_SCB_SYSAHBCLKCTRL_SYS) | + (1 << LPC_SCB_SYSAHBCLKCTRL_ROM) | + (1 << LPC_SCB_SYSAHBCLKCTRL_RAM0) | + (1 << LPC_SCB_SYSAHBCLKCTRL_FLASHARRAY) | + (1 << LPC_SCB_SYSAHBCLKCTRL_GPIO) | + (1 << LPC_SCB_SYSAHBCLKCTRL_IOCON)); + + /* Turn the IRC clock back on */ + lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_IRC_PD); + + /* Switch to the IRC clock */ + lpc_scb.mainclksel = LPC_SCB_MAINCLKSEL_SEL_IRC << LPC_SCB_MAINCLKSEL_SEL; + lpc_scb.mainclkuen = (0 << LPC_SCB_MAINCLKUEN_ENA); + lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA); + + /* Find a PLL post divider ratio that gets the FCCO in range */ + for (p = 0; p < 4; p++) + if (AO_LPC_CLKOUT << (1 + p) >= AO_LPC_FCCO_MIN) + break; + + if (p == 4) + ao_panic(AO_PANIC_CRASH); + + /* Power down the PLL before touching the registers */ + lpc_scb.pdruncfg |= (1 << LPC_SCB_PDRUNCFG_SYSPLL_PD); + + /* Set PLL divider values */ + lpc_scb.syspllctrl = ((AO_LPC_M << LPC_SCB_SYSPLLCTRL_MSEL) | + (p << LPC_SCB_SYSPLLCTRL_PSEL)); + + + /* Turn off the external crystal clock */ + lpc_scb.pdruncfg |= (1 << LPC_SCB_PDRUNCFG_SYSOSC_PD); + + /* Configure the crystal clock */ + lpc_scb.sysoscctrl = ((0 << LPC_SCB_SYSOSCCTRL_BYPASS) | /* using a crystal */ + ((AO_LPC_CLKIN > 15000000) << LPC_SCB_SYSOSCCTRL_FREQRANGE));/* set range */ + + /* Turn on the external crystal clock */ + lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_SYSOSC_PD); + + /* Select crystal as PLL input */ + + lpc_scb.syspllclksel = (LPC_SCB_SYSPLLCLKSEL_SEL_SYSOSC << LPC_SCB_SYSPLLCLKSEL_SEL); + lpc_scb.syspllclkuen = 0; + lpc_scb.syspllclkuen = (1 << LPC_SCB_SYSPLLCLKUEN_ENA); + + /* Turn on the PLL */ + lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_SYSPLL_PD); + + /* Wait for it to lock */ + + for (i = 0; i < 20000; i++) + if (lpc_scb.syspllstat & (1 << LPC_SCB_SYSPLLSTAT_LOCK)) + break; + if (i == 20000) + ao_panic(AO_PANIC_CRASH); + + /* Switch to the PLL */ + lpc_scb.mainclksel = LPC_SCB_MAINCLKSEL_SEL_PLL_OUTPUT << LPC_SCB_MAINCLKSEL_SEL; + lpc_scb.mainclkuen = 0 << LPC_SCB_MAINCLKUEN_ENA; + lpc_scb.mainclkuen = 1 << LPC_SCB_MAINCLKUEN_ENA; + + /* Set system clock divider */ + lpc_scb.sysahbclkdiv = AO_LPC_CLKOUT / AO_LPC_SYSCLK; + + /* Set USB clock source */ + lpc_scb.usbclksel = (LPC_SCB_USBCLKSEL_SEL_MAIN_CLOCK << LPC_SCB_USBCLKSEL_SEL); + lpc_scb.usbclkuen = (0 << LPC_SCB_USBCLKUEN_ENA); + lpc_scb.usbclkuen = (1 << LPC_SCB_USBCLKUEN_ENA); + + /* Shut down perhipheral clocks (enabled as needed) */ + lpc_scb.ssp0clkdiv = 0; + lpc_scb.uartclkdiv = 0; + lpc_scb.ssp1clkdiv = 0; + lpc_scb.usbclkdiv = 0; + lpc_scb.clkoutdiv = 0; +} diff --git a/src/lpc/baud_rate b/src/lpc/baud_rate new file mode 100644 index 00000000..2bfbf309 --- /dev/null +++ b/src/lpc/baud_rate @@ -0,0 +1,131 @@ +#!/usr/bin/env nickle + +/* + * Given a main clock frequency, + * compute USART clock freq and a table + * of USART config parameters for our target baud rates + */ + +real main_clock = 0; +real usart_clock = 0; + +real[] baud_rates = { 4800, 9600, 19200, 57600, 115200 }; + +void +compute_baud_rate(real rate) { + int divaddval; + int mulval; + + real dl_est = usart_clock / (16 * rate); + + if (dl_est == floor(dl_est)) { + divaddval = 0; + mulval = 1; + } else { + if (false) { + + /* This is how the docs suggest doing it; this + * generates a rate which is reasonably close + */ + + real fr_est = 1.5; + + /* Compute fractional estimate */ + do { + dl_est = floor(usart_clock / (16 * rate * fr_est) + 0.5); + fr_est = usart_clock / (16 * rate * dl_est); + } while (fr_est <= 1.1 || 1.9 <= fr_est); + + /* Given fractional estimate, compute divaddval/mulvals that work best */ + + real best_dist = 1000; + for (int tmp_divaddval = 1; tmp_divaddval < 15; tmp_divaddval++) { + for (int tmp_mulval = 1; tmp_mulval < 16; tmp_mulval++) { + real fr = 1 + tmp_divaddval / tmp_mulval; + real dist = abs(fr - fr_est); + if (dist < best_dist) { + divaddval = tmp_divaddval; + mulval = tmp_mulval; + best_dist = dist; + } + } + } + } else { + + /* This exhaustively searches for the best match */ + + real my_best_dist = 1e20; + int my_best_dl; + int my_best_divaddval; + int my_best_mulval; + for (int my_dl = 1; my_dl < 1024; my_dl++) { + for (int my_mulval = 1; my_mulval < 16; my_mulval++) { + for (int my_divaddval = 0; my_divaddval < my_mulval; my_divaddval++) { + real my_rate = usart_clock / ((16 * my_dl) * (1 + my_divaddval/my_mulval)); + + real my_dist = abs(rate - my_rate); + + if (my_dist == 0 && my_divaddval == 0) { + my_dist = -1; + } + + if (my_dist < my_best_dist) { + my_best_dl = my_dl; + my_best_divaddval = my_divaddval; + my_best_mulval = my_mulval; + my_best_dist = my_dist; + } + } + } + } + + dl_est = my_best_dl; + divaddval = my_best_divaddval; + mulval = my_best_mulval; + } + } + + int dl = floor (dl_est); + + real actual = usart_clock / ((16 * dl) * (1 + divaddval/mulval)); + + printf("\t[AO_SERIAL_SPEED_%d] = { /* actual = %8.2f */\n", floor(rate), actual); + printf("\t\t.dl = %d,\n", dl); + printf("\t\t.divaddval = %d,\n", divaddval); + printf("\t\t.mulval = %d\n", mulval); + printf("\t},\n"); +} + +void +main() { + if (dim(argv) < 2) { + printf ("usage: %s \n", argv[0]); + exit(1); + } + main_clock = string_to_real(argv[1]); + + for (int div = 0; div < 4; div++) { + if (main_clock / (1 << div) <= 12000000) { + usart_clock = main_clock / (1 << div); + break; + } + } + + if (usart_clock == 0) { + printf ("can't get usart clock in range\n"); + exit(1); + } + + printf ("#define AO_LPC_USARTCLK %d\n\n", floor(usart_clock)); + printf("static const struct {\n"); + printf("\tuint16_t dl;\n"); + printf("\tuint8_t divaddval;\n"); + printf("\tuint8_t mulval;\n"); + printf("} ao_usart_speeds[] = {\n"); + for (int i = 0; i < dim(baud_rates); i++) { + compute_baud_rate(baud_rates[i]); + } + printf ("};\n"); +} + +main(); diff --git a/src/lpc/figure-checksum b/src/lpc/figure-checksum new file mode 100755 index 00000000..0b1de578 --- /dev/null +++ b/src/lpc/figure-checksum @@ -0,0 +1,39 @@ +#!/usr/bin/env nickle + +autoimport Process; + +int byteflip(int x) { + return ((x >> 24) & 0xff) | ((x >> 8) & 0xff00) | ((x << 8) & 0xff0000) | ((x << 24) & 0xff000000); +} + +void main () { + file input = popen(popen_direction.read, true, "objdump", + "objdump", "-j", ".text", + "--start-address=0", + "--stop-address=0x20", + "-s", argv[1]); + int sum = 0; + + void add_in(int addr, int value) { + if (addr < 0x1c) { + sum += value; + } else if (addr == 0x1c) { + printf ("-DCKSUM=0x%08x\n", -sum & 0xffffffff); + exit(0); + } + } + while (!File::end(input)) { + string line = File::fgets(input); + string[] words = String::wordsplit(line, " "); + + if (dim(words) < 5) + continue; + if (words[0] == "0000" || words[0] == "0010") { + int addr = string_to_integer(words[0], 16); + for (int i = 0; i < 4; i++) + add_in(addr + i * 4, byteflip(string_to_integer(words[i+1], 16))); + } + } +} + +main(); diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h new file mode 100644 index 00000000..87af494a --- /dev/null +++ b/src/lpc/lpc.h @@ -0,0 +1,723 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _LPC_H_ +#define _LPC_H_ + +#include + +typedef volatile uint32_t vuint32_t; +typedef volatile uint16_t vuint16_t; +typedef volatile uint8_t vuint8_t; +typedef volatile void * vvoid_t; + +struct lpc_ioconf { + vuint32_t pio0_0; + vuint32_t pio0_1; + vuint32_t pio0_2; + vuint32_t pio0_3; + + vuint32_t pio0_4; + vuint32_t pio0_5; + vuint32_t pio0_6; + vuint32_t pio0_7; + + vuint32_t pio0_8; + vuint32_t pio0_9; + vuint32_t pio0_10; + vuint32_t pio0_11; + + vuint32_t pio0_12; + vuint32_t pio0_13; + vuint32_t pio0_14; + vuint32_t pio0_15; + + vuint32_t pio0_16; + vuint32_t pio0_17; + vuint32_t pio0_18; + vuint32_t pio0_19; + + vuint32_t pio0_20; + vuint32_t pio0_21; + vuint32_t pio0_22; + vuint32_t pio0_23; + + vuint32_t pio1_0; /* 0x60 */ + vuint32_t pio1_1; + vuint32_t pio1_2; + vuint32_t pio1_3; + + vuint32_t pio1_4; + vuint32_t pio1_5; + vuint32_t pio1_6; + vuint32_t pio1_7; + + vuint32_t pio1_8; /* 0x80 */ + vuint32_t pio1_9; + vuint32_t pio1_10; + vuint32_t pio1_11; + + vuint32_t pio1_12; + vuint32_t pio1_13; + vuint32_t pio1_14; + vuint32_t pio1_15; + + vuint32_t pio1_16; /* 0xa0 */ + vuint32_t pio1_17; + vuint32_t pio1_18; + vuint32_t pio1_19; + + vuint32_t pio1_20; + vuint32_t pio1_21; + vuint32_t pio1_22; + vuint32_t pio1_23; + + vuint32_t pio1_24; /* 0xc0 */ + vuint32_t pio1_25; + vuint32_t pio1_26; + vuint32_t pio1_27; + + vuint32_t pio1_28; + vuint32_t pio1_29; + vuint32_t pio1_30; + vuint32_t pio1_31; +}; + +extern struct lpc_ioconf lpc_ioconf; + +#define LPC_IOCONF_FUNC 0 + +/* PIO0_0 */ +#define LPC_IOCONF_FUNC_RESET 0 +#define LPC_IOCONF_FUNC_PIO0_0 1 + +/* PIO0_1 */ +#define LPC_IOCONF_FUNC_PIO0_1 0 +#define LPC_IOCONF_FUNC_CLKOUT 1 +#define LPC_IOCONF_FUNC_CT32B0_MAT2 2 +#define LPC_IOCONF_FUNC_USB_FTOGGLE 3 + +/* PIO0_2 */ +#define LPC_IOCONF_FUNC_PIO0_2 0 +#define LPC_IOCONF_FUNC_SSEL0 1 +#define LPC_IOCONF_FUNC_CT16B0_CAP0 2 + +/* PIO0_3 +#define LPC_IOCONF_FUNC_PIO0_3 0 +#define LPC_IOCONF_FUNC_USB_VBUS 1 + +/* PIO0_4 +#define LPC_IOCONF_FUNC_PIO0_4 0 +#define LPC_IOCONF_FUNC_I2C_SCL 1 + +/* PIO0_5 */ +#define LPC_IOCONF_FUNC_PIO0_5 0 +#define LPC_IOCONF_FUNC_I2C_SDA 1 + +/* PIO0_6 */ +#define LPC_IOCONF_FUNC_PIO0_6 0 +#define LPC_IOCONF_FUNC_USB_CONNECT 1 +#define LPC_IOCONF_FUNC_SCK0 2 + +/* PIO0_7 */ +#define LPC_IOCONF_FUNC_PIO0_7 0 +#define LPC_IOCONF_FUNC_CTS 1 + +/* PIO0_8 +#define LPC_IOCONF_FUNC_PIO0_8 0 +#define LPC_IOCONF_FUNC_MISO0 1 +#define LPC_IOCONF_FUNC_CT16B0_MAT0 2 + +/* PIO0_9 */ +#define LPC_IOCONF_FUNC_PIO0_9 0 +#define LPC_IOCONF_FUNC_MOSI0 1 +#define LPC_IOCONF_FUNC_CT16B0_MAT1 2 + +/* PIO0_10 */ +#define LPC_IOCONF_FUNC_SWCLK 0 +#define LPC_IOCONF_FUNC_PIO0_10 1 +#define LPC_IOCONF_FUNC_SCK0 2 +#define LPC_IOCONF_FUNC_CT16B0_MAT2 3 + +/* PIO0_11 */ +#define LPC_IOCONF_FUNC_TDI 0 +#define LPC_IOCONF_FUNC_PIO0_11 1 +#define LPC_IOCONF_FUNC_AD0 2 +#define LPC_IOCONF_FUNC_CT32B0_MAT3 3 + +/* PIO0_12 */ +#define LPC_IOCONF_FUNC_TMS 0 +#define LPC_IOCONF_FUNC_PIO0_12 1 +#define LPC_IOCONF_FUNC_AD1 2 +#define LPC_IOCONF_FUNC_CT32B1_CAP0 3 + +/* PIO0_13 */ +#define LPC_IOCONF_FUNC_TD0 0 +#define LPC_IOCONF_FUNC_PIO0_13 1 +#define LPC_IOCONF_FUNC_AD2 2 +#define LPC_IOCONF_FUNC_CT32B1_MAT0 3 + +/* PIO0_14 */ +#define LPC_IOCONF_FUNC_TRST 0 +#define LPC_IOCONF_FUNC_PIO0_14 1 +#define LPC_IOCONF_FUNC_AD3 2 +#define LPC_IOCONF_FUNC_PIO0_14_CT32B1_MAT1 3 + +/* PIO0_15 */ +#define LPC_IOCONF_FUNC_SWDIO 0 +#define LPC_IOCONF_FUNC_PIO0_15 1 +#define LPC_IOCONF_FUNC_AD4 2 +#define LPC_IOCONF_FUNC_CT32B1_MAT2 3 + +/* PIO0_16 */ +#define LPC_IOCONF_FUNC_PIO0_16 0 +#define LPC_IOCONF_FUNC_AD5 1 +#define LPC_IOCONF_FUNC_CT32B1_MAT3 2 + +/* PIO0_17 */ +#define LPC_IOCONF_FUNC_PIO0_17 0 +#define LPC_IOCONF_FUNC_RTS 1 +#define LPC_IOCONF_FUNC_CT32B0_CAP0 2 +#define LPC_IOCONF_FUNC_SCLK 3 + +/* PIO0_18 */ +#define LPC_IOCONF_FUNC_PIO0_18 0 +#define LPC_IOCONF_FUNC_PIO0_18_RXD 1 +#define LPC_IOCONF_FUNC_PIO0_18_CT32B0_MAT0 2 + +/* PIO0_19 */ +#define LPC_IOCONF_FUNC_PIO0_19 0 +#define LPC_IOCONF_FUNC_PIO0_19_TXD 1 +#define LPC_IOCONF_FUNC_PIO0_19_CT32B0_MAT1 2 + +/* PIO0_20 */ +#define LPC_IOCONF_FUNC_PIO0_20 0 +#define LPC_IOCONF_FUNC_CT16B1_CAP0 1 + +/* PIO0_21 */ +#define LPC_IOCONF_FUNC_PIO0_21 0 +#define LPC_IOCONF_FUNC_CT16B1_MAT0 1 +#define LPC_IOCONF_FUNC_MOSI1 2 + +/* PIO0_22 */ +#define LPC_IOCONF_FUNC_PIO0_22 0 +#define LPC_IOCONF_FUNC_AD6 1 +#define LPC_IOCONF_FUNC_CT16B1_MAT1 2 +#define LPC_IOCONF_FUNC_MISO1 3 + +/* PIO0_23 */ +#define LPC_IOCONF_FUNC_PIO0_23 0 +#define LPC_IOCONF_FUNC_AD7 1 + +/* PIO1_0 */ +#define LPC_IOCONF_FUNC_PIO1_0 0 +#define LPC_IOCONF_FUNC_CT32B1_MAT1 1 + +/* PIO1_1 */ +#define LPC_IOCONF_FUNC_PIO1_1 0 +#define LPC_IOCONF_FUNC_CT32B1_MAT1 1 + +/* PIO1_2 */ +#define LPC_IOCONF_FUNC_PIO1_2 0 +#define LPC_IOCONF_FUNC_PIO1_2_CT32B1_MAT2 1 + +/* PIO1_3*/ +#define LPC_IOCONF_FUNC_PIO1_3 0 +#define LPC_IOCONF_FUNC_PIO1_3_CT32B1_MAT3 1 + +/* PIO1_4 */ +#define LPC_IOCONF_FUNC_PIO1_4 0 +#define LPC_IOCONF_FUNC_PIO1_4_CT32B1_CAP0 1 + +/* PIO1_5 */ +#define LPC_IOCONF_FUNC_PIO1_5 0 +#define LPC_IOCONF_FUNC_CT32B1_CAP1 1 + +/* PIO1_6 */ +#define LPC_IOCONF_FUNC_PIO1_6 0 + +/* PIO1_7 */ +#define LPC_IOCONF_FUNC_PIO1_7 0 + +/* PIO1_8 */ +#define LPC_IOCONF_FUNC_PIO1_8 0 + +/* PIO1_9 */ +#define LPC_IOCONF_FUNC_PIO1_9 0 + +/* PIO1_10 */ +#define LPC_IOCONF_FUNC_PIO1_10 0 + +/* PIO1_11 */ +#define LPC_IOCONF_FUNC_PIO1_11 0 + +/* PIO1_12 */ +#define LPC_IOCONF_FUNC_PIO1_12 0 + +/* PIO1_13 */ +#define LPC_IOCONF_FUNC_PIO1_13 0 +#define LPC_IOCONF_FUNC_DTR 1 +#define LPC_IOCONF_FUNC_CT16B0_MAT0 2 +#define LPC_IOCONF_FUNC_PIO1_13_TXD 3 + +/* PIO1_14 */ +#define LPC_IOCONF_FUNC_PIO1_14 0 +#define LPC_IOCONF_FUNC_DSR 1 +#define LPC_IOCONF_FUNC_CT16B0_MAT1 2 +#define LPC_IOCONF_FUNC_PIO1_13_RXD 3 + +/* PIO1_15 */ +#define LPC_IOCONF_FUNC_PIO1_15 0 +#define LPC_IOCONF_FUNC_DCD 1 +#define LPC_IOCONF_FUNC_PIO1_15_CT16B0_MAT2 2 +#define LPC_IOCONF_FUNC_SCK1 3 + +/* PIO1_16 */ +#define LPC_IOCONF_FUNC_PIO1_16 0 +#define LPC_IOCONF_FUNC_RI 1 +#define LPC_IOCONF_FUNC_CT16B0_CAP0 2 + +/* PIO1_17 */ +#define LPC_IOCONF_FUNC_PIO1_17 0 +#define LPC_IOCONF_FUNC_CT16B0_CAP1 1 +#define LPC_IOCONF_FUNC_PIO1_17_RXD 2 + +/* PIO1_18 */ +#define LPC_IOCONF_FUNC_PIO1_18 0 +#define LPC_IOCONF_FUNC_CT16B1_CAP1 1 +#define LPC_IOCONF_FUNC_PIO1_18_TXD 2 + +/* PIO1_19 */ +#define LPC_IOCONF_FUNC_PIO1_19 0 +#define LPC_IOCONF_FUNC_DTR 1 +#define LPC_IOCONF_FUNC_SSEL1 2 + +/* PIO1_20 */ +#define LPC_IOCONF_FUNC_PIO1_20 0 +#define LPC_IOCONF_FUNC_DSR 1 +#define LPC_IOCONF_FUNC_PIO1_20_SCK1 2 + +/* PIO1_21 */ +#define LPC_IOCONF_FUNC_PIO1_21 0 +#define LPC_IOCONF_FUNC_DCD 1 +#define LPC_IOCONF_FUNC_PIO1_21_MISO1 2 + +/* PIO1_22 */ +#define LPC_IOCONF_FUNC_PIO1_22 0 +#define LPC_IOCONF_FUNC_RI 1 +#define LPC_IOCONF_FUNC_MOSI1 2 + +/* PIO1_23 */ +#define LPC_IOCONF_FUNC_PIO1_23 0 +#define LPC_IOCONF_FUNC_PIO1_23_CT16B1_MAT1 1 +#define LPC_IOCONF_FUNC_SSEL1 2 + +/* PIO1_24 */ +#define LPC_IOCONF_FUNC_PIO1_24 0 +#define LPC_IOCONF_FUNC_PIO1_24_CT32B0_MAT0 1 + +/* PIO1_25 */ +#define LPC_IOCONF_FUNC_PIO1_25 0 +#define LPC_IOCONF_FUNC_PIO1_25_CT32B0_MAT1 1 + +/* PIO1_26 */ +#define LPC_IOCONF_FUNC_PIO1_26 0 +#define LPC_IOCONF_FUNC_PIO1_26_CT32B0_MAT2 1 +#define LPC_IOCONF_FUNC_PIO1_26_RXD 2 + +/* PIO1_27 */ +#define LPC_IOCONF_FUNC_PIO1_27 0 +#define LPC_IOCONF_FUNC_PIO1_27_CT32B0_MAT3 1 +#define LPC_IOCONF_FUNC_PIO1_27_TXD 2 + +/* PIO1_28 */ +#define LPC_IOCONF_FUNC_PIO1_28 0 +#define LPC_IOCONF_FUNC_PIO1_28_CT32B0_CAP0 1 +#define LPC_IOCONF_FUNC_PIO1_28_SCLK 2 + +/* PIO1_29 */ +#define LPC_IOCONF_FUNC_PIO1_29 0 +#define LPC_IOCONF_FUNC_PIO1_29_SCK0 1 +#define LPC_IOCONF_FUNC_PIO1_29_CT32B0_CAP1 2 + +/* PIO1_31 */ +#define LPC_IOCONF_FUNC_PIO1_31 0 + +#define LPC_IOCONF_FUNC_MASK 0x7 + +#define LPC_IOCONF_MODE 3 +#define LPC_IOCONF_MODE_INACTIVE 0 +#define LPC_IOCONF_MODE_PULL_DOWN 1 +#define LPC_IOCONF_MODE_PULL_UP 2 +#define LPC_IOCONF_MODE_REPEATER 3 +#define LPC_IOCONF_MODE_MASK 3 + +#define LPC_IOCONF_HYS 5 + +#define LPC_IOCONF_INV 6 +#define LPC_IOCONF_OD 10 + +struct lpc_scb { + vuint32_t sysmemremap; /* 0x00 */ + vuint32_t presetctrl; + vuint32_t syspllctrl; + vuint32_t syspllstat; + + vuint32_t usbpllctrl; /* 0x10 */ + vuint32_t usbpllstat; + uint32_t r18; + uint32_t r1c; + + vuint32_t sysoscctrl; /* 0x20 */ + vuint32_t wdtoscctrl; + uint32_t r28; + uint32_t r2c; + + vuint32_t sysrststat; /* 0x30 */ + uint32_t r34; + uint32_t r38; + uint32_t r3c; + + vuint32_t syspllclksel; /* 0x40 */ + vuint32_t syspllclkuen; + vuint32_t usbpllclksel; + vuint32_t usbplllclkuen; + + uint32_t r50[8]; + + vuint32_t mainclksel; /* 0x70 */ + vuint32_t mainclkuen; + vuint32_t sysahbclkdiv; + uint32_t r7c; + + vuint32_t sysahbclkctrl; /* 0x80 */ + uint32_t r84[3]; + + uint32_t r90; /* 0x90 */ + vuint32_t ssp0clkdiv; + vuint32_t uartclkdiv; + vuint32_t ssp1clkdiv; + + uint32_t ra0[8]; + + vuint32_t usbclksel; /* 0xc0 */ + vuint32_t usbclkuen; + vuint32_t usbclkdiv; + uint32_t rcc; + + uint32_t rd0[4]; + + vuint32_t clkoutsel; /* 0xe0 */ + vuint32_t clkoutuen; + vuint32_t clkoutdiv; + uint32_t rec; + + uint32_t rf0[4]; /* 0xf0 */ + + vuint32_t pioporcap0; /* 0x100 */ + vuint32_t pioporcap1; + uint32_t r102[2]; + + uint32_t r110[4]; /* 0x110 */ + uint32_t r120[4]; /* 0x120 */ + uint32_t r130[4]; /* 0x130 */ + uint32_t r140[4]; /* 0x140 */ + + vuint32_t bodctrl; /* 0x150 */ + vuint32_t systckcal; + uint32_t r158[2]; + + uint32_t r160[4]; /* 0x160 */ + + vuint32_t irqlatency; /* 0x170 */ + vuint32_t nmisrc; + vuint32_t pintsel0; + vuint32_t pintsel1; + + vuint32_t pintsel2; /* 0x180 */ + vuint32_t pintsel3; + vuint32_t pintsel4; + vuint32_t pintsel5; + + vuint32_t pintsel6; /* 0x190 */ + vuint32_t pintsel7; + vuint32_t usbclkctrl; + vuint32_t usbclkst; + + uint32_t r1a0[6*4]; /* 0x1a0 */ + + uint32_t r200; /* 0x200 */ + vuint32_t starterp0; + uint32_t r208[2]; + + uint32_t r210; /* 0x210 */ + vuint32_t starterp1; + uint32_t r218[2]; + + uint32_t r220[4]; /* 0x220 */ + + vuint32_t pdsleepcfg; /* 0x230 */ + vuint32_t pdawakecfg; + vuint32_t pdruncfg; + uint32_t r23c; + + uint32_t r240[12 * 4]; /* 0x240 */ + + uint32_t r300[15 * 4]; /* 0x300 */ + + uint32_t r3f0; /* 0x3f0 */ + vuint32_t device_id; +}; + +extern struct lpc_scb lpc_scb; + +#define LPC_SCB_PRESETCTRL_SSP0_RST_N 0 +#define LPC_SCB_PRESETCTRL_I2C_RST_N 1 +#define LPC_SCB_PRESETCTRL_SSP1_RST_N 2 + +#define LPC_SCB_SYSPLLCTRL_MSEL 0 +#define LPC_SCB_SYSPLLCTRL_PSEL 5 +#define LPC_SCB_SYSPLLCTRL_PSEL_1 0 +#define LPC_SCB_SYSPLLCTRL_PSEL_2 1 +#define LPC_SCB_SYSPLLCTRL_PSEL_4 2 +#define LPC_SCB_SYSPLLCTRL_PSEL_8 3 +#define LPC_SCB_SYSPLLCTRL_PSEL_MASK 3 + +#define LPC_SCB_SYSPLLSTAT_LOCK 0 + +#define LPC_SCB_USBPLLCTRL_MSEL 0 +#define LPC_SCB_USBPLLCTRL_PSEL 5 +#define LPC_SCB_USBPLLCTRL_PSEL_1 0 +#define LPC_SCB_USBPLLCTRL_PSEL_2 1 +#define LPC_SCB_USBPLLCTRL_PSEL_4 2 +#define LPC_SCB_USBPLLCTRL_PSEL_8 3 +#define LPC_SCB_USBPLLCTRL_PSEL_MASK 3 + +#define LPC_SCB_USBPLLSTAT_LOCK 0 + +#define LPC_SCB_SYSOSCCTRL_BYPASS 0 +#define LPC_SCB_SYSOSCCTRL_FREQRANGE 1 +#define LPC_SCB_SYSOSCCTRL_FREQRANGE_1_20 0 +#define LPC_SCB_SYSOSCCTRL_FREQRANGE_15_25 1 + +#define LPC_SCB_WDTOSCCTRL_DIVSEL 0 +#define LPC_SCB_WDTOSCCTRL_DIVSEL_MASK 0x1f +#define LPC_SCB_WDTOSCCTRL_FREQSEL 5 +#define LPC_SCB_WDTOSCCTRL_FREQSEL_0_6 1 +#define LPC_SCB_WDTOSCCTRL_FREQSEL_1_05 2 +#define LPC_SCB_WDTOSCCTRL_FREQSEL_1_4 3 +#define LPC_SCB_WDTOSCCTRL_FREQSEL_1_75 4 +#define LPC_SCB_WDTOSCCTRL_FREQSEL_2_1 5 +#define LPC_SCB_WDTOSCCTRL_FREQSEL_2_4 6 +#define LPC_SCB_WDTOSCCTRL_FREQSEL_2_7 7 +#define LPC_SCB_WDTOSCCTRL_FREQSEL_3_0 8 +#define LPC_SCB_WDTOSCCTRL_FREQSEL_3_25 9 +#define LPC_SCB_WDTOSCCTRL_FREQSEL_3_5 0x0a +#define LPC_SCB_WDTOSCCTRL_FREQSEL_3_75 0x0b +#define LPC_SCB_WDTOSCCTRL_FREQSEL_4_0 0x0c +#define LPC_SCB_WDTOSCCTRL_FREQSEL_4_2 0x0d +#define LPC_SCB_WDTOSCCTRL_FREQSEL_4_4 0x0e +#define LPC_SCB_WDTOSCCTRL_FREQSEL_4_6 0x0f +#define LPC_SCB_WDTOSCCTRL_FREQSEL_MASK 0x0f + +#define LPC_SCB_SYSRSTSTAT_POR 0 +#define LPC_SCB_SYSRSTSTAT_EXTRST 1 +#define LPC_SCB_SYSRSTSTAT_WDT 2 +#define LPC_SCB_SYSRSTSTAT_BOD 3 +#define LPC_SCB_SYSRSTSTAT_SYSRST 4 + +#define LPC_SCB_SYSPLLCLKSEL_SEL 0 +#define LPC_SCB_SYSPLLCLKSEL_SEL_IRC 0 +#define LPC_SCB_SYSPLLCLKSEL_SEL_SYSOSC 1 +#define LPC_SCB_SYSPLLCLKSEL_SEL_MASK 3 + +#define LPC_SCB_SYSPLLCLKUEN_ENA 0 + +#define LPC_SCB_USBPLLCLKSEL_SEL 0 +#define LPC_SCB_USBPLLCLKSEL_SEL_IRC 0 +#define LPC_SCB_USBPLLCLKSEL_SEL_SYSOSC 1 +#define LPC_SCB_USBPLLCLKSEL_SEL_MASK 3 + +#define LPC_SCB_USBPLLCLKUEN_ENA 0 + +#define LPC_SCB_MAINCLKSEL_SEL 0 +#define LPC_SCB_MAINCLKSEL_SEL_IRC 0 +#define LPC_SCB_MAINCLKSEL_SEL_PLL_INPUT 1 +#define LPC_SCB_MAINCLKSEL_SEL_WATCHDOG 2 +#define LPC_SCB_MAINCLKSEL_SEL_PLL_OUTPUT 3 +#define LPC_SCB_MAINCLKSEL_SEL_MASK 3 + +#define LPC_SCB_MAINCLKUEN_ENA 0 + +#define LPC_SCB_SYSAHBCLKDIV_DIV 0 + +#define LPC_SCB_SYSAHBCLKCTRL_SYS 0 +#define LPC_SCB_SYSAHBCLKCTRL_ROM 1 +#define LPC_SCB_SYSAHBCLKCTRL_RAM0 2 +#define LPC_SCB_SYSAHBCLKCTRL_FLASHREG 3 +#define LPC_SCB_SYSAHBCLKCTRL_FLASHARRAY 4 +#define LPC_SCB_SYSAHBCLKCTRL_I2C 5 +#define LPC_SCB_SYSAHBCLKCTRL_GPIO 6 +#define LPC_SCB_SYSAHBCLKCTRL_CT16B0 7 +#define LPC_SCB_SYSAHBCLKCTRL_CT16B1 8 +#define LPC_SCB_SYSAHBCLKCTRL_CT32B0 9 +#define LPC_SCB_SYSAHBCLKCTRL_CT32B1 10 +#define LPC_SCB_SYSAHBCLKCTRL_SSP0 11 +#define LPC_SCB_SYSAHBCLKCTRL_USART 12 +#define LPC_SCB_SYSAHBCLKCTRL_ADC 13 +#define LPC_SCB_SYSAHBCLKCTRL_USB 14 +#define LPC_SCB_SYSAHBCLKCTRL_WWDT 15 +#define LPC_SCB_SYSAHBCLKCTRL_IOCON 16 +#define LPC_SCB_SYSAHBCLKCTRL_SSP1 18 +#define LPC_SCB_SYSAHBCLKCTRL_PINT 19 +#define LPC_SCB_SYSAHBCLKCTRL_GROUP0INT 23 +#define LPC_SCB_SYSAHBCLKCTRL_GROUP1INT 24 +#define LPC_SCB_SYSAHBCLKCTRL_RAM1 26 +#define LPC_SCB_SYSAHBCLKCTRL_USBRAM 27 + +#define LPC_SCB_SSP0CLKDIV_ +#define LPC_SCB_UARTCLKDIV_ +#define LPC_SCB_SSP1CLKDIV_ + +#define LPC_SCB_USBCLKSEL_SEL 0 +#define LPC_SCB_USBCLKSEL_SEL_USB_PLL 0 +#define LPC_SCB_USBCLKSEL_SEL_MAIN_CLOCK 1 + +#define LPC_SCB_USBCLKUEN_ENA 0 +#define LPC_SCB_USBCLKDIV_DIV 0 + +#define LPC_SCB_CLKOUTSEL_ +#define LPC_SCB_CLKOUTUEN_ + +#define LPC_SCB_PDRUNCFG_IRCOUT_PD 0 +#define LPC_SCB_PDRUNCFG_IRC_PD 1 +#define LPC_SCB_PDRUNCFG_FLASH_PD 2 +#define LPC_SCB_PDRUNCFG_BOD_PD 3 +#define LPC_SCB_PDRUNCFG_ADC_PD 4 +#define LPC_SCB_PDRUNCFG_SYSOSC_PD 5 +#define LPC_SCB_PDRUNCFG_WDTOSC_PD 6 +#define LPC_SCB_PDRUNCFG_SYSPLL_PD 7 +#define LPC_SCB_PDRUNCFG_USBPLL_PD 8 +#define LPC_SCB_PDRUNCFG_USBPAD_PD 10 + +struct lpc_flash { + uint32_t r0[4]; /* 0x0 */ + + vuint32_t flashcfg; /* 0x10 */ +}; + +extern struct lpc_flash lpc_flash; + +struct lpc_gpio_pin { +}; + +extern struct lpc_gpio_pin lpc_gpio_pin; + +struct lpc_gpio_group0 { +}; + +extern struct lpc_gpio_group0 lpc_gpio_group0; + +struct lpc_gpio_group1 { +}; + +extern struct lpc_gpio_group1 lpc_gpio_group1; + +struct lpc_gpio { + vuint8_t byte[0x40]; /* 0x0000 */ + + uint8_t r0030[0x1000 - 0x40]; + + vuint32_t word[0x40]; /* 0x1000 */ + + uint8_t r1100[0x2000 - 0x1100]; + + vuint32_t dir[2]; /* 0x2000 */ + + uint8_t r2008[0x2080 - 0x2008]; + + vuint32_t mask[2]; /* 0x2080 */ + + uint8_t r2088[0x2100 - 0x2088]; + + vuint32_t pin[2]; /* 0x2100 */ + + uint8_t r2108[0x2200 - 0x2108]; + + vuint32_t set[2]; /* 0x2200 */ + + uint8_t r2208[0x2280 - 0x2208]; + + vuint32_t clr[2]; /* 0x2280 */ + + uint8_t r2288[0x2300 - 0x2288]; + + vuint32_t not[2]; /* 0x2300 */ +}; + +extern struct lpc_gpio lpc_gpio; + +struct lpc_systick { + uint8_t r0000[0x10]; /* 0x0000 */ + + vuint32_t csr; /* 0x0010 */ + vuint32_t rvr; + vuint32_t cvr; + vuint32_t calib; +}; + +extern struct lpc_systick lpc_systick; + +#define LPC_SYSTICK_CSR_ENABLE 0 +#define LPC_SYSTICK_CSR_TICKINT 1 +#define LPC_SYSTICK_CSR_CLKSOURCE 2 +#define LPC_SYSTICK_CSR_CLKSOURCE_CPU_OVER_2 0 +#define LPC_SYSTICK_CSR_CLKSOURCE_CPU 1 +#define LPC_SYSTICK_CSR_COUNTFLAG 16 + +struct lpc_usart { + vuint32_t rbr_thr; /* 0x0000 */ + vuint32_t ier; + vuint32_t iir_fcr; + vuint32_t lcr; + + vuint32_t mcr; /* 0x0010 */ + vuint32_t lsr; + vuint32_t msr; + vuint32_t scr; + + vuint32_t acr; /* 0x0020 */ + vuint32_t icr; + vuint32_t fdr; + vuint32_t osr; + + vuint32_t ter; /* 0x0030 */ + uint32_t r34[3]; + + vuint32_t hden; /* 0x0040 */ + uint32_t r44; + vuint32_t scictrl; + vuint32_t rs485ctrl; + + vuint32_t rs485addrmatch; /* 0x0050 */ + vuint32_t rs485dly; + vuint32_t syncctrl; +}; + +extern struct lpc_usart lpc_usart; + +#endif /* _LPC_H_ */ diff --git a/src/lpc/registers.ld b/src/lpc/registers.ld new file mode 100644 index 00000000..cd6ac5f5 --- /dev/null +++ b/src/lpc/registers.ld @@ -0,0 +1,9 @@ +lpc_usart = 0x40008000; +lpc_flash = 0x4003c000; +lpc_ioconf = 0x40044000; +lpc_scb = 0x40048000; +lpc_gpio_pin = 0x4004c000; +lpc_gpio_group0 = 0x4005c000; +lpc_gpio_group1 = 0x40060000; +lpc_gpio = 0x50000000; +lpc_systick = 0xe000e000; diff --git a/src/lpcxpresso/Makefile b/src/lpcxpresso/Makefile new file mode 100644 index 00000000..bac222cc --- /dev/null +++ b/src/lpcxpresso/Makefile @@ -0,0 +1,64 @@ +# +# AltOS build +# +# + +include ../lpc/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_pins.h \ + ao_product.h \ + lpc.h + +# +# Common AltOS sources +# +ALTOS_SRC = \ + ao_interrupt.c \ + ao_romconfig.c \ + ao_product.c \ + ao_panic.c \ + ao_led_lpc.c \ + ao_task.c \ + ao_timer_lpc.c \ + ao_serial_lpc.c \ + ao_stdio.c + +PRODUCT=LpcDemo-v0.0 +PRODUCT_DEF=-DLPC_DEMO +IDPRODUCT=0x000a + +CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -g -Os + +PROG=lpc-demo.elf + +SRC=$(ALTOS_SRC) ao_demo.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) + +LDFLAGS=-L../lpc -Wl,-Taltos.ld + +$(PROG): Makefile $(OBJ) + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +$(OBJ): $(INC) + +load: $(PROG) + lpc-load $(PROG) + +distclean: clean + +clean: + rm -f *.o $(PROG) + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/lpcxpresso/ao_pins.h b/src/lpcxpresso/ao_pins.h new file mode 100644 index 00000000..56391c2b --- /dev/null +++ b/src/lpcxpresso/ao_pins.h @@ -0,0 +1,47 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#define HAS_BEEP 0 +#define HAS_LED 1 + +/* Crystal on the board */ +#define AO_LPC_CLKIN 12000000 + +/* Main clock frequency. 48MHz for USB so we don't use the USB PLL */ +#define AO_LPC_CLKOUT 48000000 + +/* System clock frequency */ +#define AO_LPC_SYSCLK 24000000 + +#define LED_PORT 0 +#define LED_PIN_RED 7 + +#define AO_LED_RED (1 << LED_PIN_RED) + +#define LEDS_AVAILABLE AO_LED_RED + +#define HAS_USB 0 + +#define PACKET_HAS_SLAVE 0 + +/* USART */ + +#define HAS_SERIAL 1 +#define SERIAL_0_18_19 1 +#define SERIAL_1_14_15 0 +#define SERIAL_1_17_18 0 +#define SERIAL_1_26_27 0 -- cgit v1.2.3 From 04b243e6ef212f54ed284cfbde6d5abb637bf60e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 18 Apr 2013 15:55:26 -0500 Subject: lpcxpresso: Add ao_demo.c Kinda necessary for the demo to build Signed-off-by: Keith Packard --- src/lpcxpresso/ao_demo.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 src/lpcxpresso/ao_demo.c (limited to 'src') diff --git a/src/lpcxpresso/ao_demo.c b/src/lpcxpresso/ao_demo.c new file mode 100644 index 00000000..bb8402f7 --- /dev/null +++ b/src/lpcxpresso/ao_demo.c @@ -0,0 +1,36 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +int +main(void) +{ + int i; + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + ao_clock_init(); + + for (;;) { + ao_led_off(AO_LED_RED); + for (i = 0; i < 100000; i++) + ao_arch_nop(); + ao_led_on(AO_LED_RED); + for (i = 0; i < 100000; i++) + ao_arch_nop(); + } +} -- cgit v1.2.3 From f9d0eb3f3154f98abb0c8952d7171f3e7d3de9b2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 18 Apr 2013 16:15:52 -0500 Subject: altos/lpc: Get 100Hz timer running Use systick, which is built into the ARM core Signed-off-by: Keith Packard --- src/lpc/ao_led_lpc.c | 5 +++-- src/lpc/ao_timer_lpc.c | 2 +- src/lpcxpresso/ao_demo.c | 26 ++++++++++++++++++++++---- 3 files changed, 26 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_led_lpc.c b/src/lpc/ao_led_lpc.c index 098dad6b..7bef51ba 100644 --- a/src/lpc/ao_led_lpc.c +++ b/src/lpc/ao_led_lpc.c @@ -22,13 +22,13 @@ __pdata uint16_t ao_led_enable; void ao_led_on(uint16_t colors) { - lpc_gpio.pin[LED_PORT] = 0xffffffff; + lpc_gpio.pin[LED_PORT] |= colors; } void ao_led_off(uint16_t colors) { - lpc_gpio.pin[LED_PORT] = 0; + lpc_gpio.pin[LED_PORT] &= ~colors; } void @@ -44,6 +44,7 @@ ao_led_set(uint16_t colors) void ao_led_toggle(uint16_t colors) { + lpc_gpio.pin[LED_PORT] ^= colors; } void diff --git a/src/lpc/ao_timer_lpc.c b/src/lpc/ao_timer_lpc.c index aa796acf..51e82525 100644 --- a/src/lpc/ao_timer_lpc.c +++ b/src/lpc/ao_timer_lpc.c @@ -61,7 +61,7 @@ ao_timer_set_adc_interval(uint8_t interval) } #endif -#define SYSTICK_RELOAD ((AO_LPC_CLKOUT / 2) / 100 - 1) +#define SYSTICK_RELOAD ((AO_LPC_SYSCLK / 2) / 100 - 1) /* Initialize our 100Hz clock */ void diff --git a/src/lpcxpresso/ao_demo.c b/src/lpcxpresso/ao_demo.c index bb8402f7..56fef706 100644 --- a/src/lpcxpresso/ao_demo.c +++ b/src/lpcxpresso/ao_demo.c @@ -17,6 +17,15 @@ #include "ao.h" +struct ao_task demo_task; + +static void demo(void) { + for (;;) { + ao_delay(100); + ao_led_toggle(AO_LED_RED); + } +} + int main(void) { @@ -24,13 +33,22 @@ main(void) ao_led_init(LEDS_AVAILABLE); ao_led_on(AO_LED_RED); ao_clock_init(); + ao_timer_init(); + + ao_task_init(); + + ao_add_task(&demo_task, demo, "demo"); + + ao_start_scheduler(); for (;;) { ao_led_off(AO_LED_RED); - for (i = 0; i < 100000; i++) - ao_arch_nop(); + for (;;) + if (ao_tick_count & 1) + break; ao_led_on(AO_LED_RED); - for (i = 0; i < 100000; i++) - ao_arch_nop(); + for (;;) + if (!(ao_tick_count & 1)) + break; } } -- cgit v1.2.3 From 9e8f6ba8b779cd9635f82d6da5f113715c3ee4c7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Apr 2013 00:20:55 -0500 Subject: altos/lpc: Get USART running Adds a simple demo thread that spews data to the serial port Signed-off-by: Keith Packard --- src/lpc/ao_serial_lpc.c | 106 ++++++++++++++++++-------- src/lpc/lpc.h | 189 +++++++++++++++++++++++++++++++++++++++++++++++ src/lpc/registers.ld | 1 + src/lpcxpresso/ao_demo.c | 11 +++ src/lpcxpresso/ao_pins.h | 9 ++- 5 files changed, 283 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_serial_lpc.c b/src/lpc/ao_serial_lpc.c index e47f743e..4ecaa175 100644 --- a/src/lpc/ao_serial_lpc.c +++ b/src/lpc/ao_serial_lpc.c @@ -27,10 +27,9 @@ ao_debug_out(char c) { if (c == '\n') ao_debug_out('\r'); -#if 0 - while (!(stm_usart1.sr & (1 << STM_USART_SR_TXE))); - stm_usart1.dr = c; -#endif + while (!(lpc_usart.lsr & (1 << LPC_USART_LSR_TEMT))) + ; + lpc_usart.rbr_thr = c; } static void @@ -39,35 +38,28 @@ _ao_serial_tx_start(void) if (!ao_fifo_empty(ao_usart_tx_fifo) & !ao_usart_tx_started) { ao_usart_tx_started = 1; -#if 0 - ao_fifo_remove(ao_usart_tx_fifo, usart->reg->dr); -#endif + ao_fifo_remove(ao_usart_tx_fifo, lpc_usart.rbr_thr); } } void lpc_usart_isr(void) { -#if 0 - uint32_t sr; - - sr = usart->reg->sr; - usart->reg->sr = 0; + (void) lpc_usart.iir_fcr; - if (sr & (1 << STM_USART_SR_RXNE)) { - char c = usart->reg->dr; + while (lpc_usart.lsr & (1 << LPC_USART_LSR_RDR)) { + char c = lpc_usart.rbr_thr; if (!ao_fifo_full(ao_usart_rx_fifo)) ao_fifo_insert(ao_usart_rx_fifo, c); - ao_wakeup(ao_usart_rx_fifo); + ao_wakeup(&ao_usart_rx_fifo); if (stdin) ao_wakeup(&ao_stdin_ready); } - if (sr & (1 << STM_USART_SR_TC)) { + if (lpc_usart.lsr & (1 << LPC_USART_LSR_THRE)) { ao_usart_tx_started = 0; - _ao_usart_tx_start(usart); - ao_wakeup(ao_usart_tx_fifo); + _ao_serial_tx_start(); + ao_wakeup(&ao_usart_tx_fifo); } -#endif } int @@ -116,24 +108,33 @@ ao_serial_drain(void) ao_arch_release_interrupts(); } +#include "ao_serial_lpc.h" + void ao_serial_set_speed(uint8_t speed) { if (speed > AO_SERIAL_SPEED_115200) return; -#if 0 - usart->reg->brr = ao_usart_speeds[speed].brr; -#endif -} -#include "ao_serial_lpc.h" + /* Flip to allow access to divisor latches */ + lpc_usart.lcr |= (1 << LPC_USART_LCR_DLAB); + + /* DL LSB */ + lpc_usart.rbr_thr = ao_usart_speeds[speed].dl & 0xff; + + /* DL MSB */ + lpc_usart.ier = (ao_usart_speeds[speed].dl >> 8) & 0xff; + + lpc_usart.fdr = ((ao_usart_speeds[speed].divaddval << LPC_USART_FDR_DIVADDVAL) | + (ao_usart_speeds[speed].mulval << LPC_USART_FDR_MULVAL)); + + /* Turn access to divisor latches back off */ + lpc_usart.lcr &= ~(1 << LPC_USART_LCR_DLAB); +} void ao_serial_init(void) { - /* Turn on the USART clock */ - lpc_scb.uartclkdiv = 1; - #if SERIAL_0_18_19 lpc_ioconf.pio0_18 = ((LPC_IOCONF_FUNC_PIO0_18_RXD << LPC_IOCONF_FUNC) | (LPC_IOCONF_MODE_INACTIVE << LPC_IOCONF_MODE) | @@ -149,6 +150,53 @@ ao_serial_init(void) /* Turn on the USART */ lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_USART); -} - + /* Turn on the USART clock */ + lpc_scb.uartclkdiv = AO_LPC_CLKOUT / AO_LPC_USARTCLK; + + /* Configure USART */ + + /* Enable FIFOs, reset fifo contents, interrupt on 1 received char */ + lpc_usart.iir_fcr = ((1 << LPC_USART_FCR_FIFOEN) | + (1 << LPC_USART_FCR_RXFIFORES) | + (1 << LPC_USART_FCR_TXFIFORES) | + (LPC_USART_FCR_RXTL_1 << LPC_USART_FCR_RXTL)); + + /* 8 n 1 */ + lpc_usart.lcr = ((LPC_USART_LCR_WLS_8 << LPC_USART_LCR_WLS) | + (LPC_USART_LCR_SBS_1 << LPC_USART_LCR_SBS) | + (0 << LPC_USART_LCR_PE) | + (LPC_USART_LCR_PS_ODD << LPC_USART_LCR_PS) | + (0 << LPC_USART_LCR_BC) | + (0 << LPC_USART_LCR_DLAB)); + + /* Disable flow control */ + lpc_usart.mcr = ((0 << LPC_USART_MCR_DTRCTRL) | + (0 << LPC_USART_MCR_RTSCTRL) | + (0 << LPC_USART_MCR_LMS) | + (0 << LPC_USART_MCR_RTSEN) | + (0 << LPC_USART_MCR_CTSEN)); + + /* 16x oversampling */ + lpc_usart.osr = ((0 << LPC_USART_OSR_OSFRAC) | + ((16 - 1) << LPC_USART_OSR_OSINT) | + (0 << LPC_USART_OSR_FDINT)); + + /* Full duplex */ + lpc_usart.hden = ((0 << LPC_USART_HDEN_HDEN)); + + /* Set baud rate */ + ao_serial_set_speed(AO_SERIAL_SPEED_9600); + + /* Enable interrupts */ + lpc_usart.ier = ((1 << LPC_USART_IER_RBRINTEN) | + (1 << LPC_USART_IER_THREINTEN)); + + lpc_nvic_set_enable(LPC_ISR_USART_POS); + lpc_nvic_set_priority(LPC_ISR_USART_POS, 0); +#if USE_SERIAL_0_STDIN + ao_add_stdio(_ao_serial_pollchar, + ao_serial_putchar, + NULL); +#endif +} diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index 87af494a..81cd0cc8 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -720,4 +720,193 @@ struct lpc_usart { extern struct lpc_usart lpc_usart; +#define LPC_USART_IER_RBRINTEN 0 +#define LPC_USART_IER_THREINTEN 1 +#define LPC_USART_IER_RSLINTEN 2 +#define LPC_USART_IER_MSINTEN 3 +#define LPC_USART_IER_ABEOINTEN 8 +#define LPC_USART_IER_ABTOINTEN 9 + +#define LPC_USART_IIR_INTSTATUS 0 +#define LPC_USART_IIR_INTID 1 +#define LPC_USART_IIR_INTID_RLS 3 +#define LPC_USART_IIR_INTID_RDA 2 +#define LPC_USART_IIR_INTID_CTI 6 +#define LPC_USART_IIR_INTID_THRE 1 +#define LPC_USART_IIR_INTID_MS 0 +#define LPC_USART_IIR_INTID_MASK 7 +#define LPC_USART_IIR_FIFOEN 6 +#define LPC_USART_IIR_ABEOINT 8 +#define LPC_USART_IIR_ABTOINT 9 + +#define LPC_USART_FCR_FIFOEN 0 +#define LPC_USART_FCR_RXFIFORES 1 +#define LPC_USART_FCR_TXFIFORES 2 +#define LPC_USART_FCR_RXTL 6 +#define LPC_USART_FCR_RXTL_1 0 +#define LPC_USART_FCR_RXTL_4 1 +#define LPC_USART_FCR_RXTL_8 2 +#define LPC_USART_FCR_RXTL_14 3 + +#define LPC_USART_LCR_WLS 0 +#define LPC_USART_LCR_WLS_5 0 +#define LPC_USART_LCR_WLS_6 1 +#define LPC_USART_LCR_WLS_7 2 +#define LPC_USART_LCR_WLS_8 3 +#define LPC_USART_LCR_WLS_MASK 3 +#define LPC_USART_LCR_SBS 2 +#define LPC_USART_LCR_SBS_1 0 +#define LPC_USART_LCR_SBS_2 1 +#define LPC_USART_LCR_SBS_MASK 1 +#define LPC_USART_LCR_PE 3 +#define LPC_USART_LCR_PS 4 +#define LPC_USART_LCR_PS_ODD 0 +#define LPC_USART_LCR_PS_EVEN 1 +#define LPC_USART_LCR_PS_ONE 2 +#define LPC_USART_LCR_PS_ZERO 3 +#define LPC_USART_LCR_PS_MASK 3 +#define LPC_USART_LCR_BC 6 +#define LPC_USART_LCR_DLAB 7 + +#define LPC_USART_MCR_DTRCTRL 0 +#define LPC_USART_MCR_RTSCTRL 1 +#define LPC_USART_MCR_LMS 4 +#define LPC_USART_MCR_RTSEN 6 +#define LPC_USART_MCR_CTSEN 7 + +#define LPC_USART_LSR_RDR 0 +#define LPC_USART_LSR_OE 1 +#define LPC_USART_LSR_PE 2 +#define LPC_USART_LSR_FE 3 +#define LPC_USART_LSR_BI 4 +#define LPC_USART_LSR_THRE 5 +#define LPC_USART_LSR_TEMT 6 +#define LPC_USART_LSR_RXFE 7 +#define LPC_USART_LSR_TXERR 8 + +#define LPC_USART_MSR_DCTS 0 +#define LPC_USART_MSR_DDSR 1 +#define LPC_USART_MSR_TERI 2 +#define LPC_USART_MSR_DDCD 3 +#define LPC_USART_MSR_CTS 4 +#define LPC_USART_MSR_DSR 5 +#define LPC_USART_MSR_RI 6 +#define LPC_USART_MSR_DCD 7 + +#define LPC_USART_ACR_START 0 +#define LPC_USART_ACR_MODE 1 +#define LPC_USART_ACR_AUTORESTART 2 +#define LPC_USART_ACR_ABEOINTCLR 8 +#define LPC_USART_ACR_ABTOINTCLR 9 + +#define LPC_USART_FDR_DIVADDVAL 0 +#define LPC_USART_FDR_MULVAL 4 + +#define LPC_USART_OSR_OSFRAC 1 +#define LPC_USART_OSR_OSINT 4 +#define LPC_USART_OSR_FDINT 8 + +#define LPC_USART_TER_TXEN 7 + +#define LPC_USART_HDEN_HDEN 0 + +#define LPC_ISR_PIN_INT0_POS 0 +#define LPC_ISR_PIN_INT1_POS 1 +#define LPC_ISR_PIN_INT2_POS 2 +#define LPC_ISR_PIN_INT3_POS 3 +#define LPC_ISR_PIN_INT4_POS 4 +#define LPC_ISR_PIN_INT5_POS 5 +#define LPC_ISR_PIN_INT6_POS 6 +#define LPC_ISR_PIN_INT7_POS 7 +#define LPC_ISR_GINT0_POS 8 +#define LPC_ISR_GINT1_POS 9 +#define LPC_ISR_SSP1_POS 14 +#define LPC_ISR_I2C_POS 15 +#define LPC_ISR_CT16B0_POS 16 +#define LPC_ISR_CT16B1_POS 17 +#define LPC_ISR_CT32B0_POS 18 +#define LPC_ISR_CT32B1_POS 19 +#define LPC_ISR_SSP0_POS 20 +#define LPC_ISR_USART_POS 21 +#define LPC_ISR_USB_IRQ_POS 22 +#define LPC_ISR_USB_FIQ_POS 23 +#define LPC_ISR_ADC_POS 24 +#define LPC_ISR_WWDT_POS 25 +#define LPC_ISR_BOD_POS 26 +#define LPC_ISR_FLASH_POS 27 +#define LPC_ISR_USB_WAKEUP_POS 30 + +struct lpc_nvic { + vuint32_t iser; /* 0x000 0xe000e100 Set Enable Register */ + + uint8_t _unused020[0x080 - 0x004]; + + vuint32_t icer; /* 0x080 0xe000e180 Clear Enable Register */ + + uint8_t _unused0a0[0x100 - 0x084]; + + vuint32_t ispr; /* 0x100 0xe000e200 Set Pending Register */ + + uint8_t _unused120[0x180 - 0x104]; + + vuint32_t icpr; /* 0x180 0xe000e280 Clear Pending Register */ + + uint8_t _unused1a0[0x300 - 0x184]; + + vuint32_t ipr[8]; /* 0x300 0xe000e400 Priority Register */ +}; + +extern struct lpc_nvic lpc_nvic; + +static inline void +lpc_nvic_set_enable(int irq) { + lpc_nvic.iser |= (1 << irq); +} + +static inline void +lpc_nvic_clear_enable(int irq) { + lpc_nvic.icer |= (1 << irq); +} + +static inline int +lpc_nvic_enabled(int irq) { + return (lpc_nvic.iser >> irq) & 1; +} + + +static inline void +lpc_nvic_set_pending(int irq) { + lpc_nvic.ispr = (1 << irq); +} + +static inline void +lpc_nvic_clear_pending(int irq) { + lpc_nvic.icpr = (1 << irq); +} + +static inline int +lpc_nvic_pending(int irq) { + return (lpc_nvic.ispr >> irq) & 1; +} + +#define IRQ_PRIO_REG(irq) ((irq) >> 2) +#define IRQ_PRIO_BIT(irq) (((irq) & 3) << 3) +#define IRQ_PRIO_MASK(irq) (0xff << IRQ_PRIO_BIT(irq)) + +static inline void +lpc_nvic_set_priority(int irq, uint8_t prio) { + int n = IRQ_PRIO_REG(irq); + uint32_t v; + + v = lpc_nvic.ipr[n]; + v &= ~IRQ_PRIO_MASK(irq); + v |= (prio) << IRQ_PRIO_BIT(irq); + lpc_nvic.ipr[n] = v; +} + +static inline uint8_t +lpc_nvic_get_priority(int irq) { + return (lpc_nvic.ipr[IRQ_PRIO_REG(irq)] >> IRQ_PRIO_BIT(irq)) & IRQ_PRIO_MASK(0); +} + #endif /* _LPC_H_ */ diff --git a/src/lpc/registers.ld b/src/lpc/registers.ld index cd6ac5f5..e444d832 100644 --- a/src/lpc/registers.ld +++ b/src/lpc/registers.ld @@ -7,3 +7,4 @@ lpc_gpio_group0 = 0x4005c000; lpc_gpio_group1 = 0x40060000; lpc_gpio = 0x50000000; lpc_systick = 0xe000e000; +lpc_nvic = 0xe000e100; diff --git a/src/lpcxpresso/ao_demo.c b/src/lpcxpresso/ao_demo.c index 56fef706..eae9503e 100644 --- a/src/lpcxpresso/ao_demo.c +++ b/src/lpcxpresso/ao_demo.c @@ -26,6 +26,14 @@ static void demo(void) { } } +static struct ao_task serial_task; + +static void serial(void) { + for (;;) { + printf ("hello, world\n"); + } +} + int main(void) { @@ -35,9 +43,12 @@ main(void) ao_clock_init(); ao_timer_init(); + ao_serial_init(); + ao_task_init(); ao_add_task(&demo_task, demo, "demo"); + ao_add_task(&serial_task, serial, "serial"); ao_start_scheduler(); diff --git a/src/lpcxpresso/ao_pins.h b/src/lpcxpresso/ao_pins.h index 56391c2b..7748f73c 100644 --- a/src/lpcxpresso/ao_pins.h +++ b/src/lpcxpresso/ao_pins.h @@ -40,8 +40,9 @@ /* USART */ -#define HAS_SERIAL 1 +#define HAS_SERIAL 1 +#define USE_SERIAL_0_STDIN 1 #define SERIAL_0_18_19 1 -#define SERIAL_1_14_15 0 -#define SERIAL_1_17_18 0 -#define SERIAL_1_26_27 0 +#define SERIAL_0_14_15 0 +#define SERIAL_0_17_18 0 +#define SERIAL_0_26_27 0 -- cgit v1.2.3 From 9bf67798b134ad796c2f4bc9240ee450722148ec Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Apr 2013 00:40:38 -0500 Subject: altos/lpc: Take advantage of USART TX fifo The USART has a 16-byte TX fifo; keep rough track of how full it is to avoid waiting for an interrupt after every TX byte. Signed-off-by: Keith Packard --- src/lpc/ao_serial_lpc.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_serial_lpc.c b/src/lpc/ao_serial_lpc.c index 4ecaa175..c0424699 100644 --- a/src/lpc/ao_serial_lpc.c +++ b/src/lpc/ao_serial_lpc.c @@ -20,7 +20,10 @@ struct ao_fifo ao_usart_rx_fifo; struct ao_fifo ao_usart_tx_fifo; -uint8_t ao_usart_tx_started; +uint8_t ao_usart_tx_avail; +uint8_t ao_usart_tx_avail_min; + +#define LPC_USART_TX_FIFO_SIZE 16 void ao_debug_out(char c) @@ -35,9 +38,10 @@ ao_debug_out(char c) static void _ao_serial_tx_start(void) { - if (!ao_fifo_empty(ao_usart_tx_fifo) & !ao_usart_tx_started) - { - ao_usart_tx_started = 1; + if (!ao_fifo_empty(ao_usart_tx_fifo) && ao_usart_tx_avail) { + ao_usart_tx_avail--; + if (ao_usart_tx_avail < ao_usart_tx_avail_min) + ao_usart_tx_avail_min = ao_usart_tx_avail; ao_fifo_remove(ao_usart_tx_fifo, lpc_usart.rbr_thr); } } @@ -56,7 +60,7 @@ lpc_usart_isr(void) ao_wakeup(&ao_stdin_ready); } if (lpc_usart.lsr & (1 << LPC_USART_LSR_THRE)) { - ao_usart_tx_started = 0; + ao_usart_tx_avail = LPC_USART_TX_FIFO_SIZE; _ao_serial_tx_start(); ao_wakeup(&ao_usart_tx_fifo); } @@ -162,6 +166,9 @@ ao_serial_init(void) (1 << LPC_USART_FCR_TXFIFORES) | (LPC_USART_FCR_RXTL_1 << LPC_USART_FCR_RXTL)); + ao_usart_tx_avail = LPC_USART_TX_FIFO_SIZE; + ao_usart_tx_avail_min = LPC_USART_TX_FIFO_SIZE; + /* 8 n 1 */ lpc_usart.lcr = ((LPC_USART_LCR_WLS_8 << LPC_USART_LCR_WLS) | (LPC_USART_LCR_SBS_1 << LPC_USART_LCR_SBS) | -- cgit v1.2.3 From 91d201abcbe9373360919406427b7e4fb9e1b42e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Apr 2013 17:10:24 -0500 Subject: altos/lpc: Start adding USB register definitions Just the bare struct, no defines yet. Signed-off-by: Keith Packard --- src/lpc/ao_usb_lpc.c | 1136 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/lpc/lpc.h | 18 + src/lpc/registers.ld | 1 + 3 files changed, 1155 insertions(+) create mode 100644 src/lpc/ao_usb_lpc.c (limited to 'src') diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c new file mode 100644 index 00000000..af2bd271 --- /dev/null +++ b/src/lpc/ao_usb_lpc.c @@ -0,0 +1,1136 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_usb.h" +#include "ao_product.h" + +#define USB_DEBUG 1 +#define USB_DEBUG_DATA 1 +#define USB_ECHO 1 + +#if USB_DEBUG +#define debug(format, args...) printf(format, ## args); +#else +#define debug(format, args...) +#endif + +#if USB_DEBUG_DATA +#define debug_data(format, args...) printf(format, ## args); +#else +#define debug_data(format, args...) +#endif + +struct ao_task ao_usb_task; + +struct ao_usb_setup { + uint8_t dir_type_recip; + uint8_t request; + uint16_t value; + uint16_t index; + uint16_t length; +} ao_usb_setup; + +static uint8_t ao_usb_ep0_state; + +/* Pending EP0 IN data */ +static const uint8_t *ao_usb_ep0_in_data; /* Remaining data */ +static uint8_t ao_usb_ep0_in_len; /* Remaining amount */ + +/* Temp buffer for smaller EP0 in data */ +static uint8_t ao_usb_ep0_in_buf[2]; + +/* Pending EP0 OUT data */ +static uint8_t *ao_usb_ep0_out_data; +static uint8_t ao_usb_ep0_out_len; + +/* + * Objects allocated in special USB memory + */ + +/* Buffer description tables */ +static union lpc_usb_bdt *ao_usb_bdt; +/* USB address of end of allocated storage */ +static uint16_t ao_usb_sram_addr; + +/* Pointer to ep0 tx/rx buffers in USB memory */ +static uint32_t *ao_usb_ep0_tx_buffer; +static uint32_t *ao_usb_ep0_rx_buffer; + +/* Pointer to bulk data tx/rx buffers in USB memory */ +static uint32_t *ao_usb_in_tx_buffer; +static uint32_t *ao_usb_out_rx_buffer; + +/* System ram shadow of USB buffer; writing individual bytes is + * too much of a pain (sigh) */ +static uint8_t ao_usb_tx_buffer[AO_USB_IN_SIZE]; +static uint8_t ao_usb_tx_count; + +static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE]; +static uint8_t ao_usb_rx_count, ao_usb_rx_pos; + +/* + * End point register indices + */ + +#define AO_USB_CONTROL_EPR 0 +#define AO_USB_INT_EPR 1 +#define AO_USB_OUT_EPR 2 +#define AO_USB_IN_EPR 3 + +/* Marks when we don't need to send an IN packet. + * This happens only when the last IN packet is not full, + * otherwise the host will expect to keep seeing packets. + * Send a zero-length packet as required + */ +static uint8_t ao_usb_in_flushed; + +/* Marks when we have delivered an IN packet to the hardware + * and it has not been received yet. ao_sleep on this address + * to wait for it to be delivered. + */ +static uint8_t ao_usb_in_pending; + +/* Marks when an OUT packet has been received by the hardware + * but not pulled to the shadow buffer. + */ +static uint8_t ao_usb_out_avail; +static uint8_t ao_usb_running; +static uint8_t ao_usb_configuration; +static uint8_t ueienx_0; + +#define AO_USB_EP0_GOT_RESET 1 +#define AO_USB_EP0_GOT_SETUP 2 +#define AO_USB_EP0_GOT_RX_DATA 4 +#define AO_USB_EP0_GOT_TX_ACK 8 + +static uint8_t ao_usb_ep0_receive; +static uint8_t ao_usb_address; +static uint8_t ao_usb_address_pending; + +static inline uint32_t set_toggle(uint32_t current_value, + uint32_t mask, + uint32_t desired_value) +{ + return (current_value ^ desired_value) & mask; +} + +static inline uint32_t *ao_usb_packet_buffer_addr(uint16_t sram_addr) +{ + return (uint32_t *) (lpc_usb_sram + 2 * sram_addr); +} + +static inline uint32_t ao_usb_epr_stat_rx(uint32_t epr) { + return (epr >> USB_USB_EPR_STAT_RX) & USB_USB_EPR_STAT_RX_MASK; +} + +static inline uint32_t ao_usb_epr_stat_tx(uint32_t epr) { + return (epr >> USB_USB_EPR_STAT_TX) & USB_USB_EPR_STAT_TX_MASK; +} + +static inline uint32_t ao_usb_epr_ctr_rx(uint32_t epr) { + return (epr >> USB_USB_EPR_CTR_RX) & 1; +} + +static inline uint32_t ao_usb_epr_ctr_tx(uint32_t epr) { + return (epr >> USB_USB_EPR_CTR_TX) & 1; +} + +static inline uint32_t ao_usb_epr_setup(uint32_t epr) { + return (epr >> USB_USB_EPR_SETUP) & 1; +} + +static inline uint32_t ao_usb_epr_dtog_rx(uint32_t epr) { + return (epr >> USB_USB_EPR_DTOG_RX) & 1; +} + +static inline uint32_t ao_usb_epr_dtog_tx(uint32_t epr) { + return (epr >> USB_USB_EPR_DTOG_TX) & 1; +} + +/* + * Set current device address and mark the + * interface as active + */ +void +ao_usb_set_address(uint8_t address) +{ + debug("ao_usb_set_address %02x\n", address); + lpc_usb.daddr = (1 << USB_USB_DADDR_EF) | address; + ao_usb_address_pending = 0; +} + +/* + * Write these values to preserve register contents under HW changes + */ + +#define USB_USB_EPR_INVARIANT ((1 << USB_USB_EPR_CTR_RX) | \ + (USB_USB_EPR_DTOG_RX_WRITE_INVARIANT << USB_USB_EPR_DTOG_RX) | \ + (USB_USB_EPR_STAT_RX_WRITE_INVARIANT << USB_USB_EPR_STAT_RX) | \ + (1 << USB_USB_EPR_CTR_TX) | \ + (USB_USB_EPR_DTOG_TX_WRITE_INVARIANT << USB_USB_EPR_DTOG_TX) | \ + (USB_USB_EPR_STAT_TX_WRITE_INVARIANT << USB_USB_EPR_STAT_TX)) + +#define USB_USB_EPR_INVARIANT_MASK ((1 << USB_USB_EPR_CTR_RX) | \ + (USB_USB_EPR_DTOG_RX_MASK << USB_USB_EPR_DTOG_RX) | \ + (USB_USB_EPR_STAT_RX_MASK << USB_USB_EPR_STAT_RX) | \ + (1 << USB_USB_EPR_CTR_TX) | \ + (USB_USB_EPR_DTOG_TX_MASK << USB_USB_EPR_DTOG_TX) | \ + (USB_USB_EPR_STAT_TX_MASK << USB_USB_EPR_STAT_TX)) + +/* + * These bits are purely under sw control, so preserve them in the + * register by re-writing what was read + */ +#define USB_USB_EPR_PRESERVE_MASK ((USB_USB_EPR_EP_TYPE_MASK << USB_USB_EPR_EP_TYPE) | \ + (1 << USB_USB_EPR_EP_KIND) | \ + (USB_USB_EPR_EA_MASK << USB_USB_EPR_EA)) + +#define TX_DBG 0 +#define RX_DBG 0 + +#if TX_DBG +#define _tx_dbg0(msg) _dbg(__LINE__,msg,0) +#define _tx_dbg1(msg,value) _dbg(__LINE__,msg,value) +#else +#define _tx_dbg0(msg) +#define _tx_dbg1(msg,value) +#endif + +#if RX_DBG +#define _rx_dbg0(msg) _dbg(__LINE__,msg,0) +#define _rx_dbg1(msg,value) _dbg(__LINE__,msg,value) +#else +#define _rx_dbg0(msg) +#define _rx_dbg1(msg,value) +#endif + +#if TX_DBG || RX_DBG +static void _dbg(int line, char *msg, uint32_t value); +#endif + +/* + * Set the state of the specified endpoint register to a new + * value. This is tricky because the bits toggle where the new + * value is one, and we need to write invariant values in other + * spots of the register. This hardware is strange... + */ +static void +_ao_usb_set_stat_tx(int ep, uint32_t stat_tx) +{ + uint32_t epr_write, epr_old; + + _tx_dbg1("set_stat_tx top", stat_tx); + epr_old = epr_write = lpc_usb.epr[ep]; + epr_write &= USB_USB_EPR_PRESERVE_MASK; + epr_write |= USB_USB_EPR_INVARIANT; + epr_write |= set_toggle(epr_old, + USB_USB_EPR_STAT_TX_MASK << USB_USB_EPR_STAT_TX, + stat_tx << USB_USB_EPR_STAT_TX); + lpc_usb.epr[ep] = epr_write; + _tx_dbg1("set_stat_tx bottom", epr_write); +} + +static void +ao_usb_set_stat_tx(int ep, uint32_t stat_tx) +{ + ao_arch_block_interrupts(); + _ao_usb_set_stat_tx(ep, stat_tx); + ao_arch_release_interrupts(); +} + +static void +_ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { + uint32_t epr_write, epr_old; + + epr_write = epr_old = lpc_usb.epr[ep]; + epr_write &= USB_USB_EPR_PRESERVE_MASK; + epr_write |= USB_USB_EPR_INVARIANT; + epr_write |= set_toggle(epr_old, + USB_USB_EPR_STAT_RX_MASK << USB_USB_EPR_STAT_RX, + stat_rx << USB_USB_EPR_STAT_RX); + lpc_usb.epr[ep] = epr_write; +} + +static void +ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { + ao_arch_block_interrupts(); + _ao_usb_set_stat_rx(ep, stat_rx); + ao_arch_release_interrupts(); +} + +/* + * Set just endpoint 0, for use during startup + */ + +static void +ao_usb_init_ep(uint8_t ep, uint32_t addr, uint32_t type, uint32_t stat_rx, uint32_t stat_tx) +{ + uint32_t epr; + ao_arch_block_interrupts(); + epr = lpc_usb.epr[ep]; + epr = ((0 << USB_USB_EPR_CTR_RX) | + (epr & (1 << USB_USB_EPR_DTOG_RX)) | + set_toggle(epr, + (USB_USB_EPR_STAT_RX_MASK << USB_USB_EPR_STAT_RX), + (stat_rx << USB_USB_EPR_STAT_RX)) | + (type << USB_USB_EPR_EP_TYPE) | + (0 << USB_USB_EPR_EP_KIND) | + (0 << USB_USB_EPR_CTR_TX) | + (epr & (1 << USB_USB_EPR_DTOG_TX)) | + set_toggle(epr, + (USB_USB_EPR_STAT_TX_MASK << USB_USB_EPR_STAT_TX), + (stat_tx << USB_USB_EPR_STAT_TX)) | + (addr << USB_USB_EPR_EA)); + lpc_usb.epr[ep] = epr; + ao_arch_release_interrupts(); + debug ("writing epr[%d] 0x%08x wrote 0x%08x\n", + ep, epr, lpc_usb.epr[ep]); +} + +static void +ao_usb_set_ep0(void) +{ + uint32_t epr; + int e; + + ao_usb_sram_addr = 0; + + /* buffer table is at the start of USB memory */ + lpc_usb.btable = 0; + ao_usb_bdt = (void *) lpc_usb_sram; + + ao_usb_sram_addr += 8 * USB_USB_BDT_SIZE; + + /* Set up EP 0 - a Control end point with 32 bytes of in and out buffers */ + + ao_usb_bdt[0].single.addr_tx = ao_usb_sram_addr; + ao_usb_bdt[0].single.count_tx = 0; + ao_usb_ep0_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_CONTROL_SIZE; + + ao_usb_bdt[0].single.addr_rx = ao_usb_sram_addr; + ao_usb_bdt[0].single.count_rx = ((1 << USB_USB_BDT_COUNT_RX_BL_SIZE) | + (((AO_USB_CONTROL_SIZE / 32) - 1) << USB_USB_BDT_COUNT_RX_NUM_BLOCK)); + ao_usb_ep0_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_CONTROL_SIZE; + + ao_usb_init_ep(AO_USB_CONTROL_EPR, AO_USB_CONTROL_EP, + USB_USB_EPR_EP_TYPE_CONTROL, + USB_USB_EPR_STAT_RX_VALID, + USB_USB_EPR_STAT_TX_NAK); + + /* Clear all of the other endpoints */ + for (e = 1; e < 8; e++) { + ao_usb_init_ep(e, 0, + USB_USB_EPR_EP_TYPE_CONTROL, + USB_USB_EPR_STAT_RX_DISABLED, + USB_USB_EPR_STAT_TX_DISABLED); + } + + ao_usb_set_address(0); +} + +static void +ao_usb_set_configuration(void) +{ + uint32_t epr; + + debug ("ao_usb_set_configuration\n"); + + /* Set up the INT end point */ + ao_usb_bdt[AO_USB_INT_EPR].single.addr_tx = ao_usb_sram_addr; + ao_usb_bdt[AO_USB_INT_EPR].single.count_tx = 0; + ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_INT_SIZE; + + ao_usb_init_ep(AO_USB_INT_EPR, + AO_USB_INT_EP, + USB_USB_EPR_EP_TYPE_INTERRUPT, + USB_USB_EPR_STAT_RX_DISABLED, + USB_USB_EPR_STAT_TX_NAK); + + /* Set up the OUT end point */ + ao_usb_bdt[AO_USB_OUT_EPR].single.addr_rx = ao_usb_sram_addr; + ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx = ((1 << USB_USB_BDT_COUNT_RX_BL_SIZE) | + (((AO_USB_OUT_SIZE / 32) - 1) << USB_USB_BDT_COUNT_RX_NUM_BLOCK)); + ao_usb_out_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_OUT_SIZE; + + ao_usb_init_ep(AO_USB_OUT_EPR, + AO_USB_OUT_EP, + USB_USB_EPR_EP_TYPE_BULK, + USB_USB_EPR_STAT_RX_VALID, + USB_USB_EPR_STAT_TX_DISABLED); + + /* Set up the IN end point */ + ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_sram_addr; + ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = 0; + ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_IN_SIZE; + + ao_usb_init_ep(AO_USB_IN_EPR, + AO_USB_IN_EP, + USB_USB_EPR_EP_TYPE_BULK, + USB_USB_EPR_STAT_RX_DISABLED, + USB_USB_EPR_STAT_TX_NAK); + + ao_usb_running = 1; +} + +static uint16_t control_count; +static uint16_t int_count; +static uint16_t in_count; +static uint16_t out_count; +static uint16_t reset_count; + +void +lpc_usb_lp_isr(void) +{ + uint32_t istr = lpc_usb.istr; + + if (istr & (1 << USB_USB_ISTR_CTR)) { + uint8_t ep = istr & USB_USB_ISTR_EP_ID_MASK; + uint32_t epr, epr_write; + + /* Preserve the SW write bits, don't mess with most HW writable bits, + * clear the CTR_RX and CTR_TX bits + */ + epr = lpc_usb.epr[ep]; + epr_write = epr; + epr_write &= USB_USB_EPR_PRESERVE_MASK; + epr_write |= USB_USB_EPR_INVARIANT; + epr_write &= ~(1 << USB_USB_EPR_CTR_RX); + epr_write &= ~(1 << USB_USB_EPR_CTR_TX); + lpc_usb.epr[ep] = epr_write; + + switch (ep) { + case 0: + ++control_count; + if (ao_usb_epr_ctr_rx(epr)) { + if (ao_usb_epr_setup(epr)) + ao_usb_ep0_receive |= AO_USB_EP0_GOT_SETUP; + else + ao_usb_ep0_receive |= AO_USB_EP0_GOT_RX_DATA; + } + if (ao_usb_epr_ctr_tx(epr)) + ao_usb_ep0_receive |= AO_USB_EP0_GOT_TX_ACK; + ao_wakeup(&ao_usb_ep0_receive); + break; + case AO_USB_OUT_EPR: + ++out_count; + if (ao_usb_epr_ctr_rx(epr)) { + _rx_dbg1("RX ISR", epr); + ao_usb_out_avail = 1; + _rx_dbg0("out avail set"); + ao_wakeup(&ao_stdin_ready); + _rx_dbg0("stdin awoken"); + } + break; + case AO_USB_IN_EPR: + ++in_count; + _tx_dbg1("TX ISR", epr); + if (ao_usb_epr_ctr_tx(epr)) { + ao_usb_in_pending = 0; + ao_wakeup(&ao_usb_in_pending); + } + break; + case AO_USB_INT_EPR: + ++int_count; + if (ao_usb_epr_ctr_tx(epr)) + _ao_usb_set_stat_tx(AO_USB_INT_EPR, USB_USB_EPR_STAT_TX_NAK); + break; + } + return; + } + + if (istr & (1 << USB_USB_ISTR_RESET)) { + ++reset_count; + lpc_usb.istr &= ~(1 << USB_USB_ISTR_RESET); + ao_usb_ep0_receive |= AO_USB_EP0_GOT_RESET; + ao_wakeup(&ao_usb_ep0_receive); + } +} + +void +lpc_usb_fs_wkup(void) +{ + /* USB wakeup, just clear the bit for now */ + lpc_usb.istr &= ~(1 << USB_USB_ISTR_WKUP); +} + +/* The USB memory holds 16 bit values on 32 bit boundaries + * and must be accessed only in 32 bit units. Sigh. + */ + +static inline void +ao_usb_write_byte(uint8_t byte, uint32_t *base, uint16_t offset) +{ + base += offset >> 1; + if (offset & 1) { + *base = (*base & 0xff) | ((uint32_t) byte << 8); + } else { + *base = (*base & 0xff00) | byte; + } +} + +static inline void +ao_usb_write_short(uint16_t data, uint32_t *base, uint16_t offset) +{ + base[offset>>1] = data; +} + +static void +ao_usb_write(const uint8_t *src, uint32_t *base, uint16_t offset, uint16_t bytes) +{ + if (!bytes) + return; + if (offset & 1) { + debug_data (" %02x", src[0]); + ao_usb_write_byte(*src++, base, offset++); + bytes--; + } + while (bytes >= 2) { + debug_data (" %02x %02x", src[0], src[1]); + ao_usb_write_short((src[1] << 8) | src[0], base, offset); + offset += 2; + src += 2; + bytes -= 2; + } + if (bytes) { + debug_data (" %02x", src[0]); + ao_usb_write_byte(*src, base, offset); + } +} + +static inline uint8_t +ao_usb_read_byte(uint32_t *base, uint16_t offset) +{ + base += offset >> 1; + if (offset & 1) + return (*base >> 8) & 0xff; + else + return *base & 0xff; +} + +static inline uint16_t +ao_usb_read_short(uint32_t *base, uint16_t offset) +{ + return base[offset>>1]; +} + +static void +ao_usb_read(uint8_t *dst, uint32_t *base, uint16_t offset, uint16_t bytes) +{ + if (!bytes) + return; + if (offset & 1) { + *dst++ = ao_usb_read_byte(base, offset++); + debug_data (" %02x", dst[-1]); + bytes--; + } + while (bytes >= 2) { + uint16_t s = ao_usb_read_short(base, offset); + dst[0] = s; + dst[1] = s >> 8; + debug_data (" %02x %02x", dst[0], dst[1]); + offset += 2; + dst += 2; + bytes -= 2; + } + if (bytes) { + *dst = ao_usb_read_byte(base, offset); + debug_data (" %02x", dst[0]); + } +} + +/* Send an IN data packet */ +static void +ao_usb_ep0_flush(void) +{ + uint8_t this_len; + + /* Check to see if the endpoint is still busy */ + if (ao_usb_epr_stat_tx(lpc_usb.epr[0]) == USB_USB_EPR_STAT_TX_VALID) { + debug("EP0 not accepting IN data\n"); + return; + } + + this_len = ao_usb_ep0_in_len; + if (this_len > AO_USB_CONTROL_SIZE) + this_len = AO_USB_CONTROL_SIZE; + + if (this_len < AO_USB_CONTROL_SIZE) + ao_usb_ep0_state = AO_USB_EP0_IDLE; + + ao_usb_ep0_in_len -= this_len; + + debug_data ("Flush EP0 len %d:", this_len); + ao_usb_write(ao_usb_ep0_in_data, ao_usb_ep0_tx_buffer, 0, this_len); + debug_data ("\n"); + ao_usb_ep0_in_data += this_len; + + /* Mark the endpoint as TX valid to send the packet */ + ao_usb_bdt[AO_USB_CONTROL_EPR].single.count_tx = this_len; + ao_usb_set_stat_tx(AO_USB_CONTROL_EPR, USB_USB_EPR_STAT_TX_VALID); + debug ("queue tx. epr 0 now %08x\n", lpc_usb.epr[AO_USB_CONTROL_EPR]); +} + +/* Read data from the ep0 OUT fifo */ +static void +ao_usb_ep0_fill(void) +{ + uint16_t len = ao_usb_bdt[0].single.count_rx & USB_USB_BDT_COUNT_RX_COUNT_RX_MASK; + + if (len > ao_usb_ep0_out_len) + len = ao_usb_ep0_out_len; + ao_usb_ep0_out_len -= len; + + /* Pull all of the data out of the packet */ + debug_data ("Fill EP0 len %d:", len); + ao_usb_read(ao_usb_ep0_out_data, ao_usb_ep0_rx_buffer, 0, len); + debug_data ("\n"); + ao_usb_ep0_out_data += len; + + /* ACK the packet */ + ao_usb_set_stat_rx(0, USB_USB_EPR_STAT_RX_VALID); +} + +static void +ao_usb_ep0_in_reset(void) +{ + ao_usb_ep0_in_data = ao_usb_ep0_in_buf; + ao_usb_ep0_in_len = 0; +} + +static void +ao_usb_ep0_in_queue_byte(uint8_t a) +{ + if (ao_usb_ep0_in_len < sizeof (ao_usb_ep0_in_buf)) + ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a; +} + +static void +ao_usb_ep0_in_set(const uint8_t *data, uint8_t len) +{ + ao_usb_ep0_in_data = data; + ao_usb_ep0_in_len = len; +} + +static void +ao_usb_ep0_out_set(uint8_t *data, uint8_t len) +{ + ao_usb_ep0_out_data = data; + ao_usb_ep0_out_len = len; +} + +static void +ao_usb_ep0_in_start(uint8_t max) +{ + /* Don't send more than asked for */ + if (ao_usb_ep0_in_len > max) + ao_usb_ep0_in_len = max; + ao_usb_ep0_flush(); +} + +static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; + +/* Walk through the list of descriptors and find a match + */ +static void +ao_usb_get_descriptor(uint16_t value) +{ + const uint8_t *descriptor; + uint8_t type = value >> 8; + uint8_t index = value; + + descriptor = ao_usb_descriptors; + while (descriptor[0] != 0) { + if (descriptor[1] == type && index-- == 0) { + uint8_t len; + if (type == AO_USB_DESC_CONFIGURATION) + len = descriptor[2]; + else + len = descriptor[0]; + ao_usb_ep0_in_set(descriptor, len); + break; + } + descriptor += descriptor[0]; + } +} + +static void +ao_usb_ep0_setup(void) +{ + /* Pull the setup packet out of the fifo */ + ao_usb_ep0_out_set((uint8_t *) &ao_usb_setup, 8); + ao_usb_ep0_fill(); + if (ao_usb_ep0_out_len != 0) { + debug ("invalid setup packet length\n"); + return; + } + + if ((ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) || ao_usb_setup.length == 0) + ao_usb_ep0_state = AO_USB_EP0_DATA_IN; + else + ao_usb_ep0_state = AO_USB_EP0_DATA_OUT; + + ao_usb_ep0_in_reset(); + + switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_TYPE_MASK) { + case AO_USB_TYPE_STANDARD: + debug ("Standard setup packet\n"); + switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_RECIP_MASK) { + case AO_USB_RECIP_DEVICE: + debug ("Device setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + debug ("get status\n"); + ao_usb_ep0_in_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); + break; + case AO_USB_REQ_SET_ADDRESS: + debug ("set address %d\n", ao_usb_setup.value); + ao_usb_address = ao_usb_setup.value; + ao_usb_address_pending = 1; + break; + case AO_USB_REQ_GET_DESCRIPTOR: + debug ("get descriptor %d\n", ao_usb_setup.value); + ao_usb_get_descriptor(ao_usb_setup.value); + break; + case AO_USB_REQ_GET_CONFIGURATION: + debug ("get configuration %d\n", ao_usb_configuration); + ao_usb_ep0_in_queue_byte(ao_usb_configuration); + break; + case AO_USB_REQ_SET_CONFIGURATION: + ao_usb_configuration = ao_usb_setup.value; + debug ("set configuration %d\n", ao_usb_configuration); + ao_usb_set_configuration(); + break; + } + break; + case AO_USB_RECIP_INTERFACE: + debug ("Interface setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + ao_usb_ep0_in_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); + break; + case AO_USB_REQ_GET_INTERFACE: + ao_usb_ep0_in_queue_byte(0); + break; + case AO_USB_REQ_SET_INTERFACE: + break; + } + break; + case AO_USB_RECIP_ENDPOINT: + debug ("Endpoint setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + ao_usb_ep0_in_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); + break; + } + break; + } + break; + case AO_USB_TYPE_CLASS: + debug ("Class setup packet\n"); + switch (ao_usb_setup.request) { + case AO_USB_SET_LINE_CODING: + debug ("set line coding\n"); + ao_usb_ep0_out_set((uint8_t *) &ao_usb_line_coding, 7); + break; + case AO_USB_GET_LINE_CODING: + debug ("get line coding\n"); + ao_usb_ep0_in_set((const uint8_t *) &ao_usb_line_coding, 7); + break; + case AO_USB_SET_CONTROL_LINE_STATE: + break; + } + break; + } + + /* If we're not waiting to receive data from the host, + * queue an IN response + */ + if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN) + ao_usb_ep0_in_start(ao_usb_setup.length); +} + +/* End point 0 receives all of the control messages. */ +static void +ao_usb_ep0(void) +{ + uint8_t intx, udint; + + debug ("usb task started\n"); + ao_usb_ep0_state = AO_USB_EP0_IDLE; + for (;;) { + uint8_t receive; + ao_arch_critical( + while (!(receive = ao_usb_ep0_receive)) + ao_sleep(&ao_usb_ep0_receive); + ao_usb_ep0_receive = 0; + ); + + if (receive & AO_USB_EP0_GOT_RESET) { + debug ("\treset\n"); + ao_usb_set_ep0(); + continue; + } + if (receive & AO_USB_EP0_GOT_SETUP) { + debug ("\tsetup\n"); + ao_usb_ep0_setup(); + } + if (receive & AO_USB_EP0_GOT_RX_DATA) { + debug ("\tgot rx data\n"); + if (ao_usb_ep0_state == AO_USB_EP0_DATA_OUT) { + ao_usb_ep0_fill(); + if (ao_usb_ep0_out_len == 0) { + ao_usb_ep0_state = AO_USB_EP0_DATA_IN; + ao_usb_ep0_in_start(0); + } + } + } + if (receive & AO_USB_EP0_GOT_TX_ACK) { + debug ("\tgot tx ack\n"); + + /* Wait until the IN packet is received from addr 0 + * before assigning our local address + */ + if (ao_usb_address_pending) + ao_usb_set_address(ao_usb_address); + if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN) + ao_usb_ep0_flush(); + } + } +} + +/* Queue the current IN buffer for transmission */ +static void +_ao_usb_in_send(void) +{ + _tx_dbg0("in_send start"); + debug ("send %d\n", ao_usb_tx_count); + while (ao_usb_in_pending) + ao_sleep(&ao_usb_in_pending); + ao_usb_in_pending = 1; + if (ao_usb_tx_count != AO_USB_IN_SIZE) + ao_usb_in_flushed = 1; + ao_usb_write(ao_usb_tx_buffer, ao_usb_in_tx_buffer, 0, ao_usb_tx_count); + ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = ao_usb_tx_count; + ao_usb_tx_count = 0; + _ao_usb_set_stat_tx(AO_USB_IN_EPR, USB_USB_EPR_STAT_TX_VALID); + _tx_dbg0("in_send end"); +} + +/* Wait for a free IN buffer. Interrupts are blocked */ +static void +_ao_usb_in_wait(void) +{ + for (;;) { + /* Check if the current buffer is writable */ + if (ao_usb_tx_count < AO_USB_IN_SIZE) + break; + + _tx_dbg0("in_wait top"); + /* Wait for an IN buffer to be ready */ + while (ao_usb_in_pending) + ao_sleep(&ao_usb_in_pending); + _tx_dbg0("in_wait bottom"); + } +} + +void +ao_usb_flush(void) +{ + if (!ao_usb_running) + return; + + /* Anytime we've sent a character since + * the last time we flushed, we'll need + * to send a packet -- the only other time + * we would send a packet is when that + * packet was full, in which case we now + * want to send an empty packet + */ + ao_arch_block_interrupts(); + while (!ao_usb_in_flushed) { + _tx_dbg0("flush top"); + _ao_usb_in_send(); + _tx_dbg0("flush end"); + } + ao_arch_release_interrupts(); +} + +void +ao_usb_putchar(char c) +{ + if (!ao_usb_running) + return; + + ao_arch_block_interrupts(); + _ao_usb_in_wait(); + + ao_usb_in_flushed = 0; + ao_usb_tx_buffer[ao_usb_tx_count++] = (uint8_t) c; + + /* Send the packet when full */ + if (ao_usb_tx_count == AO_USB_IN_SIZE) { + _tx_dbg0("putchar full"); + _ao_usb_in_send(); + _tx_dbg0("putchar flushed"); + } + ao_arch_release_interrupts(); +} + +static void +_ao_usb_out_recv(void) +{ + _rx_dbg0("out_recv top"); + ao_usb_out_avail = 0; + + ao_usb_rx_count = ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx & USB_USB_BDT_COUNT_RX_COUNT_RX_MASK; + + _rx_dbg1("out_recv count", ao_usb_rx_count); + debug ("recv %d\n", ao_usb_rx_count); + debug_data("Fill OUT len %d:", ao_usb_rx_count); + ao_usb_read(ao_usb_rx_buffer, ao_usb_out_rx_buffer, 0, ao_usb_rx_count); + debug_data("\n"); + ao_usb_rx_pos = 0; + + /* ACK the packet */ + _ao_usb_set_stat_rx(AO_USB_OUT_EPR, USB_USB_EPR_STAT_RX_VALID); +} + +int +_ao_usb_pollchar(void) +{ + uint8_t c; + + if (!ao_usb_running) + return AO_READ_AGAIN; + + for (;;) { + if (ao_usb_rx_pos != ao_usb_rx_count) + break; + + _rx_dbg0("poll check"); + /* Check to see if a packet has arrived */ + if (!ao_usb_out_avail) { + _rx_dbg0("poll none"); + return AO_READ_AGAIN; + } + _ao_usb_out_recv(); + } + + /* Pull a character out of the fifo */ + c = ao_usb_rx_buffer[ao_usb_rx_pos++]; + return c; +} + +char +ao_usb_getchar(void) +{ + int c; + + ao_arch_block_interrupts(); + while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) + ao_sleep(&ao_stdin_ready); + ao_arch_release_interrupts(); + return c; +} + +void +ao_usb_disable(void) +{ + ao_arch_block_interrupts(); + lpc_usb.cntr = (1 << USB_USB_CNTR_FRES); + lpc_usb.istr = 0; + + /* Disable USB pull-up */ + lpc_syscfg.pmc &= ~(1 << USB_SYSCFG_PMC_USB_PU); + + /* Switch off the device */ + lpc_usb.cntr = (1 << USB_USB_CNTR_PDWN) | (1 << USB_USB_CNTR_FRES); + + /* Disable the interface */ + lpc_rcc.apb1enr &+ ~(1 << USB_RCC_APB1ENR_USBEN); + ao_arch_release_interrupts(); +} + +void +ao_usb_enable(void) +{ + int t; + + /* Enable USB registers and RAM */ + lpc_scb.sysahbclkctrl |= ((1 << LPC_SCB_SYSAHBCLKCTRL_USB) | + (1 << LPC_SCB_SYSAHBCLKCTRL_USBRAM)); + + /* Enable USB PHY */ + lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_USBPAD_PD); + + /* Turn on USB clock, use 48MHz clock unchanged */ + lpc_scb.usbclkdiv = 1; + + /* Configure interrupts */ + ao_arch_block_interrupts(); + + /* Enable interrupts */ + lpc_usb. + /* Route interrupts */ + + lpc_nvic_set_priority(USB_ISR_USB_LP_POS, 3); + lpc_nvic_set_enable(USB_ISR_USB_LP_POS); + + ao_usb_configuration = 0; + + lpc_usb.cntr = (1 << USB_USB_CNTR_FRES); + + /* Clear the power down bit */ + lpc_usb.cntr = 0; + + /* Clear any spurious interrupts */ + lpc_usb.istr = 0; + + debug ("ao_usb_enable\n"); + + /* Enable interrupts */ + lpc_usb.cntr = ((1 << USB_USB_CNTR_CTRM) | + (0 << USB_USB_CNTR_PMAOVRM) | + (0 << USB_USB_CNTR_ERRM) | + (0 << USB_USB_CNTR_WKUPM) | + (0 << USB_USB_CNTR_SUSPM) | + (1 << USB_USB_CNTR_RESETM) | + (0 << USB_USB_CNTR_SOFM) | + (0 << USB_USB_CNTR_ESOFM) | + (0 << USB_USB_CNTR_RESUME) | + (0 << USB_USB_CNTR_FSUSP) | + (0 << USB_USB_CNTR_LP_MODE) | + (0 << USB_USB_CNTR_PDWN) | + (0 << USB_USB_CNTR_FRES)); + + ao_arch_release_interrupts(); + + for (t = 0; t < 1000; t++) + ao_arch_nop(); + /* Enable USB pull-up */ + lpc_syscfg.pmc |= (1 << USB_SYSCFG_PMC_USB_PU); +} + +#if USB_ECHO +struct ao_task ao_usb_echo_task; + +static void +ao_usb_echo(void) +{ + char c; + + for (;;) { + c = ao_usb_getchar(); + ao_usb_putchar(c); + ao_usb_flush(); + } +} +#endif + +#if USB_DEBUG +static void +ao_usb_irq(void) +{ + printf ("control: %d out: %d in: %d int: %d reset: %d\n", + control_count, out_count, in_count, int_count, reset_count); +} + +__code struct ao_cmds ao_usb_cmds[] = { + { ao_usb_irq, "I\0Show USB interrupt counts" }, + { 0, NULL } +}; +#endif + +void +ao_usb_init(void) +{ + ao_usb_enable(); + + debug ("ao_usb_init\n"); + ao_add_task(&ao_usb_task, ao_usb_ep0, "usb"); +#if USB_ECHO + ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo"); +#endif +#if USB_DEBUG + ao_cmd_register(&ao_usb_cmds[0]); +#endif +#if !USB_ECHO + ao_add_stdio(_ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); +#endif +} + +#if TX_DBG || RX_DBG + +struct ao_usb_dbg { + int line; + char *msg; + uint32_t value; + uint32_t primask; +#if TX_DBG + uint16_t in_count; + uint32_t in_epr; + uint32_t in_pending; + uint32_t tx_count; + uint32_t in_flushed; +#endif +#if RX_DBG + uint8_t rx_count; + uint8_t rx_pos; + uint8_t out_avail; + uint32_t out_epr; +#endif +}; + +#define NUM_USB_DBG 128 + +static struct ao_usb_dbg dbg[128]; +static int dbg_i; + +static void _dbg(int line, char *msg, uint32_t value) +{ + uint32_t primask; + dbg[dbg_i].line = line; + dbg[dbg_i].msg = msg; + dbg[dbg_i].value = value; + asm("mrs %0,primask" : "=&r" (primask)); + dbg[dbg_i].primask = primask; +#if TX_DBG + dbg[dbg_i].in_count = in_count; + dbg[dbg_i].in_epr = lpc_usb.epr[AO_USB_IN_EPR]; + dbg[dbg_i].in_pending = ao_usb_in_pending; + dbg[dbg_i].tx_count = ao_usb_tx_count; + dbg[dbg_i].in_flushed = ao_usb_in_flushed; +#endif +#if RX_DBG + dbg[dbg_i].rx_count = ao_usb_rx_count; + dbg[dbg_i].rx_pos = ao_usb_rx_pos; + dbg[dbg_i].out_avail = ao_usb_out_avail; + dbg[dbg_i].out_epr = lpc_usb.epr[AO_USB_OUT_EPR]; +#endif + if (++dbg_i == NUM_USB_DBG) + dbg_i = 0; +} +#endif diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index 81cd0cc8..5a1987f5 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -810,6 +810,24 @@ extern struct lpc_usart lpc_usart; #define LPC_USART_HDEN_HDEN 0 +struct lpc_usb { + vuint32_t devcmdstat; + vuint32_t info; + vuint32_t epliststart; + vuint32_t databufstart; + vuint32_t lpm; + vuint32_t epskip; + vuint32_t epinuse; + vuint32_t epbufcfg; + vuint32_t intstat; + vuint32_t inten; + vuint32_t intsetstat; + vuint32_t introuting; + vuint32_t eptoggle; +} lpc_usb; + +extern struct lpc_usb lpc_usb; + #define LPC_ISR_PIN_INT0_POS 0 #define LPC_ISR_PIN_INT1_POS 1 #define LPC_ISR_PIN_INT2_POS 2 diff --git a/src/lpc/registers.ld b/src/lpc/registers.ld index e444d832..51a0612f 100644 --- a/src/lpc/registers.ld +++ b/src/lpc/registers.ld @@ -5,6 +5,7 @@ lpc_scb = 0x40048000; lpc_gpio_pin = 0x4004c000; lpc_gpio_group0 = 0x4005c000; lpc_gpio_group1 = 0x40060000; +lpc_usb = 0x40080000; lpc_gpio = 0x50000000; lpc_systick = 0xe000e000; lpc_nvic = 0xe000e100; -- cgit v1.2.3 From 918342016705303baa1630c62c290aaf2dcc2801 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Apr 2013 20:38:32 -0700 Subject: altos/lpc: Start adding USB register defines Signed-off-by: Keith Packard --- src/lpc/lpc.h | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) (limited to 'src') diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index 5a1987f5..da9ac534 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -828,6 +828,67 @@ struct lpc_usb { extern struct lpc_usb lpc_usb; +#define LPC_USB_DEVCMDSTAT_DEV_ADDR 0 +#define LPC_USB_DEVCMDSTAT_DEV_ADDR_MASK 0x7f +#define LPC_USB_DEVCMDSTAT_DEV_EN 7 +#define LPC_USB_DEVCMDSTAT_SETUP 8 +#define LPC_USB_DEVCMDSTAT_PLL_ON 9 +#define LPC_USB_DEVCMDSTAT_LPM_SUP 11 +#define LPC_USB_DEVCMDSTAT_INTONNAK_AO 12 +#define LPC_USB_DEVCMDSTAT_INTONNAK_AI 13 +#define LPC_USB_DEVCMDSTAT_INTONNAK_CO 14 +#define LPC_USB_DEVCMDSTAT_INTONNAK_CI 15 +#define LPC_USB_DEVCMDSTAT_DCON 16 +#define LPC_USB_DEVCMDSTAT_DSUS 17 +#define LPC_USB_DEVCMDSTAT_LPM_SUS 19 +#define LPC_USB_DEVCMDSTAT_LPM_REWP 20 +#define LPC_USB_DEVCMDSTAT_DCON_C 24 +#define LPC_USB_DEVCMDSTAT_DSUS_C 25 +#define LPC_USB_DEVCMDSTAT_DRES_C 26 +#define LPC_USB_DEVCMDSTAT_VBUSDEBOUNCED 28 + +#define LPC_USB_INFO_FRAME_NR 0 +#define LPC_USB_INFO_FRAME_NR_MASK 0x3ff +#define LPC_USB_INFO_ERR_CODE 11 +#define LPC_USB_INFO_ERR_CODE_NO_ERROR 0 +#define LPC_USB_INFO_ERR_CODE_PID_ENCODING_ERROR 1 +#define LPC_USB_INFO_ERR_CODE_PID_UNKNOWN 2 +#define LPC_USB_INFO_ERR_CODE_PACKET_UNEXPECTED 3 +#define LPC_USB_INFO_ERR_CODE_TOKEN_CRC_ERROR 4 +#define LPC_USB_INFO_ERR_CODE_DATA_CRC_ERROR 5 +#define LPC_USB_INFO_ERR_CODE_TIME_OUT 6 +#define LPC_USB_INFO_ERR_CODE_BABBLE 7 +#define LPC_USB_INFO_ERR_CODE_TRUNCATED_EOP 8 +#define LPC_USB_INFO_ERR_CODE_SENT_RECEIVED_NAK 9 +#define LPC_USB_INFO_ERR_CODE_SENT_STALL 0xa +#define LPC_USB_INFO_ERR_CODE_OVERRUN 0xb +#define LPC_USB_INFO_ERR_CODE_SENT_EMPTY_PACKET 0xc +#define LPC_USB_INFO_ERR_CODE_BITSTUFF_ERROR 0xd +#define LPC_USB_INFO_ERR_CODE_SYNC_ERROR 0xe +#define LPC_USB_INFO_ERR_CODE_WRONG_DATA_TOGGLE 0xf +#define LPC_USB_INFO_ERR_CODE_MASK 0xf + +#define LPC_USB_EPLISTSTART_EP_LIST 0 + +#define LPC_USB_DATABUFSTART_DA_BUF 0 + +#define LPC_USB_LPM_HIRD_HW 0 +#define LPC_USB_LPM_HIRD_HW_MASK 0xf +#define LPC_USB_LPM_HIRD_SW 4 +#define LPC_USB_LPM_HIRD_SW_MASK 0xf +#define LPC_USB_LPM_DATA_PENDING 8 + +#define LPC_USB_EPSKIP_SKIP 0 + +#define LPC_USB_EPINUSE(ep) ((ep) + 2) + +#define LPC_USB_ +#define LPC_USB_ +#define LPC_USB_ +#define LPC_USB_ +#define LPC_USB_ +#define LPC_USB_ + #define LPC_ISR_PIN_INT0_POS 0 #define LPC_ISR_PIN_INT1_POS 1 #define LPC_ISR_PIN_INT2_POS 2 -- cgit v1.2.3 From 6c35e21a86ab32bc91eb10a60c071b702fc0f963 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 7 May 2013 19:27:17 -0700 Subject: altos: Finish off LPC USB register definitions Signed-off-by: Keith Packard --- src/lpc/lpc.h | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index da9ac534..4e229838 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -880,14 +880,65 @@ extern struct lpc_usb lpc_usb; #define LPC_USB_EPSKIP_SKIP 0 -#define LPC_USB_EPINUSE(ep) ((ep) + 2) - -#define LPC_USB_ -#define LPC_USB_ -#define LPC_USB_ -#define LPC_USB_ -#define LPC_USB_ -#define LPC_USB_ +#define LPC_USB_EPINUSE_BUF(ep) (ep) + +#define LPC_USB_EPBUFCFG_BUF_SB(ep) (ep) + +#define LPC_USB_INTSTAT_EP0OUT 0 +#define LPC_USB_INTSTAT_EP0IN 1 +#define LPC_USB_INTSTAT_EP1OUT 2 +#define LPC_USB_INTSTAT_EP1IN 3 +#define LPC_USB_INTSTAT_EP2OUT 4 +#define LPC_USB_INTSTAT_EP2IN 5 +#define LPC_USB_INTSTAT_EP3OUT 6 +#define LPC_USB_INTSTAT_EP3IN 7 +#define LPC_USB_INTSTAT_EP4OUT 8 +#define LPC_USB_INTSTAT_EP4IN 9 +#define LPC_USB_INTSTAT_FRAME_INT 30 +#define LPC_USB_INTSTAT_DEV_INT 31 + +#define LPC_USB_INTIN_EP_INT_EN(ep) (ep) +#define LPC_USB_INTIN_FRAME_INT_EN 30 +#define LPC_USB_INTIN_DEV_INT_EN 31 + +#define LPC_USB_INTSETSTAT_EP_SET_INT(ep) (ep) +#define LPC_USB_INTSETSTAT_FRAME_SET_INT 30 +#define LPC_USB_INTSETSTAT_DEV_SET_INT 31 + +#define LPC_USB_INTROUTING_ROUTE_INT(ep) (ep) +#define LPC_USB_INTROUTING_INT30 30 +#define LPC_USB_INTROUTING_INT31 31 + +#define LPC_USB_EPTOGGLE_TOGGLE(ep) (ep) + +struct lpc_usb_ep { + vuint16_t buffer_offset; + vuint16_t buffer_status_nbytes; +}; + +struct lpc_usb_epn { + struct lpc_usb_ep out[2]; + struct lpc_usb_ep in[2]; +}; + +struct lpc_usb_endpoint { + struct lpc_usb_ep ep0_out; + vuint16_t setup_offset; + vuint16_t reserved_06; + struct lpc_usb_ep ep0_in; + vuint16_t reserved_0c; + vuint16_t reserved_0e; + struct lpc_usb_epn epn[4]; +}; + +#define LPC_USB_EP_STATUS_ACTIVE 15 +#define LPC_USB_EP_STATUS_DISABLED 14 +#define LPC_USB_EP_STATUS_STALL 13 +#define LPC_USB_EP_STATUS_TOGGLE_RESET 12 +#define LPC_USB_EP_STATUS_RATE_FEEDBACK 11 +#define LPC_USB_EP_STATUS_ENDPOINT_TYPE 10 +#define LPC_USB_EP_STATUS_OFFSET 0 +#define LPC_USB_EP_STATUS_OFFSET_MASK 0x3ff #define LPC_ISR_PIN_INT0_POS 0 #define LPC_ISR_PIN_INT1_POS 1 -- cgit v1.2.3 From 185e6d15bcda229949a984910d7394203d301db9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 16 May 2013 18:58:24 -0700 Subject: altos: Allow target-specific USB endpoint specifications The LPC has only a small number of endpoints, and those are not configurable. Let the LPC USB driver pick the IN and OUT endpoints by itself. Signed-off-by: Keith Packard --- src/core/ao_usb.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/core/ao_usb.h b/src/core/ao_usb.h index 6bc77608..35e64e65 100644 --- a/src/core/ao_usb.h +++ b/src/core/ao_usb.h @@ -102,8 +102,11 @@ extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; #define AO_USB_INT_EP 1 #define AO_USB_INT_SIZE 8 +#ifndef AO_USB_OUT_EP #define AO_USB_OUT_EP 4 #define AO_USB_IN_EP 5 +#endif + /* * USB bulk packets can only come in 8, 16, 32 and 64 * byte sizes, so we'll use 64 for everything -- cgit v1.2.3 From ac089d4fb930b7dbc4161259fd9bddba94395ebc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 17 May 2013 03:36:47 -0700 Subject: altos/lpc: Get USB working The lpc demo now has a USB command line. Also allocates system stack so we know when ram is tight at build time Signed-off-by: Keith Packard --- src/lpc/Makefile.defs | 2 +- src/lpc/altos.ld | 5 +- src/lpc/ao_arch.h | 8 +- src/lpc/ao_arch_funcs.h | 2 +- src/lpc/ao_timer_lpc.c | 33 +- src/lpc/ao_usb_lpc.c | 811 ++++++++++++++++++++--------------------------- src/lpc/lpc.h | 89 +++--- src/lpc/registers.ld | 2 + src/lpcxpresso/Makefile | 2 + src/lpcxpresso/ao_demo.c | 26 +- src/lpcxpresso/ao_pins.h | 5 +- 11 files changed, 446 insertions(+), 539 deletions(-) (limited to 'src') diff --git a/src/lpc/Makefile.defs b/src/lpc/Makefile.defs index c18284d2..b63bdd12 100644 --- a/src/lpc/Makefile.defs +++ b/src/lpc/Makefile.defs @@ -7,7 +7,7 @@ vpath load_csv.5c ../kalman vpath matrix.5c ../kalman vpath ao-make-product.5c ../util -CC=arm-none-eabi-gcc +CC=/usr/bin/arm-none-eabi-gcc SAT=/opt/cortex SAT_CLIB=$(SAT)/lib/pdclib-cortex-m0.a SAT_CFLAGS=-I$(SAT)/include diff --git a/src/lpc/altos.ld b/src/lpc/altos.ld index 7a99e66b..bcfba1ea 100644 --- a/src/lpc/altos.ld +++ b/src/lpc/altos.ld @@ -17,7 +17,8 @@ MEMORY { rom (rx) : ORIGIN = 0x00000000, LENGTH = 32K - ram (!w) : ORIGIN = 0x10000000, LENGTH = 4K + ram (!w) : ORIGIN = 0x10000000, LENGTH = 4K - 512 + stack (!w) : ORIGIN = 0x10000000 + 4K - 512, LENGTH = 512 } INCLUDE registers.ld @@ -63,7 +64,7 @@ SECTIONS { __bss_end__ = .; } >ram - PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram)); + PROVIDE(__stack__ = ORIGIN(stack) + LENGTH(stack)); PROVIDE(end = .); } diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index 61182160..99c646f9 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -45,7 +45,10 @@ #define __interrupt(n) #define __at(n) -#define ao_arch_reboot() +#define ao_arch_reboot() arm_scb.aircr = ((0x05fa << 16) | \ + (0 << 15) | \ + (1 << 2) | \ + (0 << 1)) #define ao_arch_nop() asm("nop") @@ -114,7 +117,8 @@ extern const uint32_t ao_radio_cal; void ao_adc_init(void); - +#define AO_USB_OUT_EP 2 +#define AO_USB_IN_EP 3 void ao_serial_init(void); diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index 39222b9d..96ae0366 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -124,7 +124,7 @@ static inline void ao_arch_restore_stack(void) { /* Restore APSR */ asm("pop {r0}"); - asm("msr apsr,r0"); + asm("msr apsr_nczvq,r0"); /* Restore general registers and return */ asm("pop {r0-r7,pc}\n"); diff --git a/src/lpc/ao_timer_lpc.c b/src/lpc/ao_timer_lpc.c index 51e82525..51835baa 100644 --- a/src/lpc/ao_timer_lpc.c +++ b/src/lpc/ao_timer_lpc.c @@ -78,6 +78,14 @@ ao_timer_init(void) #define AO_LPC_FCCO_MIN 156000000 +static void +ao_clock_delay(void) +{ + uint32_t i; + for (i = 0; i < 200; i++) + ao_arch_nop(); +} + void ao_clock_init(void) { @@ -94,11 +102,15 @@ ao_clock_init(void) /* Turn the IRC clock back on */ lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_IRC_PD); + ao_clock_delay(); /* Switch to the IRC clock */ lpc_scb.mainclksel = LPC_SCB_MAINCLKSEL_SEL_IRC << LPC_SCB_MAINCLKSEL_SEL; + lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA); lpc_scb.mainclkuen = (0 << LPC_SCB_MAINCLKUEN_ENA); lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA); + while (!(lpc_scb.mainclkuen & (1 << LPC_SCB_MAINCLKUEN_ENA))) + ; /* Find a PLL post divider ratio that gets the FCCO in range */ for (p = 0; p < 4; p++) @@ -110,14 +122,15 @@ ao_clock_init(void) /* Power down the PLL before touching the registers */ lpc_scb.pdruncfg |= (1 << LPC_SCB_PDRUNCFG_SYSPLL_PD); + ao_clock_delay(); /* Set PLL divider values */ lpc_scb.syspllctrl = ((AO_LPC_M << LPC_SCB_SYSPLLCTRL_MSEL) | (p << LPC_SCB_SYSPLLCTRL_PSEL)); - /* Turn off the external crystal clock */ lpc_scb.pdruncfg |= (1 << LPC_SCB_PDRUNCFG_SYSOSC_PD); + ao_clock_delay(); /* Configure the crystal clock */ lpc_scb.sysoscctrl = ((0 << LPC_SCB_SYSOSCCTRL_BYPASS) | /* using a crystal */ @@ -125,12 +138,16 @@ ao_clock_init(void) /* Turn on the external crystal clock */ lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_SYSOSC_PD); + ao_clock_delay(); /* Select crystal as PLL input */ lpc_scb.syspllclksel = (LPC_SCB_SYSPLLCLKSEL_SEL_SYSOSC << LPC_SCB_SYSPLLCLKSEL_SEL); - lpc_scb.syspllclkuen = 0; lpc_scb.syspllclkuen = (1 << LPC_SCB_SYSPLLCLKUEN_ENA); + lpc_scb.syspllclkuen = (0 << LPC_SCB_SYSPLLCLKUEN_ENA); + lpc_scb.syspllclkuen = (1 << LPC_SCB_SYSPLLCLKUEN_ENA); + while (!(lpc_scb.syspllclkuen & (1 << LPC_SCB_SYSPLLCLKUEN_ENA))) + ; /* Turn on the PLL */ lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_SYSPLL_PD); @@ -145,17 +162,15 @@ ao_clock_init(void) /* Switch to the PLL */ lpc_scb.mainclksel = LPC_SCB_MAINCLKSEL_SEL_PLL_OUTPUT << LPC_SCB_MAINCLKSEL_SEL; - lpc_scb.mainclkuen = 0 << LPC_SCB_MAINCLKUEN_ENA; - lpc_scb.mainclkuen = 1 << LPC_SCB_MAINCLKUEN_ENA; + lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA); + lpc_scb.mainclkuen = (0 << LPC_SCB_MAINCLKUEN_ENA); + lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA); + while (!(lpc_scb.mainclkuen & (1 << LPC_SCB_MAINCLKUEN_ENA))) + ; /* Set system clock divider */ lpc_scb.sysahbclkdiv = AO_LPC_CLKOUT / AO_LPC_SYSCLK; - /* Set USB clock source */ - lpc_scb.usbclksel = (LPC_SCB_USBCLKSEL_SEL_MAIN_CLOCK << LPC_SCB_USBCLKSEL_SEL); - lpc_scb.usbclkuen = (0 << LPC_SCB_USBCLKUEN_ENA); - lpc_scb.usbclkuen = (1 << LPC_SCB_USBCLKUEN_ENA); - /* Shut down perhipheral clocks (enabled as needed) */ lpc_scb.ssp0clkdiv = 0; lpc_scb.uartclkdiv = 0; diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index af2bd271..0f881720 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -19,9 +19,9 @@ #include "ao_usb.h" #include "ao_product.h" -#define USB_DEBUG 1 -#define USB_DEBUG_DATA 1 -#define USB_ECHO 1 +#define USB_DEBUG 0 +#define USB_DEBUG_DATA 0 +#define USB_ECHO 0 #if USB_DEBUG #define debug(format, args...) printf(format, ## args); @@ -62,35 +62,26 @@ static uint8_t ao_usb_ep0_out_len; * Objects allocated in special USB memory */ -/* Buffer description tables */ -static union lpc_usb_bdt *ao_usb_bdt; /* USB address of end of allocated storage */ -static uint16_t ao_usb_sram_addr; +static uint8_t *ao_usb_sram; /* Pointer to ep0 tx/rx buffers in USB memory */ -static uint32_t *ao_usb_ep0_tx_buffer; -static uint32_t *ao_usb_ep0_rx_buffer; +static uint8_t *ao_usb_ep0_tx_buffer; +static uint8_t *ao_usb_ep0_setup_buffer; +static uint8_t *ao_usb_ep0_rx_buffer; /* Pointer to bulk data tx/rx buffers in USB memory */ -static uint32_t *ao_usb_in_tx_buffer; -static uint32_t *ao_usb_out_rx_buffer; +static uint8_t *ao_usb_in_tx_buffer; +static uint8_t *ao_usb_out_rx_buffer; -/* System ram shadow of USB buffer; writing individual bytes is - * too much of a pain (sigh) */ +/* Our data buffers */ static uint8_t ao_usb_tx_buffer[AO_USB_IN_SIZE]; static uint8_t ao_usb_tx_count; static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE]; static uint8_t ao_usb_rx_count, ao_usb_rx_pos; -/* - * End point register indices - */ - -#define AO_USB_CONTROL_EPR 0 -#define AO_USB_INT_EPR 1 -#define AO_USB_OUT_EPR 2 -#define AO_USB_IN_EPR 3 +static struct lpc_usb_endpoint lpc_usb_endpoint __attribute((aligned(256))); /* Marks when we don't need to send an IN packet. * This happens only when the last IN packet is not full, @@ -129,39 +120,6 @@ static inline uint32_t set_toggle(uint32_t current_value, return (current_value ^ desired_value) & mask; } -static inline uint32_t *ao_usb_packet_buffer_addr(uint16_t sram_addr) -{ - return (uint32_t *) (lpc_usb_sram + 2 * sram_addr); -} - -static inline uint32_t ao_usb_epr_stat_rx(uint32_t epr) { - return (epr >> USB_USB_EPR_STAT_RX) & USB_USB_EPR_STAT_RX_MASK; -} - -static inline uint32_t ao_usb_epr_stat_tx(uint32_t epr) { - return (epr >> USB_USB_EPR_STAT_TX) & USB_USB_EPR_STAT_TX_MASK; -} - -static inline uint32_t ao_usb_epr_ctr_rx(uint32_t epr) { - return (epr >> USB_USB_EPR_CTR_RX) & 1; -} - -static inline uint32_t ao_usb_epr_ctr_tx(uint32_t epr) { - return (epr >> USB_USB_EPR_CTR_TX) & 1; -} - -static inline uint32_t ao_usb_epr_setup(uint32_t epr) { - return (epr >> USB_USB_EPR_SETUP) & 1; -} - -static inline uint32_t ao_usb_epr_dtog_rx(uint32_t epr) { - return (epr >> USB_USB_EPR_DTOG_RX) & 1; -} - -static inline uint32_t ao_usb_epr_dtog_tx(uint32_t epr) { - return (epr >> USB_USB_EPR_DTOG_TX) & 1; -} - /* * Set current device address and mark the * interface as active @@ -170,36 +128,24 @@ void ao_usb_set_address(uint8_t address) { debug("ao_usb_set_address %02x\n", address); - lpc_usb.daddr = (1 << USB_USB_DADDR_EF) | address; + lpc_usb.devcmdstat = ((address << LPC_USB_DEVCMDSTAT_DEV_ADDR) | + (1 << LPC_USB_DEVCMDSTAT_DEV_EN) | + (0 << LPC_USB_DEVCMDSTAT_SETUP) | + (0 << LPC_USB_DEVCMDSTAT_PLL_ON) | + (0 << LPC_USB_DEVCMDSTAT_LPM_SUP) | + (0 << LPC_USB_DEVCMDSTAT_INTONNAK_AO) | + (0 << LPC_USB_DEVCMDSTAT_INTONNAK_AI) | + (0 << LPC_USB_DEVCMDSTAT_INTONNAK_CO) | + (0 << LPC_USB_DEVCMDSTAT_INTONNAK_CI) | + (1 << LPC_USB_DEVCMDSTAT_DCON) | + (0 << LPC_USB_DEVCMDSTAT_DSUS) | + (0 << LPC_USB_DEVCMDSTAT_DCON_C) | + (0 << LPC_USB_DEVCMDSTAT_DSUS_C) | + (0 << LPC_USB_DEVCMDSTAT_DRES_C) | + (0 << LPC_USB_DEVCMDSTAT_VBUSDEBOUNCED)); ao_usb_address_pending = 0; } -/* - * Write these values to preserve register contents under HW changes - */ - -#define USB_USB_EPR_INVARIANT ((1 << USB_USB_EPR_CTR_RX) | \ - (USB_USB_EPR_DTOG_RX_WRITE_INVARIANT << USB_USB_EPR_DTOG_RX) | \ - (USB_USB_EPR_STAT_RX_WRITE_INVARIANT << USB_USB_EPR_STAT_RX) | \ - (1 << USB_USB_EPR_CTR_TX) | \ - (USB_USB_EPR_DTOG_TX_WRITE_INVARIANT << USB_USB_EPR_DTOG_TX) | \ - (USB_USB_EPR_STAT_TX_WRITE_INVARIANT << USB_USB_EPR_STAT_TX)) - -#define USB_USB_EPR_INVARIANT_MASK ((1 << USB_USB_EPR_CTR_RX) | \ - (USB_USB_EPR_DTOG_RX_MASK << USB_USB_EPR_DTOG_RX) | \ - (USB_USB_EPR_STAT_RX_MASK << USB_USB_EPR_STAT_RX) | \ - (1 << USB_USB_EPR_CTR_TX) | \ - (USB_USB_EPR_DTOG_TX_MASK << USB_USB_EPR_DTOG_TX) | \ - (USB_USB_EPR_STAT_TX_MASK << USB_USB_EPR_STAT_TX)) - -/* - * These bits are purely under sw control, so preserve them in the - * register by re-writing what was read - */ -#define USB_USB_EPR_PRESERVE_MASK ((USB_USB_EPR_EP_TYPE_MASK << USB_USB_EPR_EP_TYPE) | \ - (1 << USB_USB_EPR_EP_KIND) | \ - (USB_USB_EPR_EA_MASK << USB_USB_EPR_EA)) - #define TX_DBG 0 #define RX_DBG 0 @@ -224,338 +170,192 @@ static void _dbg(int line, char *msg, uint32_t value); #endif /* - * Set the state of the specified endpoint register to a new - * value. This is tricky because the bits toggle where the new - * value is one, and we need to write invariant values in other - * spots of the register. This hardware is strange... + * Set just endpoint 0, for use during startup */ -static void -_ao_usb_set_stat_tx(int ep, uint32_t stat_tx) + +static uint8_t * +ao_usb_alloc_sram(uint16_t size) { - uint32_t epr_write, epr_old; - - _tx_dbg1("set_stat_tx top", stat_tx); - epr_old = epr_write = lpc_usb.epr[ep]; - epr_write &= USB_USB_EPR_PRESERVE_MASK; - epr_write |= USB_USB_EPR_INVARIANT; - epr_write |= set_toggle(epr_old, - USB_USB_EPR_STAT_TX_MASK << USB_USB_EPR_STAT_TX, - stat_tx << USB_USB_EPR_STAT_TX); - lpc_usb.epr[ep] = epr_write; - _tx_dbg1("set_stat_tx bottom", epr_write); + uint8_t *addr = ao_usb_sram; + + ao_usb_sram += (size + 63) & ~63; + return addr; } -static void -ao_usb_set_stat_tx(int ep, uint32_t stat_tx) +static uint16_t +ao_usb_sram_offset(uint8_t *addr) { - ao_arch_block_interrupts(); - _ao_usb_set_stat_tx(ep, stat_tx); - ao_arch_release_interrupts(); + return (uint16_t) ((intptr_t) addr >> 6); } static void -_ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { - uint32_t epr_write, epr_old; - - epr_write = epr_old = lpc_usb.epr[ep]; - epr_write &= USB_USB_EPR_PRESERVE_MASK; - epr_write |= USB_USB_EPR_INVARIANT; - epr_write |= set_toggle(epr_old, - USB_USB_EPR_STAT_RX_MASK << USB_USB_EPR_STAT_RX, - stat_rx << USB_USB_EPR_STAT_RX); - lpc_usb.epr[ep] = epr_write; +ao_usb_set_ep(vuint32_t *ep, uint8_t *addr, uint16_t nbytes) +{ + *ep = ((ao_usb_sram_offset(addr) << LPC_USB_EP_OFFSET) | + (nbytes << LPC_USB_EP_NBYTES) | + (0 << LPC_USB_EP_ENDPOINT_ISO) | + (0 << LPC_USB_EP_RATE_FEEDBACK) | + (0 << LPC_USB_EP_TOGGLE_RESET) | + (0 << LPC_USB_EP_STALL) | + (0 << LPC_USB_EP_DISABLED) | + (1 << LPC_USB_EP_ACTIVE)); } -static void -ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { - ao_arch_block_interrupts(); - _ao_usb_set_stat_rx(ep, stat_rx); - ao_arch_release_interrupts(); +static inline uint16_t +ao_usb_ep_count(vuint32_t *ep) +{ + return (*ep >> LPC_USB_EP_NBYTES) & LPC_USB_EP_NBYTES_MASK; } -/* - * Set just endpoint 0, for use during startup - */ - -static void -ao_usb_init_ep(uint8_t ep, uint32_t addr, uint32_t type, uint32_t stat_rx, uint32_t stat_tx) +static inline uint8_t +ao_usb_ep_stall(vuint32_t *ep) { - uint32_t epr; - ao_arch_block_interrupts(); - epr = lpc_usb.epr[ep]; - epr = ((0 << USB_USB_EPR_CTR_RX) | - (epr & (1 << USB_USB_EPR_DTOG_RX)) | - set_toggle(epr, - (USB_USB_EPR_STAT_RX_MASK << USB_USB_EPR_STAT_RX), - (stat_rx << USB_USB_EPR_STAT_RX)) | - (type << USB_USB_EPR_EP_TYPE) | - (0 << USB_USB_EPR_EP_KIND) | - (0 << USB_USB_EPR_CTR_TX) | - (epr & (1 << USB_USB_EPR_DTOG_TX)) | - set_toggle(epr, - (USB_USB_EPR_STAT_TX_MASK << USB_USB_EPR_STAT_TX), - (stat_tx << USB_USB_EPR_STAT_TX)) | - (addr << USB_USB_EPR_EA)); - lpc_usb.epr[ep] = epr; - ao_arch_release_interrupts(); - debug ("writing epr[%d] 0x%08x wrote 0x%08x\n", - ep, epr, lpc_usb.epr[ep]); + return (*ep >> LPC_USB_EP_STALL) & 1; } -static void -ao_usb_set_ep0(void) +static inline vuint32_t * +ao_usb_ep0_out(void) { - uint32_t epr; - int e; - - ao_usb_sram_addr = 0; - - /* buffer table is at the start of USB memory */ - lpc_usb.btable = 0; - ao_usb_bdt = (void *) lpc_usb_sram; - - ao_usb_sram_addr += 8 * USB_USB_BDT_SIZE; - - /* Set up EP 0 - a Control end point with 32 bytes of in and out buffers */ - - ao_usb_bdt[0].single.addr_tx = ao_usb_sram_addr; - ao_usb_bdt[0].single.count_tx = 0; - ao_usb_ep0_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); - ao_usb_sram_addr += AO_USB_CONTROL_SIZE; - - ao_usb_bdt[0].single.addr_rx = ao_usb_sram_addr; - ao_usb_bdt[0].single.count_rx = ((1 << USB_USB_BDT_COUNT_RX_BL_SIZE) | - (((AO_USB_CONTROL_SIZE / 32) - 1) << USB_USB_BDT_COUNT_RX_NUM_BLOCK)); - ao_usb_ep0_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); - ao_usb_sram_addr += AO_USB_CONTROL_SIZE; + return &lpc_usb_endpoint.ep0_out; +} - ao_usb_init_ep(AO_USB_CONTROL_EPR, AO_USB_CONTROL_EP, - USB_USB_EPR_EP_TYPE_CONTROL, - USB_USB_EPR_STAT_RX_VALID, - USB_USB_EPR_STAT_TX_NAK); +static inline vuint32_t * +ao_usb_ep0_in(void) +{ + return &lpc_usb_endpoint.ep0_in; +} - /* Clear all of the other endpoints */ - for (e = 1; e < 8; e++) { - ao_usb_init_ep(e, 0, - USB_USB_EPR_EP_TYPE_CONTROL, - USB_USB_EPR_STAT_RX_DISABLED, - USB_USB_EPR_STAT_TX_DISABLED); - } +static inline vuint32_t * +ao_usb_epn_out(uint8_t n) +{ + return &lpc_usb_endpoint.epn[n-1].out[0]; +} - ao_usb_set_address(0); +static inline vuint32_t * +ao_usb_epn_in(uint8_t n) +{ + return &lpc_usb_endpoint.epn[n-1].in[0]; } static void -ao_usb_set_configuration(void) +ao_usb_set_epn_in(uint8_t n, uint8_t *addr, uint16_t nbytes) { - uint32_t epr; - - debug ("ao_usb_set_configuration\n"); - - /* Set up the INT end point */ - ao_usb_bdt[AO_USB_INT_EPR].single.addr_tx = ao_usb_sram_addr; - ao_usb_bdt[AO_USB_INT_EPR].single.count_tx = 0; - ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); - ao_usb_sram_addr += AO_USB_INT_SIZE; - - ao_usb_init_ep(AO_USB_INT_EPR, - AO_USB_INT_EP, - USB_USB_EPR_EP_TYPE_INTERRUPT, - USB_USB_EPR_STAT_RX_DISABLED, - USB_USB_EPR_STAT_TX_NAK); - - /* Set up the OUT end point */ - ao_usb_bdt[AO_USB_OUT_EPR].single.addr_rx = ao_usb_sram_addr; - ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx = ((1 << USB_USB_BDT_COUNT_RX_BL_SIZE) | - (((AO_USB_OUT_SIZE / 32) - 1) << USB_USB_BDT_COUNT_RX_NUM_BLOCK)); - ao_usb_out_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); - ao_usb_sram_addr += AO_USB_OUT_SIZE; - - ao_usb_init_ep(AO_USB_OUT_EPR, - AO_USB_OUT_EP, - USB_USB_EPR_EP_TYPE_BULK, - USB_USB_EPR_STAT_RX_VALID, - USB_USB_EPR_STAT_TX_DISABLED); - - /* Set up the IN end point */ - ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_sram_addr; - ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = 0; - ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); - ao_usb_sram_addr += AO_USB_IN_SIZE; - - ao_usb_init_ep(AO_USB_IN_EPR, - AO_USB_IN_EP, - USB_USB_EPR_EP_TYPE_BULK, - USB_USB_EPR_STAT_RX_DISABLED, - USB_USB_EPR_STAT_TX_NAK); - - ao_usb_running = 1; + ao_usb_set_ep(ao_usb_epn_in(n), addr, nbytes); } -static uint16_t control_count; -static uint16_t int_count; -static uint16_t in_count; -static uint16_t out_count; -static uint16_t reset_count; - -void -lpc_usb_lp_isr(void) +static void +ao_usb_set_epn_out(uint8_t n, uint8_t *addr, uint16_t nbytes) { - uint32_t istr = lpc_usb.istr; - - if (istr & (1 << USB_USB_ISTR_CTR)) { - uint8_t ep = istr & USB_USB_ISTR_EP_ID_MASK; - uint32_t epr, epr_write; - - /* Preserve the SW write bits, don't mess with most HW writable bits, - * clear the CTR_RX and CTR_TX bits - */ - epr = lpc_usb.epr[ep]; - epr_write = epr; - epr_write &= USB_USB_EPR_PRESERVE_MASK; - epr_write |= USB_USB_EPR_INVARIANT; - epr_write &= ~(1 << USB_USB_EPR_CTR_RX); - epr_write &= ~(1 << USB_USB_EPR_CTR_TX); - lpc_usb.epr[ep] = epr_write; - - switch (ep) { - case 0: - ++control_count; - if (ao_usb_epr_ctr_rx(epr)) { - if (ao_usb_epr_setup(epr)) - ao_usb_ep0_receive |= AO_USB_EP0_GOT_SETUP; - else - ao_usb_ep0_receive |= AO_USB_EP0_GOT_RX_DATA; - } - if (ao_usb_epr_ctr_tx(epr)) - ao_usb_ep0_receive |= AO_USB_EP0_GOT_TX_ACK; - ao_wakeup(&ao_usb_ep0_receive); - break; - case AO_USB_OUT_EPR: - ++out_count; - if (ao_usb_epr_ctr_rx(epr)) { - _rx_dbg1("RX ISR", epr); - ao_usb_out_avail = 1; - _rx_dbg0("out avail set"); - ao_wakeup(&ao_stdin_ready); - _rx_dbg0("stdin awoken"); - } - break; - case AO_USB_IN_EPR: - ++in_count; - _tx_dbg1("TX ISR", epr); - if (ao_usb_epr_ctr_tx(epr)) { - ao_usb_in_pending = 0; - ao_wakeup(&ao_usb_in_pending); - } - break; - case AO_USB_INT_EPR: - ++int_count; - if (ao_usb_epr_ctr_tx(epr)) - _ao_usb_set_stat_tx(AO_USB_INT_EPR, USB_USB_EPR_STAT_TX_NAK); - break; - } - return; - } - - if (istr & (1 << USB_USB_ISTR_RESET)) { - ++reset_count; - lpc_usb.istr &= ~(1 << USB_USB_ISTR_RESET); - ao_usb_ep0_receive |= AO_USB_EP0_GOT_RESET; - ao_wakeup(&ao_usb_ep0_receive); - } + ao_usb_set_ep(ao_usb_epn_out(n), addr, nbytes); } -void -lpc_usb_fs_wkup(void) +static inline uint16_t +ao_usb_epn_out_count(uint8_t n) { - /* USB wakeup, just clear the bit for now */ - lpc_usb.istr &= ~(1 << USB_USB_ISTR_WKUP); + return ao_usb_ep_count(ao_usb_epn_out(n)); } -/* The USB memory holds 16 bit values on 32 bit boundaries - * and must be accessed only in 32 bit units. Sigh. - */ +static inline uint16_t +ao_usb_epn_in_count(uint8_t n) +{ + return ao_usb_ep_count(ao_usb_epn_in(n)); +} -static inline void -ao_usb_write_byte(uint8_t byte, uint32_t *base, uint16_t offset) +static uint8_t * +ao_usb_enable_ep(vuint32_t *ep, uint16_t nbytes, uint16_t set_nbytes) { - base += offset >> 1; - if (offset & 1) { - *base = (*base & 0xff) | ((uint32_t) byte << 8); - } else { - *base = (*base & 0xff00) | byte; - } + uint8_t *addr = ao_usb_alloc_sram(nbytes); + + ao_usb_set_ep(ep, addr, set_nbytes); + return addr; } -static inline void -ao_usb_write_short(uint16_t data, uint32_t *base, uint16_t offset) +static void +ao_usb_disable_ep(vuint32_t *ep) { - base[offset>>1] = data; + *ep = ((0 << LPC_USB_EP_OFFSET) | + (0 << LPC_USB_EP_NBYTES) | + (0 << LPC_USB_EP_ENDPOINT_ISO) | + (0 << LPC_USB_EP_RATE_FEEDBACK) | + (0 << LPC_USB_EP_TOGGLE_RESET) | + (0 << LPC_USB_EP_STALL) | + (1 << LPC_USB_EP_DISABLED) | + (0 << LPC_USB_EP_ACTIVE)); } static void -ao_usb_write(const uint8_t *src, uint32_t *base, uint16_t offset, uint16_t bytes) +ao_usb_enable_epn(uint8_t n, uint16_t out_bytes, uint8_t **out_addr, uint16_t in_bytes, uint8_t **in_addr) { - if (!bytes) - return; - if (offset & 1) { - debug_data (" %02x", src[0]); - ao_usb_write_byte(*src++, base, offset++); - bytes--; - } - while (bytes >= 2) { - debug_data (" %02x %02x", src[0], src[1]); - ao_usb_write_short((src[1] << 8) | src[0], base, offset); - offset += 2; - src += 2; - bytes -= 2; - } - if (bytes) { - debug_data (" %02x", src[0]); - ao_usb_write_byte(*src, base, offset); - } + uint8_t *addr; + + addr = ao_usb_enable_ep(ao_usb_epn_out(n), out_bytes, out_bytes); + if (out_addr) + *out_addr = addr; + ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].out[1]); + + addr = ao_usb_enable_ep(ao_usb_epn_in(n), in_bytes, 0); + if (in_addr) + *in_addr = addr; + ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].in[1]); } -static inline uint8_t -ao_usb_read_byte(uint32_t *base, uint16_t offset) +static void +ao_usb_disable_epn(uint8_t n) { - base += offset >> 1; - if (offset & 1) - return (*base >> 8) & 0xff; - else - return *base & 0xff; + ao_usb_disable_ep(ao_usb_epn_out(n)); + ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].out[1]); + ao_usb_disable_ep(ao_usb_epn_in(n)); + ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].in[1]); } -static inline uint16_t -ao_usb_read_short(uint32_t *base, uint16_t offset) +static void +ao_usb_set_ep0(void) { - return base[offset>>1]; + int e; + + /* Everything is single buffered for now */ + lpc_usb.epbufcfg = 0; + lpc_usb.epinuse = 0; + lpc_usb.epskip = 0xffffffff; + + ao_usb_set_address(0); + lpc_usb.intstat = 0xc00003ff; + + ao_usb_configuration = 0; + + ao_usb_sram = lpc_usb_sram; + + lpc_usb.epliststart = (uint32_t) (intptr_t) &lpc_usb_endpoint; + lpc_usb.databufstart = ((uint32_t) (intptr_t) ao_usb_sram) & 0xffc00000; + + /* Set up EP 0 - a Control end point with 32 bytes of in and out buffers */ + + ao_usb_ep0_rx_buffer = ao_usb_enable_ep(ao_usb_ep0_out(), AO_USB_CONTROL_SIZE, AO_USB_CONTROL_SIZE); + ao_usb_ep0_setup_buffer = ao_usb_alloc_sram(AO_USB_CONTROL_SIZE); + lpc_usb_endpoint.setup = ao_usb_sram_offset(ao_usb_ep0_setup_buffer); + ao_usb_ep0_tx_buffer = ao_usb_enable_ep(ao_usb_ep0_in(), AO_USB_CONTROL_SIZE, 0); + + /* Clear all of the other endpoints */ + for (e = 1; e <= 4; e++) + ao_usb_disable_epn(e); + } static void -ao_usb_read(uint8_t *dst, uint32_t *base, uint16_t offset, uint16_t bytes) +ao_usb_set_configuration(void) { - if (!bytes) - return; - if (offset & 1) { - *dst++ = ao_usb_read_byte(base, offset++); - debug_data (" %02x", dst[-1]); - bytes--; - } - while (bytes >= 2) { - uint16_t s = ao_usb_read_short(base, offset); - dst[0] = s; - dst[1] = s >> 8; - debug_data (" %02x %02x", dst[0], dst[1]); - offset += 2; - dst += 2; - bytes -= 2; - } - if (bytes) { - *dst = ao_usb_read_byte(base, offset); - debug_data (" %02x", dst[0]); - } + debug ("ao_usb_set_configuration\n"); + + /* Set up the INT end point */ + ao_usb_enable_epn(AO_USB_INT_EP, 0, NULL, 0, NULL); + + /* Set up the OUT end point */ + ao_usb_enable_epn(AO_USB_OUT_EP, AO_USB_OUT_SIZE, &ao_usb_out_rx_buffer, 0, NULL); + + /* Set up the IN end point */ + ao_usb_enable_epn(AO_USB_IN_EP, 0, NULL, AO_USB_IN_SIZE, &ao_usb_in_tx_buffer); + + ao_usb_running = 1; } /* Send an IN data packet */ @@ -564,12 +364,6 @@ ao_usb_ep0_flush(void) { uint8_t this_len; - /* Check to see if the endpoint is still busy */ - if (ao_usb_epr_stat_tx(lpc_usb.epr[0]) == USB_USB_EPR_STAT_TX_VALID) { - debug("EP0 not accepting IN data\n"); - return; - } - this_len = ao_usb_ep0_in_len; if (this_len > AO_USB_CONTROL_SIZE) this_len = AO_USB_CONTROL_SIZE; @@ -580,34 +374,43 @@ ao_usb_ep0_flush(void) ao_usb_ep0_in_len -= this_len; debug_data ("Flush EP0 len %d:", this_len); - ao_usb_write(ao_usb_ep0_in_data, ao_usb_ep0_tx_buffer, 0, this_len); + memcpy(ao_usb_ep0_tx_buffer, ao_usb_ep0_in_data, this_len); debug_data ("\n"); ao_usb_ep0_in_data += this_len; /* Mark the endpoint as TX valid to send the packet */ - ao_usb_bdt[AO_USB_CONTROL_EPR].single.count_tx = this_len; - ao_usb_set_stat_tx(AO_USB_CONTROL_EPR, USB_USB_EPR_STAT_TX_VALID); - debug ("queue tx. epr 0 now %08x\n", lpc_usb.epr[AO_USB_CONTROL_EPR]); + ao_usb_set_ep(ao_usb_ep0_in(), ao_usb_ep0_tx_buffer, this_len); + debug ("queue tx. 0 now %08x\n", *ao_usb_ep0_in()); } /* Read data from the ep0 OUT fifo */ static void ao_usb_ep0_fill(void) { - uint16_t len = ao_usb_bdt[0].single.count_rx & USB_USB_BDT_COUNT_RX_COUNT_RX_MASK; + uint16_t len; + uint8_t *rx_buffer; + + /* Pull all of the data out of the packet */ + if (lpc_usb.devcmdstat & (1 << LPC_USB_DEVCMDSTAT_SETUP)) { + rx_buffer = ao_usb_ep0_setup_buffer; + len = 8; + } else { + rx_buffer = ao_usb_ep0_rx_buffer; + len = AO_USB_CONTROL_SIZE - ao_usb_ep_count(ao_usb_ep0_out()); + } if (len > ao_usb_ep0_out_len) len = ao_usb_ep0_out_len; ao_usb_ep0_out_len -= len; - /* Pull all of the data out of the packet */ debug_data ("Fill EP0 len %d:", len); - ao_usb_read(ao_usb_ep0_out_data, ao_usb_ep0_rx_buffer, 0, len); + memcpy(ao_usb_ep0_out_data, rx_buffer, len); debug_data ("\n"); ao_usb_ep0_out_data += len; /* ACK the packet */ - ao_usb_set_stat_rx(0, USB_USB_EPR_STAT_RX_VALID); + ao_usb_set_ep(ao_usb_ep0_out(), ao_usb_ep0_rx_buffer, AO_USB_CONTROL_SIZE); + lpc_usb.devcmdstat |= (1 << LPC_USB_DEVCMDSTAT_SETUP); } static void @@ -772,55 +575,109 @@ ao_usb_ep0_setup(void) ao_usb_ep0_in_start(ao_usb_setup.length); } -/* End point 0 receives all of the control messages. */ static void -ao_usb_ep0(void) +ao_usb_ep0_handle(uint8_t receive) { - uint8_t intx, udint; + ao_usb_ep0_receive = 0; - debug ("usb task started\n"); - ao_usb_ep0_state = AO_USB_EP0_IDLE; - for (;;) { - uint8_t receive; - ao_arch_critical( - while (!(receive = ao_usb_ep0_receive)) - ao_sleep(&ao_usb_ep0_receive); - ao_usb_ep0_receive = 0; - ); - - if (receive & AO_USB_EP0_GOT_RESET) { - debug ("\treset\n"); - ao_usb_set_ep0(); - continue; - } - if (receive & AO_USB_EP0_GOT_SETUP) { - debug ("\tsetup\n"); - ao_usb_ep0_setup(); - } - if (receive & AO_USB_EP0_GOT_RX_DATA) { - debug ("\tgot rx data\n"); - if (ao_usb_ep0_state == AO_USB_EP0_DATA_OUT) { - ao_usb_ep0_fill(); - if (ao_usb_ep0_out_len == 0) { - ao_usb_ep0_state = AO_USB_EP0_DATA_IN; - ao_usb_ep0_in_start(0); - } + if (receive & AO_USB_EP0_GOT_RESET) { + debug ("\treset\n"); + ao_usb_set_ep0(); + return; + } + if (receive & AO_USB_EP0_GOT_SETUP) { + debug ("\tsetup\n"); + ao_usb_ep0_setup(); + } + if (receive & AO_USB_EP0_GOT_RX_DATA) { + debug ("\tgot rx data\n"); + if (ao_usb_ep0_state == AO_USB_EP0_DATA_OUT) { + ao_usb_ep0_fill(); + if (ao_usb_ep0_out_len == 0) { + ao_usb_ep0_state = AO_USB_EP0_DATA_IN; + ao_usb_ep0_in_start(0); } } - if (receive & AO_USB_EP0_GOT_TX_ACK) { - debug ("\tgot tx ack\n"); - - /* Wait until the IN packet is received from addr 0 - * before assigning our local address - */ - if (ao_usb_address_pending) - ao_usb_set_address(ao_usb_address); - if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN) - ao_usb_ep0_flush(); + } + if (receive & AO_USB_EP0_GOT_TX_ACK) { + debug ("\tgot tx ack\n"); + + /* Wait until the IN packet is received from addr 0 + * before assigning our local address + */ + if (ao_usb_address_pending) + ao_usb_set_address(ao_usb_address); + if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN) + ao_usb_ep0_flush(); + } +} + +static uint16_t control_count; +static uint16_t int_count; +static uint16_t in_count; +static uint16_t out_count; +static uint16_t reset_count; + +void +lpc_usb_irq_isr(void) +{ + uint32_t intstat = lpc_usb.intstat & lpc_usb.inten; + + lpc_usb.intstat = intstat; + /* Handle EP0 OUT packets */ + if (intstat & (1 << LPC_USB_INT_EPOUT(0))) { + if (lpc_usb.devcmdstat & (1 << LPC_USB_DEVCMDSTAT_SETUP)) + ao_usb_ep0_receive |= AO_USB_EP0_GOT_SETUP; + else + ao_usb_ep0_receive |= AO_USB_EP0_GOT_RX_DATA; + + ao_usb_ep0_handle(ao_usb_ep0_receive); + } + + /* Handle EP0 IN packets */ + if (intstat & (1 << LPC_USB_INT_EPIN(0))) { + ao_usb_ep0_receive |= AO_USB_EP0_GOT_TX_ACK; + + ao_usb_ep0_handle(ao_usb_ep0_receive); + } + + + /* Handle OUT packets */ + if (intstat & (1 << LPC_USB_INT_EPOUT(AO_USB_OUT_EP))) { + ++out_count; + _rx_dbg1("RX ISR", *ao_usb_epn_out(AO_USB_OUT_EP)); + ao_usb_out_avail = 1; + _rx_dbg0("out avail set"); + ao_wakeup(&ao_stdin_ready); + _rx_dbg0("stdin awoken"); + } + + /* Handle IN packets */ + if (intstat & (1 << LPC_USB_INT_EPIN(AO_USB_IN_EP))) { + ++in_count; + _tx_dbg1("TX ISR", *ao_usb_epn_in(AO_USB_IN_EP)); + ao_usb_in_pending = 0; + ao_wakeup(&ao_usb_in_pending); + } + + /* NAK all INT EP IN packets */ + if (intstat & (1 << LPC_USB_INT_EPIN(AO_USB_INT_EP))) { + ; + } + + /* Check for reset */ + if (intstat & (1 << LPC_USB_INT_DEV)) { + if (lpc_usb.devcmdstat & (1 << LPC_USB_DEVCMDSTAT_DRES_C)) + { + lpc_usb.devcmdstat |= (1 << LPC_USB_DEVCMDSTAT_DRES_C); + ao_usb_ep0_receive |= AO_USB_EP0_GOT_RESET; + ao_usb_ep0_handle(ao_usb_ep0_receive); } } } + + /* Queue the current IN buffer for transmission */ static void _ao_usb_in_send(void) @@ -832,10 +689,9 @@ _ao_usb_in_send(void) ao_usb_in_pending = 1; if (ao_usb_tx_count != AO_USB_IN_SIZE) ao_usb_in_flushed = 1; - ao_usb_write(ao_usb_tx_buffer, ao_usb_in_tx_buffer, 0, ao_usb_tx_count); - ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = ao_usb_tx_count; + memcpy(ao_usb_in_tx_buffer, ao_usb_tx_buffer, ao_usb_tx_count); + ao_usb_set_ep(ao_usb_epn_in(AO_USB_IN_EP), ao_usb_in_tx_buffer, ao_usb_tx_count); ao_usb_tx_count = 0; - _ao_usb_set_stat_tx(AO_USB_IN_EPR, USB_USB_EPR_STAT_TX_VALID); _tx_dbg0("in_send end"); } @@ -905,17 +761,17 @@ _ao_usb_out_recv(void) _rx_dbg0("out_recv top"); ao_usb_out_avail = 0; - ao_usb_rx_count = ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx & USB_USB_BDT_COUNT_RX_COUNT_RX_MASK; + ao_usb_rx_count = AO_USB_OUT_SIZE - ao_usb_epn_out_count(AO_USB_OUT_EP); _rx_dbg1("out_recv count", ao_usb_rx_count); debug ("recv %d\n", ao_usb_rx_count); debug_data("Fill OUT len %d:", ao_usb_rx_count); - ao_usb_read(ao_usb_rx_buffer, ao_usb_out_rx_buffer, 0, ao_usb_rx_count); + memcpy(ao_usb_rx_buffer, ao_usb_out_rx_buffer, ao_usb_rx_count); debug_data("\n"); ao_usb_rx_pos = 0; /* ACK the packet */ - _ao_usb_set_stat_rx(AO_USB_OUT_EPR, USB_USB_EPR_STAT_RX_VALID); + ao_usb_set_epn_out(AO_USB_OUT_EP, ao_usb_out_rx_buffer, AO_USB_OUT_SIZE); } int @@ -960,17 +816,25 @@ void ao_usb_disable(void) { ao_arch_block_interrupts(); - lpc_usb.cntr = (1 << USB_USB_CNTR_FRES); - lpc_usb.istr = 0; - /* Disable USB pull-up */ - lpc_syscfg.pmc &= ~(1 << USB_SYSCFG_PMC_USB_PU); + /* Disable interrupts */ + lpc_usb.inten = 0; + + lpc_nvic_clear_enable(LPC_ISR_USB_IRQ_POS); - /* Switch off the device */ - lpc_usb.cntr = (1 << USB_USB_CNTR_PDWN) | (1 << USB_USB_CNTR_FRES); + /* Disable the device */ + lpc_usb.devcmdstat = 0; + + /* Turn off USB clock */ + lpc_scb.usbclkdiv = 0; + + /* Disable USB PHY */ + lpc_scb.pdruncfg |= (1 << LPC_SCB_PDRUNCFG_USBPAD_PD); + + /* Disable USB registers and RAM */ + lpc_scb.sysahbclkctrl &= ~((1 << LPC_SCB_SYSAHBCLKCTRL_USB) | + (1 << LPC_SCB_SYSAHBCLKCTRL_USBRAM)); - /* Disable the interface */ - lpc_rcc.apb1enr &+ ~(1 << USB_RCC_APB1ENR_USBEN); ao_arch_release_interrupts(); } @@ -979,6 +843,23 @@ ao_usb_enable(void) { int t; + /* Enable USB pins */ +#if HAS_USB_CONNECT + lpc_ioconf.pio0_6 = ((LPC_IOCONF_FUNC_USB_CONNECT << LPC_IOCONF_FUNC) | + (LPC_IOCONF_MODE_INACTIVE << LPC_IOCONF_MODE) | + (0 << LPC_IOCONF_HYS) | + (0 << LPC_IOCONF_INV) | + (0 << LPC_IOCONF_OD) | + 0x80); +#endif +#if HAS_USB_VBUS + lpc_ioconf.pio0_3 = ((LPC_IOCONF_FUNC_USB_VBUS << LPC_IOCONF_FUNC) | + (LPC_IOCONF_MODE_INACTIVE << LPC_IOCONF_MODE) | + (0 << LPC_IOCONF_HYS) | + (0 << LPC_IOCONF_INV) | + (0 << LPC_IOCONF_OD) | + 0x80); +#endif /* Enable USB registers and RAM */ lpc_scb.sysahbclkctrl |= ((1 << LPC_SCB_SYSAHBCLKCTRL_USB) | (1 << LPC_SCB_SYSAHBCLKCTRL_USBRAM)); @@ -986,52 +867,55 @@ ao_usb_enable(void) /* Enable USB PHY */ lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_USBPAD_PD); + /* Turn on USB PLL */ + lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_USBPLL_PD); + + lpc_scb.usbpllclksel = (LPC_SCB_SYSPLLCLKSEL_SEL_SYSOSC << LPC_SCB_SYSPLLCLKSEL_SEL); + lpc_scb.usbpllclkuen = (1 << LPC_SCB_USBPLLCLKUEN_ENA); + lpc_scb.usbpllclkuen = (0 << LPC_SCB_USBPLLCLKUEN_ENA); + lpc_scb.usbpllclkuen = (1 << LPC_SCB_USBPLLCLKUEN_ENA); + while (!(lpc_scb.usbpllclkuen & (1 << LPC_SCB_USBPLLCLKUEN_ENA))) + ; + lpc_scb.usbpllctrl = 0x23; + while (!(lpc_scb.usbpllstat & 1)) + ; + + lpc_scb.usbclksel = 0; + /* Turn on USB clock, use 48MHz clock unchanged */ lpc_scb.usbclkdiv = 1; /* Configure interrupts */ ao_arch_block_interrupts(); - /* Enable interrupts */ - lpc_usb. - /* Route interrupts */ - - lpc_nvic_set_priority(USB_ISR_USB_LP_POS, 3); - lpc_nvic_set_enable(USB_ISR_USB_LP_POS); + /* Route all interrupts to the main isr */ + lpc_usb.introuting = 0; - ao_usb_configuration = 0; - - lpc_usb.cntr = (1 << USB_USB_CNTR_FRES); + /* Configure NVIC */ - /* Clear the power down bit */ - lpc_usb.cntr = 0; + lpc_nvic_set_enable(LPC_ISR_USB_IRQ_POS); + lpc_nvic_set_priority(LPC_ISR_USB_IRQ_POS, 0); /* Clear any spurious interrupts */ - lpc_usb.istr = 0; + lpc_usb.intstat = 0xffffffff; debug ("ao_usb_enable\n"); /* Enable interrupts */ - lpc_usb.cntr = ((1 << USB_USB_CNTR_CTRM) | - (0 << USB_USB_CNTR_PMAOVRM) | - (0 << USB_USB_CNTR_ERRM) | - (0 << USB_USB_CNTR_WKUPM) | - (0 << USB_USB_CNTR_SUSPM) | - (1 << USB_USB_CNTR_RESETM) | - (0 << USB_USB_CNTR_SOFM) | - (0 << USB_USB_CNTR_ESOFM) | - (0 << USB_USB_CNTR_RESUME) | - (0 << USB_USB_CNTR_FSUSP) | - (0 << USB_USB_CNTR_LP_MODE) | - (0 << USB_USB_CNTR_PDWN) | - (0 << USB_USB_CNTR_FRES)); + lpc_usb.inten = ((1 << LPC_USB_INT_EPOUT(0)) | + (1 << LPC_USB_INT_EPIN(0)) | + (1 << LPC_USB_INT_EPIN(AO_USB_INT_EP)) | + (1 << LPC_USB_INT_EPOUT(AO_USB_OUT_EP)) | + (1 << LPC_USB_INT_EPIN(AO_USB_IN_EP)) | + (1 << LPC_USB_INT_DEV)); ao_arch_release_interrupts(); + lpc_usb.devcmdstat = 0; for (t = 0; t < 1000; t++) ao_arch_nop(); - /* Enable USB pull-up */ - lpc_syscfg.pmc |= (1 << USB_SYSCFG_PMC_USB_PU); + + ao_usb_set_ep0(); } #if USB_ECHO @@ -1070,7 +954,6 @@ ao_usb_init(void) ao_usb_enable(); debug ("ao_usb_init\n"); - ao_add_task(&ao_usb_task, ao_usb_ep0, "usb"); #if USB_ECHO ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo"); #endif @@ -1091,7 +974,7 @@ struct ao_usb_dbg { uint32_t primask; #if TX_DBG uint16_t in_count; - uint32_t in_epr; + uint32_t in_ep; uint32_t in_pending; uint32_t tx_count; uint32_t in_flushed; @@ -1100,13 +983,13 @@ struct ao_usb_dbg { uint8_t rx_count; uint8_t rx_pos; uint8_t out_avail; - uint32_t out_epr; + uint32_t out_ep; #endif }; -#define NUM_USB_DBG 128 +#define NUM_USB_DBG 8 -static struct ao_usb_dbg dbg[128]; +static struct ao_usb_dbg dbg[NUM_USB_DBG]; static int dbg_i; static void _dbg(int line, char *msg, uint32_t value) @@ -1119,7 +1002,7 @@ static void _dbg(int line, char *msg, uint32_t value) dbg[dbg_i].primask = primask; #if TX_DBG dbg[dbg_i].in_count = in_count; - dbg[dbg_i].in_epr = lpc_usb.epr[AO_USB_IN_EPR]; + dbg[dbg_i].in_ep = *ao_usb_epn_in(AO_USB_IN_EP); dbg[dbg_i].in_pending = ao_usb_in_pending; dbg[dbg_i].tx_count = ao_usb_tx_count; dbg[dbg_i].in_flushed = ao_usb_in_flushed; @@ -1128,7 +1011,7 @@ static void _dbg(int line, char *msg, uint32_t value) dbg[dbg_i].rx_count = ao_usb_rx_count; dbg[dbg_i].rx_pos = ao_usb_rx_pos; dbg[dbg_i].out_avail = ao_usb_out_avail; - dbg[dbg_i].out_epr = lpc_usb.epr[AO_USB_OUT_EPR]; + dbg[dbg_i].out_ep = *ao_usb_epn_out(AO_USB_OUT_EP); #endif if (++dbg_i == NUM_USB_DBG) dbg_i = 0; diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index 4e229838..4141f356 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -116,7 +116,7 @@ extern struct lpc_ioconf lpc_ioconf; #define LPC_IOCONF_FUNC_SSEL0 1 #define LPC_IOCONF_FUNC_CT16B0_CAP0 2 -/* PIO0_3 +/* PIO0_3 */ #define LPC_IOCONF_FUNC_PIO0_3 0 #define LPC_IOCONF_FUNC_USB_VBUS 1 @@ -395,7 +395,7 @@ struct lpc_scb { vuint32_t syspllclksel; /* 0x40 */ vuint32_t syspllclkuen; vuint32_t usbpllclksel; - vuint32_t usbplllclkuen; + vuint32_t usbpllclkuen; uint32_t r50[8]; @@ -600,8 +600,13 @@ extern struct lpc_scb lpc_scb; #define LPC_SCB_USBCLKUEN_ENA 0 #define LPC_SCB_USBCLKDIV_DIV 0 -#define LPC_SCB_CLKOUTSEL_ -#define LPC_SCB_CLKOUTUEN_ +#define LPC_SCB_CLKOUTSEL_SEL 0 +#define LPC_SCB_CLKOUTSEL_SEL_IRC 0 +#define LPC_SCB_CLKOUTSEL_SEL_SYSOSC 1 +#define LPC_SCB_CLKOUTSEL_SEL_LF 2 +#define LPC_SCB_CLKOUTSEL_SEL_MAIN_CLOCK 3 + +#define LPC_SCB_CLKOUTUEN_ENA 0 #define LPC_SCB_PDRUNCFG_IRCOUT_PD 0 #define LPC_SCB_PDRUNCFG_IRC_PD 1 @@ -823,6 +828,7 @@ struct lpc_usb { vuint32_t inten; vuint32_t intsetstat; vuint32_t introuting; + uint32_t r30; vuint32_t eptoggle; } lpc_usb; @@ -884,18 +890,11 @@ extern struct lpc_usb lpc_usb; #define LPC_USB_EPBUFCFG_BUF_SB(ep) (ep) -#define LPC_USB_INTSTAT_EP0OUT 0 -#define LPC_USB_INTSTAT_EP0IN 1 -#define LPC_USB_INTSTAT_EP1OUT 2 -#define LPC_USB_INTSTAT_EP1IN 3 -#define LPC_USB_INTSTAT_EP2OUT 4 -#define LPC_USB_INTSTAT_EP2IN 5 -#define LPC_USB_INTSTAT_EP3OUT 6 -#define LPC_USB_INTSTAT_EP3IN 7 -#define LPC_USB_INTSTAT_EP4OUT 8 -#define LPC_USB_INTSTAT_EP4IN 9 -#define LPC_USB_INTSTAT_FRAME_INT 30 -#define LPC_USB_INTSTAT_DEV_INT 31 +#define LPC_USB_INT_EPOUT(ep) ((ep) << 1) +#define LPC_USB_INT_EPIN(ep) (((ep) << 1) + 1) + +#define LPC_USB_INT_FRAME 30 +#define LPC_USB_INT_DEV 31 #define LPC_USB_INTIN_EP_INT_EN(ep) (ep) #define LPC_USB_INTIN_FRAME_INT_EN 30 @@ -911,34 +910,34 @@ extern struct lpc_usb lpc_usb; #define LPC_USB_EPTOGGLE_TOGGLE(ep) (ep) -struct lpc_usb_ep { - vuint16_t buffer_offset; - vuint16_t buffer_status_nbytes; -}; - struct lpc_usb_epn { - struct lpc_usb_ep out[2]; - struct lpc_usb_ep in[2]; + vuint32_t out[2]; + vuint32_t in[2]; }; struct lpc_usb_endpoint { - struct lpc_usb_ep ep0_out; - vuint16_t setup_offset; - vuint16_t reserved_06; - struct lpc_usb_ep ep0_in; - vuint16_t reserved_0c; - vuint16_t reserved_0e; + vuint32_t ep0_out; + vuint32_t setup; + vuint32_t ep0_in; + vuint32_t reserved_0c; struct lpc_usb_epn epn[4]; }; -#define LPC_USB_EP_STATUS_ACTIVE 15 -#define LPC_USB_EP_STATUS_DISABLED 14 -#define LPC_USB_EP_STATUS_STALL 13 -#define LPC_USB_EP_STATUS_TOGGLE_RESET 12 -#define LPC_USB_EP_STATUS_RATE_FEEDBACK 11 -#define LPC_USB_EP_STATUS_ENDPOINT_TYPE 10 -#define LPC_USB_EP_STATUS_OFFSET 0 -#define LPC_USB_EP_STATUS_OFFSET_MASK 0x3ff +/* Assigned in registers.ld to point at the base + * of USB ram + */ + +extern uint8_t lpc_usb_sram[]; + +#define LPC_USB_EP_ACTIVE 31 +#define LPC_USB_EP_DISABLED 30 +#define LPC_USB_EP_STALL 29 +#define LPC_USB_EP_TOGGLE_RESET 28 +#define LPC_USB_EP_RATE_FEEDBACK 27 +#define LPC_USB_EP_ENDPOINT_ISO 26 +#define LPC_USB_EP_NBYTES 16 +#define LPC_USB_EP_NBYTES_MASK 0x3ff +#define LPC_USB_EP_OFFSET 0 #define LPC_ISR_PIN_INT0_POS 0 #define LPC_ISR_PIN_INT1_POS 1 @@ -1039,4 +1038,20 @@ lpc_nvic_get_priority(int irq) { return (lpc_nvic.ipr[IRQ_PRIO_REG(irq)] >> IRQ_PRIO_BIT(irq)) & IRQ_PRIO_MASK(0); } +struct arm_scb { + vuint32_t cpuid; + vuint32_t icsr; + uint32_t reserved08; + vuint32_t aircr; + + vuint32_t scr; + vuint32_t ccr; + uint32_t reserved18; + vuint32_t shpr2; + + vuint32_t shpr3; +}; + +extern struct arm_scb arm_scb; + #endif /* _LPC_H_ */ diff --git a/src/lpc/registers.ld b/src/lpc/registers.ld index 51a0612f..0201e55f 100644 --- a/src/lpc/registers.ld +++ b/src/lpc/registers.ld @@ -9,3 +9,5 @@ lpc_usb = 0x40080000; lpc_gpio = 0x50000000; lpc_systick = 0xe000e000; lpc_nvic = 0xe000e100; +arm_scb = 0xe000ed00; +lpc_usb_sram = 0x20004000; diff --git a/src/lpcxpresso/Makefile b/src/lpcxpresso/Makefile index bac222cc..3745f283 100644 --- a/src/lpcxpresso/Makefile +++ b/src/lpcxpresso/Makefile @@ -23,8 +23,10 @@ ALTOS_SRC = \ ao_panic.c \ ao_led_lpc.c \ ao_task.c \ + ao_cmd.c \ ao_timer_lpc.c \ ao_serial_lpc.c \ + ao_usb_lpc.c \ ao_stdio.c PRODUCT=LpcDemo-v0.0 diff --git a/src/lpcxpresso/ao_demo.c b/src/lpcxpresso/ao_demo.c index eae9503e..0c931611 100644 --- a/src/lpcxpresso/ao_demo.c +++ b/src/lpcxpresso/ao_demo.c @@ -15,24 +15,8 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" - -struct ao_task demo_task; - -static void demo(void) { - for (;;) { - ao_delay(100); - ao_led_toggle(AO_LED_RED); - } -} - -static struct ao_task serial_task; - -static void serial(void) { - for (;;) { - printf ("hello, world\n"); - } -} +#include +#include int main(void) @@ -44,12 +28,10 @@ main(void) ao_timer_init(); ao_serial_init(); - + ao_usb_init(); + ao_cmd_init(); ao_task_init(); - ao_add_task(&demo_task, demo, "demo"); - ao_add_task(&serial_task, serial, "serial"); - ao_start_scheduler(); for (;;) { diff --git a/src/lpcxpresso/ao_pins.h b/src/lpcxpresso/ao_pins.h index 7748f73c..c0074ce2 100644 --- a/src/lpcxpresso/ao_pins.h +++ b/src/lpcxpresso/ao_pins.h @@ -34,7 +34,10 @@ #define LEDS_AVAILABLE AO_LED_RED -#define HAS_USB 0 +#define HAS_USB 1 + +#define HAS_USB_CONNECT 1 +#define HAS_USB_VBUS 1 #define PACKET_HAS_SLAVE 0 -- cgit v1.2.3 From ca4f3161258356c06fe1270f7ccdf0d6939e2d34 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 02:52:49 -0700 Subject: altos: Move ao_data.c from stm to core This should be used on every processor Signed-off-by: Keith Packard --- src/core/ao_data.c | 34 ++++++++++++++++++++++++++++++++++ src/stm/ao_data.c | 34 ---------------------------------- 2 files changed, 34 insertions(+), 34 deletions(-) create mode 100644 src/core/ao_data.c delete mode 100644 src/stm/ao_data.c (limited to 'src') diff --git a/src/core/ao_data.c b/src/core/ao_data.c new file mode 100644 index 00000000..38d2f7ff --- /dev/null +++ b/src/core/ao_data.c @@ -0,0 +1,34 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; +volatile __data uint8_t ao_data_head; +volatile __data uint8_t ao_data_present; + +void +ao_data_get(__xdata struct ao_data *packet) +{ +#if HAS_FLIGHT + uint8_t i = ao_data_ring_prev(ao_sample_data); +#else + uint8_t i = ao_data_ring_prev(ao_data_head); +#endif + memcpy(packet, (void *) &ao_data_ring[i], sizeof (struct ao_data)); +} diff --git a/src/stm/ao_data.c b/src/stm/ao_data.c deleted file mode 100644 index 38d2f7ff..00000000 --- a/src/stm/ao_data.c +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include -#include - -volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; -volatile __data uint8_t ao_data_head; -volatile __data uint8_t ao_data_present; - -void -ao_data_get(__xdata struct ao_data *packet) -{ -#if HAS_FLIGHT - uint8_t i = ao_data_ring_prev(ao_sample_data); -#else - uint8_t i = ao_data_ring_prev(ao_data_head); -#endif - memcpy(packet, (void *) &ao_data_ring[i], sizeof (struct ao_data)); -} -- cgit v1.2.3 From e4385d29fc1b233b3ad56d4af68a175e760c1751 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 02:53:32 -0700 Subject: altos: Allow architecture to define the type of port registers LPC11U14 has 32-bit ports, STM32 has 16 bit ports. Signed-off-by: Keith Packard --- src/core/ao.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 71bfb6a1..7f344736 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -43,6 +43,12 @@ #define HAS_TASK 1 #endif +#ifndef AO_PORT_TYPE +#define AO_PORT_TYPE uint8_t +#endif + +typedef AO_PORT_TYPE ao_port_t; + #if HAS_TASK #include #else @@ -68,6 +74,7 @@ #define AO_PANIC_SPI 13 /* SPI communication failure */ #define AO_PANIC_CRASH 14 /* Processor crashed */ #define AO_PANIC_BUFIO 15 /* Mis-using bufio API */ +#define AO_PANIC_EXTI 16 /* Mis-using exti API */ #define AO_PANIC_SELF_TEST_CC1120 0x40 | 1 /* Self test failure */ #define AO_PANIC_SELF_TEST_HMC5883 0x40 | 2 /* Self test failure */ #define AO_PANIC_SELF_TEST_MPU6000 0x40 | 3 /* Self test failure */ -- cgit v1.2.3 From 52063c2679752033135fff928c7686e368d2a825 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 02:54:30 -0700 Subject: altos: ao_data_get is in ao_data.c now, not ao_adc.c Signed-off-by: Keith Packard --- src/core/ao_adc.h | 4 ---- src/core/ao_data.h | 4 ++++ 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/core/ao_adc.h b/src/core/ao_adc.h index 0dd87080..373db1c4 100644 --- a/src/core/ao_adc.h +++ b/src/core/ao_adc.h @@ -28,10 +28,6 @@ ao_adc_poll(void); void ao_adc_sleep(void); -/* Get a copy of the last complete sample set */ -void -ao_data_get(__xdata struct ao_data *packet); - /* Initialize the A/D converter */ void ao_adc_init(void); diff --git a/src/core/ao_data.h b/src/core/ao_data.h index 7e2f85d8..b0f086f8 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -82,6 +82,10 @@ struct ao_data { #define ao_data_ring_next(n) (((n) + 1) & (AO_DATA_RING - 1)) #define ao_data_ring_prev(n) (((n) - 1) & (AO_DATA_RING - 1)) +/* Get a copy of the last complete sample set */ +void +ao_data_get(__xdata struct ao_data *packet); + extern volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; extern volatile __data uint8_t ao_data_head; extern volatile __data uint8_t ao_data_present; -- cgit v1.2.3 From 82afe3a3b737c43dbeaad41ea5af1841357297a6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 02:54:55 -0700 Subject: altos: Check for packet mode before trying to disable it in flight code This is only relevant for telemini Signed-off-by: Keith Packard --- src/core/ao_flight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index 9d9d4c6e..782e2274 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -124,7 +124,7 @@ ao_flight(void) ao_usb_disable(); #endif -#if !HAS_ACCEL +#if !HAS_ACCEL && PACKET_HAS_SLAVE /* Disable packet mode in pad state on TeleMini */ ao_packet_slave_stop(); #endif -- cgit v1.2.3 From 28890aa5893898cd0bb0ac033e491eb307a84ca5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:02:01 -0700 Subject: altos: Use ao_data_pres macro in ao_log_tiny Now it works on easymini too Signed-off-by: Keith Packard --- src/core/ao_log_tiny.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_log_tiny.c b/src/core/ao_log_tiny.c index 492658ea..67767dc9 100644 --- a/src/core/ao_log_tiny.c +++ b/src/core/ao_log_tiny.c @@ -105,7 +105,7 @@ ao_log(void) */ ao_sleep(DATA_TO_XDATA(&ao_sample_data)); while (ao_log_data != ao_sample_data) { - sum += ao_data_ring[ao_log_data].adc.pres; + sum += ao_data_pres(&ao_data_ring[ao_log_data]); count++; ao_log_data = ao_data_ring_next(ao_log_data); } -- cgit v1.2.3 From d9b42470e8889b44bb08858a610285410a200ab9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:02:38 -0700 Subject: altos: Use ao_port_t in m25 driver This uses ao_port_t for all of the chip select masks Signed-off-by: Keith Packard --- src/drivers/ao_m25.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_m25.c b/src/drivers/ao_m25.c index 390637d7..9b768012 100644 --- a/src/drivers/ao_m25.c +++ b/src/drivers/ao_m25.c @@ -82,7 +82,7 @@ __pdata uint16_t ao_storage_unit; #if M25_MAX_CHIPS > 1 static uint8_t ao_m25_size[M25_MAX_CHIPS]; /* number of sectors in each chip */ -static uint8_t ao_m25_pin[M25_MAX_CHIPS]; /* chip select pin for each chip */ +static ao_port_t ao_m25_pin[M25_MAX_CHIPS]; /* chip select pin for each chip */ static uint8_t ao_m25_numchips; /* number of chips detected */ #endif static uint8_t ao_m25_total; /* total sectors available */ @@ -112,7 +112,7 @@ static __xdata uint8_t ao_m25_instruction[4]; * Block until the specified chip is done writing */ static void -ao_m25_wait_wip(uint8_t cs) +ao_m25_wait_wip(ao_port_t cs) { if (ao_m25_wip & cs) { M25_SELECT(cs); @@ -132,7 +132,7 @@ ao_m25_wait_wip(uint8_t cs) * so that future operations will block until the WIP bit goes off */ static void -ao_m25_write_enable(uint8_t cs) +ao_m25_write_enable(ao_port_t cs) { M25_SELECT(cs); ao_m25_instruction[0] = M25_WREN; @@ -146,7 +146,7 @@ ao_m25_write_enable(uint8_t cs) * Returns the number of 64kB sectors */ static uint8_t -ao_m25_read_capacity(uint8_t cs) +ao_m25_read_capacity(ao_port_t cs) { uint8_t capacity; M25_SELECT(cs); @@ -166,12 +166,13 @@ ao_m25_read_capacity(uint8_t cs) return 1 << (capacity - 0x10); } -static uint8_t +static ao_port_t ao_m25_set_address(uint32_t pos) { - uint8_t chip; + ao_port_t mask; #if M25_MAX_CHIPS > 1 uint8_t size; + uint8_t chip; for (chip = 0; chip < ao_m25_numchips; chip++) { size = ao_m25_size[chip]; @@ -182,16 +183,16 @@ ao_m25_set_address(uint32_t pos) if (chip == ao_m25_numchips) return 0xff; - chip = ao_m25_pin[chip]; + mask = ao_m25_pin[chip]; #else - chip = AO_M25_SPI_CS_MASK; + mask = AO_M25_SPI_CS_MASK; #endif - ao_m25_wait_wip(chip); + ao_m25_wait_wip(mask); ao_m25_instruction[1] = pos >> 16; ao_m25_instruction[2] = pos >> 8; ao_m25_instruction[3] = pos; - return chip; + return mask; } /* @@ -239,7 +240,7 @@ ao_m25_scan(void) uint8_t ao_storage_erase(uint32_t pos) __reentrant { - uint8_t cs; + ao_port_t cs; if (pos >= ao_storage_total || pos + ao_storage_block > ao_storage_total) return 0; @@ -268,7 +269,7 @@ ao_storage_erase(uint32_t pos) __reentrant uint8_t ao_storage_device_write(uint32_t pos, __xdata void *d, uint16_t len) __reentrant { - uint8_t cs; + ao_port_t cs; if (pos >= ao_storage_total || pos + len > ao_storage_total) return 0; @@ -295,7 +296,7 @@ ao_storage_device_write(uint32_t pos, __xdata void *d, uint16_t len) __reentrant uint8_t ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant { - uint8_t cs; + ao_port_t cs; if (pos >= ao_storage_total || pos + len > ao_storage_total) return 0; @@ -332,7 +333,7 @@ void ao_storage_device_info(void) __reentrant { #if M25_DEBUG - uint8_t cs; + ao_port_t cs; #endif #if M25_MAX_CHIPS > 1 uint8_t chip; -- cgit v1.2.3 From 935a7ff38010ec4ad19f315f8a2a1557c01ae554 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:13:17 -0700 Subject: altos: Add LPC spi driver Signed-off-by: Keith Packard --- src/lpc/ao_arch.h | 15 ++++ src/lpc/ao_arch_funcs.h | 51 +++++++++++++ src/lpc/ao_spi_lpc.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 260 insertions(+) create mode 100644 src/lpc/ao_spi_lpc.c (limited to 'src') diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index 99c646f9..d9f72e1a 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -28,6 +28,8 @@ #define AO_LED_TYPE uint16_t +#define AO_PORT_TYPE uint32_t + #ifndef AO_TICK_TYPE #define AO_TICK_TYPE uint16_t #define AO_TICK_SIGNED int16_t @@ -123,4 +125,17 @@ ao_adc_init(void); void ao_serial_init(void); +/* SPI definitions */ + +#define AO_SPI_SPEED_12MHz 2 +#define AO_SPI_SPEED_6MHz 4 +#define AO_SPI_SPEED_4MHz 6 +#define AO_SPI_SPEED_2MHz 12 +#define AO_SPI_SPEED_1MHz 24 +#define AO_SPI_SPEED_500kHz 48 +#define AO_SPI_SPEED_250kHz 96 +#define AO_SPI_SPEED_125kHz 192 + +#define AO_SPI_SPEED_FAST AO_SPI_SPEED_12MHz + #endif /* _AO_ARCH_H_ */ diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index 96ae0366..94d876f6 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -144,4 +144,55 @@ static inline void ao_arch_restore_stack(void) { ao_arch_release_interrupts(); \ } while (0) +/* + * SPI + */ + +#define ao_spi_set_cs(port,mask) (lpc_gpio.clr[port] = (mask)) +#define ao_spi_clr_cs(port,mask) (lpc_gpio.set[port] = (mask)) + +#define ao_spi_get_mask(port,mask,bus,speed) do { \ + ao_spi_get(bus, speed); \ + ao_spi_set_cs(port, mask); \ + } while (0) + +#define ao_spi_put_mask(reg,mask,bus) do { \ + ao_spi_clr_cs(reg,mask); \ + ao_spi_put(bus); \ + } while (0) + +#define ao_spi_get_bit(reg,bit,pin,bus,speed) ao_spi_get_mask(reg,(1< + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include + +static uint8_t ao_spi_mutex[LPC_NUM_SPI]; + +static struct lpc_ssp * const ao_lpc_ssp[LPC_NUM_SPI] = { &lpc_ssp0, &lpc_ssp1 }; + +static uint8_t spi_dev_null; + +#define spi_loop(len, put, get) do { \ + while (len--) { \ + /* Wait for space in the fifo */ \ + while ((lpc_ssp->sr & (1 << LPC_SSP_SR_TNF)) == 0) \ + ; \ + /* send a byte */ \ + lpc_ssp->dr = put; \ + \ + /* recv a byte */ \ + get lpc_ssp->dr; \ + } \ + \ + /* Wait for the fifo to drain */ \ + while ((lpc_ssp->sr & (1 << LPC_SSP_SR_BSY))) \ + ; \ + } while (0); + +void +ao_spi_send(void *block, uint16_t len, uint8_t id) +{ + uint8_t *b = block; + struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; + + spi_loop(len, *b++, (void)); +} + +void +ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t id) +{ + struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; + + spi_loop(len, value, (void)); +} + +void +ao_spi_recv(void *block, uint16_t len, uint8_t id) +{ + uint8_t *b = block; + struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; + + spi_loop(len, 0xff, *b++ =); +} + +void +ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t id) +{ + uint8_t *o = out; + uint8_t *i = in; + struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; + + spi_loop(len, *o++, *i++ =); +} + +void +ao_spi_get(uint8_t id, uint32_t speed) +{ + struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; + + ao_mutex_get(&ao_spi_mutex[id]); + + /* Set the clock prescale */ + lpc_ssp->cpsr = speed; + + /* Enable the device */ + lpc_ssp->cr1 = ((0 << LPC_SSP_CR1_LBM) | + (1 << LPC_SSP_CR1_SSE) | + (LPC_SSP_CR1_MS_MASTER << LPC_SSP_CR1_MS) | + (0 << LPC_SSP_CR1_SOD)); +} + +void +ao_spi_put(uint8_t id) +{ + struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; + + /* Disable the device */ + lpc_ssp->cr1 = ((0 << LPC_SSP_CR1_LBM) | + (0 << LPC_SSP_CR1_SSE) | + (LPC_SSP_CR1_MS_MASTER << LPC_SSP_CR1_MS) | + (0 << LPC_SSP_CR1_SOD)); + ao_mutex_put(&ao_spi_mutex[id]); +} + +static void +ao_spi_channel_init(uint8_t id) +{ + struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; + uint8_t d; + + lpc_ssp->cr0 = ((LPC_SSP_CR0_DSS_8 << LPC_SSP_CR0_DSS) | + (LPC_SSP_CR0_FRF_SPI << LPC_SSP_CR0_FRF) | + (0 << LPC_SSP_CR0_CPOL) | + (0 << LPC_SSP_CR0_CPHA) | + (0 << LPC_SSP_CR0_SCR)); + /* Drain the receive fifo */ + for (d = 0; d < LPC_SSP_FIFOSIZE; d++) + (void) lpc_ssp->dr; +} + +void +ao_spi_init(void) +{ +#if HAS_SPI_0 + /* Configure pins */ + lpc_ioconf.pio0_6 = ao_lpc_alternate(LPC_IOCONF_FUNC_SCK0); + lpc_ioconf.pio0_8 = ao_lpc_alternate(LPC_IOCONF_FUNC_MISO0); + lpc_ioconf.pio0_9 = ao_lpc_alternate(LPC_IOCONF_FUNC_MOSI0); + + /* Enable the device */ + lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_SSP0); + + /* Turn on the clock */ + lpc_scb.ssp0clkdiv = 1; + + /* Reset the device */ + lpc_scb.presetctrl &= ~(1 << LPC_SCB_PRESETCTRL_SSP0_RST_N); + lpc_scb.presetctrl |= (1 << LPC_SCB_PRESETCTRL_SSP0_RST_N); + ao_spi_channel_init(0); +#endif + +#if HAS_SPI_1 + +#if SPI_SCK1_P1_15 + lpc_ioconf.pio1_15 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO1_15_SCK1); +#define HAS_SCK1 +#endif +#if SPI_SCK1_P1_20 + lpc_ioconf.pio1_20 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO1_20_SCK1); +#define HAS_SCK1 +#endif +#ifndef HAS_SCK1 +#error "No pin specified for SCK1" +#endif + +#if SPI_MISO1_P0_22 + lpc_ioconf.pio0_22 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO0_22_MISO1); +#define HAS_MISO1 +#endif +#if SPI_MISO1_P1_21 + lpc_ioconf.pio1_21 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO1_21_MISO1); +#define HAS_MISO1 +#endif +#ifndef HAS_MISO1 +#error "No pin specified for MISO1" +#endif + +#if SPI_MOSI1_P0_21 + lpc_ioconf.pio1_21 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO0_21_MOSI1); +#define HAS_MOSI1 +#endif +#if SPI_MOSI1_P1_22 + lpc_ioconf.pio1_22 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO1_22_MOSI1); +#define HAS_MOSI1 +#endif +#ifndef HAS_MOSI1 +#error "No pin specified for MOSI1" +#endif + + /* Enable the device */ + lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_SSP1); + + /* Turn on the clock */ + lpc_scb.ssp1clkdiv = 1; + + /* De-assert reset */ + lpc_scb.presetctrl |= (1 << LPC_SCB_PRESETCTRL_SSP1_RST_N); + ao_spi_channel_init(1); +#endif /* HAS_SPI_1 */ +} -- cgit v1.2.3 From 15ca452b60271e3a0f7327216df04eef5b985240 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:14:16 -0700 Subject: altos: LPC interrupt priorities are just 0-3 Signed-off-by: Keith Packard --- src/lpc/ao_arch.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index d9f72e1a..fb68f6be 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -111,10 +111,10 @@ extern const uint32_t ao_radio_cal; #define AO_TIM91011_CLK (2 * AO_PCLK2) #endif -#define AO_STM_NVIC_HIGH_PRIORITY 4 -#define AO_STM_NVIC_CLOCK_PRIORITY 6 -#define AO_STM_NVIC_MED_PRIORITY 8 -#define AO_STM_NVIC_LOW_PRIORITY 10 +#define AO_LPC_NVIC_HIGH_PRIORITY 0 +#define AO_LPC_NVIC_CLOCK_PRIORITY 1 +#define AO_LPC_NVIC_MED_PRIORITY 2 +#define AO_LPC_NVIC_LOW_PRIORITY 3 void ao_adc_init(void); -- cgit v1.2.3 From 08887678f900adae81dcb1a7f5353d98d127aafd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:14:57 -0700 Subject: altos/lpc: Fix ao_enable_input, add ao_enable_analog Signed-off-by: Keith Packard --- src/lpc/ao_arch_funcs.h | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index 94d876f6..bc4c47ee 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -36,16 +36,29 @@ } while (0) #define ao_enable_input(port,bit,mode) do { \ + vuint32_t *_ioconf = &lpc_ioconf.pio0_0 + ((port)*24+(bit)); \ + vuint32_t _mode; \ ao_enable_port(port); \ lpc_gpio.dir[port] &= ~(1 << bit); \ if (mode == AO_EXTI_MODE_PULL_UP) \ - stm_pupdr_set(port, bit, STM_PUPDR_PULL_UP); \ + _mode = LPC_IOCONF_MODE_PULL_UP << LPC_IOCONF_MODE; \ else if (mode == AO_EXTI_MODE_PULL_DOWN) \ - stm_pupdr_set(port, bit, STM_PUPDR_PULL_DOWN); \ + _mode = LPC_IOCONF_MODE_PULL_UP << LPC_IOCONF_MODE; \ else \ - stm_pupdr_set(port, bit, STM_PUPDR_NONE); \ + _mode = LPC_IOCONF_MODE_INACTIVE << LPC_IOCONF_MODE; \ + *_ioconf = ((*_ioconf & ~(LPC_IOCONF_MODE_MASK << LPC_IOCONF_MODE)) | \ + _mode | \ + (1 << LPC_IOCONF_ADMODE)); \ } while (0) +#define ao_enable_analog(port,bit) do { \ + vuint32_t *_ioconf = &lpc_ioconf.pio0_0 + ((port)*24+(bit)); \ + ao_enable_port(port); \ + lpc_gpio.dir[port] &= ~(1 << bit); \ + *_ioconf = *_ioconf & ~((1 << LPC_IOCONF_ADMODE) | \ + (LPC_IOCONF_MODE_MASK << LPC_IOCONF_MODE)); \ + } while (0) + #define ARM_PUSH32(stack, val) (*(--(stack)) = (val)) static inline uint32_t -- cgit v1.2.3 From 2b0b7bf1462341718e582223a880f2dfcd79e2ad Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:15:58 -0700 Subject: altos/lpc: Clean up broken IOCONF defines Missing comment closes Signed-off-by: Keith Packard --- src/lpc/lpc.h | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index 4141f356..db825e93 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -137,7 +137,7 @@ extern struct lpc_ioconf lpc_ioconf; #define LPC_IOCONF_FUNC_PIO0_7 0 #define LPC_IOCONF_FUNC_CTS 1 -/* PIO0_8 +/* PIO0_8 */ #define LPC_IOCONF_FUNC_PIO0_8 0 #define LPC_IOCONF_FUNC_MISO0 1 #define LPC_IOCONF_FUNC_CT16B0_MAT0 2 @@ -211,13 +211,13 @@ extern struct lpc_ioconf lpc_ioconf; /* PIO0_21 */ #define LPC_IOCONF_FUNC_PIO0_21 0 #define LPC_IOCONF_FUNC_CT16B1_MAT0 1 -#define LPC_IOCONF_FUNC_MOSI1 2 +#define LPC_IOCONF_FUNC_PIO0_21_MOSI1 2 /* PIO0_22 */ #define LPC_IOCONF_FUNC_PIO0_22 0 #define LPC_IOCONF_FUNC_AD6 1 #define LPC_IOCONF_FUNC_CT16B1_MAT1 2 -#define LPC_IOCONF_FUNC_MISO1 3 +#define LPC_IOCONF_FUNC_PIO0_22_MISO1 3 /* PIO0_23 */ #define LPC_IOCONF_FUNC_PIO0_23 0 @@ -284,7 +284,7 @@ extern struct lpc_ioconf lpc_ioconf; #define LPC_IOCONF_FUNC_PIO1_15 0 #define LPC_IOCONF_FUNC_DCD 1 #define LPC_IOCONF_FUNC_PIO1_15_CT16B0_MAT2 2 -#define LPC_IOCONF_FUNC_SCK1 3 +#define LPC_IOCONF_FUNC_PIO1_15_SCK1 3 /* PIO1_16 */ #define LPC_IOCONF_FUNC_PIO1_16 0 @@ -319,7 +319,7 @@ extern struct lpc_ioconf lpc_ioconf; /* PIO1_22 */ #define LPC_IOCONF_FUNC_PIO1_22 0 #define LPC_IOCONF_FUNC_RI 1 -#define LPC_IOCONF_FUNC_MOSI1 2 +#define LPC_IOCONF_FUNC_PIO1_22_MOSI1 2 /* PIO1_23 */ #define LPC_IOCONF_FUNC_PIO1_23 0 @@ -359,6 +359,13 @@ extern struct lpc_ioconf lpc_ioconf; #define LPC_IOCONF_FUNC_MASK 0x7 +#define ao_lpc_alternate(func) (((func) << LPC_IOCONF_FUNC) | \ + (LPC_IOCONF_MODE_INACTIVE << LPC_IOCONF_MODE) | \ + (0 << LPC_IOCONF_HYS) | \ + (0 << LPC_IOCONF_INV) | \ + (0 << LPC_IOCONF_OD) | \ + 0x80) + #define LPC_IOCONF_MODE 3 #define LPC_IOCONF_MODE_INACTIVE 0 #define LPC_IOCONF_MODE_PULL_DOWN 1 @@ -369,6 +376,8 @@ extern struct lpc_ioconf lpc_ioconf; #define LPC_IOCONF_HYS 5 #define LPC_IOCONF_INV 6 +#define LPC_IOCONF_ADMODE 7 +#define LPC_IOCONF_FILTR 8 #define LPC_IOCONF_OD 10 struct lpc_scb { -- cgit v1.2.3 From ed25a46571d988ccf37ae915dff97b5f00bcf9cf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:16:41 -0700 Subject: altos/lpc: add gpio int, spi, adc and ct32b defines to lpc.h Lots more devices Signed-off-by: Keith Packard --- src/lpc/lpc.h | 169 ++++++++++++++++++++++++++++++++++++++++++++++++--- src/lpc/registers.ld | 7 ++- 2 files changed, 165 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index db825e93..2493a1ff 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -454,17 +454,9 @@ struct lpc_scb { vuint32_t irqlatency; /* 0x170 */ vuint32_t nmisrc; - vuint32_t pintsel0; - vuint32_t pintsel1; + vuint32_t pintsel[8]; - vuint32_t pintsel2; /* 0x180 */ - vuint32_t pintsel3; - vuint32_t pintsel4; - vuint32_t pintsel5; - - vuint32_t pintsel6; /* 0x190 */ - vuint32_t pintsel7; - vuint32_t usbclkctrl; + vuint32_t usbclkctrl; /* 0x198 */ vuint32_t usbclkst; uint32_t r1a0[6*4]; /* 0x1a0 */ @@ -637,6 +629,18 @@ struct lpc_flash { extern struct lpc_flash lpc_flash; struct lpc_gpio_pin { + vuint32_t isel; /* 0x00 */ + vuint32_t ienr; + vuint32_t sienr; + vuint32_t cienr; + + vuint32_t ienf; /* 0x10 */ + vuint32_t sienf; + vuint32_t cienf; + vuint32_t rise; + + vuint32_t fall; /* 0x20 */ + vuint32_t ist; }; extern struct lpc_gpio_pin lpc_gpio_pin; @@ -1063,4 +1067,149 @@ struct arm_scb { extern struct arm_scb arm_scb; +struct lpc_ssp { + vuint32_t cr0; /* 0x00 */ + vuint32_t cr1; + vuint32_t dr; + vuint32_t sr; + + vuint32_t cpsr; /* 0x10 */ + vuint32_t imsc; + vuint32_t ris; + vuint32_t mis; + + vuint32_t icr; /* 0x20 */ +}; + +extern struct lpc_ssp lpc_ssp0, lpc_ssp1; + +#define LPC_NUM_SPI 2 + +#define LPC_SSP_FIFOSIZE 8 + +#define LPC_SSP_CR0_DSS 0 +#define LPC_SSP_CR0_DSS_4 0x3 +#define LPC_SSP_CR0_DSS_5 0x4 +#define LPC_SSP_CR0_DSS_6 0x5 +#define LPC_SSP_CR0_DSS_7 0x6 +#define LPC_SSP_CR0_DSS_8 0x7 +#define LPC_SSP_CR0_DSS_9 0x8 +#define LPC_SSP_CR0_DSS_10 0x9 +#define LPC_SSP_CR0_DSS_11 0xa +#define LPC_SSP_CR0_DSS_12 0xb +#define LPC_SSP_CR0_DSS_13 0xc +#define LPC_SSP_CR0_DSS_14 0xd +#define LPC_SSP_CR0_DSS_15 0xe +#define LPC_SSP_CR0_DSS_16 0xf +#define LPC_SSP_CR0_FRF 4 +#define LPC_SSP_CR0_FRF_SPI 0 +#define LPC_SSP_CR0_FRF_TI 1 +#define LPC_SSP_CR0_FRF_MICROWIRE 2 +#define LPC_SSP_CR0_CPOL 6 +#define LPC_SSP_CR0_CPOL_LOW 0 +#define LPC_SSP_CR0_CPOL_HIGH 1 +#define LPC_SSP_CR0_CPHA 7 +#define LPC_SSP_CR0_CPHA_FIRST 0 +#define LPC_SSP_CR0_CPHA_SECOND 1 +#define LPC_SSP_CR0_SCR 8 + +#define LPC_SSP_CR1_LBM 0 +#define LPC_SSP_CR1_SSE 1 +#define LPC_SSP_CR1_MS 2 +#define LPC_SSP_CR1_MS_MASTER 0 +#define LPC_SSP_CR1_MS_SLAVE 1 +#define LPC_SSP_CR1_SOD 3 + +#define LPC_SSP_SR_TFE 0 +#define LPC_SSP_SR_TNF 1 +#define LPC_SSP_SR_RNE 2 +#define LPC_SSP_SR_RFF 3 +#define LPC_SSP_SR_BSY 4 + +#define LPC_SSP_IMSC_RORIM 0 +#define LPC_SSP_IMSC_RTIM 1 +#define LPC_SSP_IMSC_RXIM 2 +#define LPC_SSP_IMSC_TXIM 3 + +#define LPC_SSP_RIS_RORRIS 0 +#define LPC_SSP_RIS_RTRIS 1 +#define LPC_SSP_RIS_RXRIS 2 +#define LPC_SSP_RIS_TXRIS 3 + +#define LPC_SSP_MIS_RORMIS 0 +#define LPC_SSP_MIS_RTMIS 1 +#define LPC_SSP_MIS_RXMIS 2 +#define LPC_SSP_MIS_TXMIS 3 + +#define LPC_SSP_ICR_RORIC 0 +#define LPC_SSP_ICR_RTIC 1 + +struct lpc_adc { + vuint32_t cr; /* 0x00 */ + vuint32_t gdr; + uint32_t r08; + vuint32_t inten; + + vuint32_t dr[8]; /* 0x10 */ + + vuint32_t stat; /* 0x30 */ +}; + +extern struct lpc_adc lpc_adc; + +#define LPC_ADC_CR_SEL 0 +#define LPC_ADC_CR_CLKDIV 8 +#define LPC_ADC_CR_BURST 16 +#define LPC_ADC_CR_CLKS 17 +#define LPC_ADC_CR_CLKS_11 0 +#define LPC_ADC_CR_CLKS_10 1 +#define LPC_ADC_CR_CLKS_9 2 +#define LPC_ADC_CR_CLKS_8 3 +#define LPC_ADC_CR_CLKS_7 4 +#define LPC_ADC_CR_CLKS_6 5 +#define LPC_ADC_CR_CLKS_5 6 +#define LPC_ADC_CR_CLKS_4 7 + +#define LPC_ADC_INTEN_ADINTEN 0 +#define LPC_ADC_INTEN_ADGINTEN 8 + +#define LPC_ADC_STAT_DONE 0 +#define LPC_ADC_STAT_OVERRUN 8 +#define LPC_ADC_STAT_ADINT 16 + +struct lpc_ct32b { + vuint32_t ir; /* 0x00 */ + vuint32_t tcr; + vuint32_t tc; + vuint32_t pr; + + vuint32_t pc; /* 0x10 */ + vuint32_t mcr; + vuint32_t mr[4]; /* 0x18 */ + vuint32_t ccr; /* 0x28 */ + vuint32_t cr0; + + vuint32_t cr1_0; /* 0x30 (only for ct32b0 */ + vuint32_t cr1_1; /* 0x34 (only for ct32b1 */ + uint32_t r38; + vuint32_t emr; + + uint32_t r40[12]; + + vuint32_t ctcr; /* 0x70 */ + vuint32_t pwmc; +}; + +extern struct lpc_ct32b lpc_ct32b0, lpc_ct32b1; + +#define LPC_CT32B_TCR_CEN 0 +#define LPC_CT32B_TCR_CRST 1 + +#define LPC_CT32B_MCR_MR0R 1 + +#define LPC_CT32B_PWMC_PWMEN0 0 +#define LPC_CT32B_PWMC_PWMEN1 1 +#define LPC_CT32B_PWMC_PWMEN2 2 +#define LPC_CT32B_PWMC_PWMEN3 3 + #endif /* _LPC_H_ */ diff --git a/src/lpc/registers.ld b/src/lpc/registers.ld index 0201e55f..51866e07 100644 --- a/src/lpc/registers.ld +++ b/src/lpc/registers.ld @@ -1,8 +1,14 @@ +lpc_usb_sram = 0x20004000; lpc_usart = 0x40008000; +lpc_ct32b0 = 0x40014000; +lpc_ct32b1 = 0x40018000; +lpc_adc = 0x4001c000; lpc_flash = 0x4003c000; +lpc_ssp0 = 0x40040000; lpc_ioconf = 0x40044000; lpc_scb = 0x40048000; lpc_gpio_pin = 0x4004c000; +lpc_ssp1 = 0x40058000; lpc_gpio_group0 = 0x4005c000; lpc_gpio_group1 = 0x40060000; lpc_usb = 0x40080000; @@ -10,4 +16,3 @@ lpc_gpio = 0x50000000; lpc_systick = 0xe000e000; lpc_nvic = 0xe000e100; arm_scb = 0xe000ed00; -lpc_usb_sram = 0x20004000; -- cgit v1.2.3 From 166977c65bddb50d600a3c1e1f278c425b673697 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:18:19 -0700 Subject: altos/lpc: Add ADC driver Uses burst mode to get the whole set of values in one interrupt Signed-off-by: Keith Packard --- src/lpc/ao_adc_lpc.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 229 insertions(+) create mode 100644 src/lpc/ao_adc_lpc.c (limited to 'src') diff --git a/src/lpc/ao_adc_lpc.c b/src/lpc/ao_adc_lpc.c new file mode 100644 index 00000000..70e8b2d6 --- /dev/null +++ b/src/lpc/ao_adc_lpc.c @@ -0,0 +1,229 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +#ifndef AO_ADC_0 +#define AO_ADC_0 0 +#endif + +#ifndef AO_ADC_1 +#define AO_ADC_1 0 +#endif + +#ifndef AO_ADC_2 +#define AO_ADC_2 0 +#endif + +#ifndef AO_ADC_3 +#define AO_ADC_3 0 +#endif + +#ifndef AO_ADC_4 +#define AO_ADC_4 0 +#endif + +#ifndef AO_ADC_5 +#define AO_ADC_5 0 +#endif + +#ifndef AO_ADC_6 +#define AO_ADC_6 0 +#endif + +#ifndef AO_ADC_7 +#define AO_ADC_7 0 +#endif + +#if AO_ADC_7 +# define AO_ADC_LAST 7 +#else +# if AO_ADC_6 +# define AO_ADC_LAST 6 +# else +# if AO_ADC_5 +# define AO_ADC_LAST 5 +# else +# if AO_ADC_4 +# define AO_ADC_LAST 4 +# else +# if AO_ADC_3 +# define AO_ADC_LAST 3 +# else +# if AO_ADC_2 +# define AO_ADC_LAST 2 +# else +# if AO_ADC_1 +# define AO_ADC_LAST 1 +# else +# if AO_ADC_0 +# define AO_ADC_LAST 0 +# endif +# endif +# endif +# endif +# endif +# endif +# endif +#endif + +static uint8_t ao_adc_ready; + +void lpc_adc_isr(void) +{ + uint16_t *out = (uint16_t *) &ao_data_ring[ao_data_head].adc; + vuint32_t *in = &lpc_adc.dr[0]; + + /* Store converted values in packet */ + +#if AO_ADC_0 + *out++ = ((uint16_t) *in++) >> 1; +#endif +#if AO_ADC_1 + *out++ = ((uint16_t) *in++) >> 1; +#endif +#if AO_ADC_2 + *out++ = ((uint16_t) *in++) >> 1; +#endif +#if AO_ADC_3 + *out++ = ((uint16_t) *in++) >> 1; +#endif +#if AO_ADC_4 + *out++ = ((uint16_t) *in++) >> 1; +#endif +#if AO_ADC_5 + *out++ = ((uint16_t) *in++) >> 1; +#endif +#if AO_ADC_6 + *out++ = ((uint16_t) *in++) >> 1; +#endif +#if AO_ADC_7 + *out++ = ((uint16_t) *in++) >> 1; +#endif + + AO_DATA_PRESENT(AO_DATA_ADC); + if (ao_data_present == AO_DATA_ALL) { +#if HAS_MS5607 + ao_data_ring[ao_data_head].ms5607_raw = ao_ms5607_current; +#endif +#if HAS_MMA655X + ao_data_ring[ao_data_head].mma655x = ao_mma655x_current; +#endif +#if HAS_HMC5883 + ao_data_ring[ao_data_head].hmc5883 = ao_hmc5883_current; +#endif +#if HAS_MPU6000 + ao_data_ring[ao_data_head].mpu6000 = ao_mpu6000_current; +#endif + ao_data_ring[ao_data_head].tick = ao_tick_count; + ao_data_head = ao_data_ring_next(ao_data_head); + ao_wakeup((void *) &ao_data_head); + } + ao_adc_ready = 1; +} + +#define AO_ADC_MASK ((AO_ADC_0 << 0) | \ + (AO_ADC_1 << 1) | \ + (AO_ADC_2 << 2) | \ + (AO_ADC_3 << 3) | \ + (AO_ADC_4 << 4) | \ + (AO_ADC_5 << 5) | \ + (AO_ADC_6 << 6) | \ + (AO_ADC_7 << 7)) + +#define AO_ADC_CLKDIV (AO_LPC_CLKOUT / 4500000) + +/* + * Start the ADC sequence using the DMA engine + */ +void +ao_adc_poll(void) +{ + if (!ao_adc_ready) + return; + ao_adc_ready = 0; + + lpc_adc.cr = ((AO_ADC_MASK << LPC_ADC_CR_SEL) | + (AO_ADC_CLKDIV << LPC_ADC_CR_CLKDIV) | + (1 << LPC_ADC_CR_BURST) | + (LPC_ADC_CR_CLKS_11 << LPC_ADC_CR_CLKS)); +} + +static void +ao_adc_dump(void) __reentrant +{ + struct ao_data packet; + int16_t *d; + uint8_t i; + + ao_data_get(&packet); +#ifdef AO_ADC_DUMP + AO_ADC_DUMP(&packet); +#else + printf("tick: %5u", packet.tick); + d = (int16_t *) (&packet.adc); + for (i = 0; i < AO_NUM_ADC; i++) + printf (" %2d: %5d", i, d[i]); + printf("\n"); +#endif +} + +__code struct ao_cmds ao_adc_cmds[] = { + { ao_adc_dump, "a\0Display current ADC values" }, + { 0, NULL }, +}; + +void +ao_adc_init(void) +{ + lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_ADC); + lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_ADC_PD); + + /* Enable interrupt when last channel is complete */ + lpc_adc.inten = (1 << AO_ADC_LAST); + + lpc_nvic_set_enable(LPC_ISR_ADC_POS); + lpc_nvic_set_priority(LPC_ISR_ADC_POS, AO_LPC_NVIC_CLOCK_PRIORITY); +#if AO_ADC_0 + ao_enable_analog(0, 11); +#endif +#if AO_ADC_1 + ao_enable_analog(0, 12); +#endif +#if AO_ADC_2 + ao_enable_analog(0, 13); +#endif +#if AO_ADC_3 + ao_enable_analog(0, 14); +#endif +#if AO_ADC_4 + ao_enable_analog(0, 14); +#endif +#if AO_ADC_5 + ao_enable_analog(0, 14); +#endif +#if AO_ADC_6 + ao_enable_analog(0, 14); +#endif +#if AO_ADC_7 + ao_enable_analog(0, 14); +#endif + ao_cmd_register(&ao_adc_cmds[0]); + + ao_adc_ready = 1; +} -- cgit v1.2.3 From c0d0147251bfcebd753196b74c22c00c3116fd22 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:18:55 -0700 Subject: altos/lpc: Add beep driver Hardwired to our current beeper pin Signed-off-by: Keith Packard --- src/lpc/ao_beep_lpc.c | 83 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/lpc/ao_beep_lpc.c (limited to 'src') diff --git a/src/lpc/ao_beep_lpc.c b/src/lpc/ao_beep_lpc.c new file mode 100644 index 00000000..281f981f --- /dev/null +++ b/src/lpc/ao_beep_lpc.c @@ -0,0 +1,83 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +void +ao_beep(uint8_t beep) +{ + if (beep == 0) { + lpc_ct32b1.tcr = ((0 << LPC_CT32B_TCR_CEN) | + (1 << LPC_CT32B_TCR_CRST)); + lpc_scb.sysahbclkctrl &= ~(1 << LPC_SCB_SYSAHBCLKCTRL_CT32B1); + } else { + lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_CT32B1); + + /* Set prescaler to match cc1111 clocks + */ + lpc_ct32b1.pc = AO_LPC_CLKOUT / 750000 - 1; + + /* Write the desired data in the match registers */ + + /* Reset after two time units */ + lpc_ct32b1.mr[0] = beep << 1; + + /* Flip output after one time unit */ + lpc_ct32b1.mr[1] = beep; + + /* Reset on match 0 */ + lpc_ct32b1.mcr = (1 << LPC_CT32B_MCR_MR0R); + + /* PWM on match 1 */ + lpc_ct32b1.pwmc = (1 << LPC_CT32B_PWMC_PWMEN1); + + /* timer mode */ + lpc_ct32b1.ctcr = 0; + + /* And turn the timer on */ + lpc_ct32b1.tcr = ((1 << LPC_CT32B_TCR_CEN) | + (1 << LPC_CT32B_TCR_CRST)); + } +} + +void +ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant +{ + ao_beep(beep); + ao_delay(ticks); + ao_beep(0); +} + +void +ao_beep_init(void) +{ + /* Our beeper is on c32b1_mat1 + * which is on pin pio0_14 + */ + + lpc_ioconf.pio0_14 = ((LPC_IOCONF_FUNC_PIO0_14_CT32B1_MAT1 << LPC_IOCONF_FUNC) | + (LPC_IOCONF_MODE_INACTIVE << LPC_IOCONF_MODE) | + (0 << LPC_IOCONF_HYS) | + (0 << LPC_IOCONF_INV) | + (0 << LPC_IOCONF_OD)); + + lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_CT32B1); + + /* Disable the counter and reset the value */ + lpc_ct32b1.tcr = ((0 << LPC_CT32B_TCR_CEN) | + (1 << LPC_CT32B_TCR_CRST)); +} -- cgit v1.2.3 From f5218e2544dcb659aec6c3adee50d61cab1bba3a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:19:41 -0700 Subject: altos/lpc: Add pin interrupt driver Signed-off-by: Keith Packard --- src/lpc/ao_exti.h | 47 ++++++++++++++++ src/lpc/ao_exti_lpc.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) create mode 100644 src/lpc/ao_exti.h create mode 100644 src/lpc/ao_exti_lpc.c (limited to 'src') diff --git a/src/lpc/ao_exti.h b/src/lpc/ao_exti.h new file mode 100644 index 00000000..cbe63eaa --- /dev/null +++ b/src/lpc/ao_exti.h @@ -0,0 +1,47 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_EXTI_H_ +#define _AO_EXTI_H_ + +#define AO_EXTI_MODE_RISING 1 +#define AO_EXTI_MODE_FALLING 2 +#define AO_EXTI_MODE_PULL_UP 4 +#define AO_EXTI_MODE_PULL_DOWN 8 +#define AO_EXTI_PRIORITY_LOW 16 +#define AO_EXTI_PRIORITY_MED 0 +#define AO_EXTI_PRIORITY_HIGH 32 + +void +ao_exti_setup(uint8_t gpio, uint8_t pin, uint8_t mode, void (*callback)()); + +void +ao_exti_set_mode(uint8_t gpio, uint8_t pin, uint8_t mode); + +void +ao_exti_set_callback(uint8_t gpio, uint8_t pin, void (*callback)()); + +void +ao_exti_enable(uint8_t gpio, uint8_t pin); + +void +ao_exti_disable(uint8_t gpio, uint8_t pin); + +void +ao_exti_init(void); + +#endif /* _AO_EXTI_H_ */ diff --git a/src/lpc/ao_exti_lpc.c b/src/lpc/ao_exti_lpc.c new file mode 100644 index 00000000..2e42dabb --- /dev/null +++ b/src/lpc/ao_exti_lpc.c @@ -0,0 +1,151 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +#define LPC_NUM_PINS 56 +#define LPC_NUM_PINT 8 + +static void (*ao_exti_callback[LPC_NUM_PINT])(void); + +static uint8_t ao_pint_map[LPC_NUM_PINS]; +static uint8_t ao_pint_mode[LPC_NUM_PINS]; +static uint8_t ao_pint_inuse; +static uint8_t ao_pint_enabled; + +static void +ao_exti_isr(uint8_t pint) +{ + uint8_t mask = 1 << pint; + + if (lpc_gpio_pin.ist & mask) { + lpc_gpio_pin.ist = mask; + + (*ao_exti_callback) (); + } +} + +#define pin_isr(n) void lpc_pin_int ## n ## _isr(void) { ao_exti_isr(n); } +pin_isr(0) +pin_isr(1) +pin_isr(2) +pin_isr(3) +pin_isr(4) +pin_isr(5) +pin_isr(6) +pin_isr(7) + +#define pin_id(port,pin) ((port) * 24 + (pin)); + +void +ao_exti_setup (uint8_t port, uint8_t pin, uint8_t mode, void (*callback)(void)) { + uint8_t id = pin_id(port,pin); + uint8_t pint; + uint32_t mask; + uint8_t prio; + + for (pint = 0; pint < LPC_NUM_PINT; pint++) + if ((ao_pint_inuse & (1 << pint)) == 0) + break; + if (pint == LPC_NUM_PINT) + ao_panic(AO_PANIC_EXTI); + + mask = (1 << pint); + ao_pint_inuse |= mask; + ao_pint_enabled &= ~mask; + + ao_pint_map[id] = pint; + ao_exti_callback[pin] = callback; + + /* configure gpio to interrupt routing */ + lpc_scb.pintsel[pint] = id; + + ao_enable_input(port, pin, mode); + + /* Set edge triggered */ + lpc_gpio_pin.isel &= ~mask; + + ao_exti_set_mode(port, pin, mode); + + /* Set interrupt mask and rising/falling mode */ + + prio = AO_LPC_NVIC_MED_PRIORITY; + if (mode & AO_EXTI_PRIORITY_LOW) + prio = AO_LPC_NVIC_LOW_PRIORITY; + else if (mode & AO_EXTI_PRIORITY_HIGH) + prio = AO_LPC_NVIC_HIGH_PRIORITY; + + /* Set priority and enable */ + lpc_nvic_set_priority(LPC_ISR_PIN_INT0_POS + pint, prio); + lpc_nvic_set_enable(LPC_ISR_PIN_INT0_POS + pint); +} + +void +ao_exti_set_mode(uint8_t port, uint8_t pin, uint8_t mode) { + uint8_t id = pin_id(port,pin); + uint8_t pint = ao_pint_map[id]; + uint8_t mask = 1 << pint; + + ao_pint_mode[pint] = mode; + + if (mode & AO_EXTI_MODE_RISING) + lpc_gpio_pin.sienr = mask; + else + lpc_gpio_pin.cienr = mask; + + if (mode & AO_EXTI_MODE_FALLING) + lpc_gpio_pin.sienf = mask; + else + lpc_gpio_pin.cienf = mask; +} + +void +ao_exti_set_callback(uint8_t port, uint8_t pin, void (*callback)()) { + uint8_t id = pin_id(port,pin); + uint8_t pint = ao_pint_map[id]; + + ao_exti_callback[pint] = callback; +} + +void +ao_exti_enable(uint8_t port, uint8_t pin) +{ + uint8_t id = pin_id(port,pin); + uint8_t pint = ao_pint_map[id]; + uint8_t mask = 1 << pint; + + ao_pint_enabled |= mask; + ao_exti_set_mode(port, pin, ao_pint_mode[pint]); +} + +void +ao_exti_disable(uint8_t port, uint8_t pin) { + uint8_t id = pin_id(port,pin); + uint8_t pint = ao_pint_map[id]; + uint8_t mask = 1 << pint; + + ao_pint_enabled &= ~mask; + lpc_gpio_pin.cienr = mask; + lpc_gpio_pin.cienf = mask; +} + +void +ao_exti_init(void) +{ + lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_PINT); +} -- cgit v1.2.3 From 5311720525ac73e9d42067b68adf25fc2e054af5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:21:20 -0700 Subject: altos/lpc: Try a smaller stack. Signed-off-by: Keith Packard --- src/lpc/ao_arch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index fb68f6be..92405649 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -24,7 +24,7 @@ * LPC11U14 definitions and code fragments for AltOS */ -#define AO_STACK_SIZE 512 +#define AO_STACK_SIZE 192 #define AO_LED_TYPE uint16_t -- cgit v1.2.3 From c4991db4809ae547fdb245e3cb42517fa7524de5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:21:43 -0700 Subject: altos/lpc: Use separate interrupt stack Signed-off-by: Keith Packard --- src/lpc/ao_arch_funcs.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src') diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index bc4c47ee..3cd873ec 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -208,4 +208,17 @@ ao_spi_init(void); } \ } while (0) +#define HAS_ARCH_START_SCHEDULER 1 + +static inline void ao_arch_start_scheduler(void) { + uint32_t sp; + uint32_t control; + + asm("mrs %0,msp" : "=&r" (sp)); + asm("msr psp,%0" : : "r" (sp)); + asm("mrs %0,control" : "=&r" (control)); + control |= (1 << 1); + asm("msr control,%0" : : "r" (control)); +} + #endif /* _AO_ARCH_FUNCS_H_ */ -- cgit v1.2.3 From 3587bfd248e115bb1abb28f71b263575b4e8e367 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:22:10 -0700 Subject: altos: Add easymini-v0.1 product Signed-off-by: Keith Packard --- src/easymini-v0.1/Makefile | 85 ++++++++++++++++++++++++++ src/easymini-v0.1/ao_easymini.c | 41 +++++++++++++ src/easymini-v0.1/ao_pins.h | 128 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 254 insertions(+) create mode 100644 src/easymini-v0.1/Makefile create mode 100644 src/easymini-v0.1/ao_easymini.c create mode 100644 src/easymini-v0.1/ao_pins.h (limited to 'src') diff --git a/src/easymini-v0.1/Makefile b/src/easymini-v0.1/Makefile new file mode 100644 index 00000000..c4e60ada --- /dev/null +++ b/src/easymini-v0.1/Makefile @@ -0,0 +1,85 @@ +# +# AltOS build +# +# + +include ../lpc/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_pins.h \ + ao_product.h \ + lpc.h + +# +# Common AltOS sources +# +ALTOS_SRC = \ + ao_interrupt.c \ + ao_romconfig.c \ + ao_product.c \ + ao_mutex.c \ + ao_panic.c \ + ao_stdio.c \ + ao_storage.c \ + ao_report.c \ + ao_ignite.c \ + ao_flight.c \ + ao_kalman.c \ + ao_sample.c \ + ao_data.c \ + ao_convert_pa.c \ + ao_led_lpc.c \ + ao_task.c \ + ao_log.c \ + ao_log_tiny.c \ + ao_cmd.c \ + ao_config.c \ + ao_timer_lpc.c \ + ao_exti_lpc.c \ + ao_serial_lpc.c \ + ao_usb_lpc.c \ + ao_spi_lpc.c \ + ao_adc_lpc.c \ + ao_beep_lpc.c \ + ao_m25.c \ + ao_ms5607.c + +PRODUCT=EasyMini-v0.1 +PRODUCT_DEF=-DEASYMINI_V_0_1 +IDPRODUCT=0x000a + +CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -g -Os + +PROGNAME=easymini-v0.1 +PROG=$(PROGNAME)-$(VERSION).elf + +SRC=$(ALTOS_SRC) ao_easymini.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) + +LDFLAGS=-L../lpc -Wl,-Taltos.ld + +$(PROG): Makefile $(OBJ) + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +$(OBJ): $(INC) + +load: $(PROG) + lpc-load $(PROG) + +distclean: clean + +clean: + rm -f *.o $(PROG) + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/easymini-v0.1/ao_easymini.c b/src/easymini-v0.1/ao_easymini.c new file mode 100644 index 00000000..1cdefdd6 --- /dev/null +++ b/src/easymini-v0.1/ao_easymini.c @@ -0,0 +1,41 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +void +main(void) +{ + ao_clock_init(); + ao_task_init(); + ao_timer_init(); + ao_exti_init(); + + ao_cmd_init(); +#if 0 + ao_storage_init(); + ao_flight_init(); + ao_ms5607_init(); + ao_log_init(); + ao_report_init(); + ao_igniter_init(); +#endif + ao_usb_init(); + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/easymini-v0.1/ao_pins.h b/src/easymini-v0.1/ao_pins.h new file mode 100644 index 00000000..5bcd4673 --- /dev/null +++ b/src/easymini-v0.1/ao_pins.h @@ -0,0 +1,128 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#define HAS_BEEP 1 +#define HAS_LED 1 + +/* Crystal on the board */ +#define AO_LPC_CLKIN 12000000 + +/* Main clock frequency. 48MHz for USB so we don't use the USB PLL */ +#define AO_LPC_CLKOUT 48000000 + +/* System clock frequency */ +#define AO_LPC_SYSCLK 24000000 + +#define LED_PORT 0 +#define LED_PIN_RED 7 + +#define AO_LED_RED (1 << LED_PIN_RED) + +#define LEDS_AVAILABLE AO_LED_RED + +#define HAS_USB 1 + +#define HAS_USB_CONNECT 1 +#define HAS_USB_VBUS 1 + +#define PACKET_HAS_SLAVE 0 + +/* USART */ + +#define HAS_SERIAL 1 +#define USE_SERIAL_0_STDIN 1 +#define SERIAL_0_18_19 1 +#define SERIAL_0_14_15 0 +#define SERIAL_0_17_18 0 +#define SERIAL_0_26_27 0 + +/* SPI */ + +#define HAS_SPI_0 1 +#define HAS_SPI_1 1 +#define SPI_SCK1_P1_15 1 +#define SPI_MISO1_P0_22 1 +#define SPI_MOSI1_P0_21 1 + +/* M25 */ + +#define M25_MAX_CHIPS 1 +#define AO_M25_SPI_CS_PORT 0 +#define AO_M25_SPI_CS_MASK (1 << 23) +#define AO_M25_SPI_BUS 1 + +/* MS5607 */ + +#define HAS_MS5607 1 +#define HAS_MS5611 0 +#define AO_MS5607_PRIVATE_PINS 0 +#define AO_MS5607_CS_PORT 0 +#define AO_MS5607_CS_PIN 7 +#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) +#define AO_MS5607_MISO_PORT 0 +#define AO_MS5607_MISO_PIN 8 +#define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO) +#define AO_MS5607_SPI_INDEX 0 + +#define HAS_ACCEL 0 +#define HAS_GPS 0 +#define HAS_RADIO 0 +#define HAS_FLIGHT 1 +#define HAS_EEPROM 1 +#define HAS_TELEMETRY 0 +#define HAS_APRS 0 +#define HAS_LOG 1 +#define USE_INTERNAL_FLASH 0 + +#define AO_DATA_RING 16 + +/* + * ADC + */ + +#define HAS_ADC 1 + +#define AO_NUM_ADC 3 + +#define AO_ADC_0 1 +#define AO_ADC_1 1 +#define AO_ADC_2 1 + +struct ao_adc { + int16_t sense_d; + int16_t sense_m; + int16_t v_batt; +}; + +/* + * Igniter + */ + +#define AO_IGNITER_CLOSED 400 +#define AO_IGNITER_OPEN 60 + +#define AO_IGNITER_DROGUE_PORT 0 +#define AO_IGNITER_DROGUE_PIN 4 +#define AO_IGNITER_SET_DROGUE(v) ao_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, AO_IGNITER_DROGUE, v) + +#define AO_IGNITER_MAIN_PORT 0 +#define AO_IGNITER_MAIN_PIN 5 +#define AO_IGNITER_SET_MAIN(v) ao_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, AO_IGNITER_MAIN, v) + +#define AO_ADC_DUMP(p) \ + printf("tick: %5u drogue: %5d main: %5d batt: %5d\n", \ + (p)->tick, (p)->adc.sense_d, (p)->adc.sense_m, (p)->adc.v_batt) -- cgit v1.2.3 From cbe5eee76faf386eefe69539935ab318944ac452 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:52:14 -0700 Subject: altos/lpc: Stick USB control structure in USB memory No reason to have that in regular ram, and it means we've got space for large enough stacks now Signed-off-by: Keith Packard --- src/lpc/altos.ld | 11 ++++++++--- src/lpc/ao_arch.h | 2 +- src/lpc/ao_usb_lpc.c | 1 + 3 files changed, 10 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/lpc/altos.ld b/src/lpc/altos.ld index bcfba1ea..2778797a 100644 --- a/src/lpc/altos.ld +++ b/src/lpc/altos.ld @@ -17,8 +17,9 @@ MEMORY { rom (rx) : ORIGIN = 0x00000000, LENGTH = 32K - ram (!w) : ORIGIN = 0x10000000, LENGTH = 4K - 512 - stack (!w) : ORIGIN = 0x10000000 + 4K - 512, LENGTH = 512 + ram (!w) : ORIGIN = 0x10000000, LENGTH = 4K - 128 + usb (!x) : ORIGIN = 0x20004000 + 2K - 256, LENGTH = 256 + stack (!w) : ORIGIN = 0x10000000 + 4K - 128, LENGTH = 128 } INCLUDE registers.ld @@ -63,9 +64,13 @@ SECTIONS { *(COMMON) __bss_end__ = .; } >ram + PROVIDE(end = .); + + .usb : { + *(.usb) + } > usb PROVIDE(__stack__ = ORIGIN(stack) + LENGTH(stack)); - PROVIDE(end = .); } ENTRY(start); diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index 92405649..9dbebf4a 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -24,7 +24,7 @@ * LPC11U14 definitions and code fragments for AltOS */ -#define AO_STACK_SIZE 192 +#define AO_STACK_SIZE 320 #define AO_LED_TYPE uint16_t diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index 0f881720..cd896724 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -81,6 +81,7 @@ static uint8_t ao_usb_tx_count; static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE]; static uint8_t ao_usb_rx_count, ao_usb_rx_pos; +__attribute__((section(".usb"))) static struct lpc_usb_endpoint lpc_usb_endpoint __attribute((aligned(256))); /* Marks when we don't need to send an IN packet. -- cgit v1.2.3 From 278300b2bc98b92cc71ec016ab0fc93eb3696435 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:52:59 -0700 Subject: altos: Initialize SPI for easymini Doesn't work very well without this Signed-off-by: Keith Packard --- src/easymini-v0.1/ao_easymini.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/easymini-v0.1/ao_easymini.c b/src/easymini-v0.1/ao_easymini.c index 1cdefdd6..ce70398e 100644 --- a/src/easymini-v0.1/ao_easymini.c +++ b/src/easymini-v0.1/ao_easymini.c @@ -26,16 +26,19 @@ main(void) ao_timer_init(); ao_exti_init(); + ao_spi_init(); + ao_storage_init(); + + ao_usb_init(); + ao_cmd_init(); #if 0 - ao_storage_init(); ao_flight_init(); ao_ms5607_init(); ao_log_init(); ao_report_init(); ao_igniter_init(); #endif - ao_usb_init(); ao_config_init(); ao_start_scheduler(); } -- cgit v1.2.3 From c57e1630002c921739ff22395497d93027d381b6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:53:32 -0700 Subject: altos: Build easymini-v0.1 Signed-off-by: Keith Packard --- src/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index c3596498..5851b2a8 100644 --- a/src/Makefile +++ b/src/Makefile @@ -35,7 +35,8 @@ ARMDIRS=\ telegps-v0.1 telegps-v0.1/flash-loader \ stm-bringup stm-demo \ telelco-v0.2 telelco-v0.2/flash-loader \ - telescience-v0.2 telescience-v0.2/flash-loader + telescience-v0.2 telescience-v0.2/flash-loader \ + easymini-v0.1 ifneq ($(shell which sdcc),) SUBDIRS += $(SDCCDIRS) -- cgit v1.2.3 From 49f9cdda5f1812687b82915acc78a9d9136255bf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 May 2013 03:54:30 -0700 Subject: altos: ignore built files in easymini-v0.1 Signed-off-by: Keith Packard --- src/easymini-v0.1/.gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/easymini-v0.1/.gitignore (limited to 'src') diff --git a/src/easymini-v0.1/.gitignore b/src/easymini-v0.1/.gitignore new file mode 100644 index 00000000..e5f7d586 --- /dev/null +++ b/src/easymini-v0.1/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +*.elf -- cgit v1.2.3 From b7ab41e4dc92dcd382f4c05459088d8df8b70075 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 19:51:32 -0700 Subject: altos/attiny: Fix ao_spi_get_bit/ao_spi_put_bit macros These were never written, so just use ao_spi_get/put_mask. A precursor to changing how the MS5607 drives the SPI bus Signed-off-by: Keith Packard --- src/attiny/ao_arch_funcs.h | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/attiny/ao_arch_funcs.h b/src/attiny/ao_arch_funcs.h index 8c9d1ae6..76dc7820 100644 --- a/src/attiny/ao_arch_funcs.h +++ b/src/attiny/ao_arch_funcs.h @@ -20,21 +20,16 @@ */ #define ao_spi_get_mask(reg,mask,bus,speed) do { \ - (reg) &= ~(mask); \ + (reg) &= ~(mask); \ } while (0) #define ao_spi_put_mask(reg,mask,bus) do { \ (reg) |= (mask); \ } while (0) -#define ao_spi_get_bit(reg,bit,pin,bus,speed) do { \ - (pin) = 0; \ - } while (0) - -#define ao_spi_put_bit(reg,bit,pin,bus) do { \ - (pin) = 1; \ - } while (0) +#define ao_spi_get_bit(reg,bit,pin,bus,speed) ao_spi_get_mask(reg,(1<<(bit)),bus,speed) +#define ao_spi_put_bit(reg,bit,pin,bus) ao_spi_put_mask(reg,(1<<(bit)),bus) #define ao_gpio_token_paster(x,y) x ## y #define ao_gpio_token_evaluator(x,y) ao_gpio_token_paster(x,y) -- cgit v1.2.3 From f794e6c95697b034be315632fddb3a5475c43b5b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 19:57:23 -0700 Subject: altos: Use ao_spi_get/put_bit in MS5607 driver Replace open-coded ao_spi_get/put and ao_gpio_set sequences Signed-off-by: Keith Packard --- src/drivers/ao_ms5607.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index bd57400e..0eece584 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -26,14 +26,12 @@ static uint8_t ms5607_configured; static void ao_ms5607_start(void) { - ao_spi_get(AO_MS5607_SPI_INDEX,AO_SPI_SPEED_FAST); - ao_gpio_set(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, AO_MS5607_CS, 0); + ao_spi_get_bit(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, AO_MS5607_CS, AO_MS5607_SPI_INDEX, AO_SPI_SPEED_FAST); } static void ao_ms5607_stop(void) { - ao_gpio_set(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, AO_MS5607_CS, 1); - ao_spi_put(AO_MS5607_SPI_INDEX); + ao_spi_put_bit(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, AO_MS5607_CS, AO_MS5607_SPI_INDEX); } static void -- cgit v1.2.3 From 098fd43a740ee2a782f82b6b71965b60cdba2d62 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:00:24 -0700 Subject: altos/lpc: Make EXTI code work. Clear rise/fall bits in ISR to avoid re-entering. Block interrupts around enable/disable bits. Create shared _ao_exti_set_enable function to control mask changes. Signed-off-by: Keith Packard --- src/lpc/ao_exti_lpc.c | 64 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_exti_lpc.c b/src/lpc/ao_exti_lpc.c index 2e42dabb..ce98b4ad 100644 --- a/src/lpc/ao_exti_lpc.c +++ b/src/lpc/ao_exti_lpc.c @@ -35,8 +35,10 @@ ao_exti_isr(uint8_t pint) if (lpc_gpio_pin.ist & mask) { lpc_gpio_pin.ist = mask; + lpc_gpio_pin.rise = mask; + lpc_gpio_pin.fall = mask; - (*ao_exti_callback) (); + (*ao_exti_callback[pint]) (); } } @@ -52,6 +54,30 @@ pin_isr(7) #define pin_id(port,pin) ((port) * 24 + (pin)); +static void +_ao_exti_set_enable(uint8_t pint) +{ + uint8_t mask = 1 << pint; + uint8_t mode; + + if (ao_pint_enabled & mask) + mode = ao_pint_mode[pint]; + else + mode = 0; + + if (mode & AO_EXTI_MODE_RISING) + lpc_gpio_pin.sienr = mask; + else + lpc_gpio_pin.cienr = mask; + + if (mode & AO_EXTI_MODE_FALLING) + lpc_gpio_pin.sienf = mask; + else + lpc_gpio_pin.cienf = mask; + lpc_gpio_pin.rise = mask; + lpc_gpio_pin.fall = mask; +} + void ao_exti_setup (uint8_t port, uint8_t pin, uint8_t mode, void (*callback)(void)) { uint8_t id = pin_id(port,pin); @@ -65,22 +91,23 @@ ao_exti_setup (uint8_t port, uint8_t pin, uint8_t mode, void (*callback)(void)) if (pint == LPC_NUM_PINT) ao_panic(AO_PANIC_EXTI); + ao_arch_block_interrupts(); mask = (1 << pint); ao_pint_inuse |= mask; ao_pint_enabled &= ~mask; ao_pint_map[id] = pint; - ao_exti_callback[pin] = callback; + ao_exti_callback[pint] = callback; /* configure gpio to interrupt routing */ lpc_scb.pintsel[pint] = id; - ao_enable_input(port, pin, mode); - /* Set edge triggered */ lpc_gpio_pin.isel &= ~mask; - ao_exti_set_mode(port, pin, mode); + ao_pint_enabled &= ~mask; + ao_pint_mode[pint] = mode; + _ao_exti_set_enable(pint); /* Set interrupt mask and rising/falling mode */ @@ -93,25 +120,19 @@ ao_exti_setup (uint8_t port, uint8_t pin, uint8_t mode, void (*callback)(void)) /* Set priority and enable */ lpc_nvic_set_priority(LPC_ISR_PIN_INT0_POS + pint, prio); lpc_nvic_set_enable(LPC_ISR_PIN_INT0_POS + pint); + ao_arch_release_interrupts(); } void -ao_exti_set_mode(uint8_t port, uint8_t pin, uint8_t mode) { +ao_exti_set_mode(uint8_t port, uint8_t pin, uint8_t mode) +{ uint8_t id = pin_id(port,pin); uint8_t pint = ao_pint_map[id]; - uint8_t mask = 1 << pint; + ao_arch_block_interrupts(); ao_pint_mode[pint] = mode; - - if (mode & AO_EXTI_MODE_RISING) - lpc_gpio_pin.sienr = mask; - else - lpc_gpio_pin.cienr = mask; - - if (mode & AO_EXTI_MODE_FALLING) - lpc_gpio_pin.sienf = mask; - else - lpc_gpio_pin.cienf = mask; + _ao_exti_set_enable(pint); + ao_arch_release_interrupts(); } void @@ -129,8 +150,10 @@ ao_exti_enable(uint8_t port, uint8_t pin) uint8_t pint = ao_pint_map[id]; uint8_t mask = 1 << pint; + ao_arch_block_interrupts(); ao_pint_enabled |= mask; - ao_exti_set_mode(port, pin, ao_pint_mode[pint]); + _ao_exti_set_enable(pint); + ao_arch_release_interrupts(); } void @@ -139,9 +162,10 @@ ao_exti_disable(uint8_t port, uint8_t pin) { uint8_t pint = ao_pint_map[id]; uint8_t mask = 1 << pint; + ao_arch_block_interrupts(); ao_pint_enabled &= ~mask; - lpc_gpio_pin.cienr = mask; - lpc_gpio_pin.cienf = mask; + _ao_exti_set_enable(pint); + ao_arch_release_interrupts(); } void -- cgit v1.2.3 From 35a05041d3ca3e69a146bd3bf8038c0f1cbc1b42 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:04:29 -0700 Subject: altos: Add EXTI_PIN_NOCONFIGURE to exti interface, use for MS5607 This asks the EXTI code to not mess with the pin configuration so that the MS5607 driver can get interrupts on the MISO pin while still using it for SPI. Signed-off-by: Keith Packard --- src/attiny/ao_exti.h | 1 + src/drivers/ao_ms5607.c | 12 ++---------- src/lpc/ao_exti.h | 1 + src/lpc/ao_exti_lpc.c | 3 +++ src/stm/ao_exti.h | 1 + src/stm/ao_exti_stm.c | 30 ++++++++++++++++-------------- 6 files changed, 24 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/attiny/ao_exti.h b/src/attiny/ao_exti.h index 2ea4f47d..85bb2fba 100644 --- a/src/attiny/ao_exti.h +++ b/src/attiny/ao_exti.h @@ -30,5 +30,6 @@ ao_exti_setup_port(uint8_t pin, uint8_t mode, void (*callback)(void)); #define ao_exti_init() #define AO_EXTI_MODE_RISING 1 +#define AO_EXTI_PIN_NOCONFIGURE 0 #endif /* _AO_EXTI_H_ */ diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 0eece584..8f1dcbe1 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -247,17 +247,9 @@ ao_ms5607_init(void) */ ao_exti_setup(AO_MS5607_MISO_PORT, AO_MS5607_MISO_PIN, - AO_EXTI_MODE_RISING, + AO_EXTI_MODE_RISING| + AO_EXTI_PIN_NOCONFIGURE, ao_ms5607_isr); - -#ifdef STM_MODER_ALTERNATE - /* Reset the pin from INPUT to ALTERNATE so that SPI works - * This needs an abstraction at some point... - */ - stm_moder_set(AO_MS5607_MISO_PORT, - AO_MS5607_MISO_PIN, - STM_MODER_ALTERNATE); -#endif } #endif diff --git a/src/lpc/ao_exti.h b/src/lpc/ao_exti.h index cbe63eaa..e8599eb4 100644 --- a/src/lpc/ao_exti.h +++ b/src/lpc/ao_exti.h @@ -25,6 +25,7 @@ #define AO_EXTI_PRIORITY_LOW 16 #define AO_EXTI_PRIORITY_MED 0 #define AO_EXTI_PRIORITY_HIGH 32 +#define AO_EXTI_PIN_NOCONFIGURE 64 void ao_exti_setup(uint8_t gpio, uint8_t pin, uint8_t mode, void (*callback)()); diff --git a/src/lpc/ao_exti_lpc.c b/src/lpc/ao_exti_lpc.c index ce98b4ad..588cf58c 100644 --- a/src/lpc/ao_exti_lpc.c +++ b/src/lpc/ao_exti_lpc.c @@ -91,6 +91,9 @@ ao_exti_setup (uint8_t port, uint8_t pin, uint8_t mode, void (*callback)(void)) if (pint == LPC_NUM_PINT) ao_panic(AO_PANIC_EXTI); + if (!mode & AO_EXTI_PIN_NOCONFIGURE) + ao_enable_input(port, pin, mode); + ao_arch_block_interrupts(); mask = (1 << pint); ao_pint_inuse |= mask; diff --git a/src/stm/ao_exti.h b/src/stm/ao_exti.h index 35b56b57..ebea224d 100644 --- a/src/stm/ao_exti.h +++ b/src/stm/ao_exti.h @@ -25,6 +25,7 @@ #define AO_EXTI_PRIORITY_LOW 16 #define AO_EXTI_PRIORITY_MED 0 #define AO_EXTI_PRIORITY_HIGH 32 +#define AO_EXTI_PIN_NOCONFIGURE 64 void ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)()); diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c index 1361d0d4..c1dcdf85 100644 --- a/src/stm/ao_exti_stm.c +++ b/src/stm/ao_exti_stm.c @@ -70,21 +70,23 @@ ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback /* configure gpio to interrupt routing */ stm_exticr_set(gpio, pin); - /* configure pin as input, setting selected pull-up/down mode */ - stm_moder_set(gpio, pin, STM_MODER_INPUT); - switch (mode & (AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_PULL_DOWN)) { - case 0: - default: - pupdr = STM_PUPDR_NONE; - break; - case AO_EXTI_MODE_PULL_UP: - pupdr = STM_PUPDR_PULL_UP; - break; - case AO_EXTI_MODE_PULL_DOWN: - pupdr = STM_PUPDR_PULL_DOWN; - break; + if (!(mode & AO_EXTI_PIN_NOCONFIGURE)) { + /* configure pin as input, setting selected pull-up/down mode */ + stm_moder_set(gpio, pin, STM_MODER_INPUT); + switch (mode & (AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_PULL_DOWN)) { + case 0: + default: + pupdr = STM_PUPDR_NONE; + break; + case AO_EXTI_MODE_PULL_UP: + pupdr = STM_PUPDR_PULL_UP; + break; + case AO_EXTI_MODE_PULL_DOWN: + pupdr = STM_PUPDR_PULL_DOWN; + break; + } + stm_pupdr_set(gpio, pin, pupdr); } - stm_pupdr_set(gpio, pin, pupdr); /* Set interrupt mask and rising/falling mode */ stm_exti.imr &= ~mask; -- cgit v1.2.3 From 6343bd774f542a4f915cf1fca2053d03e93bf2c3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:06:03 -0700 Subject: altos/lpc: Don't use loader to place USB endpoint data in USB ram Instead, just assign a fixed address in registers.ld. This avoids a confusing section in the elf file. Signed-off-by: Keith Packard --- src/lpc/altos.ld | 4 ---- src/lpc/ao_usb_lpc.c | 3 +-- src/lpc/registers.ld | 1 + 3 files changed, 2 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/lpc/altos.ld b/src/lpc/altos.ld index 2778797a..4d6f35a8 100644 --- a/src/lpc/altos.ld +++ b/src/lpc/altos.ld @@ -66,10 +66,6 @@ SECTIONS { } >ram PROVIDE(end = .); - .usb : { - *(.usb) - } > usb - PROVIDE(__stack__ = ORIGIN(stack) + LENGTH(stack)); } diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index cd896724..8070acc3 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -81,8 +81,7 @@ static uint8_t ao_usb_tx_count; static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE]; static uint8_t ao_usb_rx_count, ao_usb_rx_pos; -__attribute__((section(".usb"))) -static struct lpc_usb_endpoint lpc_usb_endpoint __attribute((aligned(256))); +extern struct lpc_usb_endpoint lpc_usb_endpoint; /* Marks when we don't need to send an IN packet. * This happens only when the last IN packet is not full, diff --git a/src/lpc/registers.ld b/src/lpc/registers.ld index 51866e07..a523c39c 100644 --- a/src/lpc/registers.ld +++ b/src/lpc/registers.ld @@ -1,4 +1,5 @@ lpc_usb_sram = 0x20004000; +lpc_usb_endpoint = 0x20004700; lpc_usart = 0x40008000; lpc_ct32b0 = 0x40014000; lpc_ct32b1 = 0x40018000; -- cgit v1.2.3 From d51c9fda3478f205e4bcdf1b7bf21eb1e0a516bc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:07:52 -0700 Subject: altos/lpc: Pull ADC data from the correct registers Was just stepping through register space arbitrarily, which would have worked for EasyMini, but might have failed later if the ADC pin usage wasn't consecutive. Signed-off-by: Keith Packard --- src/lpc/ao_adc_lpc.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_adc_lpc.c b/src/lpc/ao_adc_lpc.c index 70e8b2d6..9ecc7c13 100644 --- a/src/lpc/ao_adc_lpc.c +++ b/src/lpc/ao_adc_lpc.c @@ -86,34 +86,38 @@ static uint8_t ao_adc_ready; void lpc_adc_isr(void) { + uint32_t stat = lpc_adc.stat; uint16_t *out = (uint16_t *) &ao_data_ring[ao_data_head].adc; vuint32_t *in = &lpc_adc.dr[0]; + lpc_adc.cr = 0; + lpc_adc.stat = 0; + /* Store converted values in packet */ #if AO_ADC_0 - *out++ = ((uint16_t) *in++) >> 1; + *out++ = lpc_adc.dr[0] >> 1; #endif #if AO_ADC_1 - *out++ = ((uint16_t) *in++) >> 1; + *out++ = lpc_adc.dr[1] >> 1; #endif #if AO_ADC_2 - *out++ = ((uint16_t) *in++) >> 1; + *out++ = lpc_adc.dr[2] >> 1; #endif #if AO_ADC_3 - *out++ = ((uint16_t) *in++) >> 1; + *out++ = lpc_adc.dr[3] >> 1; #endif #if AO_ADC_4 - *out++ = ((uint16_t) *in++) >> 1; + *out++ = lpc_adc.dr[4] >> 1; #endif #if AO_ADC_5 - *out++ = ((uint16_t) *in++) >> 1; + *out++ = lpc_adc.dr[5] >> 1; #endif #if AO_ADC_6 - *out++ = ((uint16_t) *in++) >> 1; + *out++ = lpc_adc.dr[6] >> 1; #endif #if AO_ADC_7 - *out++ = ((uint16_t) *in++) >> 1; + *out++ = lpc_adc.dr[7] >> 1; #endif AO_DATA_PRESENT(AO_DATA_ADC); -- cgit v1.2.3 From a78012782c779de3433b91e6b854b2fdbd7230fd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:17:48 -0700 Subject: altos/lpc: SPI runs off main clock (48MHz), not sysclk (24MHz) Update SPI speed definitions to match Signed-off-by: Keith Packard --- src/lpc/ao_arch.h | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index 9dbebf4a..f605e3d2 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -127,14 +127,13 @@ ao_serial_init(void); /* SPI definitions */ -#define AO_SPI_SPEED_12MHz 2 -#define AO_SPI_SPEED_6MHz 4 -#define AO_SPI_SPEED_4MHz 6 -#define AO_SPI_SPEED_2MHz 12 -#define AO_SPI_SPEED_1MHz 24 -#define AO_SPI_SPEED_500kHz 48 -#define AO_SPI_SPEED_250kHz 96 -#define AO_SPI_SPEED_125kHz 192 +#define AO_SPI_SPEED_12MHz 4 +#define AO_SPI_SPEED_6MHz 8 +#define AO_SPI_SPEED_4MHz 12 +#define AO_SPI_SPEED_2MHz 24 +#define AO_SPI_SPEED_1MHz 48 +#define AO_SPI_SPEED_500kHz 96 +#define AO_SPI_SPEED_250kHz 192 #define AO_SPI_SPEED_FAST AO_SPI_SPEED_12MHz -- cgit v1.2.3 From 3fe11b277dd7268eb445d120c8f9537f95148891 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:18:44 -0700 Subject: altos/lpc: Missing parens around ao_gpio_set macro Signed-off-by: Keith Packard --- src/lpc/ao_arch_funcs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index 3cd873ec..204d1227 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -25,7 +25,7 @@ #define lpc_all_bit(port,bit) (((port) << 5) | (bit)) -#define ao_gpio_set(port, bit, pin, v) (lpc_gpio.byte[lpc_all_bit(port,bit)] = v) +#define ao_gpio_set(port, bit, pin, v) (lpc_gpio.byte[lpc_all_bit(port,bit)] = (v)) #define ao_gpio_get(port, bit, pin) (lpc_gpio_byte[lpc_all_bit(port,bit)]) -- cgit v1.2.3 From 07d261c08214837b5d5cac4d2be43e51a0c47868 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:19:15 -0700 Subject: altos/lpc: Fix beeper driver Set prescale limit, not current prescale value (pr instead of pc). Flip output 1 on PWM match (set emc toggle for channel 1). Don't hold counter in reset (turn off CRST bit). Signed-off-by: Keith Packard --- src/lpc/ao_beep_lpc.c | 10 +++++++--- src/lpc/lpc.h | 10 ++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_beep_lpc.c b/src/lpc/ao_beep_lpc.c index 281f981f..eb9132b8 100644 --- a/src/lpc/ao_beep_lpc.c +++ b/src/lpc/ao_beep_lpc.c @@ -29,16 +29,19 @@ ao_beep(uint8_t beep) /* Set prescaler to match cc1111 clocks */ - lpc_ct32b1.pc = AO_LPC_CLKOUT / 750000 - 1; + lpc_ct32b1.pr = AO_LPC_SYSCLK / 750000 - 1; /* Write the desired data in the match registers */ /* Reset after two time units */ lpc_ct32b1.mr[0] = beep << 1; - /* Flip output after one time unit */ + /* PWM width is half of that */ lpc_ct32b1.mr[1] = beep; + /* Flip output 1 on PWM match */ + lpc_ct32b1.emr = (LPC_CT32B_EMR_EMC_TOGGLE << LPC_CT32B_EMR_EMC1); + /* Reset on match 0 */ lpc_ct32b1.mcr = (1 << LPC_CT32B_MCR_MR0R); @@ -50,7 +53,7 @@ ao_beep(uint8_t beep) /* And turn the timer on */ lpc_ct32b1.tcr = ((1 << LPC_CT32B_TCR_CEN) | - (1 << LPC_CT32B_TCR_CRST)); + (0 << LPC_CT32B_TCR_CRST)); } } @@ -73,6 +76,7 @@ ao_beep_init(void) (LPC_IOCONF_MODE_INACTIVE << LPC_IOCONF_MODE) | (0 << LPC_IOCONF_HYS) | (0 << LPC_IOCONF_INV) | + (1 << LPC_IOCONF_ADMODE) | (0 << LPC_IOCONF_OD)); lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_CT32B1); diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index 2493a1ff..1b48fcc9 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -1212,4 +1212,14 @@ extern struct lpc_ct32b lpc_ct32b0, lpc_ct32b1; #define LPC_CT32B_PWMC_PWMEN2 2 #define LPC_CT32B_PWMC_PWMEN3 3 +#define LPC_CT32B_EMR_EMC0 4 +#define LPC_CT32B_EMR_EMC1 6 +#define LPC_CT32B_EMR_EMC2 8 +#define LPC_CT32B_EMR_EMC3 10 + +#define LPC_CT32B_EMR_EMC_NOTHING 0 +#define LPC_CT32B_EMR_EMC_CLEAR 1 +#define LPC_CT32B_EMR_EMC_SET 2 +#define LPC_CT32B_EMR_EMC_TOGGLE 3 + #endif /* _LPC_H_ */ -- cgit v1.2.3 From e383d7a28d01729c50f933ceda77ea767d1b8087 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:22:20 -0700 Subject: altos/lpc: Create TX/RX busy macros for SPI driver Check for both fifo status *and* device busy to make sure the device is idle before we touch any registers. Signed-off-by: Keith Packard --- src/lpc/ao_spi_lpc.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_spi_lpc.c b/src/lpc/ao_spi_lpc.c index 05688f52..e7edca4c 100644 --- a/src/lpc/ao_spi_lpc.c +++ b/src/lpc/ao_spi_lpc.c @@ -23,21 +23,25 @@ static struct lpc_ssp * const ao_lpc_ssp[LPC_NUM_SPI] = { &lpc_ssp0, &lpc_ssp1 } static uint8_t spi_dev_null; +#define tx_busy(lpc_ssp) (lpc_ssp->sr & ((1 << LPC_SSP_SR_BSY) | (1 << LPC_SSP_SR_TNF))) != (1 << LPC_SSP_SR_TNF) +#define rx_busy(lpc_ssp) (lpc_ssp->sr & ((1 << LPC_SSP_SR_BSY) | (1 << LPC_SSP_SR_RNE))) != (1 << LPC_SSP_SR_RNE) + #define spi_loop(len, put, get) do { \ while (len--) { \ /* Wait for space in the fifo */ \ - while ((lpc_ssp->sr & (1 << LPC_SSP_SR_TNF)) == 0) \ + while (tx_busy(lpc_ssp)) \ ; \ + \ /* send a byte */ \ lpc_ssp->dr = put; \ \ + /* Wait for byte to appear in the fifo */ \ + while (rx_busy(lpc_ssp)) \ + ; \ + \ /* recv a byte */ \ get lpc_ssp->dr; \ } \ - \ - /* Wait for the fifo to drain */ \ - while ((lpc_ssp->sr & (1 << LPC_SSP_SR_BSY))) \ - ; \ } while (0); void -- cgit v1.2.3 From 397109139fb9ff27ec7cfb0cafa65d1dbea053bd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:24:11 -0700 Subject: altos/lpc: Leave SPI enabled all the time Might be able to turn it off with some care; more experimentation required. Signed-off-by: Keith Packard --- src/lpc/ao_spi_lpc.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_spi_lpc.c b/src/lpc/ao_spi_lpc.c index e7edca4c..7c830053 100644 --- a/src/lpc/ao_spi_lpc.c +++ b/src/lpc/ao_spi_lpc.c @@ -89,24 +89,11 @@ ao_spi_get(uint8_t id, uint32_t speed) /* Set the clock prescale */ lpc_ssp->cpsr = speed; - - /* Enable the device */ - lpc_ssp->cr1 = ((0 << LPC_SSP_CR1_LBM) | - (1 << LPC_SSP_CR1_SSE) | - (LPC_SSP_CR1_MS_MASTER << LPC_SSP_CR1_MS) | - (0 << LPC_SSP_CR1_SOD)); } void ao_spi_put(uint8_t id) { - struct lpc_ssp *lpc_ssp = ao_lpc_ssp[id]; - - /* Disable the device */ - lpc_ssp->cr1 = ((0 << LPC_SSP_CR1_LBM) | - (0 << LPC_SSP_CR1_SSE) | - (LPC_SSP_CR1_MS_MASTER << LPC_SSP_CR1_MS) | - (0 << LPC_SSP_CR1_SOD)); ao_mutex_put(&ao_spi_mutex[id]); } @@ -121,6 +108,13 @@ ao_spi_channel_init(uint8_t id) (0 << LPC_SSP_CR0_CPOL) | (0 << LPC_SSP_CR0_CPHA) | (0 << LPC_SSP_CR0_SCR)); + + /* Enable the device */ + lpc_ssp->cr1 = ((0 << LPC_SSP_CR1_LBM) | + (1 << LPC_SSP_CR1_SSE) | + (LPC_SSP_CR1_MS_MASTER << LPC_SSP_CR1_MS) | + (0 << LPC_SSP_CR1_SOD)); + /* Drain the receive fifo */ for (d = 0; d < LPC_SSP_FIFOSIZE; d++) (void) lpc_ssp->dr; -- cgit v1.2.3 From b9bb088a36fd351809f4c378356327ffa663c974 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:25:13 -0700 Subject: altos/lpc: Allow for alternate SPI SCLK0 pin usage SPI SCLK0 can appear on three different pins; let the application configure which one it wants. Signed-off-by: Keith Packard --- src/easymini-v0.1/ao_pins.h | 1 + src/lpc/ao_spi_lpc.c | 16 +++++++++++++++- src/lpc/lpc.h | 4 ++-- 3 files changed, 18 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/easymini-v0.1/ao_pins.h b/src/easymini-v0.1/ao_pins.h index 5bcd4673..2307d7d2 100644 --- a/src/easymini-v0.1/ao_pins.h +++ b/src/easymini-v0.1/ao_pins.h @@ -53,6 +53,7 @@ /* SPI */ #define HAS_SPI_0 1 +#define SPI_SCK0_P0_6 1 #define HAS_SPI_1 1 #define SPI_SCK1_P1_15 1 #define SPI_MISO1_P0_22 1 diff --git a/src/lpc/ao_spi_lpc.c b/src/lpc/ao_spi_lpc.c index 7c830053..12d44872 100644 --- a/src/lpc/ao_spi_lpc.c +++ b/src/lpc/ao_spi_lpc.c @@ -125,7 +125,21 @@ ao_spi_init(void) { #if HAS_SPI_0 /* Configure pins */ - lpc_ioconf.pio0_6 = ao_lpc_alternate(LPC_IOCONF_FUNC_SCK0); +#if SPI_SCK0_P0_6 + lpc_ioconf.pio0_6 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO0_6_SCK0); +#define HAS_SCK0 +#endif +#if SPI_SCK0_P0_10 + lpc_ioconf.pio0_10 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO0_10_SCK0); +#define HAS_SCK0 +#endif +#if SPI_SCK0_P1_29 + lpc_ioconf.pio1_29 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO1_29_SCK0); +#define HAS_SCK0 +#endif +#ifndef HAS_SCK0 +#error "No pin specified for SCK0" +#endif lpc_ioconf.pio0_8 = ao_lpc_alternate(LPC_IOCONF_FUNC_MISO0); lpc_ioconf.pio0_9 = ao_lpc_alternate(LPC_IOCONF_FUNC_MOSI0); diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index 1b48fcc9..49034c1c 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -131,7 +131,7 @@ extern struct lpc_ioconf lpc_ioconf; /* PIO0_6 */ #define LPC_IOCONF_FUNC_PIO0_6 0 #define LPC_IOCONF_FUNC_USB_CONNECT 1 -#define LPC_IOCONF_FUNC_SCK0 2 +#define LPC_IOCONF_FUNC_PIO0_6_SCK0 2 /* PIO0_7 */ #define LPC_IOCONF_FUNC_PIO0_7 0 @@ -150,7 +150,7 @@ extern struct lpc_ioconf lpc_ioconf; /* PIO0_10 */ #define LPC_IOCONF_FUNC_SWCLK 0 #define LPC_IOCONF_FUNC_PIO0_10 1 -#define LPC_IOCONF_FUNC_SCK0 2 +#define LPC_IOCONF_FUNC_PIO0_10_SCK0 2 #define LPC_IOCONF_FUNC_CT16B0_MAT2 3 /* PIO0_11 */ -- cgit v1.2.3 From e0ad8b5b5e1b4c7a9ffba9d25f3c32ce708c3ec5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:26:07 -0700 Subject: altos/lpc: Configuring wrong pin for SPI1 MOSI Was setting configuration for PIO1_21 instead of PIO0_21. Signed-off-by: Keith Packard --- src/lpc/ao_spi_lpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/lpc/ao_spi_lpc.c b/src/lpc/ao_spi_lpc.c index 12d44872..ff107e40 100644 --- a/src/lpc/ao_spi_lpc.c +++ b/src/lpc/ao_spi_lpc.c @@ -182,7 +182,7 @@ ao_spi_init(void) #endif #if SPI_MOSI1_P0_21 - lpc_ioconf.pio1_21 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO0_21_MOSI1); + lpc_ioconf.pio0_21 = ao_lpc_alternate(LPC_IOCONF_FUNC_PIO0_21_MOSI1); #define HAS_MOSI1 #endif #if SPI_MOSI1_P1_22 -- cgit v1.2.3 From c1f01cd4406063191a51cb68fc4634eabfc60fc2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:27:05 -0700 Subject: altos/lpc: Reset SPI device at startup time Wasn't doing the reset sequence correctly (write 0, then write 1). Signed-off-by: Keith Packard --- src/lpc/ao_spi_lpc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lpc/ao_spi_lpc.c b/src/lpc/ao_spi_lpc.c index ff107e40..c3587698 100644 --- a/src/lpc/ao_spi_lpc.c +++ b/src/lpc/ao_spi_lpc.c @@ -199,7 +199,8 @@ ao_spi_init(void) /* Turn on the clock */ lpc_scb.ssp1clkdiv = 1; - /* De-assert reset */ + /* Reset the device */ + lpc_scb.presetctrl &= ~(1 << LPC_SCB_PRESETCTRL_SSP1_RST_N); lpc_scb.presetctrl |= (1 << LPC_SCB_PRESETCTRL_SSP1_RST_N); ao_spi_channel_init(1); #endif /* HAS_SPI_1 */ -- cgit v1.2.3 From 35b120c4154df0351c3a802f86dda224a7643068 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:27:53 -0700 Subject: altos/lpc: Force idle mode if USB gets an address during boot time This lets EasyMini be booted to idle mode by simply plugging it into USB. Signed-off-by: Keith Packard --- src/lpc/ao_usb_lpc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index 8070acc3..aac0df04 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -605,8 +605,14 @@ ao_usb_ep0_handle(uint8_t receive) /* Wait until the IN packet is received from addr 0 * before assigning our local address */ - if (ao_usb_address_pending) + if (ao_usb_address_pending) { +#if HAS_FLIGHT + /* Go to idle mode if USB is connected + */ + ao_flight_force_idle = 1; +#endif ao_usb_set_address(ao_usb_address); + } if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN) ao_usb_ep0_flush(); } -- cgit v1.2.3 From 455802b7e853956180799c058e9561876d98d831 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:30:49 -0700 Subject: altos/easymini: Easymini doesn't have USB connect or VBUS wiring Disable these in ao_pins.h Signed-off-by: Keith Packard --- src/easymini-v0.1/ao_pins.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/easymini-v0.1/ao_pins.h b/src/easymini-v0.1/ao_pins.h index 2307d7d2..bf602787 100644 --- a/src/easymini-v0.1/ao_pins.h +++ b/src/easymini-v0.1/ao_pins.h @@ -36,8 +36,8 @@ #define HAS_USB 1 -#define HAS_USB_CONNECT 1 -#define HAS_USB_VBUS 1 +#define HAS_USB_CONNECT 0 +#define HAS_USB_VBUS 0 #define PACKET_HAS_SLAVE 0 -- cgit v1.2.3 From 16eb0b04df3d1db65bd40717133abe94db0f2a15 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:31:48 -0700 Subject: altos/easymini: MS5607 chip select bits were defined wrong Signed-off-by: Keith Packard --- src/easymini-v0.1/ao_pins.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/easymini-v0.1/ao_pins.h b/src/easymini-v0.1/ao_pins.h index bf602787..fdeb3039 100644 --- a/src/easymini-v0.1/ao_pins.h +++ b/src/easymini-v0.1/ao_pins.h @@ -73,10 +73,10 @@ #define AO_MS5607_PRIVATE_PINS 0 #define AO_MS5607_CS_PORT 0 #define AO_MS5607_CS_PIN 7 -#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) +#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS_PIN) #define AO_MS5607_MISO_PORT 0 #define AO_MS5607_MISO_PIN 8 -#define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO) +#define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO_PIN) #define AO_MS5607_SPI_INDEX 0 #define HAS_ACCEL 0 -- cgit v1.2.3 From a87a8e8067d7b2d0ff3a3274af9f1e919b5b7793 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:32:34 -0700 Subject: altos/easymini: Use different pins for igniter outputs Was using the I2C outputs which are open drain, which makes it impossible to force them high as needed to driver our igniters. Signed-off-by: Keith Packard --- src/easymini-v0.1/ao_pins.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/easymini-v0.1/ao_pins.h b/src/easymini-v0.1/ao_pins.h index fdeb3039..12d6c5db 100644 --- a/src/easymini-v0.1/ao_pins.h +++ b/src/easymini-v0.1/ao_pins.h @@ -117,11 +117,11 @@ struct ao_adc { #define AO_IGNITER_OPEN 60 #define AO_IGNITER_DROGUE_PORT 0 -#define AO_IGNITER_DROGUE_PIN 4 +#define AO_IGNITER_DROGUE_PIN 2 #define AO_IGNITER_SET_DROGUE(v) ao_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, AO_IGNITER_DROGUE, v) #define AO_IGNITER_MAIN_PORT 0 -#define AO_IGNITER_MAIN_PIN 5 +#define AO_IGNITER_MAIN_PIN 3 #define AO_IGNITER_SET_MAIN(v) ao_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, AO_IGNITER_MAIN, v) #define AO_ADC_DUMP(p) \ -- cgit v1.2.3 From a4df2575b4e782e83cc4e9b1d2e5cd2397a97dd8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 20:33:35 -0700 Subject: altos/easymini: Initialize beep and ADC. Declare use of igniter bits. This makes easymini actually work! Signed-off-by: Keith Packard --- src/easymini-v0.1/ao_easymini.c | 6 ++++-- src/easymini-v0.1/ao_pins.h | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/easymini-v0.1/ao_easymini.c b/src/easymini-v0.1/ao_easymini.c index ce70398e..97230b61 100644 --- a/src/easymini-v0.1/ao_easymini.c +++ b/src/easymini-v0.1/ao_easymini.c @@ -26,19 +26,21 @@ main(void) ao_timer_init(); ao_exti_init(); + ao_beep_init(); + + ao_adc_init(); ao_spi_init(); ao_storage_init(); ao_usb_init(); ao_cmd_init(); -#if 0 ao_flight_init(); ao_ms5607_init(); ao_log_init(); ao_report_init(); ao_igniter_init(); -#endif ao_config_init(); + ao_start_scheduler(); } diff --git a/src/easymini-v0.1/ao_pins.h b/src/easymini-v0.1/ao_pins.h index 12d6c5db..4102c21d 100644 --- a/src/easymini-v0.1/ao_pins.h +++ b/src/easymini-v0.1/ao_pins.h @@ -88,6 +88,8 @@ #define HAS_APRS 0 #define HAS_LOG 1 #define USE_INTERNAL_FLASH 0 +#define HAS_IGNITE 1 +#define HAS_IGNITE_REPORT 1 #define AO_DATA_RING 16 -- cgit v1.2.3 From 57b4d82dee10b142b820aa306028a288a85214f6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 19 May 2013 23:07:54 -0700 Subject: Add Mini logging format. Use in EasyMini This is a 16-byte record that includes all of the sensor data in each sensor record, along with records for flight state changes. Signed-off-by: Keith Packard --- altoslib/AltosEepromMini.java | 193 ++++++++++++++++++++++ altoslib/AltosEepromMiniIterable.java | 297 ++++++++++++++++++++++++++++++++++ altoslib/AltosLib.java | 1 + altoslib/AltosOrderedMiniRecord.java | 52 ++++++ altoslib/AltosRecordMini.java | 129 +++++++++++++++ altoslib/Makefile.am | 4 + altosui/AltosDataChooser.java | 7 +- altosui/AltosEepromDownload.java | 50 ++++++ altosui/AltosLanded.java | 3 + altosui/AltosUI.java | 4 + src/core/ao_log.h | 38 +++++ src/core/ao_log_mini.c | 163 +++++++++++++++++++ src/easymini-v0.1/Makefile | 2 +- src/easymini-v0.1/ao_pins.h | 9 +- 14 files changed, 947 insertions(+), 5 deletions(-) create mode 100644 altoslib/AltosEepromMini.java create mode 100644 altoslib/AltosEepromMiniIterable.java create mode 100644 altoslib/AltosOrderedMiniRecord.java create mode 100644 altoslib/AltosRecordMini.java create mode 100644 src/core/ao_log_mini.c (limited to 'src') diff --git a/altoslib/AltosEepromMini.java b/altoslib/AltosEepromMini.java new file mode 100644 index 00000000..215cd3d9 --- /dev/null +++ b/altoslib/AltosEepromMini.java @@ -0,0 +1,193 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_1; + +import java.text.*; + +public class AltosEepromMini { + public int cmd; + public int tick; + public boolean valid; + public String data; + public int config_a, config_b; + + public int data8[]; + + public static final int record_length = 16; + static final int header_length = 4; + static final int data_length = record_length - header_length; + + public int data8(int i) { + return data8[i]; + } + + public int data16(int i) { + return ((data8[i] | (data8[i+1] << 8)) << 16) >> 16; + } + + public int data24(int i) { + return data8[i] | (data8[i+1] << 8) | (data8[i+2] << 16); + } + + public int data32(int i) { + return data8[i] | (data8[i+1] << 8) | (data8[i+2] << 16) | (data8[i+3] << 24); + } + + /* AO_LOG_FLIGHT elements */ + public int flight() { return data16(0); } + public int ground_pres() { return data32(4); } + + /* AO_LOG_STATE elements */ + public int state() { return data16(0); } + public int reason() { return data16(2); } + + /* AO_LOG_SENSOR elements */ + public int pres() { return data24(0); } + public int temp() { return data24(3); } + public int sense_a() { return data16(6); } + public int sense_m() { return data16(8); } + public int v_batt() { return data16(10); } + + public AltosEepromMini (AltosEepromChunk chunk, int start) throws ParseException { + cmd = chunk.data(start); + + valid = !chunk.erased(start, record_length); + if (valid) { + if (AltosConvert.checksum(chunk.data, start, record_length) != 0) + throw new ParseException(String.format("invalid checksum at 0x%x", + chunk.address + start), 0); + } else { + cmd = AltosLib.AO_LOG_INVALID; + } + + tick = chunk.data16(start+2); + + data8 = new int[data_length]; + for (int i = 0; i < data_length; i++) + data8[i] = chunk.data(start + header_length + i); + } + + public AltosEepromMini (String line) { + valid = false; + tick = 0; + + if (line == null) { + cmd = AltosLib.AO_LOG_INVALID; + line = ""; + } else { + try { + String[] tokens = line.split("\\s+"); + + if (tokens[0].length() == 1) { + if (tokens.length != 2 + data_length) { + cmd = AltosLib.AO_LOG_INVALID; + data = line; + } else { + cmd = tokens[0].codePointAt(0); + tick = Integer.parseInt(tokens[1],16); + valid = true; + data8 = new int[data_length]; + for (int i = 0; i < data_length; i++) + data8[i] = Integer.parseInt(tokens[2 + i],16); + } + } else if (tokens[0].equals("Config") && tokens[1].equals("version:")) { + cmd = AltosLib.AO_LOG_CONFIG_VERSION; + data = tokens[2]; + } else if (tokens[0].equals("Main") && tokens[1].equals("deploy:")) { + cmd = AltosLib.AO_LOG_MAIN_DEPLOY; + config_a = Integer.parseInt(tokens[2]); + } else if (tokens[0].equals("Apogee") && tokens[1].equals("delay:")) { + cmd = AltosLib.AO_LOG_APOGEE_DELAY; + config_a = Integer.parseInt(tokens[2]); + } else if (tokens[0].equals("Radio") && tokens[1].equals("channel:")) { + cmd = AltosLib.AO_LOG_RADIO_CHANNEL; + config_a = Integer.parseInt(tokens[2]); + } else if (tokens[0].equals("Callsign:")) { + cmd = AltosLib.AO_LOG_CALLSIGN; + data = tokens[1].replaceAll("\"",""); + } else if (tokens[0].equals("Accel") && tokens[1].equals("cal")) { + cmd = AltosLib.AO_LOG_ACCEL_CAL; + config_a = Integer.parseInt(tokens[3]); + config_b = Integer.parseInt(tokens[5]); + } else if (tokens[0].equals("Radio") && tokens[1].equals("cal:")) { + cmd = AltosLib.AO_LOG_RADIO_CAL; + config_a = Integer.parseInt(tokens[2]); + } else if (tokens[0].equals("Max") && tokens[1].equals("flight") && tokens[2].equals("log:")) { + cmd = AltosLib.AO_LOG_MAX_FLIGHT_LOG; + config_a = Integer.parseInt(tokens[3]); + } else if (tokens[0].equals("manufacturer")) { + cmd = AltosLib.AO_LOG_MANUFACTURER; + data = tokens[1]; + } else if (tokens[0].equals("product")) { + cmd = AltosLib.AO_LOG_PRODUCT; + data = tokens[1]; + } else if (tokens[0].equals("serial-number")) { + cmd = AltosLib.AO_LOG_SERIAL_NUMBER; + config_a = Integer.parseInt(tokens[1]); + } else if (tokens[0].equals("log-format")) { + cmd = AltosLib.AO_LOG_LOG_FORMAT; + config_a = Integer.parseInt(tokens[1]); + } else if (tokens[0].equals("software-version")) { + cmd = AltosLib.AO_LOG_SOFTWARE_VERSION; + data = tokens[1]; + } else if (tokens[0].equals("ms5607")) { + if (tokens[1].equals("reserved:")) { + cmd = AltosLib.AO_LOG_BARO_RESERVED; + config_a = Integer.parseInt(tokens[2]); + } else if (tokens[1].equals("sens:")) { + cmd = AltosLib.AO_LOG_BARO_SENS; + config_a = Integer.parseInt(tokens[2]); + } else if (tokens[1].equals("off:")) { + cmd = AltosLib.AO_LOG_BARO_OFF; + config_a = Integer.parseInt(tokens[2]); + } else if (tokens[1].equals("tcs:")) { + cmd = AltosLib.AO_LOG_BARO_TCS; + config_a = Integer.parseInt(tokens[2]); + } else if (tokens[1].equals("tco:")) { + cmd = AltosLib.AO_LOG_BARO_TCO; + config_a = Integer.parseInt(tokens[2]); + } else if (tokens[1].equals("tref:")) { + cmd = AltosLib.AO_LOG_BARO_TREF; + config_a = Integer.parseInt(tokens[2]); + } else if (tokens[1].equals("tempsens:")) { + cmd = AltosLib.AO_LOG_BARO_TEMPSENS; + config_a = Integer.parseInt(tokens[2]); + } else if (tokens[1].equals("crc:")) { + cmd = AltosLib.AO_LOG_BARO_CRC; + config_a = Integer.parseInt(tokens[2]); + } else { + cmd = AltosLib.AO_LOG_INVALID; + data = line; + } + } else { + cmd = AltosLib.AO_LOG_INVALID; + data = line; + } + } catch (NumberFormatException ne) { + cmd = AltosLib.AO_LOG_INVALID; + data = line; + } + } + } + + public AltosEepromMini(int in_cmd, int in_tick) { + cmd = in_cmd; + tick = in_tick; + valid = true; + } +} diff --git a/altoslib/AltosEepromMiniIterable.java b/altoslib/AltosEepromMiniIterable.java new file mode 100644 index 00000000..1f221187 --- /dev/null +++ b/altoslib/AltosEepromMiniIterable.java @@ -0,0 +1,297 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_1; + +import java.io.*; +import java.util.*; +import java.text.*; + +public class AltosEepromMiniIterable extends AltosRecordIterable { + + static final int seen_flight = 1; + static final int seen_sensor = 2; + + static final int seen_basic = seen_flight|seen_sensor; + + boolean has_accel; + boolean has_gps; + boolean has_ignite; + + AltosEepromMini flight_record; + + TreeSet records; + + AltosMs5607 baro; + + LinkedList list; + + class EepromState { + int seen; + int n_pad_samples; + double ground_pres; + int boost_tick; + int sensor_tick; + + EepromState() { + seen = 0; + n_pad_samples = 0; + ground_pres = 0.0; + } + } + + void update_state(AltosRecordMini state, AltosEepromMini record, EepromState eeprom) { + state.tick = record.tick; + switch (record.cmd) { + case AltosLib.AO_LOG_FLIGHT: + eeprom.seen |= seen_flight; + state.ground_pres = record.ground_pres(); + state.flight_pres = state.ground_pres; + state.flight = record.data16(0); + eeprom.boost_tick = record.tick; + break; + case AltosLib.AO_LOG_SENSOR: + baro.set(record.pres(), record.temp()); + state.pres = baro.pa; + state.temp = baro.cc; + state.sense_m = record.sense_m(); + state.sense_a = record.sense_a(); + state.v_batt = record.v_batt(); + if (state.state < AltosLib.ao_flight_boost) { + eeprom.n_pad_samples++; + eeprom.ground_pres += state.pres; + state.ground_pres = (int) (eeprom.ground_pres / eeprom.n_pad_samples); + state.flight_pres = state.ground_pres; + } else { + state.flight_pres = (state.flight_pres * 15 + state.pres) / 16; + } + if ((eeprom.seen & seen_sensor) == 0) + eeprom.sensor_tick = record.tick - 1; + eeprom.seen |= seen_sensor; + eeprom.sensor_tick = record.tick; + break; + case AltosLib.AO_LOG_STATE: + state.state = record.state(); + break; + case AltosLib.AO_LOG_CONFIG_VERSION: + break; + case AltosLib.AO_LOG_MAIN_DEPLOY: + break; + case AltosLib.AO_LOG_APOGEE_DELAY: + break; + case AltosLib.AO_LOG_RADIO_CHANNEL: + break; + case AltosLib.AO_LOG_CALLSIGN: + state.callsign = record.data; + break; + case AltosLib.AO_LOG_RADIO_CAL: + break; + case AltosLib.AO_LOG_MANUFACTURER: + break; + case AltosLib.AO_LOG_PRODUCT: + break; + case AltosLib.AO_LOG_SERIAL_NUMBER: + state.serial = record.config_a; + break; + case AltosLib.AO_LOG_SOFTWARE_VERSION: + break; + case AltosLib.AO_LOG_BARO_RESERVED: + baro.reserved = record.config_a; + break; + case AltosLib.AO_LOG_BARO_SENS: + baro.sens =record.config_a; + break; + case AltosLib.AO_LOG_BARO_OFF: + baro.off =record.config_a; + break; + case AltosLib.AO_LOG_BARO_TCS: + baro.tcs =record.config_a; + break; + case AltosLib.AO_LOG_BARO_TCO: + baro.tco =record.config_a; + break; + case AltosLib.AO_LOG_BARO_TREF: + baro.tref =record.config_a; + break; + case AltosLib.AO_LOG_BARO_TEMPSENS: + baro.tempsens =record.config_a; + break; + case AltosLib.AO_LOG_BARO_CRC: + baro.crc =record.config_a; + break; + } + state.seen |= eeprom.seen; + } + + LinkedList make_list() { + LinkedList list = new LinkedList(); + Iterator iterator = records.iterator(); + AltosOrderedMiniRecord record = null; + AltosRecordMini state = new AltosRecordMini(); + //boolean last_reported = false; + EepromState eeprom = new EepromState(); + + state.state = AltosLib.ao_flight_pad; + + /* Pull in static data from the flight records */ + if (flight_record != null) + update_state(state, flight_record, eeprom); + + while (iterator.hasNext()) { + record = iterator.next(); + if ((eeprom.seen & seen_basic) == seen_basic && record.tick != state.tick) { + AltosRecordMini r = state.clone(); + r.time = (r.tick - eeprom.boost_tick) / 100.0; + list.add(r); + } + update_state(state, record, eeprom); + } + AltosRecordMini r = state.clone(); + r.time = (r.tick - eeprom.boost_tick) / 100.0; + list.add(r); + return list; + } + + public Iterator iterator() { + if (list == null) + list = make_list(); + return list.iterator(); + } + + public boolean has_gps() { return has_gps; } + public boolean has_accel() { return has_accel; } + public boolean has_ignite() { return has_ignite; } + + public void write_comments(PrintStream out) { + Iterator iterator = records.iterator(); + out.printf("# Comments\n"); + while (iterator.hasNext()) { + AltosOrderedMiniRecord record = iterator.next(); + switch (record.cmd) { + case AltosLib.AO_LOG_CONFIG_VERSION: + out.printf("# Config version: %s\n", record.data); + break; + case AltosLib.AO_LOG_MAIN_DEPLOY: + out.printf("# Main deploy: %s\n", record.config_a); + break; + case AltosLib.AO_LOG_APOGEE_DELAY: + out.printf("# Apogee delay: %s\n", record.config_a); + break; + case AltosLib.AO_LOG_RADIO_CHANNEL: + out.printf("# Radio channel: %s\n", record.config_a); + break; + case AltosLib.AO_LOG_CALLSIGN: + out.printf("# Callsign: %s\n", record.data); + break; + case AltosLib.AO_LOG_ACCEL_CAL: + out.printf ("# Accel cal: %d %d\n", record.config_a, record.config_b); + break; + case AltosLib.AO_LOG_RADIO_CAL: + out.printf ("# Radio cal: %d\n", record.config_a); + break; + case AltosLib.AO_LOG_MAX_FLIGHT_LOG: + out.printf ("# Max flight log: %d\n", record.config_a); + break; + case AltosLib.AO_LOG_MANUFACTURER: + out.printf ("# Manufacturer: %s\n", record.data); + break; + case AltosLib.AO_LOG_PRODUCT: + out.printf ("# Product: %s\n", record.data); + break; + case AltosLib.AO_LOG_SERIAL_NUMBER: + out.printf ("# Serial number: %d\n", record.config_a); + break; + case AltosLib.AO_LOG_SOFTWARE_VERSION: + out.printf ("# Software version: %s\n", record.data); + break; + case AltosLib.AO_LOG_BARO_RESERVED: + out.printf ("# Baro reserved: %d\n", record.config_a); + break; + case AltosLib.AO_LOG_BARO_SENS: + out.printf ("# Baro sens: %d\n", record.config_a); + break; + case AltosLib.AO_LOG_BARO_OFF: + out.printf ("# Baro off: %d\n", record.config_a); + break; + case AltosLib.AO_LOG_BARO_TCS: + out.printf ("# Baro tcs: %d\n", record.config_a); + break; + case AltosLib.AO_LOG_BARO_TCO: + out.printf ("# Baro tco: %d\n", record.config_a); + break; + case AltosLib.AO_LOG_BARO_TREF: + out.printf ("# Baro tref: %d\n", record.config_a); + break; + case AltosLib.AO_LOG_BARO_TEMPSENS: + out.printf ("# Baro tempsens: %d\n", record.config_a); + break; + case AltosLib.AO_LOG_BARO_CRC: + out.printf ("# Baro crc: %d\n", record.config_a); + break; + } + } + } + + /* + * Read the whole file, dumping records into a RB tree so + * we can enumerate them in time order -- the eeprom data + * are sometimes out of order + */ + public AltosEepromMiniIterable (FileInputStream input) { + records = new TreeSet(); + + AltosOrderedMiniRecord last_gps_time = null; + + baro = new AltosMs5607(); + + int index = 0; + int prev_tick = 0; + boolean prev_tick_valid = false; + boolean missing_time = false; + + try { + for (;;) { + String line = AltosLib.gets(input); + if (line == null) + break; + AltosOrderedMiniRecord record = new AltosOrderedMiniRecord(line, index++, prev_tick, prev_tick_valid); + if (record.cmd == AltosLib.AO_LOG_INVALID) + continue; + prev_tick = record.tick; + if (record.cmd < AltosLib.AO_LOG_CONFIG_VERSION) + prev_tick_valid = true; + if (record.cmd == AltosLib.AO_LOG_FLIGHT) { + flight_record = record; + continue; + } + + records.add(record); + + /* Bail after reading the 'landed' record; we're all done */ + if (record.cmd == AltosLib.AO_LOG_STATE && + record.state() == AltosLib.ao_flight_landed) + break; + } + } catch (IOException io) { + } catch (ParseException pe) { + } + try { + input.close(); + } catch (IOException ie) { + } + } +} diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index 25d17e72..a629260b 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -216,6 +216,7 @@ public class AltosLib { public static final int AO_LOG_FORMAT_TELEMETRY = 3; public static final int AO_LOG_FORMAT_TELESCIENCE = 4; public static final int AO_LOG_FORMAT_TELEMEGA = 5; + public static final int AO_LOG_FORMAT_MINI = 6; public static final int AO_LOG_FORMAT_NONE = 127; public static boolean isspace(int c) { diff --git a/altoslib/AltosOrderedMiniRecord.java b/altoslib/AltosOrderedMiniRecord.java new file mode 100644 index 00000000..96888941 --- /dev/null +++ b/altoslib/AltosOrderedMiniRecord.java @@ -0,0 +1,52 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_1; + +import java.text.ParseException; + +/* + * AltosRecords with an index field so they can be sorted by tick while preserving + * the original ordering for elements with matching ticks + */ +class AltosOrderedMiniRecord extends AltosEepromMini implements Comparable { + + public int index; + + public AltosOrderedMiniRecord(String line, int in_index, int prev_tick, boolean prev_tick_valid) + throws ParseException { + super(line); + if (prev_tick_valid) { + tick |= (prev_tick & ~0xffff); + if (tick < prev_tick) { + if (prev_tick - tick > 0x8000) + tick += 0x10000; + } else { + if (tick - prev_tick > 0x8000) + tick -= 0x10000; + } + } + index = in_index; + } + + public int compareTo(AltosOrderedMiniRecord o) { + int tick_diff = tick - o.tick; + if (tick_diff != 0) + return tick_diff; + return index - o.index; + } +} diff --git a/altoslib/AltosRecordMini.java b/altoslib/AltosRecordMini.java new file mode 100644 index 00000000..253f3804 --- /dev/null +++ b/altoslib/AltosRecordMini.java @@ -0,0 +1,129 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_1; + +public class AltosRecordMini extends AltosRecord { + + /* Sensor values */ + public int pres; + public int temp; + + public int sense_a; + public int sense_m; + public int v_batt; + + public int ground_pres; + + public int flight_accel; + public int flight_vel; + public int flight_pres; + + static double adc(int raw) { + return raw / 4095.0; + } + + public double pressure() { + if (pres != MISSING) + return pres; + return MISSING; + } + + public double temperature() { + if (temp != MISSING) + return temp; + return MISSING; + } + + public double ground_pressure() { + if (ground_pres != MISSING) + return ground_pres; + return MISSING; + } + + public double battery_voltage() { + if (v_batt != MISSING) + return 3.3 * adc(v_batt) * (15.0 + 27.0) / 27.0; + return MISSING; + } + + static double pyro(int raw) { + if (raw != MISSING) + return 3.3 * adc(raw) * (100.0 + 27.0) / 27.0; + return MISSING; + } + + public double main_voltage() { + return pyro(sense_m); + } + + public double apogee_voltage() { + return pyro(sense_a); + } + + public void copy (AltosRecordMini old) { + super.copy(old); + + pres = old.pres; + temp = old.temp; + + sense_a = old.sense_a; + sense_m = old.sense_m; + v_batt = old.v_batt; + + ground_pres = old.ground_pres; + + flight_accel = old.flight_accel; + flight_vel = old.flight_vel; + flight_pres = old.flight_pres; + } + + + + public AltosRecordMini clone() { + return new AltosRecordMini(this); + } + + void make_missing() { + + pres = MISSING; + + sense_a = MISSING; + sense_m = MISSING; + v_batt = MISSING; + + ground_pres = MISSING; + + flight_accel = 0; + flight_vel = 0; + flight_pres = 0; + } + + public AltosRecordMini(AltosRecord old) { + super.copy(old); + make_missing(); + } + + public AltosRecordMini(AltosRecordMini old) { + copy(old); + } + + public AltosRecordMini() { + super(); + make_missing(); + } +} diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index 18b028d6..8c1cf2ad 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -24,6 +24,8 @@ altoslib_JAVA = \ AltosEepromMegaIterable.java \ AltosEepromRecord.java \ AltosEepromTeleScience.java \ + AltosEepromMini.java \ + AltosEepromMiniIterable.java \ AltosFile.java \ AltosFlash.java \ AltosFlashListener.java \ @@ -47,6 +49,7 @@ altoslib_JAVA = \ AltosMs5607Query.java \ AltosOrderedRecord.java \ AltosOrderedMegaRecord.java \ + AltosOrderedMiniRecord.java \ AltosParse.java \ AltosPreferences.java \ AltosPreferencesBackend.java \ @@ -56,6 +59,7 @@ altoslib_JAVA = \ AltosRecordNone.java \ AltosRecordTM.java \ AltosRecordMM.java \ + AltosRecordMini.java \ AltosReplayReader.java \ AltosRomconfig.java \ AltosSensorMM.java \ diff --git a/altosui/AltosDataChooser.java b/altosui/AltosDataChooser.java index f914f138..c7b561d5 100644 --- a/altosui/AltosDataChooser.java +++ b/altosui/AltosDataChooser.java @@ -55,6 +55,9 @@ public class AltosDataChooser extends JFileChooser { } else if (filename.endsWith("mega")) { FileInputStream in = new FileInputStream(file); return new AltosEepromMegaIterable(in); + } else if (filename.endsWith("mini")) { + FileInputStream in = new FileInputStream(file); + return new AltosEepromMiniIterable(in); } else { throw new FileNotFoundException(); } @@ -77,8 +80,10 @@ public class AltosDataChooser extends JFileChooser { "telem")); setFileFilter(new FileNameExtensionFilter("TeleMega eeprom file", "mega")); + setFileFilter(new FileNameExtensionFilter("EasyMini eeprom file", + "mini")); setFileFilter(new FileNameExtensionFilter("Flight data file", - "telem", "eeprom", "mega")); + "telem", "eeprom", "mega", "mini")); setCurrentDirectory(AltosUIPreferences.logdir()); } } diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index a0523b58..53d5433f 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -302,6 +302,53 @@ public class AltosEepromDownload implements Runnable { CheckFile(false); } + void LogMini(AltosEepromMini r) throws IOException { + if (r.cmd != Altos.AO_LOG_INVALID) { + String log_line = String.format("%c %4x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x\n", + r.cmd, r.tick, + r.data8[0], r.data8[1], r.data8[2], r.data8[3], + r.data8[4], r.data8[5], r.data8[6], r.data8[7], + r.data8[8], r.data8[9], r.data8[10], r.data8[11]); + if (eeprom_file != null) + eeprom_file.write(log_line); + else + eeprom_pending.add(log_line); + } + } + + void CaptureMini(AltosEepromChunk eechunk) throws IOException { + boolean any_valid = false; + + extension = "mini"; + set_serial(flights.config_data.serial); + for (int i = 0; i < AltosEepromChunk.chunk_size && !done; i += AltosEepromMini.record_length) { + try { + AltosEepromMini r = new AltosEepromMini(eechunk, i); + if (r.cmd == Altos.AO_LOG_FLIGHT) + set_flight(r.data16(0)); + + /* Monitor state transitions to update display */ + if (r.cmd == Altos.AO_LOG_STATE && r.data16(0) <= Altos.ao_flight_landed) { + state = r.data16(0); + if (state > Altos.ao_flight_pad) + want_file = true; + } + + if (r.cmd == Altos.AO_LOG_STATE && r.data16(0) == Altos.ao_flight_landed) + done = true; + any_valid = true; + LogMini(r); + } catch (ParseException pe) { + if (parse_exception == null) + parse_exception = pe; + } + } + if (!any_valid) + done = true; + + CheckFile(false); + } + void CaptureTelemetry(AltosEepromChunk eechunk) throws IOException { } @@ -369,6 +416,9 @@ public class AltosEepromDownload implements Runnable { case AltosLib.AO_LOG_FORMAT_TELEMEGA: extension = "mega"; CaptureMega(eechunk); + case AltosLib.AO_LOG_FORMAT_MINI: + extension = "mini"; + CaptureMini(eechunk); } } CheckFile(true); diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java index 1d209bda..9dab52c4 100644 --- a/altosui/AltosLanded.java +++ b/altosui/AltosLanded.java @@ -253,6 +253,9 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio } else if (filename.endsWith("mega")) { FileInputStream in = new FileInputStream(file); records = new AltosEepromMegaIterable(in); + } else if (filename.endsWith("mini")) { + FileInputStream in = new FileInputStream(file); + records = new AltosEepromMiniIterable(in); } else { throw new FileNotFoundException(filename); } diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 9f8f6dda..4362e36c 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -354,6 +354,8 @@ public class AltosUI extends AltosUIFrame { return new AltosEepromIterable(in); else if (file.getName().endsWith("mega")) return new AltosEepromMegaIterable(in); + else if (file.getName().endsWith("mini")) + return new AltosEepromMiniIterable(in); else return new AltosTelemetryIterable(in); } catch (FileNotFoundException fe) { @@ -441,6 +443,8 @@ public class AltosUI extends AltosUIFrame { recs = new AltosEepromIterable(in); } else if (file.getName().endsWith("mega")) { recs = new AltosEepromMegaIterable(in); + } else if (file.getName().endsWith("mini")) { + recs = new AltosEepromMiniIterable(in); } else { recs = new AltosTelemetryIterable(in); } diff --git a/src/core/ao_log.h b/src/core/ao_log.h index a68a40dd..95b37649 100644 --- a/src/core/ao_log.h +++ b/src/core/ao_log.h @@ -44,6 +44,7 @@ extern __pdata enum ao_flight_state ao_log_state; #define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */ #define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ #define AO_LOG_FORMAT_TELEMEGA 5 /* 32 byte typed telemega records */ +#define AO_LOG_FORMAT_MINI 6 /* 16-byte MS5607 baro only */ #define AO_LOG_FORMAT_NONE 127 /* No log at all */ extern __code uint8_t ao_log_format; @@ -261,6 +262,40 @@ struct ao_log_mega { } u; }; +struct ao_log_mini { + char type; /* 0 */ + uint8_t csum; /* 1 */ + uint16_t tick; /* 2 */ + union { /* 4 */ + /* AO_LOG_FLIGHT */ + struct { + uint16_t flight; /* 4 */ + uint16_t r6; + uint32_t ground_pres; /* 8 */ + } flight; + /* AO_LOG_STATE */ + struct { + uint16_t state; /* 4 */ + uint16_t reason; /* 6 */ + } state; + /* AO_LOG_SENSOR */ + struct { + uint8_t pres[3]; /* 4 */ + uint8_t temp[3]; /* 7 */ + int16_t sense_a; /* 10 */ + int16_t sense_m; /* 12 */ + int16_t v_batt; /* 14 */ + } sensor; /* 16 */ + } u; /* 16 */ +}; /* 16 */ + +static inline void +ao_log_pack24(uint8_t *dst, uint32_t value) { + dst[0] = value; + dst[1] = value >> 8; + dst[2] = value >> 16; +} + /* Write a record to the eeprom log */ uint8_t ao_log_data(__xdata struct ao_log_record *log) __reentrant; @@ -268,6 +303,9 @@ ao_log_data(__xdata struct ao_log_record *log) __reentrant; uint8_t ao_log_mega(__xdata struct ao_log_mega *log) __reentrant; +uint8_t +ao_log_mini(__xdata struct ao_log_mini *log) __reentrant; + void ao_log_flush(void); diff --git a/src/core/ao_log_mini.c b/src/core/ao_log_mini.c new file mode 100644 index 00000000..1273b0e3 --- /dev/null +++ b/src/core/ao_log_mini.c @@ -0,0 +1,163 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include +#include +#include + +static __xdata uint8_t ao_log_mutex; +static __xdata struct ao_log_mini log; + +__code uint8_t ao_log_format = AO_LOG_FORMAT_MINI; + +static uint8_t +ao_log_csum(__xdata uint8_t *b) __reentrant +{ + uint8_t sum = 0x5a; + uint8_t i; + + for (i = 0; i < sizeof (struct ao_log_mini); i++) + sum += *b++; + return -sum; +} + +uint8_t +ao_log_mini(__xdata struct ao_log_mini *log) __reentrant +{ + uint8_t wrote = 0; + /* set checksum */ + log->csum = 0; + log->csum = ao_log_csum((__xdata uint8_t *) log); + ao_mutex_get(&ao_log_mutex); { + if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_stop(); + if (ao_log_running) { + wrote = 1; + ao_storage_write(ao_log_current_pos, + log, + sizeof (struct ao_log_mini)); + ao_log_current_pos += sizeof (struct ao_log_mini); + } + } ao_mutex_put(&ao_log_mutex); + return wrote; +} + +static uint8_t +ao_log_dump_check_data(void) +{ + if (ao_log_csum((uint8_t *) &log) != 0) + return 0; + return 1; +} + +static __data uint8_t ao_log_data_pos; + +/* a hack to make sure that ao_log_minis fill the eeprom block in even units */ +typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_mini))] ; + +#ifndef AO_SENSOR_INTERVAL_ASCENT +#define AO_SENSOR_INTERVAL_ASCENT 1 +#define AO_SENSOR_INTERVAL_DESCENT 10 +#endif + +void +ao_log(void) +{ + __pdata uint16_t next_sensor, next_other; + uint8_t i; + + ao_storage_setup(); + + ao_log_scan(); + + while (!ao_log_running) + ao_sleep(&ao_log_running); + +#if HAS_FLIGHT + log.type = AO_LOG_FLIGHT; + log.tick = ao_sample_tick; + log.u.flight.flight = ao_flight_number; + log.u.flight.ground_pres = ao_ground_pres; + ao_log_mini(&log); +#endif + + /* Write the whole contents of the ring to the log + * when starting up. + */ + ao_log_data_pos = ao_data_ring_next(ao_data_head); + next_other = next_sensor = ao_data_ring[ao_log_data_pos].tick; + ao_log_state = ao_flight_startup; + for (;;) { + /* Write samples to EEPROM */ + while (ao_log_data_pos != ao_data_head) { + log.tick = ao_data_ring[ao_log_data_pos].tick; + if ((int16_t) (log.tick - next_sensor) >= 0) { + log.type = AO_LOG_SENSOR; + ao_log_pack24(log.u.sensor.pres, + ao_data_ring[ao_log_data_pos].ms5607_raw.pres); + ao_log_pack24(log.u.sensor.temp, + ao_data_ring[ao_log_data_pos].ms5607_raw.temp); + log.u.sensor.sense_a = ao_data_ring[ao_log_data_pos].adc.sense_a; + log.u.sensor.sense_m = ao_data_ring[ao_log_data_pos].adc.sense_m; + log.u.sensor.v_batt = ao_data_ring[ao_log_data_pos].adc.v_batt; + ao_log_mini(&log); + if (ao_log_state <= ao_flight_coast) + next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; + else + next_sensor = log.tick + AO_SENSOR_INTERVAL_DESCENT; + } + ao_log_data_pos = ao_data_ring_next(ao_log_data_pos); + } +#if HAS_FLIGHT + /* Write state change to EEPROM */ + if (ao_flight_state != ao_log_state) { + ao_log_state = ao_flight_state; + log.type = AO_LOG_STATE; + log.tick = ao_time(); + log.u.state.state = ao_log_state; + log.u.state.reason = 0; + ao_log_mini(&log); + + if (ao_log_state == ao_flight_landed) + ao_log_stop(); + } +#endif + + ao_log_flush(); + + /* Wait for a while */ + ao_delay(AO_MS_TO_TICKS(100)); + + /* Stop logging when told to */ + while (!ao_log_running) + ao_sleep(&ao_log_running); + } +} + +uint16_t +ao_log_flight(uint8_t slot) +{ + if (!ao_storage_read(ao_log_pos(slot), + &log, + sizeof (struct ao_log_mini))) + return 0; + + if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) + return log.u.flight.flight; + return 0; +} diff --git a/src/easymini-v0.1/Makefile b/src/easymini-v0.1/Makefile index c4e60ada..612cc472 100644 --- a/src/easymini-v0.1/Makefile +++ b/src/easymini-v0.1/Makefile @@ -34,7 +34,7 @@ ALTOS_SRC = \ ao_led_lpc.c \ ao_task.c \ ao_log.c \ - ao_log_tiny.c \ + ao_log_mini.c \ ao_cmd.c \ ao_config.c \ ao_timer_lpc.c \ diff --git a/src/easymini-v0.1/ao_pins.h b/src/easymini-v0.1/ao_pins.h index 4102c21d..d4fbe7a1 100644 --- a/src/easymini-v0.1/ao_pins.h +++ b/src/easymini-v0.1/ao_pins.h @@ -106,7 +106,7 @@ #define AO_ADC_2 1 struct ao_adc { - int16_t sense_d; + int16_t sense_a; int16_t sense_m; int16_t v_batt; }; @@ -126,6 +126,9 @@ struct ao_adc { #define AO_IGNITER_MAIN_PIN 3 #define AO_IGNITER_SET_MAIN(v) ao_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, AO_IGNITER_MAIN, v) +#define AO_SENSE_DROGUE(p) ((p)->adc.sense_a) +#define AO_SENSE_MAIN(p) ((p)->adc.sense_m) + #define AO_ADC_DUMP(p) \ - printf("tick: %5u drogue: %5d main: %5d batt: %5d\n", \ - (p)->tick, (p)->adc.sense_d, (p)->adc.sense_m, (p)->adc.v_batt) + printf("tick: %5u apogee: %5d main: %5d batt: %5d\n", \ + (p)->tick, (p)->adc.sense_a, (p)->adc.sense_m, (p)->adc.v_batt) -- cgit v1.2.3 From 1bffe8caf0294e9cfef2dab1c6b5a8d1d87ac3a2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 21 May 2013 11:08:15 -0700 Subject: altos: Set the path for the STM32L compiler explicitly This makes sure we use the known toolchain for STM32L builds Signed-off-by: Keith Packard --- src/stm/Makefile.defs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index c8bb7d70..8ef30521 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -12,8 +12,8 @@ vpath ao-make-product.5c ../util .elf.ihx: objcopy -O ihex $*.elf $@ -CC=arm-none-eabi-gcc SAT=/opt/cortex +CC=$(SAT)/bin/arm-none-eabi-gcc SAT_CLIB=$(SAT)/lib/pdclib-cortex-m3.a SAT_CFLAGS=-I$(SAT)/include -- cgit v1.2.3 From 85eb75c3251d8e141d7269fc7ffa6197174ea8c3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 21 May 2013 11:30:44 -0700 Subject: altos: Can't use inline functions because SDCC doesn't do that Sigh. Signed-off-by: Keith Packard --- src/core/ao_log.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/core/ao_log.h b/src/core/ao_log.h index 95b37649..e1461a14 100644 --- a/src/core/ao_log.h +++ b/src/core/ao_log.h @@ -289,12 +289,11 @@ struct ao_log_mini { } u; /* 16 */ }; /* 16 */ -static inline void -ao_log_pack24(uint8_t *dst, uint32_t value) { - dst[0] = value; - dst[1] = value >> 8; - dst[2] = value >> 16; -} +#define ao_log_pack24(dst,value) do { \ + (dst)[0] = (value); \ + (dst)[1] = (value) >> 8; \ + (dst)[2] = (value) >> 16; \ + } while (0) /* Write a record to the eeprom log */ uint8_t -- cgit v1.2.3 From 2344ba81fa51215471099e56518112478bdf2e73 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 21 May 2013 11:31:05 -0700 Subject: Separate out cortex-m0 compiler tests in configure The summon arm toolchain doesn't work for cortex-m0 parts, but the linaro toolchain does. Look in /usr/bin for the -m0 compiler but continue to use /opt/cortex/bin for the -m3 compiler Signed-off-by: Keith Packard --- configure.ac | 12 +++++++++--- src/Makefile | 10 ++++++++-- 2 files changed, 17 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/configure.ac b/configure.ac index 4a124c90..ba4fb302 100644 --- a/configure.ac +++ b/configure.ac @@ -185,9 +185,14 @@ if test "x$HAVE_SDCC" = "xno"; then AC_MSG_WARN([No sdcc found, cc1111 binaries will not be built]) fi -AC_CHECK_PROG([HAVE_ARM_GCC], [arm-none-eabi-gcc], yes, no) +AC_CHECK_PROG([HAVE_ARM_GCC],[arm-none-eabi-gcc], yes, no,[/opt/cortex/bin]) if test "x$HAVE_ARM_GCC" = "xno"; then - AC_MSG_WARN([No arm compiler found, STM32L and LPC11U14 binaries will not be built]) + AC_MSG_WARN([No summon toolchain arm compiler found, STM32L binaries will not be built]) +fi + +AC_CHECK_PROG([HAVE_ARM_M0_GCC], [arm-none-eabi-gcc], yes, no,[/usr/bin]) +if test "x$HAVE_ARM_M0_GCC" = "xno"; then + AC_MSG_WARN([No linaro toolchain arm cortex-m0 compiler found, LPC11U14 binaries will not be built]) fi AC_CHECK_PROG([HAVE_NICKLE], [nickle], yes, no) @@ -243,7 +248,8 @@ echo "" echo " Package: ${PACKAGE_NAME} ${PACKAGE_VERSION}" echo "" echo " Configuration" -echo " STM32L/LPC11U14 support.....: ${HAVE_ARM_GCC}" +echo " STM32L support..............: ${HAVE_ARM_GCC}" +echo " LPC11U14 support............: ${HAVE_ARM_M0_GCC}" echo " CC1111 support..............: ${HAVE_SDCC}" echo " Android support.............: ${HAVE_ANDROID_SDK}" echo " STlink support..............: ${HAVE_STLINK}" diff --git a/src/Makefile b/src/Makefile index 5851b2a8..7ffc52d6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -35,7 +35,9 @@ ARMDIRS=\ telegps-v0.1 telegps-v0.1/flash-loader \ stm-bringup stm-demo \ telelco-v0.2 telelco-v0.2/flash-loader \ - telescience-v0.2 telescience-v0.2/flash-loader \ + telescience-v0.2 telescience-v0.2/flash-loader + +ARMM0DIRS=\ easymini-v0.1 ifneq ($(shell which sdcc),) @@ -46,10 +48,14 @@ ifneq ($(shell which avr-gcc),) SUBDIRS += $(AVRDIRS) endif -ifneq ($(shell which arm-none-eabi-gcc),) +ifneq ($(shell which /opt/cortex/bin/arm-none-eabi-gcc),) SUBDIRS += $(ARMDIRS) endif +ifneq ($(shell which /usr/bin/arm-none-eabi-gcc),) + SUBDIRS += $(ARMM0DIRS) +endif + ALLDIRS=$(SDCCDIRS) $(AVRDIRS) $(ARMDIRS) all: all-local all-recursive -- cgit v1.2.3 From 277577fecc71e3c52b823938f396cf42be403ebe Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 26 May 2013 19:01:58 -0600 Subject: altos: Add pyro code testing to ao_flight_test for TeleMega This parses the pyro settings and signals when the pyro channels are fired in the output. Signed-off-by: Keith Packard --- src/core/ao_pyro.c | 120 +++++++++++++++++++++++++++------------------- src/test/Makefile | 2 +- src/test/ao_flight_test.c | 57 ++++++++++++++++++++++ 3 files changed, 130 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index aac8fda5..b655eaca 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -15,10 +15,12 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#ifndef AO_FLIGHT_TEST #include -#include #include #include +#endif +#include #if IS_COMPANION #include @@ -130,12 +132,13 @@ ao_pyro_ready(struct ao_pyro *pyro) return TRUE; } +#ifndef AO_FLIGHT_TEST #define ao_pyro_fire_port(port, bit, pin) do { \ ao_gpio_set(port, bit, pin, 1); \ ao_delay(AO_MS_TO_TICKS(50)); \ ao_gpio_set(port, bit, pin, 0); \ } while (0) - +#endif static void ao_pyro_fire(uint8_t p) @@ -172,66 +175,58 @@ ao_pyro_fire(uint8_t p) uint8_t ao_pyro_wakeup; -static void -ao_pyro(void) +static uint8_t +ao_pyro_check(void) { - uint8_t p, any_waiting; struct ao_pyro *pyro; + uint8_t p, any_waiting; + + any_waiting = 0; + for (p = 0; p < AO_PYRO_NUM; p++) { + pyro = &ao_config.pyro[p]; - ao_config_get(); - while (ao_flight_state < ao_flight_boost) - ao_sleep(&ao_flight_state); - - for (;;) { - ao_alarm(AO_MS_TO_TICKS(100)); - ao_sleep(&ao_pyro_wakeup); - ao_clear_alarm(); - any_waiting = 0; - for (p = 0; p < AO_PYRO_NUM; p++) { - pyro = &ao_config.pyro[p]; + /* Ignore igniters which have already fired + */ + if (pyro->fired) + continue; - /* Ignore igniters which have already fired - */ - if (pyro->fired) - continue; + /* Ignore disabled igniters + */ + if (!pyro->flags) + continue; - /* Ignore disabled igniters - */ - if (!pyro->flags) + any_waiting = 1; + /* Check pyro state to see if it should fire + */ + if (!pyro->delay_done) { + if (!ao_pyro_ready(pyro)) continue; - any_waiting = 1; - /* Check pyro state to see if it shoule fire + /* If there's a delay set, then remember when + * it expires */ - if (!pyro->delay_done) { - if (!ao_pyro_ready(pyro)) - continue; - - /* If there's a delay set, then remember when - * it expires - */ - if (pyro->flags & ao_pyro_delay) - pyro->delay_done = ao_time() + pyro->delay; - } - - /* Check to see if we're just waiting for - * the delay to expire - */ - if (pyro->delay_done) { - if ((int16_t) (ao_time() - pyro->delay_done) < 0) - continue; + if (pyro->flags & ao_pyro_delay) { + pyro->delay_done = ao_time() + pyro->delay; + if (!pyro->delay_done) + pyro->delay_done = 1; } + } - ao_pyro_fire(p); + /* Check to see if we're just waiting for + * the delay to expire + */ + if (pyro->delay_done) { + if ((int16_t) (ao_time() - pyro->delay_done) < 0) + continue; } - if (!any_waiting) - break; + + ao_pyro_fire(p); + pyro->fired = 1; + ao_pyro_fired |= (1 << p); } - ao_exit(); + return any_waiting; } -__xdata struct ao_task ao_pyro_task; - #define NO_VALUE 0xff #define AO_PYRO_NAME_LEN 3 @@ -283,6 +278,34 @@ const struct { { "", ao_pyro_none, NO_VALUE, HELP(NULL) }, }; +#define NUM_PYRO_VALUES (sizeof ao_pyro_values / sizeof ao_pyro_values[0]) + +#ifndef AO_FLIGHT_TEST +static void +ao_pyro(void) +{ + uint8_t any_waiting; + + ao_config_get(); + while (ao_flight_state < ao_flight_boost) + ao_sleep(&ao_flight_state); + + for (;;) { + ao_alarm(AO_MS_TO_TICKS(100)); + ao_sleep(&ao_pyro_wakeup); + ao_clear_alarm(); + if (ao_flight_state >= ao_flight_landed) + break; + any_waiting = ao_pyro_check(); + if (!any_waiting) + break; + } + ao_exit(); +} + +__xdata struct ao_task ao_pyro_task; + + static void ao_pyro_print_name(uint8_t v) { @@ -449,3 +472,4 @@ ao_pyro_init(void) ao_cmd_register(&ao_pyro_cmds[0]); ao_add_task(&ao_pyro_task, ao_pyro, "pyro"); } +#endif diff --git a/src/test/Makefile b/src/test/Makefile index 8032a163..3c9ac9c6 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -29,7 +29,7 @@ ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalm ao_flight_test_accel: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c $(INCS) cc $(CFLAGS) -o $@ -DFORCE_ACCEL=1 ao_flight_test.c -ao_flight_test_mm: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c $(INCS) +ao_flight_test_mm: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c ao_pyro.c ao_pyro.h $(INCS) cc -DTELEMEGA=1 $(CFLAGS) -o $@ $< -lm ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 99bed7ee..6e53d8e1 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -137,6 +138,18 @@ int tick_offset; static int32_t ao_k_height; +int16_t +ao_time(void) +{ + return ao_data_static.tick; +} + +void +ao_delay(int16_t interval) +{ + return; +} + void ao_ignite(enum ao_igniter igniter) { @@ -200,6 +213,8 @@ struct ao_cmds { #include struct ao_ms5607_prom ms5607_prom; #include "ao_ms5607_convert.c" +#define AO_PYRO_NUM 4 +#include #else #include "ao_convert.c" #endif @@ -210,6 +225,9 @@ struct ao_config { int16_t accel_minus_g; uint8_t pad_orientation; uint16_t apogee_lockout; +#if TELEMEGA + struct ao_pyro pyro[AO_PYRO_NUM]; /* minor version 12 */ +#endif }; #define AO_PAD_ORIENTATION_ANTENNA_UP 0 @@ -246,6 +264,24 @@ uint16_t prev_tick; #include "ao_sqrt.c" #include "ao_sample.c" #include "ao_flight.c" +#if TELEMEGA +#define AO_PYRO_NUM 4 + +#define AO_PYRO_0 0 +#define AO_PYRO_1 1 +#define AO_PYRO_2 2 +#define AO_PYRO_3 3 + +static void +ao_pyro_tell(int pin) +{ + printf ("fire pyro %d\n", pin); +} + +#define ao_pyro_fire_port(port,bit,pin) ao_pyro_tell(pin) + +#include "ao_pyro.c" +#endif #define to_double(f) ((f) / 65536.0) @@ -771,6 +807,10 @@ ao_sleep(void *wchan) char *words[64]; int nword; +#if TELEMEGA + if (ao_flight_state >= ao_flight_boost && ao_flight_state < ao_flight_landed) + ao_pyro_check(); +#endif for (;;) { if (ao_records_read > 2 && ao_flight_state == ao_flight_startup) { @@ -883,6 +923,23 @@ ao_sleep(void *wchan) else if (strcmp(words[1], "crc:") == 0) ms5607_prom.crc = strtoul(words[2], NULL, 10); continue; + } else if (nword >= 3 && strcmp(words[0], "Pyro") == 0) { + int p = strtoul(words[1], NULL, 10); + int i, j; + struct ao_pyro *pyro = &ao_config.pyro[p]; + + for (i = 2; i < nword; i++) { + for (j = 0; j < NUM_PYRO_VALUES; j++) + if (!strcmp (words[2], ao_pyro_values[j].name)) + break; + if (j == NUM_PYRO_VALUES) + continue; + pyro->flags |= ao_pyro_values[j].flag; + if (ao_pyro_values[j].offset != NO_VALUE && i + 1 < nword) { + int16_t val = strtoul(words[++i], NULL, 10); + *((int16_t *) ((char *) pyro + ao_pyro_values[j].offset)) = val; + } + } } #else if (nword == 4 && log_format != AO_LOG_FORMAT_TELEMEGA) { -- cgit v1.2.3 From 62547a042d042fadec652c5081f96816a8e66970 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 26 May 2013 19:03:12 -0600 Subject: altos,altosui: Add pyro state logging for TeleMega Only in the log file (no obvious space in the telem packets), but at least we should be able to check for pyro failures. Signed-off-by: Keith Packard --- altoslib/AltosEepromMega.java | 1 + src/core/ao_log.h | 3 ++- src/core/ao_log_mega.c | 1 + src/core/ao_pyro.c | 2 ++ src/core/ao_pyro.h | 2 ++ 5 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/altoslib/AltosEepromMega.java b/altoslib/AltosEepromMega.java index b077e26c..0804c392 100644 --- a/altoslib/AltosEepromMega.java +++ b/altoslib/AltosEepromMega.java @@ -73,6 +73,7 @@ public class AltosEepromMega { public int v_pbatt() { return data16(2); } public int nsense() { return data16(4); } public int sense(int i) { return data16(6 + i * 2); } + public int pyro() { return data16(26); } /* AO_LOG_GPS_TIME elements */ public int latitude() { return data32(0); } diff --git a/src/core/ao_log.h b/src/core/ao_log.h index e1461a14..dce12f02 100644 --- a/src/core/ao_log.h +++ b/src/core/ao_log.h @@ -236,7 +236,8 @@ struct ao_log_mega { int16_t v_pbatt; /* 6 */ int16_t n_sense; /* 8 */ int16_t sense[10]; /* 10 */ - } volt; /* 30 */ + uint16_t pyro; /* 30 */ + } volt; /* 32 */ /* AO_LOG_GPS_TIME */ struct { int32_t latitude; /* 4 */ diff --git a/src/core/ao_log_mega.c b/src/core/ao_log_mega.c index abf953a6..0db1119c 100644 --- a/src/core/ao_log_mega.c +++ b/src/core/ao_log_mega.c @@ -151,6 +151,7 @@ ao_log(void) log.u.volt.n_sense = AO_ADC_NUM_SENSE; for (i = 0; i < AO_ADC_NUM_SENSE; i++) log.u.volt.sense[i] = ao_data_ring[ao_log_data_pos].adc.sense[i]; + log.u.pyro = ao_pyro_fired; ao_log_mega(&log); next_other = log.tick + AO_OTHER_INTERVAL; } diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index b655eaca..b3cda656 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -33,6 +33,8 @@ #define ao_lowbit(x) ((x) & (-x)) +uint16_t ao_pyro_fired; + /* * Given a pyro structure, figure out * if the current flight state satisfies all diff --git a/src/core/ao_pyro.h b/src/core/ao_pyro.h index cde850ad..1f838542 100644 --- a/src/core/ao_pyro.h +++ b/src/core/ao_pyro.h @@ -63,6 +63,8 @@ struct ao_pyro { extern uint8_t ao_pyro_wakeup; +extern uint16_t ao_pyro_fired; + void ao_pyro_set(void); -- cgit v1.2.3 From 956f4dff1cc521059434743624b1271fb92b96ae Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 26 May 2013 19:39:13 -0600 Subject: altos: Light pyro charges simultaneously if so configured Don't try to be nice to the battery, just let the pyro circuit deal with it and try to get all of the specified circuits going at the same time if they're configured to do so. Signed-off-by: Keith Packard --- src/core/ao_pyro.c | 49 ++++++++++++++++++++++++++++------------------- src/test/ao_flight_test.c | 6 ++---- 2 files changed, 31 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index b3cda656..84f949dc 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -135,45 +135,38 @@ ao_pyro_ready(struct ao_pyro *pyro) } #ifndef AO_FLIGHT_TEST -#define ao_pyro_fire_port(port, bit, pin) do { \ - ao_gpio_set(port, bit, pin, 1); \ - ao_delay(AO_MS_TO_TICKS(50)); \ - ao_gpio_set(port, bit, pin, 0); \ - } while (0) -#endif - static void -ao_pyro_fire(uint8_t p) +ao_pyro_pin_set(uint8_t p, uint8_t v) { switch (p) { #if AO_PYRO_NUM > 0 - case 0: ao_pyro_fire_port(AO_PYRO_PORT_0, AO_PYRO_PIN_0, AO_PYRO_0); break; + case 0: ao_gpio_set(AO_PYRO_PORT_0, AO_PYRO_PIN_0, AO_PYRO_0, v); break; #endif #if AO_PYRO_NUM > 1 - case 1: ao_pyro_fire_port(AO_PYRO_PORT_1, AO_PYRO_PIN_1, AO_PYRO_1); break; + case 1: ao_gpio_set(AO_PYRO_PORT_1, AO_PYRO_PIN_1, AO_PYRO_1, v); break; #endif #if AO_PYRO_NUM > 2 - case 2: ao_pyro_fire_port(AO_PYRO_PORT_2, AO_PYRO_PIN_2, AO_PYRO_2); break; + case 2: ao_gpio_set(AO_PYRO_PORT_2, AO_PYRO_PIN_2, AO_PYRO_2, v); break; #endif #if AO_PYRO_NUM > 3 - case 3: ao_pyro_fire_port(AO_PYRO_PORT_3, AO_PYRO_PIN_3, AO_PYRO_3); break; + case 3: ao_gpio_set(AO_PYRO_PORT_3, AO_PYRO_PIN_3, AO_PYRO_3, v); break; #endif #if AO_PYRO_NUM > 4 - case 4: ao_pyro_fire_port(AO_PYRO_PORT_4, AO_PYRO_PIN_4, AO_PYRO_4); break; + case 4: ao_gpio_set(AO_PYRO_PORT_4, AO_PYRO_PIN_4, AO_PYRO_4, v); break; #endif #if AO_PYRO_NUM > 5 - case 5: ao_pyro_fire_port(AO_PYRO_PORT_5, AO_PYRO_PIN_5, AO_PYRO_5); break; + case 5: ao_gpio_set(AO_PYRO_PORT_5, AO_PYRO_PIN_5, AO_PYRO_5, v); break; #endif #if AO_PYRO_NUM > 6 - case 6: ao_pyro_fire_port(AO_PYRO_PORT_6, AO_PYRO_PIN_6, AO_PYRO_6); break; + case 6: ao_gpio_set(AO_PYRO_PORT_6, AO_PYRO_PIN_6, AO_PYRO_6, v); break; #endif #if AO_PYRO_NUM > 7 - case 7: ao_pyro_fire_port(AO_PYRO_PORT_7, AO_PYRO_PIN_7, AO_PYRO_7); break; + case 7: ao_gpio_set(AO_PYRO_PORT_7, AO_PYRO_PIN_7, AO_PYRO_7, v); break; #endif default: break; } - ao_delay(AO_MS_TO_TICKS(50)); } +#endif uint8_t ao_pyro_wakeup; @@ -182,6 +175,7 @@ ao_pyro_check(void) { struct ao_pyro *pyro; uint8_t p, any_waiting; + uint16_t fire = 0; any_waiting = 0; for (p = 0; p < AO_PYRO_NUM; p++) { @@ -222,10 +216,25 @@ ao_pyro_check(void) continue; } - ao_pyro_fire(p); - pyro->fired = 1; - ao_pyro_fired |= (1 << p); + fire |= (1 << p); } + + if (fire) { + for (p = 0; p < AO_PYRO_NUM; p++) { + if (fire & (1 << p)) + ao_pyro_pin_set(p, 1); + } + ao_delay(AO_MS_TO_TICKS(50)); + for (p = 0; p < AO_PYRO_NUM; p++) { + if (fire & (1 << p)) { + ao_pyro_pin_set(p, 0); + ao_config.pyro[p].fired = 1; + ao_pyro_fired |= (1 << p); + } + } + ao_delay(AO_MS_TO_TICKS(50)); + } + return any_waiting; } diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 6e53d8e1..faf31aa7 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -273,13 +273,11 @@ uint16_t prev_tick; #define AO_PYRO_3 3 static void -ao_pyro_tell(int pin) +ao_pyro_pin_set(uint8_t pin, uint8_t value) { - printf ("fire pyro %d\n", pin); + printf ("set pyro %d %d\n", pin, value); } -#define ao_pyro_fire_port(port,bit,pin) ao_pyro_tell(pin) - #include "ao_pyro.c" #endif -- cgit v1.2.3 From 5ca472333a3587f0e47d54f5edc287494262ef98 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 26 May 2013 19:47:02 -0600 Subject: altos: write pyro fired to correct log field Signed-off-by: Keith Packard --- src/core/ao_log_mega.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_log_mega.c b/src/core/ao_log_mega.c index 0db1119c..ee12b907 100644 --- a/src/core/ao_log_mega.c +++ b/src/core/ao_log_mega.c @@ -151,7 +151,7 @@ ao_log(void) log.u.volt.n_sense = AO_ADC_NUM_SENSE; for (i = 0; i < AO_ADC_NUM_SENSE; i++) log.u.volt.sense[i] = ao_data_ring[ao_log_data_pos].adc.sense[i]; - log.u.pyro = ao_pyro_fired; + log.u.volt.pyro = ao_pyro_fired; ao_log_mega(&log); next_other = log.tick + AO_OTHER_INTERVAL; } -- cgit v1.2.3 From 6f131e740477d29b6623fa336da79e53f765a55b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 26 May 2013 19:48:03 -0600 Subject: altos: Make manual pyro firing command work again Signed-off-by: Keith Packard --- src/core/ao_pyro.c | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index 84f949dc..39f40dfa 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -170,6 +170,26 @@ ao_pyro_pin_set(uint8_t p, uint8_t v) uint8_t ao_pyro_wakeup; +static void +ao_pyro_pins_fire(uint16_t fire) +{ + uint8_t p; + + for (p = 0; p < AO_PYRO_NUM; p++) { + if (fire & (1 << p)) + ao_pyro_pin_set(p, 1); + } + ao_delay(AO_MS_TO_TICKS(50)); + for (p = 0; p < AO_PYRO_NUM; p++) { + if (fire & (1 << p)) { + ao_pyro_pin_set(p, 0); + ao_config.pyro[p].fired = 1; + ao_pyro_fired |= (1 << p); + } + } + ao_delay(AO_MS_TO_TICKS(50)); +} + static uint8_t ao_pyro_check(void) { @@ -219,21 +239,8 @@ ao_pyro_check(void) fire |= (1 << p); } - if (fire) { - for (p = 0; p < AO_PYRO_NUM; p++) { - if (fire & (1 << p)) - ao_pyro_pin_set(p, 1); - } - ao_delay(AO_MS_TO_TICKS(50)); - for (p = 0; p < AO_PYRO_NUM; p++) { - if (fire & (1 << p)) { - ao_pyro_pin_set(p, 0); - ao_config.pyro[p].fired = 1; - ao_pyro_fired |= (1 << p); - } - } - ao_delay(AO_MS_TO_TICKS(50)); - } + if (fire) + ao_pyro_pins_fire(fire); return any_waiting; } @@ -444,7 +451,7 @@ ao_pyro_manual(void) ao_cmd_decimal(); if (ao_cmd_lex_i < 0 || AO_PYRO_NUM <= ao_cmd_lex_i) return; - ao_pyro_fire(ao_cmd_lex_i); + ao_pyro_pins_fire(1 << ao_cmd_lex_i); } -- cgit v1.2.3 From 3e8b72a9dc5b6c3a0f6132dc2dec04f8c08a1deb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 26 May 2013 22:38:56 -0600 Subject: altos: Add pyro operations to regular ignite commands Instead of having separate commands, just mix the two sets together. Signed-off-by: Keith Packard --- src/Makefile | 2 +- src/core/ao.h | 2 ++ src/core/ao_ignite.c | 45 ++++++++++++++++++++++++++++------- src/core/ao_pyro.c | 57 ++++++++++++++++++++++++++++++++------------- src/core/ao_pyro.h | 6 +++++ src/telemega-v0.1/ao_pins.h | 2 ++ src/telemega-v0.3/ao_pins.h | 1 + 7 files changed, 89 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 7ffc52d6..ff26ac20 100644 --- a/src/Makefile +++ b/src/Makefile @@ -26,7 +26,7 @@ SDCCDIRS=\ spiradio-v0.1 AVRDIRS=\ - telescience-v0.1 telescience-pwm telepyro-v0.1 micropeak + telescience-v0.1 telescience-pwm micropeak ARMDIRS=\ telemega-v0.1 telemega-v0.1/flash-loader \ diff --git a/src/core/ao.h b/src/core/ao.h index 7f344736..0886260f 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -703,6 +703,8 @@ struct ao_ignition { uint8_t firing; }; +extern __code char * __code ao_igniter_status_names[]; + extern __xdata struct ao_ignition ao_ignition[2]; enum ao_igniter_status diff --git a/src/core/ao_ignite.c b/src/core/ao_ignite.c index 74bd0c5a..9f2ec0a7 100644 --- a/src/core/ao_ignite.c +++ b/src/core/ao_ignite.c @@ -17,7 +17,11 @@ #include "ao.h" #include +#if AO_PYRO_NUM +#include +#endif +#if HAS_IGNITE __xdata struct ao_ignition ao_ignition[2]; void @@ -150,6 +154,8 @@ ao_igniter(void) } } +#endif + void ao_ignite_manual(void) { @@ -157,33 +163,50 @@ ao_ignite_manual(void) if (!ao_match_word("DoIt")) return; ao_cmd_white(); - if (ao_cmd_lex_c == 'm') { - if(ao_match_word("main")) - ao_igniter_fire(ao_igniter_main); - } else { - if(ao_match_word("drogue")) - ao_igniter_fire(ao_igniter_drogue); +#if HAS_IGNITE + if (ao_cmd_lex_c == 'm' && ao_match_word("main")) { + ao_igniter_fire(ao_igniter_main); + return; + } + if (ao_cmd_lex_c == 'd' && ao_match_word("drogue")) { + ao_igniter_fire(ao_igniter_drogue); + return; + } +#endif +#if AO_PYRO_NUM + if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') { + ao_pyro_manual(ao_cmd_lex_c - '0'); + return; } +#endif + ao_cmd_status = ao_cmd_syntax_error; } -static __code char * __code igniter_status_names[] = { +__code char * __code ao_igniter_status_names[] = { "unknown", "ready", "active", "open" }; +#if HAS_IGNITE void ao_ignite_print_status(enum ao_igniter igniter, __code char *name) __reentrant { enum ao_igniter_status status = ao_igniter_status(igniter); printf("Igniter: %6s Status: %s\n", name, - igniter_status_names[status]); + ao_igniter_status_names[status]); } +#endif void ao_ignite_test(void) { +#if HAS_IGNITE ao_ignite_print_status(ao_igniter_drogue, "drogue"); ao_ignite_print_status(ao_igniter_main, "main"); +#endif +#if AO_PYRO_NUM + ao_pyro_print_status(); +#endif } __code struct ao_cmds ao_ignite_cmds[] = { @@ -192,6 +215,7 @@ __code struct ao_cmds ao_ignite_cmds[] = { { 0, NULL }, }; +#if HAS_IGNITE __xdata struct ao_task ao_igniter_task; void @@ -200,11 +224,14 @@ ao_ignite_set_pins(void) ao_enable_output(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, AO_IGNITER_DROGUE, 0); ao_enable_output(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, AO_IGNITER_MAIN, 0); } +#endif void ao_igniter_init(void) { +#if HAS_IGNITE ao_ignite_set_pins(); - ao_cmd_register(&ao_ignite_cmds[0]); ao_add_task(&ao_igniter_task, ao_igniter, "igniter"); +#endif + ao_cmd_register(&ao_ignite_cmds[0]); } diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index 39f40dfa..531e1f50 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -33,6 +33,40 @@ #define ao_lowbit(x) ((x) & (-x)) +#ifndef AO_FLIGHT_TEST +enum ao_igniter_status +ao_pyro_status(uint8_t p) +{ + __xdata struct ao_data packet; + __pdata int16_t value; + + ao_arch_critical( + ao_data_get(&packet); + ); + + value = (AO_IGNITER_CLOSED>>1); + value = AO_SENSE_PYRO(&packet, p); + if (value < AO_IGNITER_OPEN) + return ao_igniter_open; + else if (value > AO_IGNITER_CLOSED) + return ao_igniter_ready; + else + return ao_igniter_unknown; +} + +void +ao_pyro_print_status(void) +{ + uint8_t p; + + for(p = 0; p < AO_PYRO_NUM; p++) { + enum ao_igniter_status status = ao_pyro_status(p); + printf("Igniter: %d Status: %s\n", + p, ao_igniter_status_names[status]); + } +} +#endif + uint16_t ao_pyro_fired; /* @@ -441,25 +475,17 @@ ao_pyro_set(void) _ao_config_edit_finish(); } -static void -ao_pyro_manual(void) +void +ao_pyro_manual(uint8_t p) { - ao_cmd_white(); - if (!ao_match_word("DoIt")) + printf ("ao_pyro_manual %d\n", p); + if (p >= AO_PYRO_NUM) { + ao_cmd_status = ao_cmd_syntax_error; return; - ao_cmd_white(); - ao_cmd_decimal(); - if (ao_cmd_lex_i < 0 || AO_PYRO_NUM <= ao_cmd_lex_i) - return; - ao_pyro_pins_fire(1 << ao_cmd_lex_i); - + } + ao_pyro_pins_fire(1 << p); } -const struct ao_cmds ao_pyro_cmds[] = { - { ao_pyro_manual, "P DoIt \0Fire igniter" }, - { 0, NULL } -}; - void ao_pyro_init(void) { @@ -487,7 +513,6 @@ ao_pyro_init(void) #if AO_PYRO_NUM > 7 ao_enable_output(AO_PYRO_PORT_7, AO_PYRO_PIN_7, AO_PYRO_7, 0); #endif - ao_cmd_register(&ao_pyro_cmds[0]); ao_add_task(&ao_pyro_task, ao_pyro, "pyro"); } #endif diff --git a/src/core/ao_pyro.h b/src/core/ao_pyro.h index 1f838542..0c5642d6 100644 --- a/src/core/ao_pyro.h +++ b/src/core/ao_pyro.h @@ -74,4 +74,10 @@ ao_pyro_show(void); void ao_pyro_init(void); +void +ao_pyro_manual(uint8_t p); + +void +ao_pyro_print_status(void); + #endif diff --git a/src/telemega-v0.1/ao_pins.h b/src/telemega-v0.1/ao_pins.h index 4c645871..78e887c3 100644 --- a/src/telemega-v0.1/ao_pins.h +++ b/src/telemega-v0.1/ao_pins.h @@ -146,6 +146,8 @@ /* Number of general purpose pyro channels available */ #define AO_PYRO_NUM 4 +#define AO_SENSE_PYRO(a,p) ((a)->adc.sense[(p) + 2]) + #define AO_IGNITER_SET_DROGUE(v) stm_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, v) #define AO_IGNITER_SET_MAIN(v) stm_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, v) diff --git a/src/telemega-v0.3/ao_pins.h b/src/telemega-v0.3/ao_pins.h index bace5853..a5a9eaf4 100644 --- a/src/telemega-v0.3/ao_pins.h +++ b/src/telemega-v0.3/ao_pins.h @@ -121,6 +121,7 @@ #define HAS_IGNITE 1 #define HAS_IGNITE_REPORT 1 +#define AO_SENSE_PYRO(p,n) ((p)->adc.sense[n]) #define AO_SENSE_DROGUE(p) ((p)->adc.sense[4]) #define AO_SENSE_MAIN(p) ((p)->adc.sense[5]) #define AO_IGNITER_CLOSED 400 -- cgit v1.2.3 From 8ba2035c78293bc312804722249df76dd4692d71 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Jun 2013 09:53:07 -0700 Subject: altos: Add driver for 74hc165 shift register Just reads one byte from the shift register using the SPI driver and returns it Signed-off-by: Keith Packard --- src/drivers/ao_74hc165.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_74hc165.h | 27 ++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100644 src/drivers/ao_74hc165.c create mode 100644 src/drivers/ao_74hc165.h (limited to 'src') diff --git a/src/drivers/ao_74hc165.c b/src/drivers/ao_74hc165.c new file mode 100644 index 00000000..f24fce37 --- /dev/null +++ b/src/drivers/ao_74hc165.c @@ -0,0 +1,58 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +/* + * 74HC165 driver. + * Reads a single byte from the shift register + */ + +#include +#include + +uint8_t +ao_74hc165_read(void) +{ + static __xdata state; + ao_mutex_get(&ao_spi_mutex); + ao_spi_set_speed(AO_SPI_SPEED_FAST); + AO_74HC165_CS = 1; + ao_spi_recv(&state, 1, AO_74HC165_SPI_BUS); + AO_74HC165_CS = 0; + ao_mutex_put(&ao_spi_mutex); + return state; +} + +static void +ao_74hc165_cmd(void) +{ + uint8_t v; + + v = ao_74hc165_read(); + printf ("Switches: 0x%02x\n", v); +} + +static const struct ao_cmds ao_74hc165_cmds[] = { + { ao_74hc165_cmd, "L\0Show 74hc165" }, + { 0, NULL } +}; + +void +ao_74hc165_init(void) +{ + ao_enable_output(AO_74HC165_CS_PORT, AO_74HC165_CS_PIN, AO_74HC165_CS, 0); + ao_cmd_register(&ao_74hc165_cmds[0]); +} diff --git a/src/drivers/ao_74hc165.h b/src/drivers/ao_74hc165.h new file mode 100644 index 00000000..3ae51353 --- /dev/null +++ b/src/drivers/ao_74hc165.h @@ -0,0 +1,27 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_74HC165_H_ +#define _AO_74HC165_H_ + +uint8_t +ao_74hc165_read(void); + +void +ao_74hc165_init(void); + +#endif /* _AO_74HC165_H_ */ -- cgit v1.2.3 From 187f661c2512e4260d0ca64134de8fad199f5944 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Jun 2013 10:00:54 -0700 Subject: altos: Add telefire v0.2 support Signed-off-by: Keith Packard --- src/Makefile | 9 +-- src/cc1111/ao_adc.c | 2 +- src/drivers/ao_pad.c | 25 +++++-- src/telefire-v0.2/Makefile | 103 ++++++++++++++++++++++++++++ src/telefire-v0.2/ao_pins.h | 144 ++++++++++++++++++++++++++++++++++++++++ src/telefire-v0.2/ao_telefire.c | 45 +++++++++++++ 6 files changed, 317 insertions(+), 11 deletions(-) create mode 100644 src/telefire-v0.2/Makefile create mode 100644 src/telefire-v0.2/ao_pins.h create mode 100644 src/telefire-v0.2/ao_telefire.c (limited to 'src') diff --git a/src/Makefile b/src/Makefile index ff26ac20..ee76c325 100644 --- a/src/Makefile +++ b/src/Makefile @@ -16,14 +16,11 @@ include Version SDCCDIRS=\ telemetrum-v1.2 telemetrum-v1.1 telemetrum-v1.0 \ - teledongle-v0.2 teledongle-v0.1 \ - telemini-v1.0 telenano-v0.1 \ + teledongle-v0.2 \ + telemini-v1.0 \ telebt-v1.0 \ - telemetrum-v0.1-sky telemetrum-v0.1-sirf \ - telelaunch-v0.1 tidongle test \ teleterra-v0.2 teleshield-v0.1 \ - telefire-v0.1 \ - spiradio-v0.1 + telefire-v0.1 telefire-v0.2 AVRDIRS=\ telescience-v0.1 telescience-pwm micropeak diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index ed76179b..4a58023d 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -144,7 +144,7 @@ ao_adc_isr(void) __interrupt 1 } #endif /* telemini || telenano */ -#ifdef TELEFIRE_V_0_1 +#if defined(TELEFIRE_V_0_1) || defined(TELEFIRE_V_0_2) a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.sense[0] + sequence - AO_ADC_FIRST_PIN); a[0] = ADCL; a[1] = ADCH; diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index 6cec98ab..e0c03c74 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -17,7 +17,7 @@ #include #include -#include +#include #include static __xdata uint8_t ao_pad_ignite; @@ -218,6 +218,21 @@ ao_pad_enable(void) ao_wakeup (&ao_pad_disabled); } +#if HAS_74HC165 +static uint8_t +ao_pad_read_box(void) +{ + uint8_t byte = ao_74hc165_read(); + uint8_t h, l; + + h = byte >> 4; + l = byte & 0xf; + return h * 10 + l; +} +#else +#define ao_pad_read_box() 0 +#endif + static void ao_pad(void) { @@ -236,8 +251,10 @@ ao_pad(void) if (ret != AO_RADIO_CMAC_OK) continue; - PRINTD ("tick %d box %d cmd %d channels %02x\n", - command.tick, command.box, command.cmd, command.channels); + ao_pad_box = ao_pad_read_box(); + + PRINTD ("tick %d box %d (me %d) cmd %d channels %02x\n", + command.tick, command.box, ao_pad_box, command.cmd, command.channels); switch (command.cmd) { case AO_LAUNCH_ARM: @@ -327,7 +344,7 @@ ao_pad_test(void) } for (c = 0; c < AO_PAD_NUM; c++) { - printf ("Pad %d: "); + printf ("Pad %d: ", c); switch (query.igniter_status[c]) { case AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED: printf ("No igniter. Relay closed\n"); break; case AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN: printf ("No igniter. Relay open\n"); break; diff --git a/src/telefire-v0.2/Makefile b/src/telefire-v0.2/Makefile new file mode 100644 index 00000000..3353bc1a --- /dev/null +++ b/src/telefire-v0.2/Makefile @@ -0,0 +1,103 @@ +# +# TeleFire build file +# + +TELEFIRE_VER=0.2 +TELEFIRE_DEF=0_2 + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_pad.h \ + cc1111.h \ + ao_product.h + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_convert.c \ + ao_mutex.c \ + ao_panic.c \ + ao_stdio.c \ + ao_storage.c \ + ao_task.c \ + ao_freq.c + +CC1111_SRC = \ + ao_adc.c \ + ao_aes.c \ + ao_beep.c \ + ao_dma.c \ + ao_intflash.c \ + ao_radio.c \ + ao_radio_cmac.c \ + ao_romconfig.c \ + ao_serial.c \ + ao_spi.c \ + ao_string.c \ + ao_timer.c \ + ao_usb.c \ + _bp.c + +DRIVER_SRC = \ + ao_pca9922.c \ + ao_74hc165.c \ + ao_pad.c \ + ao_radio_cmac_cmd.c + +PRODUCT_SRC = \ + ao_telefire.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROGNAME = telefire-v$(TELEFIRE_VER) +PROG = $(PROGNAME)-$(VERSION).ihx +PRODUCT=TeleFire-v$(TELEFIRE_VER) +PRODUCT_DEF=-DTELEFIRE_V_$(TELEFIRE_DEF) +IDPRODUCT=0x000f +CODESIZE=0x6700 + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: clean-cc1111 + +install: + +uninstall: + diff --git a/src/telefire-v0.2/ao_pins.h b/src/telefire-v0.2/ao_pins.h new file mode 100644 index 00000000..f4050722 --- /dev/null +++ b/src/telefire-v0.2/ao_pins.h @@ -0,0 +1,144 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_RADIO 1 + +#define HAS_FLIGHT 0 +#define HAS_USB 1 +#define HAS_BEEP 0 +#define HAS_GPS 0 +#define HAS_SERIAL_1 0 +#define HAS_ADC 1 +#define HAS_DBG 0 +#define HAS_EEPROM 1 +#define HAS_LOG 0 +#define HAS_PAD 1 +#define USE_INTERNAL_FLASH 1 +#define DBG_ON_P1 0 +#define IGNITE_ON_P2 0 +#define IGNITE_ON_P1 1 +#define IGNITE_ON_P0 0 +#define PACKET_HAS_MASTER 0 +#define PACKET_HAS_SLAVE 0 + +#define AO_LED_CONTINUITY(c) (1 << (c)) +#define AO_LED_CONTINUITY_MASK (0xf) +#define AO_LED_RX 0x10 +#define AO_LED_TX 0x20 +#define AO_LED_ARMED 0x40 +#define AO_LED_POWER 0x80 + +#define AO_LED_RED AO_LED_TX +#define AO_LED_GREEN AO_LED_RX + +#define LEDS_AVAILABLE (0xff) +#define HAS_EXTERNAL_TEMP 0 +#define HAS_ACCEL_REF 0 +#define SPI_CS_ON_P1 1 +#define HAS_AES 1 +#define DMA_SHARE_AES_RADIO 1 + +#define SPI_CS_PORT P1 +#define SPI_CS_SEL P1SEL +#define SPI_CS_DIR P1DIR + +#define SPI_CONST 0x00 + +#define HAS_SPI_0 0 +#define HAS_SPI_1 1 +#define SPI_1_ALT_1 0 +#define SPI_1_ALT_2 1 + +#define HAS_74HC165 1 +#define AO_74HC165_CS_PORT P1 +#define AO_74HC165_CS_PIN 4 +#define AO_74HC165_CS P1_4 + +#define AO_PCA9922_CS_PORT P2 +#define AO_PCA9922_CS_PIN 0 +#define AO_PCA9922_CS P2_0 + +#define AO_PAD_NUM 4 +#define AO_PAD_PORT P1 +#define AO_PAD_DIR P1DIR + +#define AO_PAD_PIN_0 0 +#define AO_PAD_0 P1_0 +#define AO_PAD_ADC_0 0 + +#define AO_PAD_PIN_1 1 +#define AO_PAD_1 P1_1 +#define AO_PAD_ADC_1 1 + +#define AO_PAD_PIN_2 2 +#define AO_PAD_2 P1_2 +#define AO_PAD_ADC_2 2 + +#define AO_PAD_PIN_3 3 +#define AO_PAD_3 P1_3 +#define AO_PAD_ADC_3 3 + +#define AO_PAD_ALL_PINS ((1 << AO_PAD_PIN_0) | (1 << AO_PAD_PIN_1) | (1 << AO_PAD_PIN_2) | (1 << AO_PAD_PIN_3)) +#define AO_PAD_ALL_CHANNELS ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3)) + +#define AO_SIREN_PORT P2 +#define AO_SIREN_DIR P2DIR +#define AO_SIREN_PIN 3 +#define AO_SIREN P2_3 + +#define AO_STROBE_PORT P2 +#define AO_STROBE_DIR P2DIR +#define AO_STROBE_PIN 4 +#define AO_STROBE P2_4 + +/* test these values with real igniters */ +#define AO_PAD_RELAY_CLOSED 3524 +#define AO_PAD_NO_IGNITER 16904 +#define AO_PAD_GOOD_IGNITER 22514 + +#define AO_PAD_ADC_PYRO 4 +#define AO_PAD_ADC_BATT 5 + +#define AO_ADC_FIRST_PIN 0 + +struct ao_adc { + int16_t sense[AO_PAD_NUM]; + int16_t pyro; + int16_t batt; +}; + +#define AO_ADC_DUMP(p) \ + printf ("tick: %5u 0: %5d 1: %5d 2: %5d 3: %5d pyro: %5d batt %5d\n", \ + (p)->tick, \ + (p)->adc.sense[0], \ + (p)->adc.sense[1], \ + (p)->adc.sense[2], \ + (p)->adc.sense[3], \ + (p)->adc.pyro, \ + (p)->adc.batt) + +#define AO_ADC_PINS ((1 << AO_PAD_ADC_0) | \ + (1 << AO_PAD_ADC_1) | \ + (1 << AO_PAD_ADC_2) | \ + (1 << AO_PAD_ADC_3) | \ + (1 << AO_PAD_ADC_PYRO) | \ + (1 << AO_PAD_ADC_BATT)) + +#endif /* _AO_PINS_H_ */ diff --git a/src/telefire-v0.2/ao_telefire.c b/src/telefire-v0.2/ao_telefire.c new file mode 100644 index 00000000..f27ca5e8 --- /dev/null +++ b/src/telefire-v0.2/ao_telefire.c @@ -0,0 +1,45 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include + +void +main(void) +{ + ao_clock_init(); + + ao_led_init(LEDS_AVAILABLE); + + ao_task_init(); + + ao_timer_init(); + ao_adc_init(); + ao_cmd_init(); + ao_spi_init(); + ao_74hc165_init(); + ao_storage_init(); + ao_usb_init(); + ao_radio_init(); + ao_aes_init(); + ao_pad_init(); +// ao_radio_cmac_cmd_init(); + ao_config_init(); + ao_start_scheduler(); +} -- cgit v1.2.3 From 47b7e1d819e48aaebf6ffda49effbee041ce8750 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Jun 2013 12:13:06 -0700 Subject: altos/telefire: Leave siren on all the time. Add siren/strobe debugging. The 50% duty cycle wasn't actually loud enough outside. Signed-off-by: Keith Packard --- src/drivers/ao_pad.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index e0c03c74..e205f99b 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -182,10 +182,7 @@ ao_pad_monitor(void) if (ao_pad_armed) { ao_strobe(1); - if (sample & 2) - ao_siren(1); - else - ao_siren(0); + ao_siren(1); beeping = 1; } else if (query.arm_status == AO_PAD_ARM_STATUS_ARMED && !beeping) { if (arm_beep_time == 0) { @@ -379,6 +376,26 @@ ao_pad_set_debug(void) if (ao_cmd_status == ao_cmd_success) ao_pad_debug = ao_cmd_lex_i != 0; } + + +static void +ao_pad_alarm_debug(void) +{ + uint8_t which, value; + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + which = ao_cmd_lex_i; + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + value = ao_cmd_lex_i; + printf ("Set %s to %d\n", which ? "siren" : "strobe", value); + if (which) + ao_siren(value); + else + ao_strobe(value); +} #endif __code struct ao_cmds ao_pad_cmds[] = { @@ -386,6 +403,7 @@ __code struct ao_cmds ao_pad_cmds[] = { { ao_pad_manual, "i \0Fire igniter. is doit with D&I" }, #if DEBUG { ao_pad_set_debug, "D <0 off, 1 on>\0Debug" }, + { ao_pad_alarm_debug, "S <0 strobe, 1 siren> <0 off, 1 on>\0Set alarm output" }, #endif { 0, NULL } }; -- cgit v1.2.3 From 72b6c699d355fcd41addb9919d846e63105b9db7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 13 May 2013 22:34:19 -0700 Subject: altos: Add debounce helper. Use in button and quadrature drivers for TeleLCO Signed-off-by: Keith Packard --- src/core/ao_debounce.h | 52 ++++++++++++ src/drivers/ao_button.c | 82 ++++++++++++------- src/drivers/ao_event.c | 17 +--- src/drivers/ao_event.h | 6 +- src/drivers/ao_quadrature.c | 108 +++++++++++++++++-------- src/stm-demo/Makefile | 5 +- src/stm-demo/ao_demo.c | 4 +- src/stm/ao_debounce.c | 187 ++++++++++++++++++++++++++++++++++++++++++++ src/telelco-v0.2/Makefile | 2 + src/telelco-v0.2/ao_lco.c | 22 ++---- 10 files changed, 389 insertions(+), 96 deletions(-) create mode 100644 src/core/ao_debounce.h create mode 100644 src/stm/ao_debounce.c (limited to 'src') diff --git a/src/core/ao_debounce.h b/src/core/ao_debounce.h new file mode 100644 index 00000000..ebe290e1 --- /dev/null +++ b/src/core/ao_debounce.h @@ -0,0 +1,52 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_DEBOUNCE_H_ +#define _AO_DEBOUNCE_H_ + +struct ao_debounce { + struct ao_debounce *next; + + /* time that pin value must be stable before accepting */ + int8_t hold; + + /* last value reported to app; don't report it twice */ + uint8_t value; + + /* current count of intervals pin value has been stable */ + int8_t count; + + /* This pin is running */ + uint8_t running; + + /* Get the current pin value */ + uint8_t (*_get)(struct ao_debounce *debounce); + + /* The stable value has changed */ + void (*_set)(struct ao_debounce *debounce, uint8_t value); +}; + +void +_ao_debounce_start(struct ao_debounce *debounce); + +void +_ao_debounce_stop(struct ao_debounce *debounce); + +void +ao_debounce_init(void); + +#endif /* _AO_DEBOUNCE_H_ */ diff --git a/src/drivers/ao_button.c b/src/drivers/ao_button.c index a507c909..7b1fb530 100644 --- a/src/drivers/ao_button.c +++ b/src/drivers/ao_button.c @@ -18,6 +18,7 @@ #include #include #include +#include #if AO_EVENT #include #define ao_button_queue(b,v) ao_event_put_isr(AO_EVENT_BUTTON, b, v) @@ -25,55 +26,70 @@ #define ao_button_queue(b,v) #endif -static uint8_t ao_button[AO_BUTTON_COUNT]; -static AO_TICK_TYPE ao_button_time[AO_BUTTON_COUNT]; +#define AO_BUTTON_DEBOUNCE_HOLD 10 -#define AO_DEBOUNCE AO_MS_TO_TICKS(20) +static struct ao_debounce ao_button_debounce[AO_BUTTON_COUNT]; #define port(q) AO_BUTTON_ ## q ## _PORT #define bit(q) AO_BUTTON_ ## q #define pin(q) AO_BUTTON_ ## q ## _PIN -static void -ao_button_do(uint8_t b, uint8_t v) -{ - /* Debounce */ - if ((AO_TICK_SIGNED) (ao_tick_count - ao_button_time[b]) < AO_DEBOUNCE) - return; - - /* pins are inverted */ - v = !v; - if (ao_button[b] != v) { - ao_button[b] = v; - ao_button_time[b] = ao_tick_count; - ao_button_queue(b, v); - ao_wakeup(&ao_button[b]); - } -} +/* pins are inverted */ +#define ao_button_value(b) !ao_gpio_get(port(b), bit(b), pin(b)) -#define ao_button_update(b) ao_button_do(b, ao_gpio_get(port(b), bit(b), pin(b))) - -static void -ao_button_isr(void) +static uint8_t +_ao_button_get(struct ao_debounce *debounce) { + uint8_t b = debounce - ao_button_debounce; + + switch (b) { #if AO_BUTTON_COUNT > 0 - ao_button_update(0); + case 0: return ao_button_value(0); #endif #if AO_BUTTON_COUNT > 1 - ao_button_update(1); + case 1: return ao_button_value(1); #endif #if AO_BUTTON_COUNT > 2 - ao_button_update(2); + case 2: return ao_button_value(2); #endif #if AO_BUTTON_COUNT > 3 - ao_button_update(3); + case 3: return ao_button_value(3); #endif #if AO_BUTTON_COUNT > 4 - ao_button_update(4); + case 4: return ao_button_value(4); #endif + } +} + +static void +_ao_button_set(struct ao_debounce *debounce, uint8_t value) +{ + uint8_t b = debounce - ao_button_debounce; + + ao_button_queue(b, value); +} + + +#define ao_button_update(b) ao_button_do(b, ao_gpio_get(port(b), bit(b), pin(b))) + +static void +ao_button_debounce_init(struct ao_debounce *debounce) { + debounce->hold = AO_BUTTON_DEBOUNCE_HOLD; + debounce->_get = _ao_button_get; + debounce->_set = _ao_button_set; +} + +static void +ao_button_isr(void) +{ + uint8_t b; + + for (b = 0; b < AO_BUTTON_COUNT; b++) + _ao_debounce_start(&ao_button_debounce[b]); } #define init(b) do { \ + ao_button_debounce_init(&ao_button_debounce[b]); \ ao_enable_port(port(b)); \ \ ao_exti_setup(port(b), bit(b), \ @@ -91,4 +107,14 @@ ao_button_init(void) #if AO_BUTTON_COUNT > 1 init(1); #endif +#if AO_BUTTON_COUNT > 2 + init(2); +#endif +#if AO_BUTTON_COUNT > 3 + init(3); +#endif +#if AO_BUTTON_COUNT > 4 + init(4); +#endif + ao_debounce_init(); } diff --git a/src/drivers/ao_event.c b/src/drivers/ao_event.c index 440ef2de..c428125d 100644 --- a/src/drivers/ao_event.c +++ b/src/drivers/ao_event.c @@ -25,11 +25,6 @@ #define ao_event_queue_empty() (ao_event_queue_insert == ao_event_queue_remove) #define ao_event_queue_full() (ao_event_queue_next(ao_event_queue_insert) == ao_event_queue_remove) -/* - * Whether a sequence of events from the same device should be collapsed - */ -#define ao_event_can_collapse(type) ((type) == AO_EVENT_QUADRATURE) - struct ao_event ao_event_queue[AO_EVENT_QUEUE]; uint8_t ao_event_queue_insert; uint8_t ao_event_queue_remove; @@ -48,17 +43,9 @@ ao_event_get(struct ao_event *ev) /* called with interrupts disabled */ void -ao_event_put_isr(uint8_t type, uint8_t unit, uint32_t value) +ao_event_put_isr(uint8_t type, uint8_t unit, int32_t value) { if (!ao_event_queue_full()) { - - if (ao_event_can_collapse(type) && !ao_event_queue_empty()) { - uint8_t prev = ao_event_queue_prev(ao_event_queue_insert); - - if (ao_event_queue[prev].type == type && - ao_event_queue[prev].unit == unit) - ao_event_queue_insert = prev; - } ao_event_queue[ao_event_queue_insert] = (struct ao_event) { .type = type, .unit = unit, @@ -71,7 +58,7 @@ ao_event_put_isr(uint8_t type, uint8_t unit, uint32_t value) } void -ao_event_put(uint8_t type, uint8_t unit, uint32_t value) +ao_event_put(uint8_t type, uint8_t unit, int32_t value) { ao_arch_critical(ao_event_put_isr(type, unit, value);); } diff --git a/src/drivers/ao_event.h b/src/drivers/ao_event.h index 25c49c35..ed9a7433 100644 --- a/src/drivers/ao_event.h +++ b/src/drivers/ao_event.h @@ -26,16 +26,16 @@ struct ao_event { uint8_t type; uint8_t unit; uint16_t tick; - uint32_t value; + int32_t value; }; uint8_t ao_event_get(struct ao_event *ev); void -ao_event_put_isr(uint8_t type, uint8_t unit, uint32_t value); +ao_event_put_isr(uint8_t type, uint8_t unit, int32_t value); void -ao_event_put(uint8_t type, uint8_t unit, uint32_t value); +ao_event_put(uint8_t type, uint8_t unit, int32_t value); #endif /* _AO_EVENT_H_ */ diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c index 6cc2467a..cfa58da6 100644 --- a/src/drivers/ao_quadrature.c +++ b/src/drivers/ao_quadrature.c @@ -18,12 +18,14 @@ #include #include #include -#if AO_EVENT +#include #include -#define ao_quadrature_queue(q) ao_event_put_isr(AO_EVENT_QUADRATURE, q, ao_quadrature_count[q]) -#else -#define ao_quadrature_queue(q) -#endif + +#define AO_QUADRATURE_DEBOUNCE_HOLD 3 + +static __xdata struct ao_debounce ao_quadrature_debounce[AO_QUADRATURE_COUNT]; + +#define debounce_id(d) ((d) - ao_quadrature_debounce) __xdata int32_t ao_quadrature_count[AO_QUADRATURE_COUNT]; @@ -35,41 +37,77 @@ static uint8_t ao_quadrature_state[AO_QUADRATURE_COUNT]; #define port(q) AO_QUADRATURE_ ## q ## _PORT #define bita(q) AO_QUADRATURE_ ## q ## _A #define bitb(q) AO_QUADRATURE_ ## q ## _B +#define pina(q) AO_QUADRATURE_ ## q ## _A ## _PIN +#define pinb(q) AO_QUADRATURE_ ## q ## _B ## _PIN -#define ao_quadrature_update(q) do { \ - ao_quadrature_state[q] = ((ao_quadrature_state[q] & 3) << 2); \ - ao_quadrature_state[q] |= ao_gpio_get(port(q), bita(q), 0); \ - ao_quadrature_state[q] |= ao_gpio_get(port(q), bitb(q), 0) << 1; \ - } while (0) - +#define q_case(q) case q: v = (!ao_gpio_get(port(q), bita(q), pina(q))) | ((!ao_gpio_get(port(q), bitb(q), pinb(q))) << 1); break -static void -ao_quadrature_isr(void) -{ - uint8_t q; +uint8_t quad_raw[64]; +uint8_t quad_r; + +static uint8_t +_ao_quadrature_get(struct ao_debounce *debounce) { + uint8_t q = debounce_id(debounce); + uint8_t v = 0; + + switch (q) { #if AO_QUADRATURE_COUNT > 0 - ao_quadrature_update(0); + q_case(0); #endif #if AO_QUADRATURE_COUNT > 1 - ao_quadrature_update(1); + q_case(1); #endif + } + if (q == 0) { + quad_raw[quad_r] = v; + quad_r = (quad_r + 1) & 63; + } + return v; +} - for (q = 0; q < AO_QUADRATURE_COUNT; q++) { - switch (ao_quadrature_state[q]) { - case STATE(0, 1, 0, 0): - ao_quadrature_count[q]++; - break; - case STATE(1, 0, 0, 0): - ao_quadrature_count[q]--; - break; - default: - continue; - } - ao_quadrature_queue(q); - ao_wakeup(&ao_quadrature_count[q]); +static void +_ao_quadrature_queue(uint8_t q, int8_t step) +{ + ao_quadrature_count[q] += step; +#if AO_EVENT + ao_event_put_isr(AO_EVENT_QUADRATURE, q, step); +#endif + ao_wakeup(&ao_quadrature_count[q]); +} + +uint8_t quad_history[64]; +uint8_t quad_h; + +static void +_ao_quadrature_set(struct ao_debounce *debounce, uint8_t value) { + uint8_t q = debounce_id(debounce); + + ao_quadrature_state[q] = ((ao_quadrature_state[q] & 3) << 2); + ao_quadrature_state[q] |= value; + + if (q == 0) { + quad_history[quad_h] = ao_quadrature_state[0]; + quad_h = (quad_h + 1) & 63; + } + + switch (ao_quadrature_state[q]) { + case STATE(0, 1, 0, 0): + _ao_quadrature_queue(q, 1); + break; + case STATE(1, 0, 0, 0): + _ao_quadrature_queue(q, -1); + break; } } +static void +ao_quadrature_isr(void) +{ + uint8_t q; + for (q = 0; q < AO_QUADRATURE_COUNT; q++) + _ao_debounce_start(&ao_quadrature_debounce[q]); +} + int32_t ao_quadrature_poll(uint8_t q) { @@ -107,9 +145,16 @@ static const struct ao_cmds ao_quadrature_cmds[] = { { 0, NULL } }; +static void +ao_quadrature_debounce_init(struct ao_debounce *debounce) { + debounce->hold = AO_QUADRATURE_DEBOUNCE_HOLD; + debounce->_get = _ao_quadrature_get; + debounce->_set = _ao_quadrature_set; +} + #define init(q) do { \ ao_enable_port(port(q)); \ - \ + ao_quadrature_debounce_init(&ao_quadrature_debounce[q]); \ ao_exti_setup(port(q), bita(q), \ AO_QUADRATURE_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \ ao_quadrature_isr); \ @@ -124,6 +169,7 @@ static const struct ao_cmds ao_quadrature_cmds[] = { void ao_quadrature_init(void) { + ao_debounce_init(); #if AO_QUADRATURE_COUNT > 0 init(0); #endif diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index d1f825db..48fa07eb 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -36,10 +36,7 @@ ALTOS_SRC = \ ao_data.c \ ao_i2c_stm.c \ ao_usb_stm.c \ - ao_exti_stm.c \ - ao_event.c \ - ao_quadrature.c \ - ao_button.c + ao_exti_stm.c PRODUCT=StmDemo-v0.0 PRODUCT_DEF=-DSTM_DEMO diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 5677cdf4..58cf651b 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -153,6 +153,7 @@ ao_temp (void) printf ("temp: %d\n", temp); } +#if 0 static void ao_event(void) { @@ -168,6 +169,7 @@ ao_event(void) } } +#endif __code struct ao_cmds ao_demo_cmds[] = { { ao_dma_test, "D\0DMA test" }, @@ -175,7 +177,7 @@ __code struct ao_cmds ao_demo_cmds[] = { { ao_spi_read, "R\0SPI read" }, { ao_i2c_write, "i\0I2C write" }, { ao_temp, "t\0Show temp" }, - { ao_event, "e\0Monitor event queue" }, +/* { ao_event, "e\0Monitor event queue" }, */ { 0, NULL } }; diff --git a/src/stm/ao_debounce.c b/src/stm/ao_debounce.c new file mode 100644 index 00000000..22cdf230 --- /dev/null +++ b/src/stm/ao_debounce.c @@ -0,0 +1,187 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +static uint8_t ao_debounce_initialized; +static uint8_t ao_debounce_running; +static struct ao_debounce *ao_debounce; + +static void +ao_debounce_on(void) +{ + stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) | + (0 << STM_TIM67_CR1_OPM) | + (1 << STM_TIM67_CR1_URS) | + (0 << STM_TIM67_CR1_UDIS) | + (1 << STM_TIM67_CR1_CEN)); +} + +static void +ao_debounce_off(void) +{ + stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) | + (0 << STM_TIM67_CR1_OPM) | + (1 << STM_TIM67_CR1_URS) | + (0 << STM_TIM67_CR1_UDIS) | + (0 << STM_TIM67_CR1_CEN)); +} + +static void +_ao_debounce_set(struct ao_debounce *debounce, uint8_t value) +{ + if (value != debounce->value) { + debounce->value = value; + debounce->_set(debounce, value); + } + _ao_debounce_stop(debounce); +} + +/* + * Get the current value, set the result when we've + * reached the debounce count limit + */ +static void +_ao_debounce_check(struct ao_debounce *debounce) +{ + if (debounce->_get(debounce)) { + if (debounce->count < 0) + debounce->count = 0; + if (debounce->count < debounce->hold) { + if (++debounce->count == debounce->hold) + _ao_debounce_set(debounce, 1); + } + } else { + if (debounce->count > 0) + debounce->count = 0; + if (debounce->count > -debounce->hold) { + if (--debounce->count == -debounce->hold) + _ao_debounce_set(debounce, 0); + } + } +} + +/* + * Start monitoring one pin + */ +void +_ao_debounce_start(struct ao_debounce *debounce) +{ + if (debounce->running) + return; + debounce->running = 1; + + /* Reset the counter */ + debounce->count = 0; + + /* Link into list */ + debounce->next = ao_debounce; + ao_debounce = debounce; + + /* Make sure the timer is running */ + if (!ao_debounce_running++) + ao_debounce_on(); + + /* And go check the current value */ + _ao_debounce_check(debounce); +} + +/* + * Stop monitoring one pin + */ +void +_ao_debounce_stop(struct ao_debounce *debounce) +{ + struct ao_debounce **prev; + if (!debounce->running) + return; + + debounce->running = 0; + + /* Unlink */ + for (prev = &ao_debounce; (*prev); prev = &((*prev)->next)) { + if (*prev == debounce) { + *prev = debounce->next; + break; + } + } + debounce->next = NULL; + + /* Turn off the timer if possible */ + if (!--ao_debounce_running) + ao_debounce_off(); +} + +void stm_tim6_isr(void) +{ + struct ao_debounce *debounce, *next; + if (stm_tim6.sr & (1 << STM_TIM67_SR_UIF)) { + stm_tim6.sr = 0; + + /* Walk the current list, allowing the current + * object to be removed from the list + */ + for (debounce = ao_debounce; debounce; debounce = next) { + next = debounce->next; + _ao_debounce_check(debounce); + } + } +} + +/* + * According to the STM clock-configuration, timers run + * twice as fast as the APB1 clock *if* the APB1 prescaler + * is greater than 1. + */ + +#if AO_APB1_PRESCALER > 1 +#define TIMER_23467_SCALER 2 +#else +#define TIMER_23467_SCALER 1 +#endif + +#define TIMER_100kHz ((AO_PCLK1 * TIMER_23467_SCALER) / 100000) + +void +ao_debounce_init(void) +{ + if (ao_debounce_initialized) + return; + ao_debounce_initialized = 1; + + stm_nvic_set_enable(STM_ISR_TIM6_POS); + stm_nvic_set_priority(STM_ISR_TIM6_POS, AO_STM_NVIC_CLOCK_PRIORITY); + + /* Turn on timer 6 */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN); + + stm_tim6.psc = TIMER_100kHz; + stm_tim6.arr = 9; + stm_tim6.cnt = 0; + + /* Enable update interrupt */ + stm_tim6.dier = (1 << STM_TIM67_DIER_UIE); + + /* Poke timer to reload values */ + stm_tim6.egr |= (1 << STM_TIM67_EGR_UG); + + stm_tim6.cr2 = (STM_TIM67_CR2_MMS_RESET << STM_TIM67_CR2_MMS); + + /* And turn it off (for now) */ + ao_debounce_off(); +} diff --git a/src/telelco-v0.2/Makefile b/src/telelco-v0.2/Makefile index cc6e62c4..42a5a7ee 100644 --- a/src/telelco-v0.2/Makefile +++ b/src/telelco-v0.2/Makefile @@ -21,6 +21,7 @@ INC = \ ao_radio_spi.h \ ao_radio_cmac.h \ ao_cc1120_CC1120.h \ + ao_debounce.h \ stm32l.h # @@ -59,6 +60,7 @@ ALTOS_SRC = \ ao_fec_tx.c \ ao_fec_rx.c \ ao_seven_segment.c \ + ao_debounce.c \ ao_quadrature.c \ ao_button.c \ ao_event.c \ diff --git a/src/telelco-v0.2/ao_lco.c b/src/telelco-v0.2/ao_lco.c index 418c0509..6e490247 100644 --- a/src/telelco-v0.2/ao_lco.c +++ b/src/telelco-v0.2/ao_lco.c @@ -114,11 +114,9 @@ ao_lco_input(void) switch (event.unit) { case AO_QUADRATURE_PAD: if (!ao_lco_armed) { - if (event.value == ao_lco_pad) - break; - dir = ((int8_t) event.value - (int8_t) ao_lco_pad) > 0 ? 1 : -1; - new_pad = event.value; - while (!ao_lco_pad_present(new_pad)) { + dir = (int8_t) event.value; + new_pad = ao_lco_pad; + do { new_pad += dir; if (new_pad > AO_PAD_MAX_CHANNELS) new_pad = 0; @@ -126,21 +124,18 @@ ao_lco_input(void) new_pad = AO_PAD_MAX_CHANNELS - 1; if (new_pad == ao_lco_pad) break; - } + } while (!ao_lco_pad_present(new_pad)); if (new_pad != ao_lco_pad) { ao_lco_pad = new_pad; - ao_quadrature_count[AO_QUADRATURE_PAD] = ao_lco_pad; ao_lco_set_pad(); } } break; case AO_QUADRATURE_BOX: if (!ao_lco_armed) { - if (event.value == ao_lco_box) - break; - dir = ((int8_t) event.value - (int8_t) ao_lco_box) > 0 ? 1 : -1; - new_box = event.value; - while (!ao_lco_box_present(new_box)) { + dir = (int8_t) event.value; + new_box = ao_lco_box; + do { new_box += dir; if (new_box > ao_lco_max_box) new_box = ao_lco_min_box; @@ -148,8 +143,7 @@ ao_lco_input(void) new_box = ao_lco_min_box; if (new_box == ao_lco_box) break; - } - ao_quadrature_count[AO_QUADRATURE_PAD] = new_box; + } while (!ao_lco_box_present(new_box)); if (ao_lco_box != new_box) { ao_lco_box = new_box; ao_lco_got_channels = 0; -- cgit v1.2.3 From 988924b51980ad43e39bc4785a625ff25eb16449 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Jun 2013 22:09:13 -0700 Subject: altos: Add fast-timer API. Use for quadrature and button drivers This splits the fast-timer portion out of the debounce helper code and shares that with the quadrature driver which now uses it directly. Signed-off-by: Keith Packard --- src/core/ao.h | 1 + src/core/ao_debounce.c | 163 ++++++++++++++++++++++++++++++++++++++ src/core/ao_debounce.h | 26 +++++- src/drivers/ao_button.c | 7 +- src/drivers/ao_quadrature.c | 130 ++++++++++++++---------------- src/stm/ao_debounce.c | 187 -------------------------------------------- src/stm/ao_fast_timer.c | 120 ++++++++++++++++++++++++++++ src/stm/ao_fast_timer.h | 34 ++++++++ src/stm/stm32l.h | 5 ++ src/telelco-v0.2/Makefile | 1 + src/telelco-v0.2/ao_pins.h | 1 - 11 files changed, 411 insertions(+), 264 deletions(-) create mode 100644 src/core/ao_debounce.c delete mode 100644 src/stm/ao_debounce.c create mode 100644 src/stm/ao_fast_timer.c create mode 100644 src/stm/ao_fast_timer.h (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 0886260f..caa0ec19 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -75,6 +75,7 @@ typedef AO_PORT_TYPE ao_port_t; #define AO_PANIC_CRASH 14 /* Processor crashed */ #define AO_PANIC_BUFIO 15 /* Mis-using bufio API */ #define AO_PANIC_EXTI 16 /* Mis-using exti API */ +#define AO_PANIC_FAST_TIMER 17 /* Mis-using fast timer API */ #define AO_PANIC_SELF_TEST_CC1120 0x40 | 1 /* Self test failure */ #define AO_PANIC_SELF_TEST_HMC5883 0x40 | 2 /* Self test failure */ #define AO_PANIC_SELF_TEST_MPU6000 0x40 | 3 /* Self test failure */ diff --git a/src/core/ao_debounce.c b/src/core/ao_debounce.c new file mode 100644 index 00000000..b9d67729 --- /dev/null +++ b/src/core/ao_debounce.c @@ -0,0 +1,163 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include + +static uint8_t ao_debounce_initialized; +static uint8_t ao_debounce_running; +static struct ao_debounce *ao_debounce; + +static uint8_t values[64]; +static uint8_t n; + +#define d_step(n) (((n) + 1) & 63) + +static void +_ao_debounce_set(struct ao_debounce *debounce, uint8_t value) +{ + if (value != debounce->value) { + values[n] = value; + n = (n + 1) & 63; + debounce->value = value; + debounce->_set(debounce, value); + } + _ao_debounce_stop(debounce); +} + +void +ao_debounce_dump(void) +{ + uint8_t s; + + for (s = 0; s < n; s++) { + printf ("%d: %d\n", + s, values[s]); + } + n = 0; +} + +/* + * Get the current value, set the result when we've + * reached the debounce count limit + */ +static void +_ao_debounce_check(struct ao_debounce *debounce) +{ + uint8_t next = debounce->_get(debounce); + + if (next == debounce->current) { + if (debounce->count < debounce->hold) { + if (++debounce->count == debounce->hold) + _ao_debounce_set(debounce, debounce->current); + } + } else { + debounce->count = 0; + debounce->current = next; + } +} + +static void +_ao_debounce_isr(void) +{ + struct ao_debounce *debounce, *next; + + for (debounce = ao_debounce; debounce; debounce = next) { + next = debounce->next; + _ao_debounce_check(debounce); + } +} + +static void +ao_debounce_on(void) +{ + ao_fast_timer_on(_ao_debounce_isr); +} + +static void +ao_debounce_off(void) +{ + ao_fast_timer_off(_ao_debounce_isr); +} + +/* + * Start monitoring one pin + */ +void +_ao_debounce_start(struct ao_debounce *debounce) +{ + uint32_t m; + + m = ao_arch_irqsave(); + if (!debounce->running) { + debounce->running = 1; + + /* Reset the counter */ + debounce->count = 0; + + /* Link into list */ + debounce->next = ao_debounce; + ao_debounce = debounce; + + /* Make sure the timer is running */ + if (!ao_debounce_running++) + ao_debounce_on(); + + /* And go check the current value */ + _ao_debounce_check(debounce); + } + ao_arch_irqrestore(m); +} + +/* + * Stop monitoring one pin + */ +void +_ao_debounce_stop(struct ao_debounce *debounce) +{ + struct ao_debounce **prev; + uint32_t m; + + m = ao_arch_irqsave(); + if (debounce->running) { + debounce->running = 0; + + /* Unlink */ + for (prev = &ao_debounce; (*prev); prev = &((*prev)->next)) { + if (*prev == debounce) { + *prev = debounce->next; + break; + } + } + debounce->next = NULL; + + /* Turn off the timer if possible */ + if (!--ao_debounce_running) + ao_debounce_off(); + } + ao_arch_irqrestore(m); +} + +void +ao_debounce_init(void) +{ + if (ao_debounce_initialized) + return; + ao_debounce_initialized = 1; + ao_fast_timer_init(); +} diff --git a/src/core/ao_debounce.h b/src/core/ao_debounce.h index ebe290e1..19c620f5 100644 --- a/src/core/ao_debounce.h +++ b/src/core/ao_debounce.h @@ -22,13 +22,16 @@ struct ao_debounce { struct ao_debounce *next; /* time that pin value must be stable before accepting */ - int8_t hold; + uint8_t hold; /* last value reported to app; don't report it twice */ uint8_t value; + /* current value received from pins */ + uint8_t current; + /* current count of intervals pin value has been stable */ - int8_t count; + uint8_t count; /* This pin is running */ uint8_t running; @@ -40,6 +43,22 @@ struct ao_debounce { void (*_set)(struct ao_debounce *debounce, uint8_t value); }; +static inline void +ao_debounce_config(struct ao_debounce *debounce, + uint8_t (*_get)(struct ao_debounce *debounce), + void (*_set)(struct ao_debounce *debounce, uint8_t value), + uint8_t hold) +{ + debounce->next = 0; + debounce->hold = hold; + debounce->value = 0xff; + debounce->current = 0xff; + debounce->count = 0; + debounce->running = 0; + debounce->_get = _get; + debounce->_set = _set; +} + void _ao_debounce_start(struct ao_debounce *debounce); @@ -49,4 +68,7 @@ _ao_debounce_stop(struct ao_debounce *debounce); void ao_debounce_init(void); +void +ao_debounce_dump(void); + #endif /* _AO_DEBOUNCE_H_ */ diff --git a/src/drivers/ao_button.c b/src/drivers/ao_button.c index 7b1fb530..25c0cd5c 100644 --- a/src/drivers/ao_button.c +++ b/src/drivers/ao_button.c @@ -74,9 +74,10 @@ _ao_button_set(struct ao_debounce *debounce, uint8_t value) static void ao_button_debounce_init(struct ao_debounce *debounce) { - debounce->hold = AO_BUTTON_DEBOUNCE_HOLD; - debounce->_get = _ao_button_get; - debounce->_set = _ao_button_set; + ao_debounce_config(debounce, + _ao_button_get, + _ao_button_set, + AO_BUTTON_DEBOUNCE_HOLD); } static void diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c index cfa58da6..d07488d0 100644 --- a/src/drivers/ao_quadrature.c +++ b/src/drivers/ao_quadrature.c @@ -18,18 +18,12 @@ #include #include #include -#include +#include #include -#define AO_QUADRATURE_DEBOUNCE_HOLD 3 - -static __xdata struct ao_debounce ao_quadrature_debounce[AO_QUADRATURE_COUNT]; - -#define debounce_id(d) ((d) - ao_quadrature_debounce) - __xdata int32_t ao_quadrature_count[AO_QUADRATURE_COUNT]; - static uint8_t ao_quadrature_state[AO_QUADRATURE_COUNT]; +static int8_t ao_quadrature_raw[AO_QUADRATURE_COUNT]; #define BIT(a,b) ((a) | ((b) << 1)) #define STATE(old_a, old_b, new_a, new_b) (((BIT(old_a, old_b) << 2) | BIT(new_a, new_b))) @@ -39,32 +33,17 @@ static uint8_t ao_quadrature_state[AO_QUADRATURE_COUNT]; #define bitb(q) AO_QUADRATURE_ ## q ## _B #define pina(q) AO_QUADRATURE_ ## q ## _A ## _PIN #define pinb(q) AO_QUADRATURE_ ## q ## _B ## _PIN +#define isr(q) ao_quadrature_isr_ ## q -#define q_case(q) case q: v = (!ao_gpio_get(port(q), bita(q), pina(q))) | ((!ao_gpio_get(port(q), bitb(q), pinb(q))) << 1); break - -uint8_t quad_raw[64]; -uint8_t quad_r; - -static uint8_t -_ao_quadrature_get(struct ao_debounce *debounce) { - uint8_t q = debounce_id(debounce); - uint8_t v = 0; +static inline uint16_t +ao_quadrature_read(struct stm_gpio *gpio, uint8_t pin_a, uint8_t pin_b) { + uint16_t v = stm_gpio_get_all(gpio); - switch (q) { -#if AO_QUADRATURE_COUNT > 0 - q_case(0); -#endif -#if AO_QUADRATURE_COUNT > 1 - q_case(1); -#endif - } - if (q == 0) { - quad_raw[quad_r] = v; - quad_r = (quad_r + 1) & 63; - } - return v; + return ~((((v >> pin_a) & 1) | (((v >> pin_b) & 1) << 1))) & 3; } +#define _ao_quadrature_get(q) ao_quadrature_read(port(q), bita(q), bitb(q)) + static void _ao_quadrature_queue(uint8_t q, int8_t step) { @@ -75,37 +54,51 @@ _ao_quadrature_queue(uint8_t q, int8_t step) ao_wakeup(&ao_quadrature_count[q]); } -uint8_t quad_history[64]; -uint8_t quad_h; +static const int8_t step[16] = { + [STATE(0,0,0,0)] = 0, + [STATE(0,0,0,1)] = -1, + [STATE(0,0,1,0)] = 1, + [STATE(0,0,1,1)] = 0, + [STATE(0,1,0,0)] = 1, + [STATE(0,1,1,0)] = 0, + [STATE(0,1,1,1)] = -1, + [STATE(1,0,0,0)] = -1, + [STATE(1,0,0,1)] = 0, + [STATE(1,0,1,0)] = 0, + [STATE(1,0,1,1)] = 1, + [STATE(1,1,0,0)] = 0, + [STATE(1,1,0,1)] = 1, + [STATE(1,1,1,0)] = -1, + [STATE(1,1,1,1)] = 0 +}; static void -_ao_quadrature_set(struct ao_debounce *debounce, uint8_t value) { - uint8_t q = debounce_id(debounce); +_ao_quadrature_set(uint8_t q, uint8_t value) { + uint8_t v; - ao_quadrature_state[q] = ((ao_quadrature_state[q] & 3) << 2); - ao_quadrature_state[q] |= value; - - if (q == 0) { - quad_history[quad_h] = ao_quadrature_state[0]; - quad_h = (quad_h + 1) & 63; - } + v = ao_quadrature_state[q] & 3; + value = value & 3; - switch (ao_quadrature_state[q]) { - case STATE(0, 1, 0, 0): - _ao_quadrature_queue(q, 1); - break; - case STATE(1, 0, 0, 0): - _ao_quadrature_queue(q, -1); - break; + if (v == value) + return; + + ao_quadrature_state[q] = (v << 2) | value; + + ao_quadrature_raw[q] += step[ao_quadrature_state[q]]; + if (value == 0) { + if (ao_quadrature_raw[q] == 4) + _ao_quadrature_queue(q, 1); + else if (ao_quadrature_raw[q] == -4) + _ao_quadrature_queue(q, -1); + ao_quadrature_raw[q] = 0; } } static void ao_quadrature_isr(void) { - uint8_t q; - for (q = 0; q < AO_QUADRATURE_COUNT; q++) - _ao_debounce_start(&ao_quadrature_debounce[q]); + _ao_quadrature_set(0, _ao_quadrature_get(0)); + _ao_quadrature_set(1, _ao_quadrature_get(1)); } int32_t @@ -130,6 +123,15 @@ ao_quadrature_test(void) ao_cmd_decimal(); q = ao_cmd_lex_i; + if (q >= AO_QUADRATURE_COUNT) { + ao_cmd_status = ao_cmd_syntax_error; + return; + } + printf ("count %d state %x raw %d\n", + ao_quadrature_count[q], + ao_quadrature_state[q], + ao_quadrature_raw[q]); +#if 0 for (;;) { int32_t c; flush(); @@ -138,6 +140,7 @@ ao_quadrature_test(void) if (c == 100) break; } +#endif } static const struct ao_cmds ao_quadrature_cmds[] = { @@ -145,36 +148,21 @@ static const struct ao_cmds ao_quadrature_cmds[] = { { 0, NULL } }; -static void -ao_quadrature_debounce_init(struct ao_debounce *debounce) { - debounce->hold = AO_QUADRATURE_DEBOUNCE_HOLD; - debounce->_get = _ao_quadrature_get; - debounce->_set = _ao_quadrature_set; -} - -#define init(q) do { \ - ao_enable_port(port(q)); \ - ao_quadrature_debounce_init(&ao_quadrature_debounce[q]); \ - ao_exti_setup(port(q), bita(q), \ - AO_QUADRATURE_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \ - ao_quadrature_isr); \ - ao_exti_enable(port(q), bita(q)); \ - \ - ao_exti_setup(port(q), bitb(q), \ - AO_QUADRATURE_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \ - ao_quadrature_isr); \ - ao_exti_enable(port(q), bitb(q)); \ +#define init(q) do { \ + ao_enable_input(port(q), bita(q), 0); \ + ao_enable_input(port(q), bitb(q), 0); \ } while (0) void ao_quadrature_init(void) { - ao_debounce_init(); #if AO_QUADRATURE_COUNT > 0 init(0); #endif #if AO_QUADRATURE_COUNT > 1 init(1); #endif + ao_fast_timer_init(); + ao_fast_timer_on(ao_quadrature_isr); ao_cmd_register(&ao_quadrature_cmds[0]); } diff --git a/src/stm/ao_debounce.c b/src/stm/ao_debounce.c deleted file mode 100644 index 22cdf230..00000000 --- a/src/stm/ao_debounce.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright © 2013 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include -#include - -static uint8_t ao_debounce_initialized; -static uint8_t ao_debounce_running; -static struct ao_debounce *ao_debounce; - -static void -ao_debounce_on(void) -{ - stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) | - (0 << STM_TIM67_CR1_OPM) | - (1 << STM_TIM67_CR1_URS) | - (0 << STM_TIM67_CR1_UDIS) | - (1 << STM_TIM67_CR1_CEN)); -} - -static void -ao_debounce_off(void) -{ - stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) | - (0 << STM_TIM67_CR1_OPM) | - (1 << STM_TIM67_CR1_URS) | - (0 << STM_TIM67_CR1_UDIS) | - (0 << STM_TIM67_CR1_CEN)); -} - -static void -_ao_debounce_set(struct ao_debounce *debounce, uint8_t value) -{ - if (value != debounce->value) { - debounce->value = value; - debounce->_set(debounce, value); - } - _ao_debounce_stop(debounce); -} - -/* - * Get the current value, set the result when we've - * reached the debounce count limit - */ -static void -_ao_debounce_check(struct ao_debounce *debounce) -{ - if (debounce->_get(debounce)) { - if (debounce->count < 0) - debounce->count = 0; - if (debounce->count < debounce->hold) { - if (++debounce->count == debounce->hold) - _ao_debounce_set(debounce, 1); - } - } else { - if (debounce->count > 0) - debounce->count = 0; - if (debounce->count > -debounce->hold) { - if (--debounce->count == -debounce->hold) - _ao_debounce_set(debounce, 0); - } - } -} - -/* - * Start monitoring one pin - */ -void -_ao_debounce_start(struct ao_debounce *debounce) -{ - if (debounce->running) - return; - debounce->running = 1; - - /* Reset the counter */ - debounce->count = 0; - - /* Link into list */ - debounce->next = ao_debounce; - ao_debounce = debounce; - - /* Make sure the timer is running */ - if (!ao_debounce_running++) - ao_debounce_on(); - - /* And go check the current value */ - _ao_debounce_check(debounce); -} - -/* - * Stop monitoring one pin - */ -void -_ao_debounce_stop(struct ao_debounce *debounce) -{ - struct ao_debounce **prev; - if (!debounce->running) - return; - - debounce->running = 0; - - /* Unlink */ - for (prev = &ao_debounce; (*prev); prev = &((*prev)->next)) { - if (*prev == debounce) { - *prev = debounce->next; - break; - } - } - debounce->next = NULL; - - /* Turn off the timer if possible */ - if (!--ao_debounce_running) - ao_debounce_off(); -} - -void stm_tim6_isr(void) -{ - struct ao_debounce *debounce, *next; - if (stm_tim6.sr & (1 << STM_TIM67_SR_UIF)) { - stm_tim6.sr = 0; - - /* Walk the current list, allowing the current - * object to be removed from the list - */ - for (debounce = ao_debounce; debounce; debounce = next) { - next = debounce->next; - _ao_debounce_check(debounce); - } - } -} - -/* - * According to the STM clock-configuration, timers run - * twice as fast as the APB1 clock *if* the APB1 prescaler - * is greater than 1. - */ - -#if AO_APB1_PRESCALER > 1 -#define TIMER_23467_SCALER 2 -#else -#define TIMER_23467_SCALER 1 -#endif - -#define TIMER_100kHz ((AO_PCLK1 * TIMER_23467_SCALER) / 100000) - -void -ao_debounce_init(void) -{ - if (ao_debounce_initialized) - return; - ao_debounce_initialized = 1; - - stm_nvic_set_enable(STM_ISR_TIM6_POS); - stm_nvic_set_priority(STM_ISR_TIM6_POS, AO_STM_NVIC_CLOCK_PRIORITY); - - /* Turn on timer 6 */ - stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN); - - stm_tim6.psc = TIMER_100kHz; - stm_tim6.arr = 9; - stm_tim6.cnt = 0; - - /* Enable update interrupt */ - stm_tim6.dier = (1 << STM_TIM67_DIER_UIE); - - /* Poke timer to reload values */ - stm_tim6.egr |= (1 << STM_TIM67_EGR_UG); - - stm_tim6.cr2 = (STM_TIM67_CR2_MMS_RESET << STM_TIM67_CR2_MMS); - - /* And turn it off (for now) */ - ao_debounce_off(); -} diff --git a/src/stm/ao_fast_timer.c b/src/stm/ao_fast_timer.c new file mode 100644 index 00000000..d61b40c9 --- /dev/null +++ b/src/stm/ao_fast_timer.c @@ -0,0 +1,120 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include +#include + +static void (*ao_fast_timer_callback[AO_FAST_TIMER_MAX])(void); +static uint8_t ao_fast_timer_count; +static uint8_t ao_fast_timer_users; + +static void +ao_fast_timer_enable(void) +{ + stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) | + (0 << STM_TIM67_CR1_OPM) | + (1 << STM_TIM67_CR1_URS) | + (0 << STM_TIM67_CR1_UDIS) | + (1 << STM_TIM67_CR1_CEN)); +} + +static void +ao_fast_timer_disable(void) +{ + stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) | + (0 << STM_TIM67_CR1_OPM) | + (1 << STM_TIM67_CR1_URS) | + (0 << STM_TIM67_CR1_UDIS) | + (0 << STM_TIM67_CR1_CEN)); +} + +void +ao_fast_timer_on(void (*callback)(void)) +{ + ao_fast_timer_callback[ao_fast_timer_count] = callback; + if (!ao_fast_timer_count++) + ao_fast_timer_enable(); +} + +void +ao_fast_timer_off(void (*callback)(void)) +{ + uint8_t n; + + for (n = 0; n < ao_fast_timer_count; n++) + if (ao_fast_timer_callback[n] == callback) { + for (; n < ao_fast_timer_count-1; n++) { + ao_fast_timer_callback[n] = ao_fast_timer_callback[n+1]; + } + if (!--ao_fast_timer_count) + ao_fast_timer_disable(); + break; + } +} + +void stm_tim6_isr(void) +{ + uint8_t i; + if (stm_tim6.sr & (1 << STM_TIM67_SR_UIF)) { + stm_tim6.sr = 0; + + for (i = 0; i < ao_fast_timer_count; i++) + (*ao_fast_timer_callback[i])(); + } +} + +/* + * According to the STM clock-configuration, timers run + * twice as fast as the APB1 clock *if* the APB1 prescaler + * is greater than 1. + */ + +#if AO_APB1_PRESCALER > 1 +#define TIMER_23467_SCALER 2 +#else +#define TIMER_23467_SCALER 1 +#endif + +#define TIMER_10kHz ((AO_PCLK1 * TIMER_23467_SCALER) / 10000) + +void +ao_fast_timer_init(void) +{ + if (!ao_fast_timer_users) { + stm_nvic_set_enable(STM_ISR_TIM6_POS); + stm_nvic_set_priority(STM_ISR_TIM6_POS, AO_STM_NVIC_CLOCK_PRIORITY); + + /* Turn on timer 6 */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN); + + stm_tim6.psc = TIMER_10kHz; + stm_tim6.arr = 9; + stm_tim6.cnt = 0; + + /* Enable update interrupt */ + stm_tim6.dier = (1 << STM_TIM67_DIER_UIE); + + /* Poke timer to reload values */ + stm_tim6.egr |= (1 << STM_TIM67_EGR_UG); + + stm_tim6.cr2 = (STM_TIM67_CR2_MMS_RESET << STM_TIM67_CR2_MMS); + ao_fast_timer_disable(); + } + if (ao_fast_timer_users == AO_FAST_TIMER_MAX) + ao_panic(AO_PANIC_FAST_TIMER); + ao_fast_timer_users++; +} + diff --git a/src/stm/ao_fast_timer.h b/src/stm/ao_fast_timer.h new file mode 100644 index 00000000..90fb3930 --- /dev/null +++ b/src/stm/ao_fast_timer.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_FAST_TIMER_H_ +#define _AO_FAST_TIMER_H_ + +void +ao_fast_timer_init(void); + +#ifndef AO_FAST_TIMER_MAX +#define AO_FAST_TIMER_MAX 2 +#endif + +void +ao_fast_timer_on(void (*callback)(void)); + +void +ao_fast_timer_off(void (*callback)(void)); + +#endif /* _AO_FAST_TIMER_H_ */ diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 63bde0f8..1868468f 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -171,6 +171,11 @@ stm_gpio_get(struct stm_gpio *gpio, int pin) { return (gpio->idr >> pin) & 1; } +static inline uint16_t +stm_gpio_get_all(struct stm_gpio *gpio) { + return gpio->idr; +} + extern struct stm_gpio stm_gpioa; extern struct stm_gpio stm_gpiob; extern struct stm_gpio stm_gpioc; diff --git a/src/telelco-v0.2/Makefile b/src/telelco-v0.2/Makefile index 42a5a7ee..f78ca9e2 100644 --- a/src/telelco-v0.2/Makefile +++ b/src/telelco-v0.2/Makefile @@ -50,6 +50,7 @@ ALTOS_SRC = \ ao_beep_stm.c \ ao_storage.c \ ao_eeprom_stm.c \ + ao_fast_timer.c \ ao_lcd_stm.c \ ao_usb_stm.c \ ao_exti_stm.c \ diff --git a/src/telelco-v0.2/ao_pins.h b/src/telelco-v0.2/ao_pins.h index 07ea1b45..d86782f3 100644 --- a/src/telelco-v0.2/ao_pins.h +++ b/src/telelco-v0.2/ao_pins.h @@ -235,7 +235,6 @@ */ #define AO_QUADRATURE_COUNT 2 -#define AO_QUADRATURE_MODE 0 #define AO_QUADRATURE_0_PORT &stm_gpioe #define AO_QUADRATURE_0_A 3 -- cgit v1.2.3 From 15063cbb8f76bffea71575d295ca87b7ceca36d8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Jun 2013 23:18:09 -0700 Subject: altos/telelco: Add 30ms delay in search after finding a box This gives the remote boxes time to get back to listening for messages after receiving the packet from the found box. Signed-off-by: Keith Packard --- src/telelco-v0.2/ao_lco.c | 59 ++++++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/telelco-v0.2/ao_lco.c b/src/telelco-v0.2/ao_lco.c index 6e490247..e8d16ca9 100644 --- a/src/telelco-v0.2/ao_lco.c +++ b/src/telelco-v0.2/ao_lco.c @@ -49,16 +49,16 @@ static uint16_t ao_lco_tick_offset; static struct ao_pad_query ao_pad_query; static void -ao_lco_set_pad(void) +ao_lco_set_pad(uint8_t pad) { - ao_seven_segment_set(AO_LCO_PAD_DIGIT, ao_lco_pad + 1); + ao_seven_segment_set(AO_LCO_PAD_DIGIT, pad + 1); } static void -ao_lco_set_box(void) +ao_lco_set_box(uint8_t box) { - ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, ao_lco_box % 10); - ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, ao_lco_box / 10); + ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, box % 10); + ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, box / 10); } #define MASK_SIZE(n) (((n) + 7) >> 3) @@ -103,8 +103,6 @@ ao_lco_input(void) int8_t dir, new_box, new_pad; ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); - ao_lco_set_pad(); - ao_lco_set_box(); for (;;) { ao_event_get(&event); PRINTD("event type %d unit %d value %d\n", @@ -127,7 +125,7 @@ ao_lco_input(void) } while (!ao_lco_pad_present(new_pad)); if (new_pad != ao_lco_pad) { ao_lco_pad = new_pad; - ao_lco_set_pad(); + ao_lco_set_pad(ao_lco_pad); } } break; @@ -140,14 +138,14 @@ ao_lco_input(void) if (new_box > ao_lco_max_box) new_box = ao_lco_min_box; else if (new_box < ao_lco_min_box) - new_box = ao_lco_min_box; + new_box = ao_lco_max_box; if (new_box == ao_lco_box) break; } while (!ao_lco_box_present(new_box)); if (ao_lco_box != new_box) { ao_lco_box = new_box; ao_lco_got_channels = 0; - ao_lco_set_box(); + ao_lco_set_box(ao_lco_box); } } break; @@ -213,7 +211,7 @@ ao_lco_update(void) ao_lco_valid = 1; if (!c) { ao_lco_pad = ao_lco_pad_first(); - ao_lco_set_pad(); + ao_lco_set_pad(ao_lco_pad); } } else ao_lco_valid = 0; @@ -226,13 +224,24 @@ ao_lco_update(void) query.igniter_status[2], query.igniter_status[3]); #endif - ao_wakeup(&ao_pad_query); } +static void +ao_lco_box_reset_present(void) +{ + ao_lco_min_box = 0xff; + ao_lco_max_box = 0x00; + memset(ao_lco_box_mask, 0, sizeof (ao_lco_box_mask)); +} + static void ao_lco_box_set_present(uint8_t box) { + if (box < ao_lco_min_box) + ao_lco_min_box = box; + if (box > ao_lco_max_box) + ao_lco_max_box = box; if (box >= AO_PAD_MAX_BOXES) return; ao_lco_box_mask[MASK_ID(box)] |= 1 << MASK_SHIFT(box); @@ -243,19 +252,18 @@ ao_lco_search(void) { uint16_t tick_offset; int8_t r; - - ao_lco_min_box = 0xff; - ao_lco_max_box = 0x00; - for (ao_lco_box = 0; ao_lco_box < AO_PAD_MAX_BOXES; ao_lco_box++) { - if ((ao_lco_box % 10) == 0) - ao_lco_set_box(); - r = ao_lco_query(ao_lco_box, &ao_pad_query, &ao_lco_tick_offset); + uint8_t box; + + ao_lco_box_reset_present(); + for (box = 0; box < AO_PAD_MAX_BOXES; box++) { + if ((box % 10) == 0) + ao_lco_set_box(box); + tick_offset = 0; + r = ao_lco_query(box, &ao_pad_query, &tick_offset); + PRINTD("box %d result %d\n", box, r); if (r == AO_RADIO_CMAC_OK) { - if (ao_lco_box < ao_lco_min_box) - ao_lco_min_box = ao_lco_box; - if (ao_lco_box > ao_lco_max_box) - ao_lco_max_box = ao_lco_box; - ao_lco_box_set_present(ao_lco_box); + ao_lco_box_set_present(box); + ao_delay(AO_MS_TO_TICKS(30)); } } if (ao_lco_min_box <= ao_lco_max_box) @@ -265,6 +273,8 @@ ao_lco_search(void) ao_lco_valid = 0; ao_lco_got_channels = 0; ao_lco_pad = 0; + ao_lco_set_pad(ao_lco_pad); + ao_lco_set_box(ao_lco_box); } static void @@ -376,6 +386,7 @@ ao_lco_set_debug(void) __code struct ao_cmds ao_lco_cmds[] = { { ao_lco_set_debug, "D <0 off, 1 on>\0Debug" }, + { ao_lco_search, "s\0Search for pad boxes" }, { 0, NULL } }; #endif -- cgit v1.2.3 From 7361371190bf3805b6d0414e61f697aca7c7cff1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 14 Jun 2013 04:38:11 -0700 Subject: altos/lpc: Make ADC inputs work They're still very unstable (bouncing around a lot), but at least they seem to report useful stuff now. Signed-off-by: Keith Packard --- src/lpc/ao_adc_lpc.c | 52 +++++++++++++++++++++++++++++-------------------- src/lpc/ao_arch_funcs.h | 18 +++++++++++++---- 2 files changed, 45 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_adc_lpc.c b/src/lpc/ao_adc_lpc.c index 9ecc7c13..25a121b5 100644 --- a/src/lpc/ao_adc_lpc.c +++ b/src/lpc/ao_adc_lpc.c @@ -82,19 +82,33 @@ # endif #endif +#define AO_ADC_MASK ((AO_ADC_0 << 0) | \ + (AO_ADC_1 << 1) | \ + (AO_ADC_2 << 2) | \ + (AO_ADC_3 << 3) | \ + (AO_ADC_4 << 4) | \ + (AO_ADC_5 << 5) | \ + (AO_ADC_6 << 6) | \ + (AO_ADC_7 << 7)) + +#define AO_ADC_CLKDIV (AO_LPC_SYSCLK / 4500000 - 1) + static uint8_t ao_adc_ready; void lpc_adc_isr(void) { uint32_t stat = lpc_adc.stat; - uint16_t *out = (uint16_t *) &ao_data_ring[ao_data_head].adc; - vuint32_t *in = &lpc_adc.dr[0]; + uint16_t *out; - lpc_adc.cr = 0; + lpc_adc.cr = ((AO_ADC_MASK << LPC_ADC_CR_SEL) | + (AO_ADC_CLKDIV << LPC_ADC_CR_CLKDIV) | + (0 << LPC_ADC_CR_BURST) | + (LPC_ADC_CR_CLKS_11 << LPC_ADC_CR_CLKS)); lpc_adc.stat = 0; /* Store converted values in packet */ + out = (uint16_t *) &ao_data_ring[ao_data_head].adc; #if AO_ADC_0 *out++ = lpc_adc.dr[0] >> 1; #endif @@ -141,16 +155,6 @@ void lpc_adc_isr(void) ao_adc_ready = 1; } -#define AO_ADC_MASK ((AO_ADC_0 << 0) | \ - (AO_ADC_1 << 1) | \ - (AO_ADC_2 << 2) | \ - (AO_ADC_3 << 3) | \ - (AO_ADC_4 << 4) | \ - (AO_ADC_5 << 5) | \ - (AO_ADC_6 << 6) | \ - (AO_ADC_7 << 7)) - -#define AO_ADC_CLKDIV (AO_LPC_CLKOUT / 4500000) /* * Start the ADC sequence using the DMA engine @@ -204,29 +208,35 @@ ao_adc_init(void) lpc_nvic_set_enable(LPC_ISR_ADC_POS); lpc_nvic_set_priority(LPC_ISR_ADC_POS, AO_LPC_NVIC_CLOCK_PRIORITY); #if AO_ADC_0 - ao_enable_analog(0, 11); + ao_enable_analog(0, 11, 0); #endif #if AO_ADC_1 - ao_enable_analog(0, 12); + ao_enable_analog(0, 12, 1); #endif #if AO_ADC_2 - ao_enable_analog(0, 13); + ao_enable_analog(0, 13, 2); #endif #if AO_ADC_3 - ao_enable_analog(0, 14); + ao_enable_analog(0, 14, 3); #endif #if AO_ADC_4 - ao_enable_analog(0, 14); + ao_enable_analog(0, 15, 4); #endif #if AO_ADC_5 - ao_enable_analog(0, 14); + ao_enable_analog(0, 16, 5); #endif #if AO_ADC_6 - ao_enable_analog(0, 14); + ao_enable_analog(0, 22, 6); #endif #if AO_ADC_7 - ao_enable_analog(0, 14); + ao_enable_analog(0, 23, 7); #endif + + lpc_adc.cr = ((AO_ADC_MASK << LPC_ADC_CR_SEL) | + (AO_ADC_CLKDIV << LPC_ADC_CR_CLKDIV) | + (0 << LPC_ADC_CR_BURST) | + (LPC_ADC_CR_CLKS_11 << LPC_ADC_CR_CLKS)); + ao_cmd_register(&ao_adc_cmds[0]); ao_adc_ready = 1; diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index 204d1227..179b2f4d 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -51,12 +51,22 @@ (1 << LPC_IOCONF_ADMODE)); \ } while (0) -#define ao_enable_analog(port,bit) do { \ - vuint32_t *_ioconf = &lpc_ioconf.pio0_0 + ((port)*24+(bit)); \ +#define lpc_token_paster_2(x,y) x ## y +#define lpc_token_evaluator_2(x,y) lpc_token_paster_2(x,y) +#define lpc_token_paster_3(x,y,z) x ## y ## z +#define lpc_token_evaluator_3(x,y,z) lpc_token_paster_3(x,y,z) +#define lpc_token_paster_4(w,x,y,z) w ## x ## y ## z +#define lpc_token_evaluator_4(w,x,y,z) lpc_token_paster_4(w,x,y,z) +#define analog_reg(port,bit) lpc_token_evaluator_4(pio,port,_,bit) +#define analog_func(id) lpc_token_evaluator_2(LPC_IOCONF_FUNC_AD,id) + +#define ao_enable_analog(port,bit,id) do { \ + uint32_t _mode; \ ao_enable_port(port); \ lpc_gpio.dir[port] &= ~(1 << bit); \ - *_ioconf = *_ioconf & ~((1 << LPC_IOCONF_ADMODE) | \ - (LPC_IOCONF_MODE_MASK << LPC_IOCONF_MODE)); \ + _mode = ((analog_func(id) << LPC_IOCONF_FUNC) | \ + (0 << LPC_IOCONF_ADMODE)); \ + lpc_ioconf.analog_reg(port,bit) = _mode; \ } while (0) #define ARM_PUSH32(stack, val) (*(--(stack)) = (val)) -- cgit v1.2.3 From be9ee9ed2d041c4ab4e77ee2010fe3c7a1ca6597 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Jun 2013 01:20:49 -0700 Subject: altos/lpc: Filter ADC inputs They're amazingly noisy on EasyMini, so just filter them as the only thing we use them for is battery and pyro numbers. Signed-off-by: Keith Packard --- src/lpc/ao_adc_lpc.c | 39 +++++++++++++++++++++++++-------------- src/lpc/ao_arch_funcs.h | 6 ++---- src/lpc/lpc.h | 7 +++++++ 3 files changed, 34 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_adc_lpc.c b/src/lpc/ao_adc_lpc.c index 25a121b5..40173aa4 100644 --- a/src/lpc/ao_adc_lpc.c +++ b/src/lpc/ao_adc_lpc.c @@ -91,47 +91,58 @@ (AO_ADC_6 << 6) | \ (AO_ADC_7 << 7)) -#define AO_ADC_CLKDIV (AO_LPC_SYSCLK / 4500000 - 1) +#define AO_ADC_CLKDIV (AO_LPC_SYSCLK / 4500000) -static uint8_t ao_adc_ready; +static uint8_t ao_adc_ready; + +static uint16_t ao_adc_prev[AO_NUM_ADC]; + +#define sample(id) do { \ + uint16_t p = *prev; \ + uint16_t v = lpc_adc.dr[id]; \ + p -= p >> 4; \ + p += v >> 4; \ + *prev++ = p; \ + *out++ = p >> 1; \ + } while (0) void lpc_adc_isr(void) { uint32_t stat = lpc_adc.stat; uint16_t *out; + uint16_t *prev; - lpc_adc.cr = ((AO_ADC_MASK << LPC_ADC_CR_SEL) | - (AO_ADC_CLKDIV << LPC_ADC_CR_CLKDIV) | - (0 << LPC_ADC_CR_BURST) | - (LPC_ADC_CR_CLKS_11 << LPC_ADC_CR_CLKS)); + /* Turn off burst mode */ + lpc_adc.cr = 0; lpc_adc.stat = 0; /* Store converted values in packet */ out = (uint16_t *) &ao_data_ring[ao_data_head].adc; + prev = ao_adc_prev; #if AO_ADC_0 - *out++ = lpc_adc.dr[0] >> 1; + sample(0); #endif #if AO_ADC_1 - *out++ = lpc_adc.dr[1] >> 1; + sample(1); #endif #if AO_ADC_2 - *out++ = lpc_adc.dr[2] >> 1; + sample(2); #endif #if AO_ADC_3 - *out++ = lpc_adc.dr[3] >> 1; + sample(3); #endif #if AO_ADC_4 - *out++ = lpc_adc.dr[4] >> 1; + sample(4); #endif #if AO_ADC_5 - *out++ = lpc_adc.dr[5] >> 1; + sample(5); #endif #if AO_ADC_6 - *out++ = lpc_adc.dr[6] >> 1; + sample(6); #endif #if AO_ADC_7 - *out++ = lpc_adc.dr[7] >> 1; + sample(7); #endif AO_DATA_PRESENT(AO_DATA_ADC); diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index 179b2f4d..1bbb14f5 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -61,12 +61,10 @@ #define analog_func(id) lpc_token_evaluator_2(LPC_IOCONF_FUNC_AD,id) #define ao_enable_analog(port,bit,id) do { \ - uint32_t _mode; \ ao_enable_port(port); \ lpc_gpio.dir[port] &= ~(1 << bit); \ - _mode = ((analog_func(id) << LPC_IOCONF_FUNC) | \ - (0 << LPC_IOCONF_ADMODE)); \ - lpc_ioconf.analog_reg(port,bit) = _mode; \ + lpc_ioconf.analog_reg(port,bit) = ((analog_func(id) << LPC_IOCONF_FUNC) | \ + (0 << LPC_IOCONF_ADMODE)); \ } while (0) #define ARM_PUSH32(stack, val) (*(--(stack)) = (val)) diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index 49034c1c..d66f0dd0 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -1169,6 +1169,13 @@ extern struct lpc_adc lpc_adc; #define LPC_ADC_CR_CLKS_6 5 #define LPC_ADC_CR_CLKS_5 6 #define LPC_ADC_CR_CLKS_4 7 +#define LPC_ADC_CR_START 24 +#define LPC_ADC_CR_START_NONE 0 +#define LPC_ADC_CR_START_NOW 1 + +#define LPC_ADC_GDR_CHN 24 +#define LPC_ADC_GDR_OVERRUN 30 +#define LPC_ADC_GDR_DONE 31 #define LPC_ADC_INTEN_ADINTEN 0 #define LPC_ADC_INTEN_ADGINTEN 8 -- cgit v1.2.3 From 1676c7dbc3dcce2962be9ef9a58d37c7b48e3c0f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Jun 2013 15:07:54 -0700 Subject: altos/lpc: Turn off more clocks, disable USART for easymini Try to reduce noise on the power supply. Signed-off-by: Keith Packard --- src/easymini-v0.1/Makefile | 1 - src/easymini-v0.1/ao_pins.h | 2 +- src/lpc/ao_timer_lpc.c | 11 +++++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/easymini-v0.1/Makefile b/src/easymini-v0.1/Makefile index 612cc472..dfa7624c 100644 --- a/src/easymini-v0.1/Makefile +++ b/src/easymini-v0.1/Makefile @@ -39,7 +39,6 @@ ALTOS_SRC = \ ao_config.c \ ao_timer_lpc.c \ ao_exti_lpc.c \ - ao_serial_lpc.c \ ao_usb_lpc.c \ ao_spi_lpc.c \ ao_adc_lpc.c \ diff --git a/src/easymini-v0.1/ao_pins.h b/src/easymini-v0.1/ao_pins.h index d4fbe7a1..e14e1eb4 100644 --- a/src/easymini-v0.1/ao_pins.h +++ b/src/easymini-v0.1/ao_pins.h @@ -43,7 +43,7 @@ /* USART */ -#define HAS_SERIAL 1 +#define HAS_SERIAL 0 #define USE_SERIAL_0_STDIN 1 #define SERIAL_0_18_19 1 #define SERIAL_0_14_15 0 diff --git a/src/lpc/ao_timer_lpc.c b/src/lpc/ao_timer_lpc.c index 51835baa..73a0e258 100644 --- a/src/lpc/ao_timer_lpc.c +++ b/src/lpc/ao_timer_lpc.c @@ -177,4 +177,15 @@ ao_clock_init(void) lpc_scb.ssp1clkdiv = 0; lpc_scb.usbclkdiv = 0; lpc_scb.clkoutdiv = 0; + + /* Power down everything we don't need */ + lpc_scb.pdruncfg = ((1 << LPC_SCB_PDRUNCFG_IRCOUT_PD) | + (1 << LPC_SCB_PDRUNCFG_IRC_PD) | + (1 << LPC_SCB_PDRUNCFG_BOD_PD) | + (1 << LPC_SCB_PDRUNCFG_ADC_PD) | + (1 << LPC_SCB_PDRUNCFG_WDTOSC_PD) | + (1 << LPC_SCB_PDRUNCFG_USBPLL_PD) | + (1 << LPC_SCB_PDRUNCFG_USBPAD_PD) | + (1 << 11) | + (7 << 13)); } -- cgit v1.2.3 From d040adeef9df4cda31dce603db81dc7ce19ec0d1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Jun 2013 22:31:31 -0700 Subject: altos/lpc: Don't disable all of the clocks just yet, USB doesn't work Signed-off-by: Keith Packard --- src/lpc/ao_timer_lpc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/lpc/ao_timer_lpc.c b/src/lpc/ao_timer_lpc.c index 73a0e258..62235d1e 100644 --- a/src/lpc/ao_timer_lpc.c +++ b/src/lpc/ao_timer_lpc.c @@ -178,6 +178,7 @@ ao_clock_init(void) lpc_scb.usbclkdiv = 0; lpc_scb.clkoutdiv = 0; +#if 0 /* Power down everything we don't need */ lpc_scb.pdruncfg = ((1 << LPC_SCB_PDRUNCFG_IRCOUT_PD) | (1 << LPC_SCB_PDRUNCFG_IRC_PD) | @@ -188,4 +189,5 @@ ao_clock_init(void) (1 << LPC_SCB_PDRUNCFG_USBPAD_PD) | (1 << 11) | (7 << 13)); +#endif } -- cgit v1.2.3 From dcf769198863c1b0f1b05f41d0c052a3dbfef247 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Jun 2013 22:31:58 -0700 Subject: altos/lpc: Remove spurious semicolon Signed-off-by: Keith Packard --- src/lpc/ao_spi_lpc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/lpc/ao_spi_lpc.c b/src/lpc/ao_spi_lpc.c index c3587698..a889137c 100644 --- a/src/lpc/ao_spi_lpc.c +++ b/src/lpc/ao_spi_lpc.c @@ -42,7 +42,7 @@ static uint8_t spi_dev_null; /* recv a byte */ \ get lpc_ssp->dr; \ } \ - } while (0); + } while (0) void ao_spi_send(void *block, uint16_t len, uint8_t id) -- cgit v1.2.3 From 2e2f3f2556e714833d8b7d0f65877b07b3dc2cb5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Jun 2013 22:32:16 -0700 Subject: altos: Declare m25 write-in-progress as 'ao_port_t' This lets us use port bits greater than 7 for M25 chip selects Signed-off-by: Keith Packard --- src/drivers/ao_m25.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_m25.c b/src/drivers/ao_m25.c index 9b768012..e6c7bb4d 100644 --- a/src/drivers/ao_m25.c +++ b/src/drivers/ao_m25.c @@ -86,7 +86,7 @@ static ao_port_t ao_m25_pin[M25_MAX_CHIPS]; /* chip select pin for each chip */ static uint8_t ao_m25_numchips; /* number of chips detected */ #endif static uint8_t ao_m25_total; /* total sectors available */ -static uint8_t ao_m25_wip; /* write in progress */ +static ao_port_t ao_m25_wip; /* write in progress */ static __xdata uint8_t ao_m25_mutex; @@ -250,7 +250,6 @@ ao_storage_erase(uint32_t pos) __reentrant cs = ao_m25_set_address(pos); - ao_m25_wait_wip(cs); ao_m25_write_enable(cs); ao_m25_instruction[0] = M25_SE; -- cgit v1.2.3 From b3ad488477def157e277e239e81f164b49725925 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 17 Jun 2013 13:58:41 -0700 Subject: altos: Disable USB on all flight computers when in flight mode There was a check to only disable USB on boards with radios, but for EasyMini, we want to disable USB too for flight mode. Signed-off-by: Keith Packard --- src/core/ao_flight.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index 782e2274..1322195b 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -117,7 +117,7 @@ ao_flight(void) { /* Set pad mode - we can fly! */ ao_flight_state = ao_flight_pad; -#if HAS_USB && HAS_RADIO && !HAS_FLIGHT_DEBUG && !HAS_SAMPLE_PROFILE +#if HAS_USB && !HAS_FLIGHT_DEBUG && !HAS_SAMPLE_PROFILE /* Disable the USB controller in flight mode * to save power */ -- cgit v1.2.3 From 298e54856b5f8809b43f24407caa4a6be60822f3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 17 Jun 2013 14:00:11 -0700 Subject: altos/lpc: Get the IRC turned off after boot time This involved carefully moving the USB away from the IRC before turning it off. Signed-off-by: Keith Packard --- src/lpc/ao_timer_lpc.c | 17 ++++++++++++++--- src/lpc/ao_usb_lpc.c | 10 +++++++--- 2 files changed, 21 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_timer_lpc.c b/src/lpc/ao_timer_lpc.c index 62235d1e..c0de90a3 100644 --- a/src/lpc/ao_timer_lpc.c +++ b/src/lpc/ao_timer_lpc.c @@ -106,12 +106,18 @@ ao_clock_init(void) /* Switch to the IRC clock */ lpc_scb.mainclksel = LPC_SCB_MAINCLKSEL_SEL_IRC << LPC_SCB_MAINCLKSEL_SEL; - lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA); lpc_scb.mainclkuen = (0 << LPC_SCB_MAINCLKUEN_ENA); lpc_scb.mainclkuen = (1 << LPC_SCB_MAINCLKUEN_ENA); while (!(lpc_scb.mainclkuen & (1 << LPC_SCB_MAINCLKUEN_ENA))) ; + /* Switch USB to the main clock */ + lpc_scb.usbclksel = (LPC_SCB_USBCLKSEL_SEL_MAIN_CLOCK << LPC_SCB_USBCLKSEL_SEL); + lpc_scb.usbclkuen = (0 << LPC_SCB_USBCLKUEN_ENA); + lpc_scb.usbclkuen = (1 << LPC_SCB_USBCLKUEN_ENA); + while (!(lpc_scb.usbclkuen & (1 << LPC_SCB_USBCLKUEN_ENA))) + ; + /* Find a PLL post divider ratio that gets the FCCO in range */ for (p = 0; p < 4; p++) if (AO_LPC_CLKOUT << (1 + p) >= AO_LPC_FCCO_MIN) @@ -178,7 +184,13 @@ ao_clock_init(void) lpc_scb.usbclkdiv = 0; lpc_scb.clkoutdiv = 0; -#if 0 + /* Switch USB PLL source to system osc so we can power down the IRC */ + lpc_scb.usbpllclksel = (LPC_SCB_USBPLLCLKSEL_SEL_SYSOSC << LPC_SCB_USBPLLCLKSEL_SEL); + lpc_scb.usbpllclkuen = (0 << LPC_SCB_USBPLLCLKUEN_ENA); + lpc_scb.usbpllclkuen = (1 << LPC_SCB_USBPLLCLKUEN_ENA); + while (!(lpc_scb.usbpllclkuen & (1 << LPC_SCB_USBPLLCLKUEN_ENA))) + ; + /* Power down everything we don't need */ lpc_scb.pdruncfg = ((1 << LPC_SCB_PDRUNCFG_IRCOUT_PD) | (1 << LPC_SCB_PDRUNCFG_IRC_PD) | @@ -189,5 +201,4 @@ ao_clock_init(void) (1 << LPC_SCB_PDRUNCFG_USBPAD_PD) | (1 << 11) | (7 << 13)); -#endif } diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index aac0df04..e574f1e2 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -834,8 +834,9 @@ ao_usb_disable(void) /* Turn off USB clock */ lpc_scb.usbclkdiv = 0; - /* Disable USB PHY */ - lpc_scb.pdruncfg |= (1 << LPC_SCB_PDRUNCFG_USBPAD_PD); + /* Disable USB PHY and PLL */ + lpc_scb.pdruncfg |= ((1 << LPC_SCB_PDRUNCFG_USBPAD_PD) | + (1 << LPC_SCB_PDRUNCFG_USBPLL_PD)); /* Disable USB registers and RAM */ lpc_scb.sysahbclkctrl &= ~((1 << LPC_SCB_SYSAHBCLKCTRL_USB) | @@ -877,7 +878,6 @@ ao_usb_enable(void) lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_USBPLL_PD); lpc_scb.usbpllclksel = (LPC_SCB_SYSPLLCLKSEL_SEL_SYSOSC << LPC_SCB_SYSPLLCLKSEL_SEL); - lpc_scb.usbpllclkuen = (1 << LPC_SCB_USBPLLCLKUEN_ENA); lpc_scb.usbpllclkuen = (0 << LPC_SCB_USBPLLCLKUEN_ENA); lpc_scb.usbpllclkuen = (1 << LPC_SCB_USBPLLCLKUEN_ENA); while (!(lpc_scb.usbpllclkuen & (1 << LPC_SCB_USBPLLCLKUEN_ENA))) @@ -887,6 +887,10 @@ ao_usb_enable(void) ; lpc_scb.usbclksel = 0; + lpc_scb.usbclkuen = (0 << LPC_SCB_USBCLKUEN_ENA); + lpc_scb.usbclkuen = (1 << LPC_SCB_USBCLKUEN_ENA); + while (!(lpc_scb.usbclkuen & (1 << LPC_SCB_USBCLKUEN_ENA))) + ; /* Turn on USB clock, use 48MHz clock unchanged */ lpc_scb.usbclkdiv = 1; -- cgit v1.2.3 From 025beb0fea011d0e3dab59b5d16e7ffae97c613c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 17 Jun 2013 14:52:32 -0700 Subject: altos/lpc: Get rid of ADC filter Now that the source of the Vcc noise has been identified, remove the unnecessary ADC filtering. Signed-off-by: Keith Packard --- src/lpc/ao_adc_lpc.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_adc_lpc.c b/src/lpc/ao_adc_lpc.c index 40173aa4..874d2d29 100644 --- a/src/lpc/ao_adc_lpc.c +++ b/src/lpc/ao_adc_lpc.c @@ -95,22 +95,12 @@ static uint8_t ao_adc_ready; -static uint16_t ao_adc_prev[AO_NUM_ADC]; - -#define sample(id) do { \ - uint16_t p = *prev; \ - uint16_t v = lpc_adc.dr[id]; \ - p -= p >> 4; \ - p += v >> 4; \ - *prev++ = p; \ - *out++ = p >> 1; \ - } while (0) +#define sample(id) (*out++ = lpc_adc.dr[id] >> 1) void lpc_adc_isr(void) { uint32_t stat = lpc_adc.stat; uint16_t *out; - uint16_t *prev; /* Turn off burst mode */ lpc_adc.cr = 0; @@ -119,7 +109,6 @@ void lpc_adc_isr(void) /* Store converted values in packet */ out = (uint16_t *) &ao_data_ring[ao_data_head].adc; - prev = ao_adc_prev; #if AO_ADC_0 sample(0); #endif -- cgit v1.2.3 From 572faa19b9a496866e3b589d5eb9f37a680206ab Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 19 Jun 2013 22:42:58 -0700 Subject: altos/cc1111: Fetch RSSI for TeleFire from correct byte Reading the status byte doesn't provide very useful RSSI info Signed-off-by: Keith Packard --- src/cc1111/ao_radio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index 88b8f686..190647ce 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -374,7 +374,7 @@ ao_radio_recv(__xdata void *packet, uint8_t size, uint8_t timeout) __reentrant } #if NEED_RADIO_RSSI else - ao_radio_rssi = AO_RSSI_FROM_RADIO(((uint8_t *)packet)[size - 1]); + ao_radio_rssi = AO_RSSI_FROM_RADIO(((uint8_t *)packet)[size - 2]); #endif ao_radio_put(); return ao_radio_dma_done; -- cgit v1.2.3 From d90c2fa650de4cdb008d5e2559463c08da8db934 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 19 Jun 2013 22:44:16 -0700 Subject: altos: PCA9922 LED driver needs Enable driven low to latch values Driving Enable high means anything going past on the clock and data pair is reflected on the LEDs, which isn't terribly useful Signed-off-by: Keith Packard --- src/drivers/ao_pca9922.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_pca9922.c b/src/drivers/ao_pca9922.c index 6d8d18d8..fe070b88 100644 --- a/src/drivers/ao_pca9922.c +++ b/src/drivers/ao_pca9922.c @@ -30,9 +30,12 @@ ao_led_apply(void) /* Don't try the SPI bus during initialization */ if (!ao_cur_task) return; - ao_spi_get_bit(AO_PCA9922_CS_PORT, AO_PCA9922_CS_PIN, AO_PCA9922_CS, AO_PCA9922_SPI_BUS, AO_SPI_SPEED_FAST); + ao_mutex_get(&ao_spi_mutex); + ao_spi_set_speed(AO_SPI_SPEED_FAST); + AO_PCA9922_CS = 1; ao_spi_send(&ao_led_state, 1, AO_PCA9922_SPI_BUS); - ao_spi_put_bit(AO_PCA9922_CS_PORT, AO_PCA9922_CS_PIN, AO_PCA9922_CS, AO_PCA9922_SPI_BUS); + AO_PCA9922_CS = 0; + ao_mutex_put(&ao_spi_mutex); } void -- cgit v1.2.3 From e9e713bc8ab2080d5c1c38570b112f13c886bd11 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 19 Jun 2013 22:45:54 -0700 Subject: altos/telefire: Radio status (no data, weak data, good data) on LEDs Instead of blinking RX/TX, report the radio status on the telefire nodes, just like telelco does. This makes the LEDs on telefire *exactly the same* as the LEDs on telelco, which seems like a good idea. Signed-off-by: Keith Packard --- src/drivers/ao_pad.c | 18 +++++++++++++----- src/telefire-v0.2/ao_pins.h | 11 ++++------- 2 files changed, 17 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index e205f99b..62ae68e9 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -27,6 +27,7 @@ static __pdata uint8_t ao_pad_armed; static __pdata uint16_t ao_pad_arm_time; static __pdata uint8_t ao_pad_box; static __xdata uint8_t ao_pad_disabled; +static __pdata uint16_t ao_pad_packet_time; #define DEBUG 1 @@ -135,6 +136,12 @@ ao_pad_monitor(void) query.arm_status = AO_PAD_ARM_STATUS_UNKNOWN; arm_beep_time = 0; } + if ((ao_time() - ao_pad_packet_time) > AO_SEC_TO_TICKS(2)) + cur |= AO_LED_RED; + else if (ao_radio_cmac_rssi < -90) + cur |= AO_LED_AMBER; + else + cur |= AO_LED_GREEN; for (c = 0; c < AO_PAD_NUM; c++) { int16_t sense = packet->adc.sense[c]; @@ -171,9 +178,10 @@ ao_pad_monitor(void) query.igniter_status[c] = status; } if (cur != prev) { - PRINTD("change leds from %02x to %02x mask %02x\n", - prev, cur, AO_LED_CONTINUITY_MASK|AO_LED_ARMED); - ao_led_set_mask(cur, AO_LED_CONTINUITY_MASK | AO_LED_ARMED); + PRINTD("change leds from %02x to %02x\n", + prev, cur); + FLUSHD(); + ao_led_set(cur); prev = cur; } @@ -238,15 +246,15 @@ ao_pad(void) ao_pad_box = 0; ao_led_set(0); - ao_led_on(AO_LED_POWER); for (;;) { FLUSHD(); while (ao_pad_disabled) ao_sleep(&ao_pad_disabled); ret = ao_radio_cmac_recv(&command, sizeof (command), 0); - PRINTD ("cmac_recv %d\n", ret); + PRINTD ("cmac_recv %d %d\n", ret, ao_radio_cmac_rssi); if (ret != AO_RADIO_CMAC_OK) continue; + ao_pad_packet_time = ao_time(); ao_pad_box = ao_pad_read_box(); diff --git a/src/telefire-v0.2/ao_pins.h b/src/telefire-v0.2/ao_pins.h index f4050722..96e6b066 100644 --- a/src/telefire-v0.2/ao_pins.h +++ b/src/telefire-v0.2/ao_pins.h @@ -40,13 +40,10 @@ #define AO_LED_CONTINUITY(c) (1 << (c)) #define AO_LED_CONTINUITY_MASK (0xf) -#define AO_LED_RX 0x10 -#define AO_LED_TX 0x20 -#define AO_LED_ARMED 0x40 -#define AO_LED_POWER 0x80 - -#define AO_LED_RED AO_LED_TX -#define AO_LED_GREEN AO_LED_RX +#define AO_LED_ARMED 0x10 +#define AO_LED_RED 0x20 +#define AO_LED_AMBER 0x40 +#define AO_LED_GREEN 0x80 #define LEDS_AVAILABLE (0xff) #define HAS_EXTERNAL_TEMP 0 -- cgit v1.2.3 From 23f11b188fc6aacd29e7f01a7d8a40853b7655df Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 21 Jun 2013 19:39:27 -0700 Subject: altos/lpc: Enable brown-out-detector Make sure the processor does something sensible when the power disappears. Signed-off-by: Keith Packard --- src/lpc/ao_timer_lpc.c | 11 ++++++++++- src/lpc/lpc.h | 12 ++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lpc/ao_timer_lpc.c b/src/lpc/ao_timer_lpc.c index c0de90a3..44fb410e 100644 --- a/src/lpc/ao_timer_lpc.c +++ b/src/lpc/ao_timer_lpc.c @@ -100,6 +100,15 @@ ao_clock_init(void) (1 << LPC_SCB_SYSAHBCLKCTRL_GPIO) | (1 << LPC_SCB_SYSAHBCLKCTRL_IOCON)); + /* Enable the brown-out detection at the highest voltage to + * make sure the flash part remains happy + */ + + lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_BOD_PD); + lpc_scb.bodctrl = ((LPC_SCB_BOD_BODRSTLEV_2_63 << LPC_SCB_BOD_BODRSTLEV) | + (LPC_SCB_BOD_BODINTVAL_RESERVED << LPC_SCB_BOD_BODINTVAL) | + (1 << LPC_SCB_BOD_BODRSTENA)); + /* Turn the IRC clock back on */ lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_IRC_PD); ao_clock_delay(); @@ -194,7 +203,7 @@ ao_clock_init(void) /* Power down everything we don't need */ lpc_scb.pdruncfg = ((1 << LPC_SCB_PDRUNCFG_IRCOUT_PD) | (1 << LPC_SCB_PDRUNCFG_IRC_PD) | - (1 << LPC_SCB_PDRUNCFG_BOD_PD) | + (0 << LPC_SCB_PDRUNCFG_BOD_PD) | (1 << LPC_SCB_PDRUNCFG_ADC_PD) | (1 << LPC_SCB_PDRUNCFG_WDTOSC_PD) | (1 << LPC_SCB_PDRUNCFG_USBPLL_PD) | diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index d66f0dd0..f13ec615 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -609,6 +609,18 @@ extern struct lpc_scb lpc_scb; #define LPC_SCB_CLKOUTUEN_ENA 0 +#define LPC_SCB_BOD_BODRSTLEV 0 +# define LPC_SCB_BOD_BODRSTLEV_1_46 0 +# define LPC_SCB_BOD_BODRSTLEV_2_06 1 +# define LPC_SCB_BOD_BODRSTLEV_2_35 2 +# define LPC_SCB_BOD_BODRSTLEV_2_63 3 +#define LPC_SCB_BOD_BODINTVAL 2 +# define LPC_SCB_BOD_BODINTVAL_RESERVED 0 +# define LPC_SCB_BOD_BODINTVAL_2_22 1 +# define LPC_SCB_BOD_BODINTVAL_2_52 2 +# define LPC_SCB_BOD_BODINTVAL_2_80 3 +#define LPC_SCB_BOD_BODRSTENA 4 + #define LPC_SCB_PDRUNCFG_IRCOUT_PD 0 #define LPC_SCB_PDRUNCFG_IRC_PD 1 #define LPC_SCB_PDRUNCFG_FLASH_PD 2 -- cgit v1.2.3 From 9081d881bc48bf7fdce617d300ac02c1a5962239 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 21 Jun 2013 19:40:03 -0700 Subject: altos/lpc: Remove ao_usb_task structure It's not used Signed-off-by: Keith Packard --- src/lpc/ao_usb_lpc.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index e574f1e2..4e6b9c66 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -35,8 +35,6 @@ #define debug_data(format, args...) #endif -struct ao_task ao_usb_task; - struct ao_usb_setup { uint8_t dir_type_recip; uint8_t request; -- cgit v1.2.3 From 58eda6f873f5d6e8e219f769bdf67ce4dbc96fd7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 21 Jun 2013 19:40:59 -0700 Subject: altos/lpc: Don't disable all interrupts when disabling one interrupt The nvic iser and icer registers read value indicates all enabled interrupts, icer writes disable the set interrupts. Re-writing icer with the current value ends up disabling all interrupts, not exactly what we wanted. Signed-off-by: Keith Packard --- src/lpc/lpc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index f13ec615..8fb78649 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -1014,12 +1014,12 @@ extern struct lpc_nvic lpc_nvic; static inline void lpc_nvic_set_enable(int irq) { - lpc_nvic.iser |= (1 << irq); + lpc_nvic.iser = (1 << irq); } static inline void lpc_nvic_clear_enable(int irq) { - lpc_nvic.icer |= (1 << irq); + lpc_nvic.icer = (1 << irq); } static inline int -- cgit v1.2.3 From 2568b36ae9d38ae1607ec08b84b06e0fe84bd3ba Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 22 Jun 2013 00:53:38 -0700 Subject: altos/telefire-v0.1: Use same LED selection as the v0.2 setup Signed-off-by: Keith Packard --- src/telefire-v0.1/ao_pins.h | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/telefire-v0.1/ao_pins.h b/src/telefire-v0.1/ao_pins.h index 774d59f4..f7a3ff2c 100644 --- a/src/telefire-v0.1/ao_pins.h +++ b/src/telefire-v0.1/ao_pins.h @@ -40,13 +40,10 @@ #define AO_LED_CONTINUITY(c) (1 << ((c) + 2)) #define AO_LED_CONTINUITY_MASK (0xc) -#define AO_LED_RX 0x10 -#define AO_LED_TX 0x20 -#define AO_LED_ARMED 0x40 -#define AO_LED_POWER 0x80 - -#define AO_LED_RED AO_LED_TX -#define AO_LED_GREEN AO_LED_RX +#define AO_LED_ARMED 0x10 +#define AO_LED_RED 0x20 +#define AO_LED_AMBER 0x40 +#define AO_LED_GREEN 0x80 #define LEDS_AVAILABLE (0xff) #define HAS_EXTERNAL_TEMP 0 -- cgit v1.2.3 From 0dd148e388944d8d265da51d62806c4a00b2c13d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 24 Jun 2013 14:23:53 -0700 Subject: altos/lpc: Add boot loader Support the USB boot loader, add USB pull-up support. Signed-off-by: Keith Packard --- src/easymini-v0.1/Makefile | 5 +- src/easymini-v0.1/ao_pins.h | 5 ++ src/easymini-v0.1/flash-loader/Makefile | 8 +++ src/easymini-v0.1/flash-loader/ao_pins.h | 33 +++++++++++++ src/lpc/altos-loader.ld | 80 ++++++++++++++++++++++++++++++ src/lpc/altos-standalone.ld | 85 ++++++++++++++++++++++++++++++++ src/lpc/altos.ld | 26 ++++++++-- src/lpc/ao_arch.h | 4 ++ src/lpc/ao_arch_funcs.h | 16 ++++-- src/lpc/ao_boot.h | 39 +++++++++++++++ src/lpc/ao_boot_chain.c | 67 +++++++++++++++++++++++++ src/lpc/ao_boot_pin.c | 46 +++++++++++++++++ src/lpc/ao_flash.h | 30 +++++++++++ src/lpc/ao_flash_loader_lpc.c | 32 ++++++++++++ src/lpc/ao_flash_lpc_pins.h | 32 ++++++++++++ src/lpc/ao_interrupt.c | 27 ++++++++-- src/lpc/ao_usb_lpc.c | 27 ++++++++-- src/lpc/lpc.h | 5 ++ src/product/ao_flash_pins.h | 2 + src/product/ao_flash_task.c | 13 ++--- 20 files changed, 557 insertions(+), 25 deletions(-) create mode 100644 src/easymini-v0.1/flash-loader/Makefile create mode 100644 src/easymini-v0.1/flash-loader/ao_pins.h create mode 100644 src/lpc/altos-loader.ld create mode 100644 src/lpc/altos-standalone.ld create mode 100644 src/lpc/ao_boot.h create mode 100644 src/lpc/ao_boot_chain.c create mode 100644 src/lpc/ao_boot_pin.c create mode 100644 src/lpc/ao_flash.h create mode 100644 src/lpc/ao_flash_loader_lpc.c create mode 100644 src/lpc/ao_flash_lpc_pins.h (limited to 'src') diff --git a/src/easymini-v0.1/Makefile b/src/easymini-v0.1/Makefile index dfa7624c..9847656c 100644 --- a/src/easymini-v0.1/Makefile +++ b/src/easymini-v0.1/Makefile @@ -18,6 +18,7 @@ INC = \ # ALTOS_SRC = \ ao_interrupt.c \ + ao_boot_chain.c \ ao_romconfig.c \ ao_product.c \ ao_mutex.c \ @@ -48,7 +49,7 @@ ALTOS_SRC = \ PRODUCT=EasyMini-v0.1 PRODUCT_DEF=-DEASYMINI_V_0_1 -IDPRODUCT=0x000a +IDPRODUCT=0x0026 CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -g -Os @@ -62,7 +63,7 @@ all: $(PROG) LDFLAGS=-L../lpc -Wl,-Taltos.ld -$(PROG): Makefile $(OBJ) +$(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc ao_product.h: ao-make-product.5c ../Version diff --git a/src/easymini-v0.1/ao_pins.h b/src/easymini-v0.1/ao_pins.h index e14e1eb4..6f102dbe 100644 --- a/src/easymini-v0.1/ao_pins.h +++ b/src/easymini-v0.1/ao_pins.h @@ -18,6 +18,8 @@ #define HAS_BEEP 1 #define HAS_LED 1 +#define IS_FLASH_LOADER 0 + /* Crystal on the board */ #define AO_LPC_CLKIN 12000000 @@ -38,6 +40,9 @@ #define HAS_USB_CONNECT 0 #define HAS_USB_VBUS 0 +#define HAS_USB_PULLUP 1 +#define AO_USB_PULLUP_PORT 0 +#define AO_USB_PULLUP_PIN 20 #define PACKET_HAS_SLAVE 0 diff --git a/src/easymini-v0.1/flash-loader/Makefile b/src/easymini-v0.1/flash-loader/Makefile new file mode 100644 index 00000000..ab828b22 --- /dev/null +++ b/src/easymini-v0.1/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=easymini-v0.1 +include $(TOPDIR)/lpc/Makefile-flash.defs diff --git a/src/easymini-v0.1/flash-loader/ao_pins.h b/src/easymini-v0.1/flash-loader/ao_pins.h new file mode 100644 index 00000000..4330151d --- /dev/null +++ b/src/easymini-v0.1/flash-loader/ao_pins.h @@ -0,0 +1,33 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#include + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO 0 +#define AO_BOOT_APPLICATION_PIN 19 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +#define HAS_USB_PULLUP 1 +#define AO_USB_PULLUP_PORT 0 +#define AO_USB_PULLUP_PIN 20 + +#endif /* _AO_PINS_H_ */ diff --git a/src/lpc/altos-loader.ld b/src/lpc/altos-loader.ld new file mode 100644 index 00000000..4f78f552 --- /dev/null +++ b/src/lpc/altos-loader.ld @@ -0,0 +1,80 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +MEMORY { + rom : ORIGIN = 0x00000000, LENGTH = 4K + ram : ORIGIN = 0x10000000, LENGTH = 4k - 128 - 32 + usb (!x) : ORIGIN = 0x20004000 + 2K - 256, LENGTH = 256 + stack (!w) : ORIGIN = 0x10000000 + 4K - 128 - 32, LENGTH = 128 +} + +INCLUDE registers.ld + +EXTERN (lpc_interrupt_vector) + +SECTIONS { + /* + * Rom contents + */ + + .interrupt : { + __text_start__ = .; + *(.interrupt) /* Interrupt vectors */ + + } > rom + + .text ORIGIN(rom) + 0x100 : { + ao_romconfig.o(.romconfig*) + ao_product.o(.romconfig*) + + *(.text*) /* Executable code */ + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + *(.rodata*) /* Constants */ + __text_end__ = .; + } > rom + + /* Boot data which must live at the start of ram so that + * the application and bootloader share the same addresses. + * This must be all uninitialized data + */ + .boot ORIGIN(ram) + SIZEOF(.interrupt) (NOLOAD) : { + __boot_start__ = .; + *(.boot) + __boot_end__ = .; + } >ram + + /* Data -- relocated to RAM, but written to ROM + */ + .data : { + __data_start__ = .; + *(.data) /* initialized data */ + __data_end__ = .; + } >ram AT>rom + + + .bss : { + __bss_start__ = .; + *(.bss) + *(COMMON) + __bss_end__ = .; + } >ram + + PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram)); + PROVIDE(end = .); +} + +ENTRY(start); diff --git a/src/lpc/altos-standalone.ld b/src/lpc/altos-standalone.ld new file mode 100644 index 00000000..032406f8 --- /dev/null +++ b/src/lpc/altos-standalone.ld @@ -0,0 +1,85 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +MEMORY { + rom (rx) : ORIGIN = 0x00000000, LENGTH = 32K + ram (!w) : ORIGIN = 0x10000000, LENGTH = 4K - 128 - 32 + usb (!x) : ORIGIN = 0x20004000 + 2K - 256, LENGTH = 256 + stack (!w) : ORIGIN = 0x10000000 + 4K - 128 - 32, LENGTH = 128 +} + +INCLUDE registers.ld + +EXTERN (lpc_interrupt_vector) + +SECTIONS { + /* + * Rom contents + */ + + .text ORIGIN(rom) : { + __text_start__ = .; + *(.interrupt) /* Interrupt vectors */ + + . = ORIGIN(rom) + 0x100; + + ao_romconfig.o(.romconfig*) + ao_product.o(.romconfig*) + + *(.text*) /* Executable code */ + *(.rodata*) /* Constants */ + + } > rom + + .ARM.exidx : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __text_end__ = .; + } > rom + + /* Boot data which must live at the start of ram so that + * the application and bootloader share the same addresses. + * This must be all uninitialized data + */ + .boot (NOLOAD) : { + __boot_start__ = .; + *(.boot) + . = ALIGN(4); + __boot_end__ = .; + } >ram + + /* Data -- relocated to RAM, but written to ROM + */ + .data ORIGIN(ram) : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + __data_start__ = .; + *(.data) /* initialized data */ + __data_end__ = .; + __bss_start__ = .; + } >ram + + .bss : { + *(.bss) + *(COMMON) + __bss_end__ = .; + } >ram + PROVIDE(end = .); + + PROVIDE(__stack__ = ORIGIN(stack) + LENGTH(stack)); +} + +ENTRY(start); + + diff --git a/src/lpc/altos.ld b/src/lpc/altos.ld index 4d6f35a8..00d4f18a 100644 --- a/src/lpc/altos.ld +++ b/src/lpc/altos.ld @@ -16,7 +16,7 @@ */ MEMORY { - rom (rx) : ORIGIN = 0x00000000, LENGTH = 32K + rom (rx) : ORIGIN = 0x00001000, LENGTH = 28K ram (!w) : ORIGIN = 0x10000000, LENGTH = 4K - 128 usb (!x) : ORIGIN = 0x20004000 + 2K - 256, LENGTH = 256 stack (!w) : ORIGIN = 0x10000000 + 4K - 128, LENGTH = 128 @@ -31,11 +31,15 @@ SECTIONS { * Rom contents */ - .text ORIGIN(rom) : { - __text_start__ = .; + .interrupt ORIGIN(ram) : AT (ORIGIN(rom)) { + __interrupt_start__ = .; + __interrupt_rom__ = ORIGIN(rom); *(.interrupt) /* Interrupt vectors */ + __interrupt_end__ = .; + } > ram - . = ORIGIN(rom) + 0x100; + .text ORIGIN(rom) + 0x100 : { + __text_start__ = .; ao_romconfig.o(.romconfig*) ao_product.o(.romconfig*) @@ -50,9 +54,20 @@ SECTIONS { __text_end__ = .; } > rom + /* Boot data which must live at the start of ram so that + * the application and bootloader share the same addresses. + * This must be all uninitialized data + */ + .boot : { + __boot_start__ = .; + *(.boot) + . = ALIGN(4); + __boot_end__ = .; + } >ram + /* Data -- relocated to RAM, but written to ROM */ - .data ORIGIN(ram) : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + .data : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { __data_start__ = .; *(.data) /* initialized data */ __data_end__ = .; @@ -60,6 +75,7 @@ SECTIONS { } >ram .bss : { + __bss_start__ = .; *(.bss) *(COMMON) __bss_end__ = .; diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index f605e3d2..a8d3cfc4 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -137,4 +137,8 @@ ao_serial_init(void); #define AO_SPI_SPEED_FAST AO_SPI_SPEED_12MHz +#define AO_BOOT_APPLICATION_BASE ((uint32_t *) 0x00001000) +#define AO_BOOT_LOADER_BASE ((uint32_t *) 0x00000000) +#define HAS_BOOT_LOADER 1 + #endif /* _AO_ARCH_H_ */ diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index 1bbb14f5..9a3219a2 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -22,12 +22,13 @@ #define ao_spi_put_bit(reg,bit,pin,bus) ao_spi_put_mask(reg,(1< + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_BOOT_H_ +#define _AO_BOOT_H_ + +void +ao_boot_chain(uint32_t *base); + +void +ao_boot_check_pin(void); + +/* Return true to switch to application (if present) */ +int +ao_boot_check_chain(void); + +void +ao_boot_reboot(uint32_t *base); + +static inline void +ao_boot_loader(void) { + ao_boot_reboot(AO_BOOT_LOADER_BASE); +} + +#endif /* _AO_BOOT_H_ */ diff --git a/src/lpc/ao_boot_chain.c b/src/lpc/ao_boot_chain.c new file mode 100644 index 00000000..a08d1f2c --- /dev/null +++ b/src/lpc/ao_boot_chain.c @@ -0,0 +1,67 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +void +ao_boot_chain(uint32_t *base) +{ + uint32_t sp; + uint32_t pc; + + sp = base[0]; + pc = base[1]; + if (0x00000100 <= pc && pc <= 0x00008000 && (pc & 1) == 1) { + asm ("mov sp, %0" : : "r" (sp)); + asm ("mov lr, %0" : : "r" (pc)); + asm ("bx lr"); + } +} + +#define AO_BOOT_SIGNAL 0x5a5aa5a5 +#define AO_BOOT_CHECK 0xc3c33c3c + +struct ao_boot { + uint32_t *base; + uint32_t signal; + uint32_t check; +}; + +static struct ao_boot __attribute__ ((section(".boot"))) ao_boot; + +int +ao_boot_check_chain(void) +{ + if (ao_boot.signal == AO_BOOT_SIGNAL && ao_boot.check == AO_BOOT_CHECK) { + ao_boot.signal = 0; + ao_boot.check = 0; + if (ao_boot.base == 0) + return 0; + ao_boot_chain(ao_boot.base); + } + return 1; +} + +void +ao_boot_reboot(uint32_t *base) +{ + ao_boot.base = base; + ao_boot.signal = AO_BOOT_SIGNAL; + ao_boot.check = AO_BOOT_CHECK; + ao_arch_reboot(); +} diff --git a/src/lpc/ao_boot_pin.c b/src/lpc/ao_boot_pin.c new file mode 100644 index 00000000..51ecc0a9 --- /dev/null +++ b/src/lpc/ao_boot_pin.c @@ -0,0 +1,46 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include + +void +ao_boot_check_pin(void) +{ + uint16_t v; + + /* Enable power interface clock */ +// stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); + + /* Enable the input pin */ + ao_enable_input(AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, + AO_BOOT_APPLICATION_MODE); + + for (v = 0; v < 100; v++) + ao_arch_nop(); + + /* Read the value */ + v = ao_gpio_get(AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, AO_BOOT_APPLICATION); + + /* Reset the chip to turn off the port and the power interface clock */ + ao_gpio_set_mode(AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, 0); + ao_disable_port(AO_BOOT_APPLICATION_GPIO); +// stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_PWREN); + if (v == AO_BOOT_APPLICATION_VALUE) + ao_boot_chain(AO_BOOT_APPLICATION_BASE); +} diff --git a/src/lpc/ao_flash.h b/src/lpc/ao_flash.h new file mode 100644 index 00000000..aaf66b39 --- /dev/null +++ b/src/lpc/ao_flash.h @@ -0,0 +1,30 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_FLASH_H_ +#define _AO_FLASH_H_ + +uint32_t +ao_flash_erase_page(uint8_t *page); + +uint32_t +ao_flash_page(uint8_t *page, uint8_t *src); + +uint32_t +ao_lpc_read_part_id(void); + +#endif /* _AO_FLASH_H_ */ diff --git a/src/lpc/ao_flash_loader_lpc.c b/src/lpc/ao_flash_loader_lpc.c new file mode 100644 index 00000000..2ab548cf --- /dev/null +++ b/src/lpc/ao_flash_loader_lpc.c @@ -0,0 +1,32 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include +#include +#include + +int +main(void) +{ + ao_clock_init(); + + ao_usb_init(); + + ao_flash_task(); + return 0; +} diff --git a/src/lpc/ao_flash_lpc_pins.h b/src/lpc/ao_flash_lpc_pins.h new file mode 100644 index 00000000..e2243d5c --- /dev/null +++ b/src/lpc/ao_flash_lpc_pins.h @@ -0,0 +1,32 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_FLASH_LPC_PINS_H_ +#define _AO_FLASH_LPC_PINS_H_ + +#include + +/* Crystal on the board */ +#define AO_LPC_CLKIN 12000000 + +/* Main clock frequency. 48MHz for USB so we don't use the USB PLL */ +#define AO_LPC_CLKOUT 48000000 + +/* System clock frequency */ +#define AO_LPC_SYSCLK 24000000 + +#endif /* _AO_FLASH_STM_PINS_H_ */ diff --git a/src/lpc/ao_interrupt.c b/src/lpc/ao_interrupt.c index b5e67007..c4dc7867 100644 --- a/src/lpc/ao_interrupt.c +++ b/src/lpc/ao_interrupt.c @@ -17,12 +17,25 @@ #include #include +#include + +#ifndef IS_FLASH_LOADER +#error Should define IS_FLASH_LOADER +#define IS_FLASH_LOADER 0 +#endif + +#if !IS_FLASH_LOADER +#define RELOCATE_INTERRUPT 1 +#endif extern void main(void); extern char __stack__; extern char __text_start__, __text_end__; extern char __data_start__, __data_end__; extern char __bss_start__, __bss_end__; +#if RELOCATE_INTERRUPT +extern char __interrupt_rom__, __interrupt_start__, __interrupt_end__; +#endif /* Interrupt functions */ @@ -35,10 +48,18 @@ void lpc_ignore_isr(void) { } -int x; - void start(void) { - x = 0; +#ifdef AO_BOOT_CHAIN + if (ao_boot_check_chain()) { +#ifdef AO_BOOT_PIN + ao_boot_check_pin(); +#endif + } +#endif +#if RELOCATE_INTERRUPT + memcpy(&__interrupt_start__, &__interrupt_rom__, &__interrupt_end__ - &__interrupt_start__); + lpc_scb.sysmemremap = LPC_SCB_SYSMEMREMAP_MAP_RAM << LPC_SCB_SYSMEMREMAP_MAP; +#endif memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__); memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__); main(); diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index 4e6b9c66..144d1075 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -19,6 +19,16 @@ #include "ao_usb.h" #include "ao_product.h" +#ifndef USE_USB_STDIO +#define USE_USB_STDIO 1 +#endif + +#if USE_USB_STDIO +#define AO_USB_OUT_SLEEP_ADDR (&ao_stdin_ready) +#else +#define AO_USB_OUT_SLEEP_ADDR (&ao_usb_out_avail) +#endif + #define USB_DEBUG 0 #define USB_DEBUG_DATA 0 #define USB_ECHO 0 @@ -652,7 +662,7 @@ lpc_usb_irq_isr(void) _rx_dbg1("RX ISR", *ao_usb_epn_out(AO_USB_OUT_EP)); ao_usb_out_avail = 1; _rx_dbg0("out avail set"); - ao_wakeup(&ao_stdin_ready); + ao_wakeup(AO_USB_OUT_SLEEP_ADDR) _rx_dbg0("stdin awoken"); } @@ -811,7 +821,7 @@ ao_usb_getchar(void) ao_arch_block_interrupts(); while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) - ao_sleep(&ao_stdin_ready); + ao_sleep(AO_USB_OUT_SLEEP_ADDR); ao_arch_release_interrupts(); return c; } @@ -821,6 +831,9 @@ ao_usb_disable(void) { ao_arch_block_interrupts(); +#if HAS_USB_PULLUP + ao_gpio_set(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, AO_USB_PULLUP, 0); +#endif /* Disable interrupts */ lpc_usb.inten = 0; @@ -923,6 +936,10 @@ ao_usb_enable(void) for (t = 0; t < 1000; t++) ao_arch_nop(); +#if HAS_USB_PULLUP + ao_gpio_set(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, AO_USB_PULLUP, 1); +#endif + ao_usb_set_ep0(); } @@ -959,6 +976,10 @@ __code struct ao_cmds ao_usb_cmds[] = { void ao_usb_init(void) { +#if HAS_USB_PULLUP + ao_enable_output(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, AO_USB_PULLUP, 0); +#endif + ao_usb_enable(); debug ("ao_usb_init\n"); @@ -968,7 +989,7 @@ ao_usb_init(void) #if USB_DEBUG ao_cmd_register(&ao_usb_cmds[0]); #endif -#if !USB_ECHO +#if USE_USB_STDIO ao_add_stdio(_ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); #endif } diff --git a/src/lpc/lpc.h b/src/lpc/lpc.h index 8fb78649..3300c86f 100644 --- a/src/lpc/lpc.h +++ b/src/lpc/lpc.h @@ -486,6 +486,11 @@ struct lpc_scb { extern struct lpc_scb lpc_scb; +#define LPC_SCB_SYSMEMREMAP_MAP 0 +# define LPC_SCB_SYSMEMREMAP_MAP_BOOT_LOADER 0 +# define LPC_SCB_SYSMEMREMAP_MAP_RAM 1 +# define LPC_SCB_SYSMEMREMAP_MAP_FLASH 2 + #define LPC_SCB_PRESETCTRL_SSP0_RST_N 0 #define LPC_SCB_PRESETCTRL_I2C_RST_N 1 #define LPC_SCB_PRESETCTRL_SSP1_RST_N 2 diff --git a/src/product/ao_flash_pins.h b/src/product/ao_flash_pins.h index b774df6d..439ba75c 100644 --- a/src/product/ao_flash_pins.h +++ b/src/product/ao_flash_pins.h @@ -37,4 +37,6 @@ #define AO_BOOT_CHAIN 1 #define AO_BOOT_PIN 1 +#define IS_FLASH_LOADER 1 + #endif /* _AO_FLASH_PINS_H_ */ diff --git a/src/product/ao_flash_task.c b/src/product/ao_flash_task.c index fdc4d0aa..4cfbf75f 100644 --- a/src/product/ao_flash_task.c +++ b/src/product/ao_flash_task.c @@ -73,7 +73,7 @@ static void ao_block_erase(void) { uint32_t addr = ao_get_hex32(); - uint32_t *p = (uint32_t *) addr; + void *p = (void *) addr; ao_flash_erase_page(p); } @@ -82,11 +82,8 @@ static void ao_block_write(void) { uint32_t addr = ao_get_hex32(); - uint32_t *p = (uint32_t *) addr; - union { - uint8_t data8[256]; - uint32_t data32[64]; - } u; + void *p = (void *) addr; + uint8_t data[256]; uint16_t i; if (addr < (uint32_t) AO_BOOT_APPLICATION_BASE) { @@ -94,8 +91,8 @@ ao_block_write(void) return; } for (i = 0; i < 256; i++) - u.data8[i] = ao_usb_getchar(); - ao_flash_page(p, u.data32); + data[i] = ao_usb_getchar(); + ao_flash_page(p, (void *) data); } static void -- cgit v1.2.3 From e148582217d6e02ac90a68e2bb2532947378d36f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 24 Jun 2013 14:28:06 -0700 Subject: altos: Support mega-style logging without ADC Used for TeleGPS, just exposes the necessary log writing function without also including the ADC writing code. Signed-off-by: Keith Packard --- src/core/ao_log.c | 5 +++++ src/core/ao_log_mega.c | 2 ++ 2 files changed, 7 insertions(+) (limited to 'src') diff --git a/src/core/ao_log.c b/src/core/ao_log.c index 7884ec3c..8bcb7707 100644 --- a/src/core/ao_log.c +++ b/src/core/ao_log.c @@ -278,6 +278,11 @@ ao_log_init(void) ao_cmd_register(&ao_log_cmds[0]); +#ifndef HAS_ADC +#error Define HAS_ADC for ao_log.c +#endif +#if HAS_ADC /* Create a task to log events to eeprom */ ao_add_task(&ao_log_task, ao_log, "log"); +#endif } diff --git a/src/core/ao_log_mega.c b/src/core/ao_log_mega.c index ee12b907..768947d5 100644 --- a/src/core/ao_log_mega.c +++ b/src/core/ao_log_mega.c @@ -65,6 +65,7 @@ ao_log_dump_check_data(void) return 1; } +#if HAS_ADC static __data uint8_t ao_log_data_pos; /* a hack to make sure that ao_log_megas fill the eeprom block in even units */ @@ -182,6 +183,7 @@ ao_log(void) ao_sleep(&ao_log_running); } } +#endif uint16_t ao_log_flight(uint8_t slot) -- cgit v1.2.3 From c542a2ed0f222bd0ec84e4a9651585d441dd7ccf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 24 Jun 2013 14:29:01 -0700 Subject: altos/lpc: Rename serial port to 'serial0' This lets existing serial port users find the right function. Signed-off-by: Keith Packard --- src/lpc/ao_serial_lpc.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_serial_lpc.c b/src/lpc/ao_serial_lpc.c index c0424699..d6b0082a 100644 --- a/src/lpc/ao_serial_lpc.c +++ b/src/lpc/ao_serial_lpc.c @@ -67,7 +67,7 @@ lpc_usart_isr(void) } int -_ao_serial_pollchar(void) +_ao_serial0_pollchar(void) { int c; @@ -82,18 +82,18 @@ _ao_serial_pollchar(void) } char -ao_serial_getchar(void) +ao_serial0_getchar(void) { int c; ao_arch_block_interrupts(); - while ((c = _ao_serial_pollchar()) == AO_READ_AGAIN) + while ((c = _ao_serial0_pollchar()) == AO_READ_AGAIN) ao_sleep(&ao_usart_rx_fifo); ao_arch_release_interrupts(); return (char) c; } void -ao_serial_putchar(char c) +ao_serial0_putchar(char c) { ao_arch_block_interrupts(); while (ao_fifo_full(ao_usart_tx_fifo)) @@ -104,7 +104,7 @@ ao_serial_putchar(char c) } void -ao_serial_drain(void) +ao_serial0_drain(void) { ao_arch_block_interrupts(); while (!ao_fifo_empty(ao_usart_tx_fifo)) @@ -115,7 +115,7 @@ ao_serial_drain(void) #include "ao_serial_lpc.h" void -ao_serial_set_speed(uint8_t speed) +ao_serial0_set_speed(uint8_t speed) { if (speed > AO_SERIAL_SPEED_115200) return; @@ -193,7 +193,7 @@ ao_serial_init(void) lpc_usart.hden = ((0 << LPC_USART_HDEN_HDEN)); /* Set baud rate */ - ao_serial_set_speed(AO_SERIAL_SPEED_9600); + ao_serial0_set_speed(AO_SERIAL_SPEED_9600); /* Enable interrupts */ lpc_usart.ier = ((1 << LPC_USART_IER_RBRINTEN) | -- cgit v1.2.3 From d95a2c5d1ddce913dcb1d1ab5dc59f6a588ab599 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 24 Jun 2013 14:29:43 -0700 Subject: altos: Remove ao_radio_gpio_bits from normal build Only needed for the CC115L_TRACE code, and it only builds on STM Signed-off-by: Keith Packard --- src/drivers/ao_cc115l.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/drivers/ao_cc115l.c b/src/drivers/ao_cc115l.c index 05e6a762..56afc3c7 100644 --- a/src/drivers/ao_cc115l.c +++ b/src/drivers/ao_cc115l.c @@ -655,12 +655,14 @@ ao_radio_test_cmd(void) } } +#if CC115L_TRACE static inline int16_t ao_radio_gpio_bits(void) { return AO_CC115L_DONE_INT_PORT->idr & ((1 << AO_CC115L_FIFO_INT_PIN) | (1 << AO_CC115L_DONE_INT_PIN)); } +#endif static void ao_radio_wait_fifo(void) -- cgit v1.2.3 From fa0859a51576efe231effcb5995f325f9e7e0fcb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 17 Aug 2013 16:01:44 +0200 Subject: altos: Make FAT test program link explicitly against libcrypto For some reason, the MD5_Final symbol isn't resolved when linking only against libssl. Signed-off-by: Keith Packard --- src/test/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/test/Makefile b/src/test/Makefile index 3c9ac9c6..75b1f848 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -69,7 +69,7 @@ ao_micropeak_test: ao_micropeak_test.c ao_microflight.c ao_kalman.h cc $(CFLAGS) -o $@ ao_micropeak_test.c -lm ao_fat_test: ao_fat_test.c ao_fat.c ao_bufio.c - cc $(CFLAGS) -o $@ ao_fat_test.c -lssl + cc $(CFLAGS) -o $@ ao_fat_test.c -lssl -lcrypto ao_aes_test: ao_aes_test.c ao_aes.c ao_aes_tables.c cc $(CFLAGS) -o $@ ao_aes_test.c -- cgit v1.2.3 From e0a0a747624c2df66ca4a73b5a0de014ea204dca Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 17 Aug 2013 17:36:35 +0200 Subject: altos: allow projects to override default config values Override default radio power and APRS interval Signed-off-by: Keith Packard --- src/core/ao_config.c | 7 ++++++- src/core/ao_telemetry.c | 4 ++++ 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 1a500c79..b480e14c 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -28,6 +28,9 @@ __pdata uint8_t ao_config_loaded; __pdata uint8_t ao_config_dirty; __xdata uint8_t ao_config_mutex; +#ifndef AO_CONFIG_DEFAULT_APRS_INTERVAL +#define AO_CONFIG_DEFAULT_APRS_INTERVAL 0 +#endif #define AO_CONFIG_DEFAULT_MAIN_DEPLOY 250 #define AO_CONFIG_DEFAULT_RADIO_CHANNEL 0 #define AO_CONFIG_DEFAULT_CALLSIGN "N0CALL" @@ -47,7 +50,9 @@ __xdata uint8_t ao_config_mutex; #define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 192 * (uint32_t) 1024) #endif #endif +#ifndef AO_CONFIG_DEFAULT_RADIO_POWER #define AO_CONFIG_DEFAULT_RADIO_POWER 0x60 +#endif #define AO_CONFIG_DEFAULT_RADIO_AMP 0 #if HAS_EEPROM @@ -142,7 +147,7 @@ _ao_config_get(void) memset(&ao_config.pyro, '\0', sizeof (ao_config.pyro)); #endif if (minor < 13) - ao_config.aprs_interval = 0; + ao_config.aprs_interval = AO_CONFIG_DEFAULT_APRS_INTERVAL; #if HAS_RADIO_POWER if (minor < 14) ao_config.radio_power = AO_CONFIG_DEFAULT_RADIO_POWER; diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index c3bbfec5..dfde2235 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -198,7 +198,11 @@ ao_send_configuration(void) { telemetry.generic.type = AO_TELEMETRY_CONFIGURATION; telemetry.configuration.device = AO_idProduct_NUMBER; +#if HAS_LOG telemetry.configuration.flight = ao_log_full() ? 0 : ao_flight_number; +#else + telemetry.configuration.flight = ao_flight_number; +#endif telemetry.configuration.config_major = AO_CONFIG_MAJOR; telemetry.configuration.config_minor = AO_CONFIG_MINOR; telemetry.configuration.apogee_delay = ao_config.apogee_delay; -- cgit v1.2.3 From 9a22a300009679a14d66214a5d61e9e6a177279f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 17 Aug 2013 17:40:33 +0200 Subject: altos: Allow ublox to run at other baud rates Provides a configuration option to set the ublox serial baud rate to something other than 57600 baud Signed-off-by: Keith Packard --- src/drivers/ao_gps_ublox.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_gps_ublox.c b/src/drivers/ao_gps_ublox.c index 80869561..fa6ff0e0 100644 --- a/src/drivers/ao_gps_ublox.c +++ b/src/drivers/ao_gps_ublox.c @@ -26,11 +26,21 @@ __pdata uint16_t ao_gps_tick; __xdata struct ao_telemetry_location ao_gps_data; __xdata struct ao_telemetry_satellite ao_gps_tracking_data; -static const char ao_gps_set_nmea[] = "\r\n$PUBX,41,1,3,1,57600,0*2d\r\n"; +#ifndef AO_SERIAL_SPEED_UBLOX +#define AO_SERIAL_SPEED_UBLOX AO_SERIAL_SPEED_57600 +#endif -const char ao_gps_config[] = { +#if AO_SERIAL_SPEED_UBLOX == AO_SERIAL_SPEED_57600 +#define SERIAL_SPEED_STRING "57600" +#endif +#if AO_SERIAL_SPEED_UBLOX == AO_SERIAL_SPEED_19200 +#define SERIAL_SPEED_STRING "19200" +#endif +#if AO_SERIAL_SPEED_UBLOX == AO_SERIAL_SPEED_9600 +#define SERIAL_SPEED_STRING "9600" +#endif -}; +static const char ao_gps_set_nmea[] = "\r\n$PUBX,41,1,3,1," SERIAL_SPEED_STRING ",0*2d\r\n"; struct ao_ublox_cksum { uint8_t a, b; @@ -419,10 +429,12 @@ ao_gps_setup(void) for (i = 0; i < sizeof (ao_gps_set_nmea); i++) ao_gps_putchar(ao_gps_set_nmea[i]); +#if AO_SERIAL_SPEED_UBLOX != AO_SERIAL_SPEED_9600 /* * Increase the baud rate */ - ao_gps_set_speed(AO_SERIAL_SPEED_57600); + ao_gps_set_speed(AO_SERIAL_SPEED_UBLOX); +#endif /* * Pad with nulls to give the chip -- cgit v1.2.3 From a0dd93ccf0920260b41c4003955617fd0cd1c8b4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 17 Aug 2013 17:43:18 +0200 Subject: altos: Set default LPC stack to 512 bytes, Em to 384 bytes The default for lpc has been raised to 512 bytes, but Em doesn't have enough RAM for that. Signed-off-by: Keith Packard --- src/easymini-v0.1/ao_pins.h | 2 ++ src/lpc/ao_arch.h | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/easymini-v0.1/ao_pins.h b/src/easymini-v0.1/ao_pins.h index 6f102dbe..c09fb4c2 100644 --- a/src/easymini-v0.1/ao_pins.h +++ b/src/easymini-v0.1/ao_pins.h @@ -18,6 +18,8 @@ #define HAS_BEEP 1 #define HAS_LED 1 +#define AO_STACK_SIZE 384 + #define IS_FLASH_LOADER 0 /* Crystal on the board */ diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index a8d3cfc4..d04bf2c8 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -24,7 +24,9 @@ * LPC11U14 definitions and code fragments for AltOS */ -#define AO_STACK_SIZE 320 +#ifndef AO_STACK_SIZE +#define AO_STACK_SIZE 512 +#endif #define AO_LED_TYPE uint16_t -- cgit v1.2.3 From 0dd55f66d79f54b450fd8122aecd84d68b810bf4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 17 Aug 2013 17:45:06 +0200 Subject: altos: Wake up on LPC usart ISR only once Instead of waking up after every character, wait until the FIFO is empty to reduce overhead Signed-off-by: Keith Packard --- src/lpc/ao_serial_lpc.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_serial_lpc.c b/src/lpc/ao_serial_lpc.c index d6b0082a..431ae98a 100644 --- a/src/lpc/ao_serial_lpc.c +++ b/src/lpc/ao_serial_lpc.c @@ -49,21 +49,25 @@ _ao_serial_tx_start(void) void lpc_usart_isr(void) { + uint8_t wake_input = 0; (void) lpc_usart.iir_fcr; while (lpc_usart.lsr & (1 << LPC_USART_LSR_RDR)) { char c = lpc_usart.rbr_thr; if (!ao_fifo_full(ao_usart_rx_fifo)) ao_fifo_insert(ao_usart_rx_fifo, c); - ao_wakeup(&ao_usart_rx_fifo); - if (stdin) - ao_wakeup(&ao_stdin_ready); + wake_input = 1; } if (lpc_usart.lsr & (1 << LPC_USART_LSR_THRE)) { ao_usart_tx_avail = LPC_USART_TX_FIFO_SIZE; _ao_serial_tx_start(); ao_wakeup(&ao_usart_tx_fifo); } + if (wake_input) { + ao_wakeup(&ao_usart_rx_fifo); + if (stdin) + ao_wakeup(&ao_stdin_ready); + } } int -- cgit v1.2.3 From e2f385946132690ca6dc141d7c7830ae0cfe3458 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 20 Aug 2013 08:54:44 -0700 Subject: altos: various cc115l driver hacks Try to recover from TX_FIFO_UNDERFLOW by resetting the chip at idle time. Do a calibration phase during setup. Program power to ramp up to limit key down noise. Signed-off-by: Keith Packard --- src/drivers/ao_cc115l.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_cc115l.c b/src/drivers/ao_cc115l.c index 56afc3c7..0fa1e899 100644 --- a/src/drivers/ao_cc115l.c +++ b/src/drivers/ao_cc115l.c @@ -245,6 +245,8 @@ ao_radio_idle(void) uint8_t state = ao_radio_strobe(CC115L_SIDLE); if ((state >> CC115L_STATUS_STATE) == CC115L_STATUS_STATE_IDLE) break; + if ((state >> CC115L_STATUS_STATE) == CC115L_STATUS_STATE_TX_FIFO_UNDERFLOW) + ao_radio_strobe(CC115L_SFTX); } /* Flush any pending TX bytes */ ao_radio_strobe(CC115L_SFTX); @@ -476,6 +478,8 @@ ao_radio_setup(void) ao_config_get(); + ao_radio_strobe(CC115L_SCAL); + ao_radio_configured = 1; } @@ -494,7 +498,6 @@ static void ao_radio_get(void) { static uint32_t last_radio_setting; - static uint8_t last_power_setting; ao_mutex_get(&ao_radio_mutex); if (!ao_radio_configured) @@ -505,10 +508,6 @@ ao_radio_get(void) ao_radio_reg_write(CC115L_FREQ0, ao_config.radio_setting); last_radio_setting = ao_config.radio_setting; } - if (ao_config.radio_power != last_power_setting) { - ao_radio_reg_write(CC115L_PA, ao_config.radio_power); - last_power_setting = ao_config.radio_power; - } } static void @@ -614,6 +613,20 @@ ao_radio_rdf_abort(void) ao_wakeup(&ao_radio_wake); } +#define POWER_STEP 0x08 + +static void +ao_radio_stx(void) +{ + uint8_t power; + ao_radio_pa_on(); + ao_radio_reg_write(CC115L_PA, 0); + ao_radio_strobe(CC115L_STX); + for (power = POWER_STEP; power < ao_config.radio_power; power += POWER_STEP) + ao_radio_reg_write(CC115L_PA, power); + ao_radio_reg_write(CC115L_PA, ao_config.radio_power); +} + static void ao_radio_test_cmd(void) { @@ -633,11 +646,10 @@ ao_radio_test_cmd(void) ao_packet_slave_stop(); #endif ao_radio_get(); - ao_radio_set_len(0xff); - ao_radio_set_mode(AO_RADIO_MODE_RDF|AO_RADIO_MODE_BITS_FIXED); ao_radio_strobe(CC115L_SFTX); - ao_radio_pa_on(); - ao_radio_strobe(CC115L_STX); + ao_radio_set_len(0xff); + ao_radio_set_mode(AO_RADIO_MODE_RDF); + ao_radio_stx(); radio_on = 1; } if (mode == 3) { @@ -740,6 +752,10 @@ _ao_radio_send_lots(ao_radio_fill_func fill, uint8_t mode) uint8_t fifo_space; fifo_space = CC115L_FIFO_SIZE; + ao_radio_abort = 0; + + ao_radio_strobe(CC115L_SFTX); + ao_radio_done = 0; ao_radio_fifo = 0; while (!done) { @@ -786,8 +802,7 @@ _ao_radio_send_lots(ao_radio_fill_func fill, uint8_t mode) ao_exti_enable(AO_CC115L_DONE_INT_PORT, AO_CC115L_DONE_INT_PIN); if (!started) { - ao_radio_pa_on(); - ao_radio_strobe(CC115L_STX); + ao_radio_stx(); started = 1; } } -- cgit v1.2.3 From a1ec15f4585e23eb67affbe7d9d97261576b198d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 24 Aug 2013 23:21:53 -0700 Subject: altos: Add telegps v0.3 product Signed-off-by: Keith Packard --- src/telegps-v0.3/Makefile | 84 +++++++++++++++++++++++ src/telegps-v0.3/ao_pins.h | 114 ++++++++++++++++++++++++++++++++ src/telegps-v0.3/ao_telegps.c | 64 ++++++++++++++++++ src/telegps-v0.3/flash-loader/Makefile | 8 +++ src/telegps-v0.3/flash-loader/ao_pins.h | 33 +++++++++ 5 files changed, 303 insertions(+) create mode 100644 src/telegps-v0.3/Makefile create mode 100644 src/telegps-v0.3/ao_pins.h create mode 100644 src/telegps-v0.3/ao_telegps.c create mode 100644 src/telegps-v0.3/flash-loader/Makefile create mode 100644 src/telegps-v0.3/flash-loader/ao_pins.h (limited to 'src') diff --git a/src/telegps-v0.3/Makefile b/src/telegps-v0.3/Makefile new file mode 100644 index 00000000..ca7d7c2b --- /dev/null +++ b/src/telegps-v0.3/Makefile @@ -0,0 +1,84 @@ +# +# AltOS build +# +# + +include ../lpc/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_pins.h \ + ao_product.h \ + ao_task.h \ + ao_whiten.h \ + ao_cc115l.h \ + ao_fec.h \ + lpc.h \ + Makefile + + +ALTOS_SRC = \ + ao_interrupt.c \ + ao_boot_chain.c \ + ao_product.c \ + ao_romconfig.c \ + ao_cmd.c \ + ao_config.c \ + ao_task.c \ + ao_stdio.c \ + ao_panic.c \ + ao_timer_lpc.c \ + ao_mutex.c \ + ao_freq.c \ + ao_spi_lpc.c \ + ao_usb_lpc.c \ + ao_exti_lpc.c \ + ao_serial_lpc.c \ + ao_gps_ublox.c \ + ao_gps_show.c \ + ao_cc115l.c \ + ao_fec_tx.c \ + ao_aprs.c \ + ao_telemetry.c \ + ao_storage.c \ + ao_m25.c \ + ao_log.c \ + ao_log_mega.c \ + ao_gps_report_mega.c \ + $(SAMPLE_PROFILE) + +PRODUCT=TeleGPS-v0.3 +PRODUCT_DEF=-DTELEGPS +IDPRODUCT=0x0025 + +CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) $(PROFILE_DEF) -Os -g + +PROGNAME=telegps-v0.3 +PROG=$(PROGNAME)-$(VERSION).elf + +SRC=$(ALTOS_SRC) ao_telegps.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) + +LDFLAGS=-L../lpc -Wl,-Taltos.ld + +$(PROG): Makefile $(OBJ) altos.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + +$(OBJ): $(INC) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f *.o ao_serial_lpc.h $(PROGNAME)-*.elf + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/telegps-v0.3/ao_pins.h b/src/telegps-v0.3/ao_pins.h new file mode 100644 index 00000000..a4afaa54 --- /dev/null +++ b/src/telegps-v0.3/ao_pins.h @@ -0,0 +1,114 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define AO_STACK_SIZE 448 + +#define IS_FLASH_LOADER 0 + +/* Crystal on the board */ +#define AO_LPC_CLKIN 12000000 + +/* Main clock frequency. 48MHz for USB so we don't use the USB PLL */ +#define AO_LPC_CLKOUT 48000000 + +/* System clock frequency */ +#define AO_LPC_SYSCLK 24000000 + +#define HAS_SERIAL_0 1 +#define SERIAL_0_18_19 1 +#define USE_SERIAL_0_STDIN 0 + +#define ao_gps_getchar ao_serial0_getchar +#define ao_gps_putchar ao_serial0_putchar +#define ao_gps_set_speed ao_serial0_set_speed +#define ao_gps_fifo (ao_usart_rx_fifo) + +#define HAS_EEPROM 1 +#define USE_INTERNAL_FLASH 0 +#define HAS_USB 1 +#define HAS_BEEP 0 +#define HAS_RADIO 1 +#define HAS_TELEMETRY 1 +#define HAS_RDF 0 +#define HAS_APRS 1 +#define HAS_RADIO_RECV 0 + +#define HAS_USB_PULLUP 1 +#define AO_USB_PULLUP_PORT 0 +#define AO_USB_PULLUP_PIN 7 + +/* Flash part */ +#define HAS_SPI_0 1 +#define SPI_SCK0_P0_6 1 +#define SPI_0_OSPEEDR AO_SPI_OSPEED_12MHz + +/* Radio */ +#define HAS_SPI_1 1 +#define SPI_SCK1_P1_15 1 +#define SPI_MISO1_P0_22 1 +#define SPI_MOSI1_P0_21 1 + +#define HAS_GPS 1 +#define HAS_FLIGHT 0 +#define HAS_ADC 0 +#define HAS_LOG 1 + +#define AO_CONFIG_DEFAULT_APRS_INTERVAL 5 +#define AO_CONFIG_DEFAULT_RADIO_POWER 0xc0 + +/* + * GPS + */ + +#define AO_SERIAL_SPEED_UBLOX AO_SERIAL_SPEED_9600 + +/* + * Radio (cc115l) + */ + +/* gets pretty close to 434.550 */ + +#define AO_RADIO_CAL_DEFAULT 0x10b6a5 + +#define HAS_RADIO_POWER 1 +#define AO_FEC_DEBUG 0 +#define AO_CC115L_SPI_CS_PORT 0 +#define AO_CC115L_SPI_CS_PIN 3 +#define AO_CC115L_SPI_BUS 0 + +#define AO_CC115L_FIFO_INT_GPIO_IOCFG CC115L_IOCFG2 +#define AO_CC115L_FIFO_INT_PORT 0 +#define AO_CC115L_FIFO_INT_PIN 20 + +#define AO_CC115L_DONE_INT_GPIO_IOCFG CC115L_IOCFG0 +#define AO_CC115L_DONE_INT_PORT 0 +#define AO_CC115L_DONE_INT_PIN 2 + +/* + * Flash (M25) + */ +#define M25_MAX_CHIPS 1 +#define AO_M25_SPI_CS_PORT 0 +#define AO_M25_SPI_CS_MASK (1 << 23) +#define AO_M25_SPI_BUS 1 + +#define PACKET_HAS_SLAVE 0 + +#endif /* _AO_PINS_H_ */ diff --git a/src/telegps-v0.3/ao_telegps.c b/src/telegps-v0.3/ao_telegps.c new file mode 100644 index 00000000..f9f62316 --- /dev/null +++ b/src/telegps-v0.3/ao_telegps.c @@ -0,0 +1,64 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include + +uint16_t ao_flight_number = 1; + +int +main(void) +{ + ao_clock_init(); + +#if HAS_STACK_GUARD + ao_mpu_init(); +#endif + + ao_task_init(); + ao_timer_init(); + + + ao_spi_init(); + ao_exti_init(); + + ao_storage_init(); + + ao_serial_init(); + + ao_cmd_init(); + + ao_usb_init(); + ao_radio_init(); + + ao_gps_init(); +#if HAS_LOG + ao_gps_report_mega_init(); +#endif + + ao_telemetry_init(); + ao_telemetry_set_interval(AO_SEC_TO_TICKS(1)); + +#if HAS_SAMPLE_PROFILE + ao_sample_profile_init(); +#endif + ao_config_init(); + + ao_start_scheduler(); + return 0; +} diff --git a/src/telegps-v0.3/flash-loader/Makefile b/src/telegps-v0.3/flash-loader/Makefile new file mode 100644 index 00000000..6f4ce0d8 --- /dev/null +++ b/src/telegps-v0.3/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telegps-v0.3 +include $(TOPDIR)/lpc/Makefile-flash.defs diff --git a/src/telegps-v0.3/flash-loader/ao_pins.h b/src/telegps-v0.3/flash-loader/ao_pins.h new file mode 100644 index 00000000..91097a25 --- /dev/null +++ b/src/telegps-v0.3/flash-loader/ao_pins.h @@ -0,0 +1,33 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#include + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO 0 +#define AO_BOOT_APPLICATION_PIN 19 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +#define HAS_USB_PULLUP 1 +#define AO_USB_PULLUP_PORT 0 +#define AO_USB_PULLUP_PIN 7 + +#endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 4babe7310f78338ca36ab9d31ac833eada27485f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 24 Aug 2013 23:22:18 -0700 Subject: altos: Allow products to disable RDF entirely TeleGPS doesn't ever want RDF Signed-off-by: Keith Packard --- src/core/ao_telemetry.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index dfde2235..03a8a273 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -19,9 +19,16 @@ #include "ao_log.h" #include "ao_product.h" +#ifndef HAS_RDF +#define HAS_RDF 1 +#endif + static __pdata uint16_t ao_telemetry_interval; static __pdata uint8_t ao_rdf = 0; + +#if HAS_RDF static __pdata uint16_t ao_rdf_time; +#endif #if HAS_APRS static __pdata uint16_t ao_aprs_time; @@ -299,7 +306,10 @@ ao_telemetry(void) for (;;) { while (ao_telemetry_interval == 0) ao_sleep(&telemetry); - time = ao_rdf_time = ao_time(); + time = ao_time(); +#if HAS_RDF + ao_rdf_time = time; +#endif #if HAS_APRS ao_aprs_time = time; #endif @@ -332,6 +342,7 @@ ao_telemetry(void) #endif } #ifndef AO_SEND_ALL_BARO +#if HAS_RDF if (ao_rdf && #if HAS_APRS !(ao_config.radio_enable & AO_RADIO_DISABLE_RDF) && @@ -349,6 +360,7 @@ ao_telemetry(void) #endif ao_radio_rdf(); } +#endif /* HAS_RDF */ #if HAS_APRS if (ao_config.aprs_interval != 0 && (int16_t) (ao_time() - ao_aprs_time) >= 0) @@ -415,6 +427,7 @@ ao_telemetry_set_interval(uint16_t interval) ao_wakeup(&telemetry); } +#if HAS_RDF void ao_rdf_set(uint8_t rdf) { @@ -425,6 +438,7 @@ ao_rdf_set(uint8_t rdf) ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; } } +#endif __xdata struct ao_task ao_telemetry_task; -- cgit v1.2.3 From 1aed2eb5c7d477a2f3d4fada22980041aba97cb8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Aug 2013 11:22:10 -0700 Subject: altos/lpc: Stop using burst mode for LPC ADC Burst mode doesn't stop after one round of conversions, so we end up getting incorrect values in whatever the last conversion register is. Just use single conversions and take an interrupt per channel. Also, slow down the ADC so that our values are more stable -- just need to make sure we get the whole conversion sequence done 100 times a second. Signed-off-by: Keith Packard --- src/lpc/ao_adc_lpc.c | 119 ++++++++++++++++++++------------------------------- 1 file changed, 46 insertions(+), 73 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_adc_lpc.c b/src/lpc/ao_adc_lpc.c index 874d2d29..7005f86e 100644 --- a/src/lpc/ao_adc_lpc.c +++ b/src/lpc/ao_adc_lpc.c @@ -50,89 +50,65 @@ #define AO_ADC_7 0 #endif -#if AO_ADC_7 -# define AO_ADC_LAST 7 -#else -# if AO_ADC_6 -# define AO_ADC_LAST 6 -# else -# if AO_ADC_5 -# define AO_ADC_LAST 5 -# else -# if AO_ADC_4 -# define AO_ADC_LAST 4 -# else -# if AO_ADC_3 -# define AO_ADC_LAST 3 -# else -# if AO_ADC_2 -# define AO_ADC_LAST 2 -# else -# if AO_ADC_1 -# define AO_ADC_LAST 1 -# else -# if AO_ADC_0 -# define AO_ADC_LAST 0 -# endif -# endif -# endif -# endif -# endif -# endif -# endif -#endif - -#define AO_ADC_MASK ((AO_ADC_0 << 0) | \ - (AO_ADC_1 << 1) | \ - (AO_ADC_2 << 2) | \ - (AO_ADC_3 << 3) | \ - (AO_ADC_4 << 4) | \ - (AO_ADC_5 << 5) | \ - (AO_ADC_6 << 6) | \ - (AO_ADC_7 << 7)) - -#define AO_ADC_CLKDIV (AO_LPC_SYSCLK / 4500000) - -static uint8_t ao_adc_ready; +#define AO_ADC_NUM (AO_ADC_0 + AO_ADC_1 + AO_ADC_2 + AO_ADC_3 + \ + AO_ADC_4 + AO_ADC_5 + AO_ADC_6 + AO_ADC_7) -#define sample(id) (*out++ = lpc_adc.dr[id] >> 1) - -void lpc_adc_isr(void) -{ - uint32_t stat = lpc_adc.stat; - uint16_t *out; - - /* Turn off burst mode */ - lpc_adc.cr = 0; - lpc_adc.stat = 0; +/* ADC clock is divided by this value + 1, which ensures that + * the ADC clock will be strictly less than 4.5MHz as required + */ +#define AO_ADC_CLKDIV (AO_LPC_SYSCLK / 450000) - /* Store converted values in packet */ +static uint8_t ao_adc_ready; +static uint8_t ao_adc_sequence; - out = (uint16_t *) &ao_data_ring[ao_data_head].adc; +static const uint8_t ao_adc_mask_seq[AO_ADC_NUM] = { #if AO_ADC_0 - sample(0); + 1 << 0, #endif #if AO_ADC_1 - sample(1); + 1 << 1, #endif #if AO_ADC_2 - sample(2); + 1 << 2, #endif #if AO_ADC_3 - sample(3); + 1 << 3, #endif #if AO_ADC_4 - sample(4); + 1 << 4, #endif #if AO_ADC_5 - sample(5); + 1 << 6, #endif #if AO_ADC_6 - sample(6); + 1 << 6, #endif #if AO_ADC_7 - sample(7); + 1 << 7, #endif +}; + +#define sample(id) (*out++ = (uint16_t) lpc_adc.dr[id] >> 1) + +static inline void lpc_adc_start(void) { + lpc_adc.cr = ((ao_adc_mask_seq[ao_adc_sequence] << LPC_ADC_CR_SEL) | + (AO_ADC_CLKDIV << LPC_ADC_CR_CLKDIV) | + (0 << LPC_ADC_CR_BURST) | + (LPC_ADC_CR_CLKS_11 << LPC_ADC_CR_CLKS) | + (LPC_ADC_CR_START_NOW << LPC_ADC_CR_START)); +} + +void lpc_adc_isr(void) +{ + uint16_t *out; + + /* Store converted value in packet */ + out = (uint16_t *) &ao_data_ring[ao_data_head].adc; + out[ao_adc_sequence] = (uint16_t) lpc_adc.gdr >> 1; + if (++ao_adc_sequence < AO_ADC_NUM) { + lpc_adc_start(); + return; + } AO_DATA_PRESENT(AO_DATA_ADC); if (ao_data_present == AO_DATA_ALL) { @@ -157,7 +133,7 @@ void lpc_adc_isr(void) /* - * Start the ADC sequence using the DMA engine + * Start the ADC sequence using burst mode */ void ao_adc_poll(void) @@ -165,11 +141,8 @@ ao_adc_poll(void) if (!ao_adc_ready) return; ao_adc_ready = 0; - - lpc_adc.cr = ((AO_ADC_MASK << LPC_ADC_CR_SEL) | - (AO_ADC_CLKDIV << LPC_ADC_CR_CLKDIV) | - (1 << LPC_ADC_CR_BURST) | - (LPC_ADC_CR_CLKS_11 << LPC_ADC_CR_CLKS)); + ao_adc_sequence = 0; + lpc_adc_start(); } static void @@ -202,8 +175,8 @@ ao_adc_init(void) lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_ADC); lpc_scb.pdruncfg &= ~(1 << LPC_SCB_PDRUNCFG_ADC_PD); - /* Enable interrupt when last channel is complete */ - lpc_adc.inten = (1 << AO_ADC_LAST); + /* Enable interrupt when channel is complete */ + lpc_adc.inten = (1 << LPC_ADC_INTEN_ADGINTEN); lpc_nvic_set_enable(LPC_ISR_ADC_POS); lpc_nvic_set_priority(LPC_ISR_ADC_POS, AO_LPC_NVIC_CLOCK_PRIORITY); @@ -232,7 +205,7 @@ ao_adc_init(void) ao_enable_analog(0, 23, 7); #endif - lpc_adc.cr = ((AO_ADC_MASK << LPC_ADC_CR_SEL) | + lpc_adc.cr = ((0 << LPC_ADC_CR_SEL) | (AO_ADC_CLKDIV << LPC_ADC_CR_CLKDIV) | (0 << LPC_ADC_CR_BURST) | (LPC_ADC_CR_CLKS_11 << LPC_ADC_CR_CLKS)); -- cgit v1.2.3 From e908eb090fc2aaa03b35dc37c3e008b05ad44d80 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Aug 2013 11:24:18 -0700 Subject: altos: Use installed arm compiler for LPC Signed-off-by: Keith Packard --- src/lpc/Makefile.defs | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/lpc/Makefile.defs b/src/lpc/Makefile.defs index b63bdd12..9e87cee1 100644 --- a/src/lpc/Makefile.defs +++ b/src/lpc/Makefile.defs @@ -12,6 +12,8 @@ SAT=/opt/cortex SAT_CLIB=$(SAT)/lib/pdclib-cortex-m0.a SAT_CFLAGS=-I$(SAT)/include +#CC=/opt/arm-gcc-bits/bin/arm-none-eabi-gcc + ifndef VERSION include ../Version endif -- cgit v1.2.3 From 10f88c46df9a266f62452dc25275c79a3bb0653d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 17 Aug 2013 17:43:18 +0200 Subject: altos: Set default LPC stack to 512 bytes, Em to 384 bytes The default for lpc has been raised to 512 bytes, but Em doesn't have enough RAM for that. Signed-off-by: Keith Packard --- src/easymini-v0.1/ao_pins.h | 2 ++ src/lpc/ao_arch.h | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/easymini-v0.1/ao_pins.h b/src/easymini-v0.1/ao_pins.h index 6f102dbe..c09fb4c2 100644 --- a/src/easymini-v0.1/ao_pins.h +++ b/src/easymini-v0.1/ao_pins.h @@ -18,6 +18,8 @@ #define HAS_BEEP 1 #define HAS_LED 1 +#define AO_STACK_SIZE 384 + #define IS_FLASH_LOADER 0 /* Crystal on the board */ diff --git a/src/lpc/ao_arch.h b/src/lpc/ao_arch.h index a8d3cfc4..d04bf2c8 100644 --- a/src/lpc/ao_arch.h +++ b/src/lpc/ao_arch.h @@ -24,7 +24,9 @@ * LPC11U14 definitions and code fragments for AltOS */ -#define AO_STACK_SIZE 320 +#ifndef AO_STACK_SIZE +#define AO_STACK_SIZE 512 +#endif #define AO_LED_TYPE uint16_t -- cgit v1.2.3 From aa2948803d33dbee6f1eab30370178252df2b56d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 17 Aug 2013 17:45:06 +0200 Subject: altos: Wake up on LPC usart ISR only once Instead of waking up after every character, wait until the FIFO is empty to reduce overhead Signed-off-by: Keith Packard --- src/lpc/ao_serial_lpc.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_serial_lpc.c b/src/lpc/ao_serial_lpc.c index c0424699..b34de704 100644 --- a/src/lpc/ao_serial_lpc.c +++ b/src/lpc/ao_serial_lpc.c @@ -49,21 +49,25 @@ _ao_serial_tx_start(void) void lpc_usart_isr(void) { + uint8_t wake_input = 0; (void) lpc_usart.iir_fcr; while (lpc_usart.lsr & (1 << LPC_USART_LSR_RDR)) { char c = lpc_usart.rbr_thr; if (!ao_fifo_full(ao_usart_rx_fifo)) ao_fifo_insert(ao_usart_rx_fifo, c); - ao_wakeup(&ao_usart_rx_fifo); - if (stdin) - ao_wakeup(&ao_stdin_ready); + wake_input = 1; } if (lpc_usart.lsr & (1 << LPC_USART_LSR_THRE)) { ao_usart_tx_avail = LPC_USART_TX_FIFO_SIZE; _ao_serial_tx_start(); ao_wakeup(&ao_usart_tx_fifo); } + if (wake_input) { + ao_wakeup(&ao_usart_rx_fifo); + if (stdin) + ao_wakeup(&ao_stdin_ready); + } } int -- cgit v1.2.3 From b363a628fc6137c3395a48ef13de7a799ec3e2c3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 22 May 2013 19:31:15 -0600 Subject: altos: MS5607 pressure computation for low temperatures was wrong MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Second correction only applies to temps < -15°C, not 15°C. Signed-off-by: Keith Packard --- src/drivers/ao_ms5607_convert.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_ms5607_convert.c b/src/drivers/ao_ms5607_convert.c index e61d19ed..bfb952a4 100644 --- a/src/drivers/ao_ms5607_convert.c +++ b/src/drivers/ao_ms5607_convert.c @@ -42,11 +42,14 @@ ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value int32_t TEMPM = TEMP - 2000; int64_t OFF2 = (61 * (int64_t) TEMPM * (int64_t) TEMPM) >> 4; int64_t SENS2 = 2 * (int64_t) TEMPM * (int64_t) TEMPM; - if (TEMP < 1500) { + if (TEMP < -1500) { int32_t TEMPP = TEMP + 1500; - int64_t TEMPP2 = TEMPP * TEMPP; - OFF2 = OFF2 + 15 * TEMPP2; - SENS2 = SENS2 + 8 * TEMPP2; + /* You'd think this would need a 64-bit int, but + * that would imply a temperature below -327.67°C... + */ + int32_t TEMPP2 = TEMPP * TEMPP; + OFF2 = OFF2 + (int64_t) 15 * TEMPP2; + SENS2 = SENS2 + (int64_t) 8 * TEMPP2; } TEMP -= T2; OFF -= OFF2; -- cgit v1.2.3 From 3ded57394f6dfd7beb9526c031a5c6c6c9926917 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 25 Aug 2013 22:22:55 -0700 Subject: altos: Explicitly list the linker script needed for AVR targets. Something changed in the binutils-avr package which makes the linker fail to find the script in the default location. Signed-off-by: Keith Packard --- src/micropeak/Makefile | 2 ++ src/telescience-pwm/Makefile | 2 ++ src/telescience-v0.1/Makefile | 2 ++ 3 files changed, 6 insertions(+) (limited to 'src') diff --git a/src/micropeak/Makefile b/src/micropeak/Makefile index 315b93f6..44e0b873 100644 --- a/src/micropeak/Makefile +++ b/src/micropeak/Makefile @@ -16,6 +16,8 @@ LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: CC=avr-gcc OBJCOPY=avr-objcopy +LDFLAGS=-L/usr/lib/ldscripts -Tavr25.x + ifndef VERSION include ../Version endif diff --git a/src/telescience-pwm/Makefile b/src/telescience-pwm/Makefile index 43d77e2e..ce2a8fde 100644 --- a/src/telescience-pwm/Makefile +++ b/src/telescience-pwm/Makefile @@ -14,6 +14,8 @@ LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: CC=avr-gcc OBJCOPY=avr-objcopy +LDFLAGS=-L/usr/lib/ldscripts -Tavr5.x + ifndef VERSION include ../Version endif diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index d24128ef..81054a75 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -14,6 +14,8 @@ LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: CC=avr-gcc OBJCOPY=avr-objcopy +LDFLAGS=-L/usr/lib/ldscripts -Tavr5.x + ifndef VERSION include ../Version endif -- cgit v1.2.3 From d0b4e926ecececa7499a301b6135189be119512e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 22 May 2013 13:03:06 -0700 Subject: Initial TeleMini bits Signed-off-by: Keith Packard --- src/cc1111/ao_adc.c | 5 ++ src/cc1111/ao_usb.c | 5 ++ src/core/ao_data.c | 2 + src/core/ao_data.h | 2 +- src/core/ao_log_mini.c | 1 - src/core/ao_telemetry.c | 40 +++++++++- src/core/ao_telemetry.h | 27 +++++++ src/drivers/ao_ms5607.c | 40 +++++----- src/drivers/ao_ms5607.h | 2 +- src/drivers/ao_ms5607_convert_8051.c | 60 +++++++++++++++ src/telemini-v2.0/Makefile | 108 +++++++++++++++++++++++++++ src/telemini-v2.0/ao_pins.h | 140 +++++++++++++++++++++++++++++++++++ src/telemini-v2.0/ao_telemini.c | 54 ++++++++++++++ src/test/Makefile | 5 +- 14 files changed, 466 insertions(+), 25 deletions(-) create mode 100644 src/drivers/ao_ms5607_convert_8051.c create mode 100644 src/telemini-v2.0/Makefile create mode 100644 src/telemini-v2.0/ao_pins.h create mode 100644 src/telemini-v2.0/ao_telemini.c (limited to 'src') diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index 4a58023d..6cc08399 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -162,6 +162,11 @@ ao_adc_isr(void) __interrupt 1 #define GOT_ADC #endif +#ifdef FETCH_ADC + FETCH_ADC() +#define GOT_ADC +#endif + #ifndef GOT_ADC #error No known ADC configuration set #endif diff --git a/src/cc1111/ao_usb.c b/src/cc1111/ao_usb.c index a655d1be..b0ab409d 100644 --- a/src/cc1111/ao_usb.c +++ b/src/cc1111/ao_usb.c @@ -201,6 +201,11 @@ ao_usb_ep0_setup(void) ao_usb_ep0_queue_byte(0); break; case AO_USB_REQ_SET_ADDRESS: +#if USB_FORCE_FLIGHT_IDLE + /* Go to idle mode if USB is connected + */ + ao_flight_force_idle = 1; +#endif ao_usb_set_address(ao_usb_setup.value); break; case AO_USB_REQ_GET_DESCRIPTOR: diff --git a/src/core/ao_data.c b/src/core/ao_data.c index 38d2f7ff..6a3d02a1 100644 --- a/src/core/ao_data.c +++ b/src/core/ao_data.c @@ -22,6 +22,7 @@ volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; volatile __data uint8_t ao_data_head; volatile __data uint8_t ao_data_present; +#ifndef ao_data_count void ao_data_get(__xdata struct ao_data *packet) { @@ -32,3 +33,4 @@ ao_data_get(__xdata struct ao_data *packet) #endif memcpy(packet, (void *) &ao_data_ring[i], sizeof (struct ao_data)); } +#endif diff --git a/src/core/ao_data.h b/src/core/ao_data.h index b0f086f8..080a534f 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -101,7 +101,7 @@ extern volatile __data uint8_t ao_data_count; * signaled by the timer tick */ #define AO_DATA_WAIT() do { \ - ao_sleep((void *) &ao_data_count); \ + ao_sleep(DATA_TO_XDATA ((void *) &ao_data_count)); \ } while (0) #endif /* AO_DATA_RING */ diff --git a/src/core/ao_log_mini.c b/src/core/ao_log_mini.c index 1273b0e3..46b285f3 100644 --- a/src/core/ao_log_mini.c +++ b/src/core/ao_log_mini.c @@ -79,7 +79,6 @@ void ao_log(void) { __pdata uint16_t next_sensor, next_other; - uint8_t i; ao_storage_setup(); diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 03a8a273..9c673030 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -171,6 +171,36 @@ ao_send_mega_data(void) } #endif /* AO_SEND_MEGA */ +#ifdef AO_SEND_MINI + +static void +ao_send_mini(void) +{ + __xdata struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; + + telemetry.generic.tick = packet->tick; + telemetry.generic.type = AO_TELEMETRY_MINI; + + telemetry.mini.state = ao_flight_state; + + telemetry.mini.v_batt = packet->adc.v_batt; + telemetry.mini.sense_a = packet->adc.sense_a; + telemetry.mini.sense_m = packet->adc.sense_m; + + telemetry.mini.pres = ao_data_pres(packet); + telemetry.mini.temp = ao_data_temp(packet); + + telemetry.mini.acceleration = ao_accel; + telemetry.mini.speed = ao_speed; + telemetry.mini.height = ao_height; + + telemetry.mini.ground_pres = ao_ground_pres; + + ao_radio_send(&telemetry, sizeof (telemetry)); +} + +#endif + #ifdef AO_SEND_ALL_BARO static uint8_t ao_baro_sample; @@ -323,12 +353,16 @@ ao_telemetry(void) ao_send_baro(); #endif #if HAS_FLIGHT -#ifdef AO_SEND_MEGA +# ifdef AO_SEND_MEGA ao_send_mega_sensor(); ao_send_mega_data(); -#else +# else +# ifdef AO_SEND_MINI + ao_send_mini(); +# else ao_send_sensor(); -#endif +# endif +# endif #endif #if HAS_COMPANION diff --git a/src/core/ao_telemetry.h b/src/core/ao_telemetry.h index f2d201de..77601529 100644 --- a/src/core/ao_telemetry.h +++ b/src/core/ao_telemetry.h @@ -207,6 +207,32 @@ struct ao_telemetry_mega_data { }; +#define AO_TELEMETRY_MINI 0x10 + +struct ao_telemetry_mini { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t state; /* 5 flight state */ + + int16_t v_batt; /* 6 battery voltage */ + int16_t sense_a; /* 8 apogee continuity */ + int16_t sense_m; /* 10 main continuity */ + + int32_t pres; /* 12 Pa * 10 */ + int16_t temp; /* 16 °C * 100 */ + + int16_t acceleration; /* 18 m/s² * 16 */ + int16_t speed; /* 20 m/s * 16 */ + int16_t height; /* 22 m */ + + int32_t ground_pres; /* 24 average pres on pad */ + + int32_t pad28; /* 28 */ + /* 32 */ +}; + /* #define AO_SEND_ALL_BARO */ #define AO_TELEMETRY_BARO 0x80 @@ -240,6 +266,7 @@ union ao_telemetry_all { struct ao_telemetry_companion companion; struct ao_telemetry_mega_sensor mega_sensor; struct ao_telemetry_mega_data mega_data; + struct ao_telemetry_mini mini; struct ao_telemetry_baro baro; }; diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 8f1dcbe1..5259b265 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -21,7 +21,7 @@ #if HAS_MS5607 || HAS_MS5611 -static struct ao_ms5607_prom ms5607_prom; +static __xdata struct ao_ms5607_prom ms5607_prom; static uint8_t ms5607_configured; static void @@ -40,7 +40,7 @@ ao_ms5607_reset(void) { cmd = AO_MS5607_RESET; ao_ms5607_start(); - ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); + ao_spi_send(DATA_TO_XDATA(&cmd), 1, AO_MS5607_SPI_INDEX); ao_delay(AO_MS_TO_TICKS(10)); ao_ms5607_stop(); } @@ -69,17 +69,17 @@ ao_ms5607_crc(uint8_t *prom) } static void -ao_ms5607_prom_read(struct ao_ms5607_prom *prom) +ao_ms5607_prom_read(__xdata struct ao_ms5607_prom *prom) { - uint8_t addr; - uint8_t crc; - uint16_t *r; + uint8_t addr; + uint8_t crc; + __xdata uint16_t *r; - r = (uint16_t *) prom; + r = (__xdata uint16_t *) prom; for (addr = 0; addr < 8; addr++) { uint8_t cmd = AO_MS5607_PROM_READ(addr); ao_ms5607_start(); - ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); + ao_spi_send(DATA_TO_XDATA(&cmd), 1, AO_MS5607_SPI_INDEX); ao_spi_recv(r, 2, AO_MS5607_SPI_INDEX); ao_ms5607_stop(); r++; @@ -114,25 +114,25 @@ ao_ms5607_setup(void) ao_ms5607_prom_read(&ms5607_prom); } -static volatile uint8_t ao_ms5607_done; +static __xdata volatile uint8_t ao_ms5607_done; static void ao_ms5607_isr(void) { ao_exti_disable(AO_MS5607_MISO_PORT, AO_MS5607_MISO_PIN); ao_ms5607_done = 1; - ao_wakeup((void *) &ao_ms5607_done); + ao_wakeup((__xdata void *) &ao_ms5607_done); } static uint32_t ao_ms5607_get_sample(uint8_t cmd) { - uint8_t reply[3]; - uint8_t read; + __xdata uint8_t reply[3]; + __xdata uint8_t read; ao_ms5607_done = 0; ao_ms5607_start(); - ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); + ao_spi_send(DATA_TO_XDATA(&cmd), 1, AO_MS5607_SPI_INDEX); ao_exti_enable(AO_MS5607_MISO_PORT, AO_MS5607_MISO_PIN); @@ -179,10 +179,14 @@ ao_ms5607_sample(struct ao_ms5607_sample *sample) sample->temp = ao_ms5607_get_sample(AO_CONVERT_D2); } +#ifdef _CC1111_H_ +#include "ao_ms5607_convert_8051.c" +#else #include "ao_ms5607_convert.c" +#endif #if HAS_TASK -struct ao_ms5607_sample ao_ms5607_current; +__xdata struct ao_ms5607_sample ao_ms5607_current; static void ao_ms5607(void) @@ -191,10 +195,10 @@ ao_ms5607(void) for (;;) { ao_ms5607_sample(&ao_ms5607_current); - ao_arch_critical( - AO_DATA_PRESENT(AO_DATA_MS5607); - AO_DATA_WAIT(); - ); + ao_arch_block_interrupts(); + AO_DATA_PRESENT(AO_DATA_MS5607); + AO_DATA_WAIT(); + ao_arch_release_interrupts(); } } diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h index b2f98a59..3fd43fd4 100644 --- a/src/drivers/ao_ms5607.h +++ b/src/drivers/ao_ms5607.h @@ -56,7 +56,7 @@ struct ao_ms5607_value { int32_t temp; /* in °C * 100 */ }; -extern struct ao_ms5607_sample ao_ms5607_current; +extern __xdata struct ao_ms5607_sample ao_ms5607_current; void ao_ms5607_setup(void); diff --git a/src/drivers/ao_ms5607_convert_8051.c b/src/drivers/ao_ms5607_convert_8051.c new file mode 100644 index 00000000..f47972c9 --- /dev/null +++ b/src/drivers/ao_ms5607_convert_8051.c @@ -0,0 +1,60 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include + +void +ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value) +{ +#if 0 + int32_t dT; + int32_t TEMP; + int64_t OFF; + int64_t SENS; + + dT = sample->temp - ((int32_t) ms5607_prom.tref << 8); + + TEMP = 2000 + (((int64_t) dT * ms5607_prom.tempsens) >> 23); + +#if HAS_MS5611 + OFF = ((int64_t) ms5607_prom.off << 16) + (((int64_t) ms5607_prom.tco * dT) >> 7); + SENS = ((int64_t) ms5607_prom.sens << 15) + (((int64_t) ms5607_prom.tcs * dT) >> 8); +#else + OFF = ((int64_t) ms5607_prom.off << 17) + (((int64_t) ms5607_prom.tco * dT) >> 6); + SENS = ((int64_t) ms5607_prom.sens << 16) + (((int64_t) ms5607_prom.tcs * dT) >> 7); +#endif + + if (TEMP < 2000) { + int32_t T2 = ((int64_t) dT * (int64_t) dT) >> 31; + int32_t TEMPM = TEMP - 2000; + int64_t OFF2 = (61 * (int64_t) TEMPM * (int64_t) TEMPM) >> 4; + int64_t SENS2 = 2 * (int64_t) TEMPM * (int64_t) TEMPM; + if (TEMP < 1500) { + int32_t TEMPP = TEMP + 1500; + int64_t TEMPP2 = TEMPP * TEMPP; + OFF2 = OFF2 + 15 * TEMPP2; + SENS2 = SENS2 + 8 * TEMPP2; + } + TEMP -= T2; + OFF -= OFF2; + SENS -= SENS2; + } + + value->pres = ((((int64_t) sample->pres * SENS) >> 21) - OFF) >> 15; + value->temp = TEMP; +#endif +} diff --git a/src/telemini-v2.0/Makefile b/src/telemini-v2.0/Makefile new file mode 100644 index 00000000..afd529f0 --- /dev/null +++ b/src/telemini-v2.0/Makefile @@ -0,0 +1,108 @@ +# +# TeleMini build file +# + +TELEMINI_VER=2.0 +TELEMINI_DEF=2_0 + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ + cc1111.h \ + ao_product.h + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_convert.c \ + ao_flight.c \ + ao_kalman.c \ + ao_log.c \ + ao_log_mini.c \ + ao_mutex.c \ + ao_panic.c \ + ao_report.c \ + ao_sample.c \ + ao_stdio.c \ + ao_storage.c \ + ao_task.c \ + ao_telemetry.c \ + ao_freq.c + +CC1111_SRC = \ + ao_adc.c \ + ao_dma.c \ + ao_ignite.c \ + ao_led.c \ + ao_packet.c \ + ao_packet_slave.c \ + ao_radio.c \ + ao_romconfig.c \ + ao_string.c \ + ao_spi.c \ + ao_usb.c \ + ao_convert_pa.c \ + ao_data.c \ + ao_beep.c \ + ao_timer.c \ + _bp.c + +DRIVER_SRC = \ + ao_ms5607.c \ + ao_m25.c + +PRODUCT_SRC = \ + ao_telemini.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROGNAME = telemini-v$(TELEMINI_VER) +PROG = $(PROGNAME)-$(VERSION).ihx +PRODUCT=TeleMini-v$(TELEMINI_VER) +PRODUCT_DEF=-DTELEMINI_V_$(TELEMINI_DEF) +IDPRODUCT=0x000a + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: clean-cc1111 + +install: + +uninstall: + diff --git a/src/telemini-v2.0/ao_pins.h b/src/telemini-v2.0/ao_pins.h new file mode 100644 index 00000000..386c8dc3 --- /dev/null +++ b/src/telemini-v2.0/ao_pins.h @@ -0,0 +1,140 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_RADIO 1 + +#define HAS_FLIGHT 1 +#define HAS_USB 1 +#define USB_FORCE_FLIGHT_IDLE 1 +#define HAS_BEEP 1 +#define HAS_GPS 0 +#define HAS_SERIAL_1 0 +#define HAS_EEPROM 1 +#define HAS_LOG 1 +#define USE_INTERNAL_FLASH 0 +#define HAS_DBG 0 +#define PACKET_HAS_SLAVE 1 +#define USE_FAST_ASCENT_LOG 1 + +#define AO_LED_GREEN 1 +#define AO_LED_RED 2 +#define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) +#define HAS_EXTERNAL_TEMP 0 +#define HAS_ACCEL 0 +#define HAS_IGNITE 1 +#define HAS_IGNITE_REPORT 1 +#define HAS_MONITOR 0 + +/* + * SPI + */ + +#define SPI_CS_PORT P1 +#define SPI_CS_SEL P1SEL +#define SPI_CS_DIR P1DIR + +/* + * Flash + */ +#define AO_M25_SPI_CS_PORT SPI_CS_PORT +#define AO_M25_SPI_CS_MASK 0x04 /* cs_flash is P1_2 */ +#define M25_MAX_CHIPS 1 + +/* + * MS5607 + */ + +#define HAS_MS5607 1 +#define HAS_MS5611 0 +#define AO_MS5607_PRIVATE_PINS 0 +#define AO_MS5607_CS_PORT P1 +#define AO_MS5607_CS_PIN 3 +#define AO_MS5607_CS P1_3 +#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS_PIN) +#define AO_MS5607_MISO_PORT P0 +#define AO_MS5607_MISO_PIN 2 +#define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO_PIN) +#define AO_MS5607_SPI_INDEX 0 + +/* + * Igniters + */ +#define AO_IGNITER_PORT P2 +#define AO_IGNITER_DROGUE_PORT AO_IGNITER_PORT +#define AO_IGNITER_DROGUE P2_3 +#define AO_IGNITER_MAIN P2_4 +#define AO_IGNITER_DIR P2DIR +#define AO_IGNITER_DROGUE_BIT (1 << 3) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#define AO_IGNITER_DROGUE_PIN 3 +#define AO_IGNITER_MAIN_PIN 4 + +#define AO_IGNITER_DROGUE_PORT AO_IGNITER_PORT +#define AO_IGNITER_MAIN_PORT AO_IGNITER_PORT + +/* test these values with real igniters */ +#define AO_IGNITER_OPEN 1000 +#define AO_IGNITER_CLOSED 7000 +#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) +#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) + +#define AO_SEND_MINI + +/* + * ADC + */ + +#define HAS_ADC 1 +#define AO_ADC_FIRST_PIN 0 + +struct ao_adc { + int16_t sense_a; /* apogee continuity sense */ + int16_t sense_m; /* main continuity sense */ + int16_t v_batt; /* battery voltage */ +}; + +#define ao_data_count ao_adc_count + +#define AO_SENSE_DROGUE(p) ((p)->adc.sense_a) +#define AO_SENSE_MAIN(p) ((p)->adc.sense_m) + +#define AO_ADC_DUMP(p) \ + printf("tick: %5u apogee: %5d main: %5d batt: %5d\n", \ + (p)->tick, (p)->adc.sense_a, (p)->adc.sense_m, (p)->adc.v_batt) + +#define FETCH_ADC() \ + a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc); \ + switch (sequence) { \ + case 4: \ + a += 4; \ + sequence = 0; \ + break; \ + case 1: \ + a += 2; \ + sequence = 4; \ + break; \ + case 0: \ + sequence = 1; \ + break; \ + } \ + if (sequence) \ + ; + +#endif /* _AO_PINS_H_ */ diff --git a/src/telemini-v2.0/ao_telemini.c b/src/telemini-v2.0/ao_telemini.c new file mode 100644 index 00000000..84df2b8c --- /dev/null +++ b/src/telemini-v2.0/ao_telemini.c @@ -0,0 +1,54 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +__xdata uint8_t ao_force_freq; + +void +main(void) +{ + /* + * Reduce the transient on the ignite pins at startup by + * pulling the pins low as soon as possible at power up + */ + ao_ignite_set_pins(); + + ao_clock_init(); + + /* Turn on the red LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + + ao_task_init(); + + ao_timer_init(); + ao_adc_init(); + ao_cmd_init(); + ao_storage_init(); + ao_ms5607_init(); + ao_flight_init(); + ao_log_init(); + ao_report_init(); + ao_telemetry_init(); + ao_radio_init(); + ao_packet_slave_init(TRUE); + ao_igniter_init(); + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/test/Makefile b/src/test/Makefile index 75b1f848..9c304318 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -2,7 +2,7 @@ vpath % ..:../core:../drivers:../util:../micropeak:../aes PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_flight_test_mm \ ao_gps_test ao_gps_test_skytraq ao_gps_test_ublox ao_convert_test ao_convert_pa_test ao_fec_test \ - ao_aprs_test ao_micropeak_test ao_fat_test ao_aes_test + ao_aprs_test ao_micropeak_test ao_fat_test ao_aes_test ao_int64_test INCS=ao_kalman.h ao_ms5607.h ao_log.h ao_data.h altitude-pa.h altitude.h @@ -73,3 +73,6 @@ ao_fat_test: ao_fat_test.c ao_fat.c ao_bufio.c ao_aes_test: ao_aes_test.c ao_aes.c ao_aes_tables.c cc $(CFLAGS) -o $@ ao_aes_test.c + +ao_int64_test: ao_int64_test.c ao_int64.c ao_int64.h + cc $(CFLAGS) -o $@ ao_int64_test.c -- cgit v1.2.3 From 3114baef45803250a2e5cdd2ee4a9171f2045b0c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 22 May 2013 14:32:50 -0700 Subject: altos: Add 64-bit add/mul/shift for SDCC SDCC doeesn't provide a native 64-bit type (sigh), so implement the minimal operations necessary for the MS5607 conversion routine. Signed-off-by: Keith Packard --- src/core/ao_int64.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++ src/core/ao_int64.h | 39 ++++++++++++++++ src/test/ao_int64_test.c | 78 +++++++++++++++++++++++++++++++ 3 files changed, 236 insertions(+) create mode 100644 src/core/ao_int64.c create mode 100644 src/core/ao_int64.h create mode 100644 src/test/ao_int64_test.c (limited to 'src') diff --git a/src/core/ao_int64.c b/src/core/ao_int64.c new file mode 100644 index 00000000..1fe717dc --- /dev/null +++ b/src/core/ao_int64.c @@ -0,0 +1,119 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include + +void ao_plus64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b) { + uint32_t t; + + r->low = t = a->low + b->low; + r->high = a->high + b->high; + if (t < a->low) + r->high++; +} + +void ao_rshift64(ao_int64_t *r, ao_int64_t *a, uint8_t d) { + if (d < 32) { + r->high = (int32_t) a->high >> d; + r->low = a->low >> d; + if (d) + r->low |= a->high << (32 - d); + } else { + d &= 0x1f; + r->high = 0; + r->low = (int32_t) a->high >> d; + } +} + +void ao_lshift64(ao_int64_t *r, ao_int64_t *a, uint8_t d) { + if (d < 32) { + r->high = a->high << d; + r->low = a->low << d; + if (d) + r->high |= a->low >> (32 - d); + } else { + d &= 0x1f; + r->low = 0; + r->high = a->low << d; + } +} + +void ao_umul64(ao_int64_t *r, uint32_t a, uint32_t b) +{ + uint32_t r1; + uint32_t r2, r3, r4; + ao_int64_t s,t,u,v; + r1 = (uint32_t) (uint16_t) a * (uint16_t) b; + r2 = (uint32_t) (uint16_t) (a >> 16) * (uint16_t) b; + r3 = (uint32_t) (uint16_t) a * (uint16_t) (b >> 16); + r4 = (uint32_t) (uint16_t) (a >> 16) * (uint16_t) (b >> 16); + + s.low = r1; + s.high = r4; + + t.high = (uint32_t) r2 >> 16; + t.low = r2 << 16; + ao_plus64(&u, &s, &t); + + v.high = (int32_t) r3 >> 16; + v.low = r3 << 16; + ao_plus64(r, &u, &v); +} + +void ao_neg64(ao_int64_t *r, ao_int64_t *a) { + r->high = ~a->high; + r->low = ~a->low; + if (!++r->low) + r->high++; +} + +void ao_mul64(ao_int64_t *r, int32_t a, int32_t b) { + uint8_t negative = 0; + + if (a < 0) { + a = -a; + negative = 1; + } + if (b < 0) { + b = -b; + negative = !negative; + } + ao_umul64(r, a, b); + if (negative) + ao_neg64(r, r); +} + +void ao_umul64_16(ao_int64_t *r, ao_int64_t *a, uint16_t b) { + uint32_t low = a->low; + ao_umul64(r, (uint32_t) low >> 1, (uint32_t) b << 1); + if (low & 1) { + if ((uint32_t) (r->low += b) < (uint32_t) b) + r->high++; + } + r->high += a->high * b; +} + +void ao_mul64_16(ao_int64_t *r, ao_int64_t *a, uint16_t b) { + if ((int32_t) a->high < 0) { + ao_int64_t t; + + ao_neg64(&t, a); + ao_umul64_16(r, &t, b); + ao_neg64(r, r); + } else + ao_umul64_16(r, a, b); +} diff --git a/src/core/ao_int64.h b/src/core/ao_int64.h new file mode 100644 index 00000000..93aa87e4 --- /dev/null +++ b/src/core/ao_int64.h @@ -0,0 +1,39 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_INT64_H_ +#define _AO_INT64_H_ + +#include + +typedef struct { + uint32_t high; + uint32_t low; +} ao_int64_t; + +void ao_plus64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b); +void ao_rshift64(ao_int64_t *r, ao_int64_t *a, uint8_t d); +void ao_lshift64(ao_int64_t *r, ao_int64_t *a, uint8_t d); +void ao_mul64(ao_int64_t *r, int32_t a, int32_t b); +void ao_mul64_16(ao_int64_t *r, ao_int64_t *a, uint16_t b); + +#define ao_int64_init32(r, a) (((r)->high = 0), (r)->low = (a)) +#define ao_int64_init64(r, a, b) (((r)->high = (a)), (r)->low = (b)) + +#define ao_cast64(a) (((int64_t) (a)->high << 32) | (a)->low) + +#endif /* _AO_INT64_H_ */ diff --git a/src/test/ao_int64_test.c b/src/test/ao_int64_test.c new file mode 100644 index 00000000..67ba6ec5 --- /dev/null +++ b/src/test/ao_int64_test.c @@ -0,0 +1,78 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include + +int errors; + +#define test(op,func,a,b,ao_a,ao_b) do { \ + r = (a) op (b); \ + func(&ao_r, ao_a, ao_b); \ + c = ao_cast64(&ao_r); \ + if (c != r) { \ + printf ("trial %4d: %lld " #func " %lld = %lld (should be %lld)\n", \ + trial, (int64_t) (a), (int64_t) b, c, r); \ + ++errors; \ + } \ + } while (0) + + +void +do_test(int trial, int64_t a, int64_t b) +{ + int64_t r, c; + ao_int64_t ao_a, ao_b, ao_r; + + ao_int64_init64(&ao_a, a >> 32, a); + ao_int64_init64(&ao_b, b >> 32, b); + + test(+, ao_plus64, a, b, &ao_a, &ao_b); + test(*, ao_mul64,(int64_t) (int32_t) a, (int32_t) b, (int32_t) a, (int32_t) b); + test(>>, ao_rshift64, a, (uint8_t) b & 0x3f, &ao_a, (uint8_t) b & 0x3f); + test(<<, ao_lshift64, a, (uint8_t) b & 0x3f, &ao_a, (uint8_t) b & 0x3f); + test(*, ao_mul64_16, a, (uint16_t) b, &ao_a, (uint16_t) b); +} + +#define TESTS 10000000 + +static int64_t +random64(void) +{ + return (int64_t) random() + ((int64_t) random() << 31) /* + ((int64_t) random() << 33) */; +} + +int +main (int argc, char **argv) +{ + int i, start; + + if (argv[1]) + start = atoi(argv[1]); + else + start = 0; + srandom(1000); + for (i = 0; i < TESTS; i++) { + int64_t a = random64(); + int64_t b = random64(); + if (i >= start) + do_test(i, a, b); + } + return errors; +} -- cgit v1.2.3 From f7602ae566a5cbf2d2cbb1d68bad7e2d1177a33a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 22 May 2013 14:38:19 -0700 Subject: altos: Make 64x16 mul a bit faster the unsigned 32x32 multiply really does work, just use it Signed-off-by: Keith Packard --- src/core/ao_int64.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/core/ao_int64.c b/src/core/ao_int64.c index 1fe717dc..8e3caa24 100644 --- a/src/core/ao_int64.c +++ b/src/core/ao_int64.c @@ -86,11 +86,11 @@ void ao_mul64(ao_int64_t *r, int32_t a, int32_t b) { if (a < 0) { a = -a; - negative = 1; + negative = ~0; } if (b < 0) { b = -b; - negative = !negative; + negative = ~negative; } ao_umul64(r, a, b); if (negative) @@ -98,12 +98,7 @@ void ao_mul64(ao_int64_t *r, int32_t a, int32_t b) { } void ao_umul64_16(ao_int64_t *r, ao_int64_t *a, uint16_t b) { - uint32_t low = a->low; - ao_umul64(r, (uint32_t) low >> 1, (uint32_t) b << 1); - if (low & 1) { - if ((uint32_t) (r->low += b) < (uint32_t) b) - r->high++; - } + ao_umul64(r, a->low, b); r->high += a->high * b; } -- cgit v1.2.3 From 5ccd902d0fd2adc40c72982babb60fac4da6a087 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 22 May 2013 17:08:55 -0700 Subject: altos: Add 64x64 multiply. Test 64 ops for dest same as either source The test change is to ensure that the destination may be one of the 64 bit sources. Signed-off-by: Keith Packard --- src/core/ao_int64.c | 71 +++++++++++++++++++++++++++++++++++------------- src/core/ao_int64.h | 9 ++++-- src/test/ao_int64_test.c | 36 +++++++++++++++++++++--- 3 files changed, 91 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/core/ao_int64.c b/src/core/ao_int64.c index 8e3caa24..5307342d 100644 --- a/src/core/ao_int64.c +++ b/src/core/ao_int64.c @@ -20,39 +20,40 @@ void ao_plus64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b) { uint32_t t; - r->low = t = a->low + b->low; r->high = a->high + b->high; + t = a->low + b->low; if (t < a->low) r->high++; + r->low = t; } void ao_rshift64(ao_int64_t *r, ao_int64_t *a, uint8_t d) { if (d < 32) { - r->high = (int32_t) a->high >> d; r->low = a->low >> d; if (d) r->low |= a->high << (32 - d); + r->high = (int32_t) a->high >> d; } else { d &= 0x1f; - r->high = 0; r->low = (int32_t) a->high >> d; + r->high = 0; } } void ao_lshift64(ao_int64_t *r, ao_int64_t *a, uint8_t d) { if (d < 32) { r->high = a->high << d; - r->low = a->low << d; if (d) r->high |= a->low >> (32 - d); + r->low = a->low << d; } else { d &= 0x1f; - r->low = 0; r->high = a->low << d; + r->low = 0; } } -void ao_umul64(ao_int64_t *r, uint32_t a, uint32_t b) +static void ao_umul64_32_32(ao_int64_t *r, uint32_t a, uint32_t b) { uint32_t r1; uint32_t r2, r3, r4; @@ -65,11 +66,11 @@ void ao_umul64(ao_int64_t *r, uint32_t a, uint32_t b) s.low = r1; s.high = r4; - t.high = (uint32_t) r2 >> 16; + t.high = r2 >> 16; t.low = r2 << 16; ao_plus64(&u, &s, &t); - v.high = (int32_t) r3 >> 16; + v.high = r3 >> 16; v.low = r3 << 16; ao_plus64(r, &u, &v); } @@ -81,7 +82,7 @@ void ao_neg64(ao_int64_t *r, ao_int64_t *a) { r->high++; } -void ao_mul64(ao_int64_t *r, int32_t a, int32_t b) { +void ao_mul64_32_32(ao_int64_t *r, int32_t a, int32_t b) { uint8_t negative = 0; if (a < 0) { @@ -92,23 +93,55 @@ void ao_mul64(ao_int64_t *r, int32_t a, int32_t b) { b = -b; negative = ~negative; } - ao_umul64(r, a, b); + ao_umul64_32_32(r, a, b); if (negative) ao_neg64(r, r); } -void ao_umul64_16(ao_int64_t *r, ao_int64_t *a, uint16_t b) { - ao_umul64(r, a->low, b); - r->high += a->high * b; +static void ao_umul64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b) { + ao_int64_t r2, r3; + + ao_umul64_32_32(&r2, a->high, b->low); + ao_umul64_32_32(&r3, a->low, b->high); + ao_umul64_32_32(r, a->low, b->low); + + r->high += r2.low + r3.low; } -void ao_mul64_16(ao_int64_t *r, ao_int64_t *a, uint16_t b) { - if ((int32_t) a->high < 0) { - ao_int64_t t; +void ao_mul64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b) { + uint8_t negative = 0; + ao_int64_t ap, bp; - ao_neg64(&t, a); - ao_umul64_16(r, &t, b); + if (ao_int64_negativep(a)) { + ao_neg64(&ap, a); + a = ≈ + negative = ~0; + } + if (ao_int64_negativep(b)) { + ao_neg64(&bp, b); + b = &bp; + negative = ~negative; + } + ao_umul64(r, a, b); + if (negative) ao_neg64(r, r); +} + +void ao_umul64_64_16(ao_int64_t *r, ao_int64_t *a, uint16_t b) { + uint32_t h = a->high * b; + ao_umul64_32_32(r, a->low, b); + r->high += h; +} + +void ao_mul64_64_16(ao_int64_t *r, ao_int64_t *a, uint16_t b) { + ao_int64_t ap; + uint8_t negative = 0; + if ((int32_t) a->high < 0) { + ao_neg64(&ap, a); + a = ≈ + negative = ~0; } else - ao_umul64_16(r, a, b); + ao_umul64_64_16(r, a, b); + if (negative) + ao_neg64(r, r); } diff --git a/src/core/ao_int64.h b/src/core/ao_int64.h index 93aa87e4..e5eee823 100644 --- a/src/core/ao_int64.h +++ b/src/core/ao_int64.h @@ -26,14 +26,19 @@ typedef struct { } ao_int64_t; void ao_plus64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b); +void ao_neg64(ao_int64_t *r, ao_int64_t *a); +void ao_lshift64_16(ao_int64_t *r, uint16_t a, uint8_t d); void ao_rshift64(ao_int64_t *r, ao_int64_t *a, uint8_t d); void ao_lshift64(ao_int64_t *r, ao_int64_t *a, uint8_t d); -void ao_mul64(ao_int64_t *r, int32_t a, int32_t b); -void ao_mul64_16(ao_int64_t *r, ao_int64_t *a, uint16_t b); +void ao_mul64_64_64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b); +void ao_mul64_32_32(ao_int64_t *r, int32_t a, int32_t b); +void ao_mul64_64_16(ao_int64_t *r, ao_int64_t *a, uint16_t b); #define ao_int64_init32(r, a) (((r)->high = 0), (r)->low = (a)) #define ao_int64_init64(r, a, b) (((r)->high = (a)), (r)->low = (b)) #define ao_cast64(a) (((int64_t) (a)->high << 32) | (a)->low) +#define ao_int64_negativep(a) (((int32_t) (a)->high) < 0) + #endif /* _AO_INT64_H_ */ diff --git a/src/test/ao_int64_test.c b/src/test/ao_int64_test.c index 67ba6ec5..4c88b1a1 100644 --- a/src/test/ao_int64_test.c +++ b/src/test/ao_int64_test.c @@ -22,17 +22,35 @@ int errors; -#define test(op,func,a,b,ao_a,ao_b) do { \ +#define test_o(op,func,mod,a,b,ao_a,ao_b) do { \ r = (a) op (b); \ func(&ao_r, ao_a, ao_b); \ c = ao_cast64(&ao_r); \ if (c != r) { \ - printf ("trial %4d: %lld " #func " %lld = %lld (should be %lld)\n", \ + printf ("trial %4d: %lld " #func mod " %lld = %lld (should be %lld)\n", \ trial, (int64_t) (a), (int64_t) b, c, r); \ ++errors; \ } \ } while (0) +#define test(op,func,a,b,ao_a,ao_b) test_o(op,func,"",a,b,ao_a,ao_b) + +#define test_a(op,func,a,b,ao_a,ao_b) do { \ + ao_r = *ao_a; \ + test_o(op,func,"_a",a,b,&ao_r,ao_b); \ + } while (0) + +#define test_b(op,func,a,b,ao_a,ao_b) do { \ + ao_r = *ao_b; \ + test_o(op,func,"_b",a,b,ao_a,&ao_r); \ + } while (0) + +#define test_x(op,func,a,b,ao_a,ao_b) do { \ + ao_r = *ao_a; \ + test_o(op,func,"_xa",a,a,&ao_r,&ao_r); \ + ao_r = *ao_b; \ + test_o(op,func,"_xb",b,b,&ao_r,&ao_r); \ + } while (0) void do_test(int trial, int64_t a, int64_t b) @@ -44,10 +62,20 @@ do_test(int trial, int64_t a, int64_t b) ao_int64_init64(&ao_b, b >> 32, b); test(+, ao_plus64, a, b, &ao_a, &ao_b); - test(*, ao_mul64,(int64_t) (int32_t) a, (int32_t) b, (int32_t) a, (int32_t) b); + test_a(+, ao_plus64, a, b, &ao_a, &ao_b); + test_b(+, ao_plus64, a, b, &ao_a, &ao_b); + test_x(+, ao_plus64, a, b, &ao_a, &ao_b); + test(*, ao_mul64_32_32,(int64_t) (int32_t) a, (int32_t) b, (int32_t) a, (int32_t) b); + test(*, ao_mul64, a, b, &ao_a, &ao_b); + test_a(*, ao_mul64, a, b, &ao_a, &ao_b); + test_b(*, ao_mul64, a, b, &ao_a, &ao_b); + test_x(*, ao_mul64, a, b, &ao_a, &ao_b); + test(*, ao_mul64_64_16, a, (uint16_t) b, &ao_a, (uint16_t) b); + test_a(*, ao_mul64_64_16, a, (uint16_t) b, &ao_a, (uint16_t) b); test(>>, ao_rshift64, a, (uint8_t) b & 0x3f, &ao_a, (uint8_t) b & 0x3f); + test_a(>>, ao_rshift64, a, (uint8_t) b & 0x3f, &ao_a, (uint8_t) b & 0x3f); test(<<, ao_lshift64, a, (uint8_t) b & 0x3f, &ao_a, (uint8_t) b & 0x3f); - test(*, ao_mul64_16, a, (uint16_t) b, &ao_a, (uint16_t) b); + test_a(<<, ao_lshift64, a, (uint8_t) b & 0x3f, &ao_a, (uint8_t) b & 0x3f); } #define TESTS 10000000 -- cgit v1.2.3 From cb844328322fd7d9f4dafb58b322257a70b347e6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 22 May 2013 19:20:54 -0600 Subject: altos: Add 64-bit subtraction Signed-off-by: Keith Packard --- src/core/ao_int64.c | 11 +++++++++++ src/core/ao_int64.h | 2 ++ src/test/ao_int64_test.c | 4 ++++ 3 files changed, 17 insertions(+) (limited to 'src') diff --git a/src/core/ao_int64.c b/src/core/ao_int64.c index 5307342d..07cdb357 100644 --- a/src/core/ao_int64.c +++ b/src/core/ao_int64.c @@ -27,6 +27,17 @@ void ao_plus64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b) { r->low = t; } +void ao_minus64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b) { + uint32_t t; + + + r->high = a->high - b->high; + t = a->low - b->low; + if (t > a->low) + r->high--; + r->low = t; +} + void ao_rshift64(ao_int64_t *r, ao_int64_t *a, uint8_t d) { if (d < 32) { r->low = a->low >> d; diff --git a/src/core/ao_int64.h b/src/core/ao_int64.h index e5eee823..cf12f0d8 100644 --- a/src/core/ao_int64.h +++ b/src/core/ao_int64.h @@ -26,6 +26,7 @@ typedef struct { } ao_int64_t; void ao_plus64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b); +void ao_minus64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b); void ao_neg64(ao_int64_t *r, ao_int64_t *a); void ao_lshift64_16(ao_int64_t *r, uint16_t a, uint8_t d); void ao_rshift64(ao_int64_t *r, ao_int64_t *a, uint8_t d); @@ -33,6 +34,7 @@ void ao_lshift64(ao_int64_t *r, ao_int64_t *a, uint8_t d); void ao_mul64_64_64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b); void ao_mul64_32_32(ao_int64_t *r, int32_t a, int32_t b); void ao_mul64_64_16(ao_int64_t *r, ao_int64_t *a, uint16_t b); +void ao_mul64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b); #define ao_int64_init32(r, a) (((r)->high = 0), (r)->low = (a)) #define ao_int64_init64(r, a, b) (((r)->high = (a)), (r)->low = (b)) diff --git a/src/test/ao_int64_test.c b/src/test/ao_int64_test.c index 4c88b1a1..c26a63b0 100644 --- a/src/test/ao_int64_test.c +++ b/src/test/ao_int64_test.c @@ -65,6 +65,10 @@ do_test(int trial, int64_t a, int64_t b) test_a(+, ao_plus64, a, b, &ao_a, &ao_b); test_b(+, ao_plus64, a, b, &ao_a, &ao_b); test_x(+, ao_plus64, a, b, &ao_a, &ao_b); + test(-, ao_minus64, a, b, &ao_a, &ao_b); + test_a(-, ao_minus64, a, b, &ao_a, &ao_b); + test_b(-, ao_minus64, a, b, &ao_a, &ao_b); + test_x(-, ao_minus64, a, b, &ao_a, &ao_b); test(*, ao_mul64_32_32,(int64_t) (int32_t) a, (int32_t) b, (int32_t) a, (int32_t) b); test(*, ao_mul64, a, b, &ao_a, &ao_b); test_a(*, ao_mul64, a, b, &ao_a, &ao_b); -- cgit v1.2.3 From 56911f27376b0fe91a464e369bb8aa1531b3c7dc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 23 May 2013 02:17:51 -0600 Subject: altos: Make TeleMini v2.0 fit Mash lots of storage locations and code around to shrink stuff down to size Signed-off-by: Keith Packard --- src/core/ao.h | 2 +- src/core/ao_cmd.c | 4 +- src/core/ao_int64.c | 88 ++++++++++++------------ src/core/ao_int64.h | 22 +++--- src/core/ao_kalman.c | 4 +- src/core/ao_log_telem.c | 2 +- src/core/ao_sample.h | 4 +- src/core/ao_task.h | 3 + src/drivers/ao_ms5607.c | 4 +- src/drivers/ao_ms5607.h | 7 +- src/drivers/ao_ms5607_convert_8051.c | 126 ++++++++++++++++++++++++++++------- src/telemini-v2.0/Makefile | 9 ++- src/telemini-v2.0/ao_pins.h | 2 + src/test/Makefile | 6 +- src/test/ao_int64_test.c | 5 ++ src/test/ao_ms5607_convert_test.c | 96 ++++++++++++++++++++++++++ 16 files changed, 289 insertions(+), 95 deletions(-) create mode 100644 src/test/ao_ms5607_convert_test.c (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index caa0ec19..e7320327 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -182,7 +182,7 @@ void ao_cmd_hex(void); void -ao_cmd_decimal(void); +ao_cmd_decimal(void) __reentrant; /* Read a single hex nibble off stdin. */ uint8_t diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 5113548b..4ebaa607 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -206,9 +206,9 @@ ao_cmd_hex(void) } void -ao_cmd_decimal(void) +ao_cmd_decimal(void) __reentrant { - __pdata uint8_t r = ao_cmd_lex_error; + uint8_t r = ao_cmd_lex_error; ao_cmd_lex_u32 = 0; ao_cmd_white(); diff --git a/src/core/ao_int64.c b/src/core/ao_int64.c index 07cdb357..aa23dbe0 100644 --- a/src/core/ao_int64.c +++ b/src/core/ao_int64.c @@ -17,8 +17,10 @@ #include -void ao_plus64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b) { - uint32_t t; +__pdata ao_int64_t *__data ao_64r, *__data ao_64a, *__data ao_64b; + +void ao_plus64(__pdata ao_int64_t *r, __pdata ao_int64_t *a, __pdata ao_int64_t *b) __FATTR { + __LOCAL uint32_t t; r->high = a->high + b->high; t = a->low + b->low; @@ -27,9 +29,8 @@ void ao_plus64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b) { r->low = t; } -void ao_minus64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b) { - uint32_t t; - +void ao_minus64(__pdata ao_int64_t *r, __pdata ao_int64_t *a, __pdata ao_int64_t *b) __FATTR { + __LOCAL uint32_t t; r->high = a->high - b->high; t = a->low - b->low; @@ -38,7 +39,7 @@ void ao_minus64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b) { r->low = t; } -void ao_rshift64(ao_int64_t *r, ao_int64_t *a, uint8_t d) { +void ao_rshift64(__pdata ao_int64_t *r, __pdata ao_int64_t *a, uint8_t d) __FATTR { if (d < 32) { r->low = a->low >> d; if (d) @@ -51,7 +52,7 @@ void ao_rshift64(ao_int64_t *r, ao_int64_t *a, uint8_t d) { } } -void ao_lshift64(ao_int64_t *r, ao_int64_t *a, uint8_t d) { +void ao_lshift64(__pdata ao_int64_t *r, __pdata ao_int64_t *a, uint8_t d) __FATTR { if (d < 32) { r->high = a->high << d; if (d) @@ -64,53 +65,49 @@ void ao_lshift64(ao_int64_t *r, ao_int64_t *a, uint8_t d) { } } -static void ao_umul64_32_32(ao_int64_t *r, uint32_t a, uint32_t b) -{ - uint32_t r1; - uint32_t r2, r3, r4; - ao_int64_t s,t,u,v; - r1 = (uint32_t) (uint16_t) a * (uint16_t) b; - r2 = (uint32_t) (uint16_t) (a >> 16) * (uint16_t) b; - r3 = (uint32_t) (uint16_t) a * (uint16_t) (b >> 16); - r4 = (uint32_t) (uint16_t) (a >> 16) * (uint16_t) (b >> 16); - - s.low = r1; - s.high = r4; - - t.high = r2 >> 16; - t.low = r2 << 16; - ao_plus64(&u, &s, &t); - - v.high = r3 >> 16; - v.low = r3 << 16; - ao_plus64(r, &u, &v); +static void ao_umul64_32_32(__ARG ao_int64_t *r, uint32_t a, uint32_t b) __reentrant { + __LOCAL uint32_t s; + __LOCAL ao_int64_t t; + r->low = (uint32_t) (uint16_t) a * (uint16_t) b; + r->high = (uint32_t) (uint16_t) (a >> 16) * (uint16_t) (b >> 16); + + s = (uint32_t) (uint16_t) (a >> 16) * (uint16_t) b; + + t.high = s >> 16; + t.low = s << 16; + ao_plus64(r, r, &t); + + s = (uint32_t) (uint16_t) a * (uint16_t) (b >> 16); + + t.high = s >> 16; + t.low = s << 16; + ao_plus64(r, r, &t); } -void ao_neg64(ao_int64_t *r, ao_int64_t *a) { +void ao_neg64(__pdata ao_int64_t *r, __pdata ao_int64_t *a) __FATTR { r->high = ~a->high; - r->low = ~a->low; - if (!++r->low) + if (!(r->low = ~a->low + 1)) r->high++; } -void ao_mul64_32_32(ao_int64_t *r, int32_t a, int32_t b) { +void ao_mul64_32_32(__ARG ao_int64_t *r, int32_t a, int32_t b) __FATTR { uint8_t negative = 0; if (a < 0) { a = -a; - negative = ~0; + ++negative; } if (b < 0) { b = -b; - negative = ~negative; + --negative; } ao_umul64_32_32(r, a, b); if (negative) ao_neg64(r, r); } -static void ao_umul64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b) { - ao_int64_t r2, r3; +static void ao_umul64(__ARG ao_int64_t *r, __ARG ao_int64_t *a, __ARG ao_int64_t *b) __reentrant { + __LOCAL ao_int64_t r2, r3; ao_umul64_32_32(&r2, a->high, b->low); ao_umul64_32_32(&r3, a->low, b->high); @@ -119,38 +116,41 @@ static void ao_umul64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b) { r->high += r2.low + r3.low; } -void ao_mul64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b) { +static __ARG ao_int64_t ap, bp; + +void ao_mul64(__ARG ao_int64_t *r, __ARG ao_int64_t *a, __ARG ao_int64_t *b) __FATTR { uint8_t negative = 0; - ao_int64_t ap, bp; if (ao_int64_negativep(a)) { ao_neg64(&ap, a); a = ≈ - negative = ~0; + ++negative; } if (ao_int64_negativep(b)) { ao_neg64(&bp, b); b = &bp; - negative = ~negative; + --negative; } ao_umul64(r, a, b); if (negative) ao_neg64(r, r); } -void ao_umul64_64_16(ao_int64_t *r, ao_int64_t *a, uint16_t b) { - uint32_t h = a->high * b; +static void ao_umul64_64_16(__ARG ao_int64_t *r, __ARG ao_int64_t *a, uint16_t b) __reentrant { + __LOCAL uint32_t h; + + h = a->high * b; ao_umul64_32_32(r, a->low, b); r->high += h; } -void ao_mul64_64_16(ao_int64_t *r, ao_int64_t *a, uint16_t b) { - ao_int64_t ap; +void ao_mul64_64_16(__ARG ao_int64_t *r, __ARG ao_int64_t *a, __ARG uint16_t b) __FATTR { uint8_t negative = 0; + if ((int32_t) a->high < 0) { ao_neg64(&ap, a); a = ≈ - negative = ~0; + negative++; } else ao_umul64_64_16(r, a, b); if (negative) diff --git a/src/core/ao_int64.h b/src/core/ao_int64.h index cf12f0d8..b16db58c 100644 --- a/src/core/ao_int64.h +++ b/src/core/ao_int64.h @@ -25,16 +25,18 @@ typedef struct { uint32_t low; } ao_int64_t; -void ao_plus64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b); -void ao_minus64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b); -void ao_neg64(ao_int64_t *r, ao_int64_t *a); -void ao_lshift64_16(ao_int64_t *r, uint16_t a, uint8_t d); -void ao_rshift64(ao_int64_t *r, ao_int64_t *a, uint8_t d); -void ao_lshift64(ao_int64_t *r, ao_int64_t *a, uint8_t d); -void ao_mul64_64_64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b); -void ao_mul64_32_32(ao_int64_t *r, int32_t a, int32_t b); -void ao_mul64_64_16(ao_int64_t *r, ao_int64_t *a, uint16_t b); -void ao_mul64(ao_int64_t *r, ao_int64_t *a, ao_int64_t *b); +#define __FATTR +#define __ARG __pdata +#define __LOCAL static __pdata + +void ao_plus64(__pdata ao_int64_t *ao_64r, __pdata ao_int64_t *ao_64a, __pdata ao_int64_t *ao_64b) __FATTR; +void ao_minus64(__pdata ao_int64_t *ao_64r, __pdata ao_int64_t *ao_64a, __pdata ao_int64_t *ao_64b) __FATTR; +void ao_neg64(__pdata ao_int64_t *ao_64r, __pdata ao_int64_t *ao_64a) __FATTR; +void ao_rshift64(__pdata ao_int64_t *ao_64r, __pdata ao_int64_t *ao_64a, uint8_t d) __FATTR; +void ao_lshift64(__pdata ao_int64_t *ao_64r, __pdata ao_int64_t *ao_64a, uint8_t d) __FATTR; +void ao_mul64_32_32(__ARG ao_int64_t *r, __ARG int32_t a, __ARG int32_t b) __FATTR; +void ao_mul64_64_16(__ARG ao_int64_t *r, __ARG ao_int64_t *a, __ARG uint16_t b) __FATTR; +void ao_mul64(__ARG ao_int64_t * __ARG r, __ARG ao_int64_t * __ARG a, __ARG ao_int64_t *__ARG b) __FATTR; #define ao_int64_init32(r, a) (((r)->high = 0), (r)->low = (a)) #define ao_int64_init64(r, a, b) (((r)->high = (a)), (r)->low = (b)) diff --git a/src/core/ao_kalman.c b/src/core/ao_kalman.c index 59ffd8b2..762b2c0a 100644 --- a/src/core/ao_kalman.c +++ b/src/core/ao_kalman.c @@ -40,9 +40,9 @@ static __pdata int32_t ao_k_accel; __pdata int16_t ao_height; __pdata int16_t ao_speed; __pdata int16_t ao_accel; -__pdata int16_t ao_max_height; +__xdata int16_t ao_max_height; static __pdata int32_t ao_avg_height_scaled; -__pdata int16_t ao_avg_height; +__xdata int16_t ao_avg_height; __pdata int16_t ao_error_h; __pdata int16_t ao_error_h_sq_avg; diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index 23ebf7dd..095aca37 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -23,7 +23,7 @@ __code uint8_t ao_log_format = AO_LOG_FORMAT_TELEMETRY; static __data uint8_t ao_log_monitor_pos; __pdata enum ao_flight_state ao_flight_state; -__pdata int16_t ao_max_height; /* max of ao_height */ +__xdata int16_t ao_max_height; /* max of ao_height */ __pdata int16_t sense_d, sense_m; __pdata uint8_t ao_igniter_present; diff --git a/src/core/ao_sample.h b/src/core/ao_sample.h index a2dac979..5bd29536 100644 --- a/src/core/ao_sample.h +++ b/src/core/ao_sample.h @@ -136,8 +136,8 @@ uint8_t ao_sample(void); extern __pdata int16_t ao_height; /* meters */ extern __pdata int16_t ao_speed; /* m/s * 16 */ extern __pdata int16_t ao_accel; /* m/s² * 16 */ -extern __pdata int16_t ao_max_height; /* max of ao_height */ -extern __pdata int16_t ao_avg_height; /* running average of height */ +extern __xdata int16_t ao_max_height; /* max of ao_height */ +extern __xdata int16_t ao_avg_height; /* running average of height */ extern __pdata int16_t ao_error_h; extern __pdata int16_t ao_error_h_sq_avg; diff --git a/src/core/ao_task.h b/src/core/ao_task.h index 1a4b5b6b..e3a311ed 100644 --- a/src/core/ao_task.h +++ b/src/core/ao_task.h @@ -45,7 +45,10 @@ struct ao_task { #endif }; +#ifndef AO_NUM_TASKS #define AO_NUM_TASKS 16 /* maximum number of tasks */ +#endif + #define AO_NO_TASK 0 /* no task id */ extern __xdata struct ao_task * __xdata ao_tasks[AO_NUM_TASKS]; diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 5259b265..4b4403a7 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -173,7 +173,7 @@ ao_ms5607_get_sample(uint8_t cmd) { #define AO_CONVERT_D2 token_evaluator(AO_MS5607_CONVERT_D2_, AO_MS5607_TEMP_OVERSAMPLE) void -ao_ms5607_sample(struct ao_ms5607_sample *sample) +ao_ms5607_sample(__xdata struct ao_ms5607_sample *sample) { sample->pres = ao_ms5607_get_sample(AO_CONVERT_D1); sample->temp = ao_ms5607_get_sample(AO_CONVERT_D2); @@ -220,7 +220,7 @@ ao_ms5607_info(void) static void ao_ms5607_dump(void) { - struct ao_ms5607_value value; + __xdata struct ao_ms5607_value value; ao_ms5607_convert(&ao_ms5607_current, &value); printf ("Pressure: %8u %8d\n", ao_ms5607_current.pres, value.pres); diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h index 3fd43fd4..206efd64 100644 --- a/src/drivers/ao_ms5607.h +++ b/src/drivers/ao_ms5607.h @@ -68,12 +68,13 @@ void ao_ms5607_info(void); void -ao_ms5607_sample(struct ao_ms5607_sample *sample); +ao_ms5607_sample(__xdata struct ao_ms5607_sample *sample); void -ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value); +ao_ms5607_convert(__xdata struct ao_ms5607_sample *sample, + __xdata struct ao_ms5607_value *value); void -ao_ms5607_get_prom(struct ao_ms5607_prom *prom); +ao_ms5607_get_prom(__data struct ao_ms5607_prom *prom); #endif /* _AO_MS5607_H_ */ diff --git a/src/drivers/ao_ms5607_convert_8051.c b/src/drivers/ao_ms5607_convert_8051.c index f47972c9..f3a48c46 100644 --- a/src/drivers/ao_ms5607_convert_8051.c +++ b/src/drivers/ao_ms5607_convert_8051.c @@ -16,45 +16,121 @@ */ #include +#include + +#if HAS_MS5611 +#define SHIFT_OFF 16 +#define SHIFT_TCO 7 +#define SHIFT_SENS 15 +#define SHFIT_TCS 8 +#else +#define SHIFT_OFF 17 +#define SHIFT_TCO 6 +#define SHIFT_SENS 16 +#define SHIFT_TCS 7 +#endif void -ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value) +ao_ms5607_convert(__xdata struct ao_ms5607_sample *sample, + __xdata struct ao_ms5607_value *value) { -#if 0 - int32_t dT; - int32_t TEMP; - int64_t OFF; - int64_t SENS; + __LOCAL int32_t dT; + __LOCAL int32_t TEMP; + __LOCAL ao_int64_t OFF; + __LOCAL ao_int64_t SENS; + __LOCAL ao_int64_t a; dT = sample->temp - ((int32_t) ms5607_prom.tref << 8); - TEMP = 2000 + (((int64_t) dT * ms5607_prom.tempsens) >> 23); + /* TEMP = 2000 + (((int64_t) dT * ms5607_prom.tempsens) >> 23); */ + ao_mul64_32_32(&a, dT, ms5607_prom.tempsens); + ao_rshift64(&a, &a, 23); + TEMP = 2000 + a.low; + /* */ -#if HAS_MS5611 - OFF = ((int64_t) ms5607_prom.off << 16) + (((int64_t) ms5607_prom.tco * dT) >> 7); - SENS = ((int64_t) ms5607_prom.sens << 15) + (((int64_t) ms5607_prom.tcs * dT) >> 8); + /* OFF = ((int64_t) ms5607_prom.off << SHIFT_OFF) + (((int64_t) ms5607_prom.tco * dT) >> SHIFT_TCO);*/ +#if SHIFT_OFF > 16 + OFF.high = ms5607_prom.off >> (32 - SHIFT_OFF); #else - OFF = ((int64_t) ms5607_prom.off << 17) + (((int64_t) ms5607_prom.tco * dT) >> 6); - SENS = ((int64_t) ms5607_prom.sens << 16) + (((int64_t) ms5607_prom.tcs * dT) >> 7); + OFF.high = 0; #endif + OFF.low = (uint32_t) ms5607_prom.off << SHIFT_OFF; + ao_mul64_32_32(&a, ms5607_prom.tco, dT); + ao_rshift64(&a, &a, SHIFT_TCO); + ao_plus64(&OFF, &OFF, &a); + /**/ + + /* SENS = ((int64_t) ms5607_prom.sens << SHIFT_SENS) + (((int64_t) ms5607_prom.tcs * dT) >> SHIFT_TCS); */ + SENS.high = 0; + SENS.low = (uint32_t) ms5607_prom.sens << SHIFT_SENS; + ao_mul64_32_32(&a, ms5607_prom.tcs, dT); + ao_rshift64(&a, &a, SHIFT_TCS); + ao_plus64(&SENS, &SENS, &a); + /**/ if (TEMP < 2000) { - int32_t T2 = ((int64_t) dT * (int64_t) dT) >> 31; - int32_t TEMPM = TEMP - 2000; - int64_t OFF2 = (61 * (int64_t) TEMPM * (int64_t) TEMPM) >> 4; - int64_t SENS2 = 2 * (int64_t) TEMPM * (int64_t) TEMPM; - if (TEMP < 1500) { - int32_t TEMPP = TEMP + 1500; - int64_t TEMPP2 = TEMPP * TEMPP; - OFF2 = OFF2 + 15 * TEMPP2; - SENS2 = SENS2 + 8 * TEMPP2; + __LOCAL int32_t T2; + __LOCAL int32_t TEMPM; + __LOCAL ao_int64_t OFF2; + __LOCAL ao_int64_t SENS2; + + /* T2 = ((int64_t) dT * (int64_t) dT) >> 31; */ + ao_mul64_32_32(&a, dT, dT); + T2 = (a.low >> 31) | (a.high << 1); + /**/ + + TEMPM = TEMP - 2000; + + /* OFF2 = (61 * (int64_t) TEMPM * (int64_t) TEMPM) >> 4; */ + ao_mul64_32_32(&OFF2, TEMPM, TEMPM); + ao_mul64_64_16(&OFF2, &OFF2, 61); + ao_rshift64(&OFF2, &OFF2, 4); + /**/ + + /* SENS2 = 2 * (int64_t) TEMPM * (int64_t) TEMPM; */ + ao_mul64_32_32(&SENS2, TEMPM, TEMPM); + ao_lshift64(&SENS2, &SENS2, 1); + /**/ + + if (TEMP < -1500) { + int32_t TEMPP; + int32_t TEMPP2; + + TEMPP = TEMP + 1500; + TEMPP2 = TEMPP * TEMPP; + + /* OFF2 = OFF2 + 15 * TEMPP2; */ + ao_mul64_32_32(&a, 15, TEMPP2); + ao_plus64(&OFF2, &OFF2, &a); + /**/ + + /* SENS2 = SENS2 + 8 * TEMPP2; */ + a.high = 0; + a.low = TEMPP2; + ao_lshift64(&a, &a, 3); + ao_plus64(&SENS2, &SENS2, &a); + /**/ } TEMP -= T2; - OFF -= OFF2; - SENS -= SENS2; + + /* OFF -= OFF2; */ + ao_minus64(&OFF, &OFF, &OFF2); + /**/ + + /* SENS -= SENS2; */ + ao_minus64(&SENS, &SENS, &SENS2); + /**/ } - value->pres = ((((int64_t) sample->pres * SENS) >> 21) - OFF) >> 15; + /* value->pres = ((((int64_t) sample->pres * SENS) >> 21) - OFF) >> 15; */ + a.high = 0; + a.low = sample->pres; + ao_mul64(&a, &a, &SENS); + ao_rshift64(&a, &a, 21); + ao_minus64(&a, &a, &OFF); + ao_rshift64(&a, &a, 15); + value->pres = a.low; + /**/ + value->temp = TEMP; -#endif } diff --git a/src/telemini-v2.0/Makefile b/src/telemini-v2.0/Makefile index afd529f0..984406a9 100644 --- a/src/telemini-v2.0/Makefile +++ b/src/telemini-v2.0/Makefile @@ -19,7 +19,11 @@ INC = \ ao_arch.h \ ao_arch_funcs.h \ cc1111.h \ - ao_product.h + ao_ms5607.h \ + ao_ms5607_convert_8051.c \ + ao_product.h \ + ao_int64.h \ + ao_sample.h CORE_SRC = \ ao_cmd.c \ @@ -37,7 +41,8 @@ CORE_SRC = \ ao_storage.c \ ao_task.c \ ao_telemetry.c \ - ao_freq.c + ao_freq.c \ + ao_int64.c CC1111_SRC = \ ao_adc.c \ diff --git a/src/telemini-v2.0/ao_pins.h b/src/telemini-v2.0/ao_pins.h index 386c8dc3..fad029e2 100644 --- a/src/telemini-v2.0/ao_pins.h +++ b/src/telemini-v2.0/ao_pins.h @@ -115,6 +115,8 @@ struct ao_adc { #define AO_SENSE_DROGUE(p) ((p)->adc.sense_a) #define AO_SENSE_MAIN(p) ((p)->adc.sense_m) +#define AO_NUM_TASKS 10 + #define AO_ADC_DUMP(p) \ printf("tick: %5u apogee: %5d main: %5d batt: %5d\n", \ (p)->tick, (p)->adc.sense_a, (p)->adc.sense_m, (p)->adc.v_batt) diff --git a/src/test/Makefile b/src/test/Makefile index 9c304318..5eee6bbb 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -2,7 +2,8 @@ vpath % ..:../core:../drivers:../util:../micropeak:../aes PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_flight_test_mm \ ao_gps_test ao_gps_test_skytraq ao_gps_test_ublox ao_convert_test ao_convert_pa_test ao_fec_test \ - ao_aprs_test ao_micropeak_test ao_fat_test ao_aes_test ao_int64_test + ao_aprs_test ao_micropeak_test ao_fat_test ao_aes_test ao_int64_test \ + ao_ms5607_convert_test INCS=ao_kalman.h ao_ms5607.h ao_log.h ao_data.h altitude-pa.h altitude.h @@ -76,3 +77,6 @@ ao_aes_test: ao_aes_test.c ao_aes.c ao_aes_tables.c ao_int64_test: ao_int64_test.c ao_int64.c ao_int64.h cc $(CFLAGS) -o $@ ao_int64_test.c + +ao_ms5607_convert_test: ao_ms5607_convert_test.c ao_ms5607_convert_8051.c ao_int64.c ao_int64.h + cc $(CFLAGS) -o $@ ao_ms5607_convert_test.c diff --git a/src/test/ao_int64_test.c b/src/test/ao_int64_test.c index c26a63b0..8557a1c7 100644 --- a/src/test/ao_int64_test.c +++ b/src/test/ao_int64_test.c @@ -15,6 +15,11 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#define __data +#define __pdata +#define __xdata +#define __reentrant + #include #include #include diff --git a/src/test/ao_ms5607_convert_test.c b/src/test/ao_ms5607_convert_test.c new file mode 100644 index 00000000..ad593204 --- /dev/null +++ b/src/test/ao_ms5607_convert_test.c @@ -0,0 +1,96 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#define __xdata +#define __data +#define __pdata +#define __reentrant + +#include +#include + +struct ao_ms5607_prom ms5607_prom = { + 0x002c, + 0xa6e0, + 0x988e, + 0x6814, + 0x5eff, + 0x8468, + 0x6c86, + 0xa271, +}; + +int32_t D1_mm = 6179630; +int32_t D2_mm = 8933155; + +#include +#define ao_ms5607_convert ao_ms5607_convert_8051 +#include +#include +#include +#include + +struct ao_ms5607_sample ao_sample = { + 6179630, + 8933155 +}; + +int errors; + +void test(int trial, struct ao_ms5607_sample *sample) +{ + struct ao_ms5607_value value, value_8051; + + ao_ms5607_convert(sample, &value); + ao_ms5607_convert_8051(sample, &value_8051); + if (value.temp != value_8051.temp || value.pres != value_8051.pres) { + ++errors; + printf ("trial %d: %d, %d -> %d, %d (should be %d, %d)\n", + trial, + sample->pres, sample->temp, + value_8051.pres, value_8051.temp, + value.pres, value.temp); + } +} + +#define TESTS 10000000 + +#include + +static int32_t rand24(void) { return random() & 0xffffff; } + +int +main(int argc, char **argv) +{ + struct ao_ms5607_sample sample; + int i, start; + + if (argv[1]) + start = atoi(argv[1]); + else + start = 0; + + srandom(10000); + test(-1, &ao_sample); + for (i = 0; i < TESTS; i++) { + sample.pres = rand24(); + sample.temp = rand24(); + if (i >= start) + test(i, &sample); + } + return errors; +} -- cgit v1.2.3 From 2c2bbfd9a1a4b9de42cf566f21f179ff5ede0419 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 23 May 2013 16:52:59 -0600 Subject: altos: Add exti and spi to telemini-v2.0 No longer builds like this Signed-off-by: Keith Packard --- src/telemini-v2.0/Makefile | 1 + src/telemini-v2.0/ao_pins.h | 2 ++ src/telemini-v2.0/ao_telemini.c | 2 ++ 3 files changed, 5 insertions(+) (limited to 'src') diff --git a/src/telemini-v2.0/Makefile b/src/telemini-v2.0/Makefile index 984406a9..adb1256c 100644 --- a/src/telemini-v2.0/Makefile +++ b/src/telemini-v2.0/Makefile @@ -60,6 +60,7 @@ CC1111_SRC = \ ao_data.c \ ao_beep.c \ ao_timer.c \ + ao_exti.c \ _bp.c DRIVER_SRC = \ diff --git a/src/telemini-v2.0/ao_pins.h b/src/telemini-v2.0/ao_pins.h index fad029e2..c27f47f1 100644 --- a/src/telemini-v2.0/ao_pins.h +++ b/src/telemini-v2.0/ao_pins.h @@ -46,6 +46,8 @@ * SPI */ +#define HAS_SPI_0 1 +#define HAS_SPI_1 1 #define SPI_CS_PORT P1 #define SPI_CS_SEL P1SEL #define SPI_CS_DIR P1DIR diff --git a/src/telemini-v2.0/ao_telemini.c b/src/telemini-v2.0/ao_telemini.c index 84df2b8c..b85ce8c8 100644 --- a/src/telemini-v2.0/ao_telemini.c +++ b/src/telemini-v2.0/ao_telemini.c @@ -41,6 +41,8 @@ main(void) ao_adc_init(); ao_cmd_init(); ao_storage_init(); + ao_exti_init(); + ao_spi_init(); ao_ms5607_init(); ao_flight_init(); ao_log_init(); -- cgit v1.2.3 From 312f6194a4bc75473cb0d61a6d58b66fb1f7c068 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 12 Jun 2013 00:43:31 -0700 Subject: altos/teletiny-v2.0: Support multiple SPI busses on CC1111 Needed for TeleMini v2.0 Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 5 + src/cc1111/ao_arch_funcs.h | 82 +++++++++---- src/cc1111/ao_spi.c | 257 +++++++++++++++++++++++++--------------- src/drivers/ao_ms5607.c | 2 +- src/telemini-v2.0/ao_pins.h | 4 + src/telemini-v2.0/ao_telemini.c | 1 + 6 files changed, 231 insertions(+), 120 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 9097557f..34235b08 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -321,4 +321,9 @@ void ao_serial1_tx_isr(void) ao_arch_interrupt(14); #endif +#if HAS_EXTI_0 +void +ao_p0_isr(void) __interrupt(13); +#endif + #endif /* _AO_ARCH_H_ */ diff --git a/src/cc1111/ao_arch_funcs.h b/src/cc1111/ao_arch_funcs.h index 8f1cc094..ae184108 100644 --- a/src/cc1111/ao_arch_funcs.h +++ b/src/cc1111/ao_arch_funcs.h @@ -19,46 +19,74 @@ * ao_spi.c */ -extern __xdata uint8_t ao_spi_mutex; +#if !HAS_SPI_0 && !HAS_SPI_1 +#define HAS_SPI_0 1 +#define SPI_0_ALT_2 1 +#endif + +#if HAS_SPI_0 && HAS_SPI_1 +#define MULTI_SPI 1 +#define N_SPI 2 +#else +#define MULTI_SPI 0 +#define N_SPI 1 +#endif + +extern __xdata uint8_t ao_spi_mutex[N_SPI]; + +#if MULTI_SPI +#define ao_spi_get(bus) ao_mutex_get(&ao_spi_mutex[bus]) +#define ao_spi_put(bus) ao_mutex_put(&ao_spi_mutex[bus]) +#else +#define ao_spi_get(bus) ao_mutex_get(&ao_spi_mutex[0]) +#define ao_spi_put(bus) ao_mutex_put(&ao_spi_mutex[0]) +#endif #define AO_SPI_SPEED_FAST 17 #define AO_SPI_SPEED_200kHz 13 -#define ao_spi_set_speed(speed) (U0GCR = (UxGCR_CPOL_NEGATIVE | \ - UxGCR_CPHA_FIRST_EDGE | \ - UxGCR_ORDER_MSB | \ - ((speed) << UxGCR_BAUD_E_SHIFT))) +#if MULTI_SPI +#define ao_spi_set_speed(bus,speed) (*(bus ? &U1GCR : &U0GCR) =(UxGCR_CPOL_NEGATIVE | \ + UxGCR_CPHA_FIRST_EDGE | \ + UxGCR_ORDER_MSB | \ + ((speed) << UxGCR_BAUD_E_SHIFT))) +#else +#define ao_spi_set_speed(bus,speed) (U0GCR = (UxGCR_CPOL_NEGATIVE | \ + UxGCR_CPHA_FIRST_EDGE | \ + UxGCR_ORDER_MSB | \ + ((speed) << UxGCR_BAUD_E_SHIFT))) +#endif #define ao_spi_get_slave(bus) do { \ - ao_mutex_get(&ao_spi_mutex); \ - ao_spi_set_speed(AO_SPI_SPEED_FAST); \ + ao_spi_get(bus); \ + ao_spi_set_speed(bus,AO_SPI_SPEED_FAST); \ } while (0) #define ao_spi_put_slave(bus) do { \ - ao_mutex_put(&ao_spi_mutex); \ + ao_spi_put(bus); \ } while (0) #define ao_spi_get_mask(reg,mask,bus,speed) do { \ - ao_mutex_get(&ao_spi_mutex); \ - ao_spi_set_speed(speed); \ + ao_spi_get(bus); \ + ao_spi_set_speed(bus,speed); \ (reg) &= ~(mask); \ } while (0) #define ao_spi_put_mask(reg,mask,bus) do { \ (reg) |= (mask); \ - ao_mutex_put(&ao_spi_mutex); \ + ao_spi_put(bus); \ } while (0) #define ao_spi_get_bit(reg,bit,pin,bus,speed) do { \ - ao_mutex_get(&ao_spi_mutex); \ - ao_spi_set_speed(speed); \ - pin = 0; \ + ao_spi_get(bus); \ + ao_spi_set_speed(bus,speed); \ + pin = 0; \ } while (0) #define ao_spi_put_bit(reg,bit,pin,bus) do { \ pin = 1; \ - ao_mutex_put(&ao_spi_mutex); \ + ao_spi_put(bus); \ } while (0) @@ -68,6 +96,13 @@ extern __xdata uint8_t ao_spi_mutex; * from chip select low to chip select high */ +#if MULTI_SPI +void +ao_spi_send(void __xdata *block, uint16_t len, uint8_t bus) __reentrant; + +void +ao_spi_recv(void __xdata *block, uint16_t len, uint8_t bus) __reentrant; +#else void ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant; @@ -76,6 +111,7 @@ ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant; #define ao_spi_send(block, len, bus) ao_spi_send_bus(block, len) #define ao_spi_recv(block, len, bus) ao_spi_recv_bus(block, len) +#endif #if AO_SPI_SLAVE void @@ -88,10 +124,15 @@ ao_spi_recv_wait(void); void ao_spi_init(void); -#define ao_spi_init_cs(port, mask) do { \ - SPI_CS_PORT |= mask; \ - SPI_CS_DIR |= mask; \ - SPI_CS_SEL &= ~mask; \ +#define token_paster(x,y) x ## y +#define token_paster3(x,y,z) x ## y ## z +#define token_evaluator(x,y) token_paster(x,y) +#define token_evaluator3(x,y,z) token_paster3(x,y,z) + +#define ao_spi_init_cs(port, mask) do { \ + port |= mask; \ + token_evaluator(port,DIR) |= mask; \ + token_evaluator(port,SEL) &= ~mask; \ } while (0) #define cc1111_enable_output(port,dir,sel,pin,bit,v) do { \ @@ -102,7 +143,6 @@ ao_spi_init(void); #define disable_unreachable _Pragma("disable_warning 126") -#define token_paster(x,y) x ## y -#define token_evaluator(x,y) token_paster(x,y) #define ao_enable_output(port,bit,pin,v) cc1111_enable_output(port,token_evaluator(port,DIR), token_evaluator(port,SEL), pin, bit, v) #define ao_gpio_set(port, bit, pin, v) ((pin) = (v)) + diff --git a/src/cc1111/ao_spi.c b/src/cc1111/ao_spi.c index cdef6bda..fb08f3f5 100644 --- a/src/cc1111/ao_spi.c +++ b/src/cc1111/ao_spi.c @@ -18,10 +18,6 @@ #include "ao.h" /* Default pin usage for existing Altus Metrum devices */ -#if !HAS_SPI_0 && !HAS_SPI_1 -#define HAS_SPI_0 1 -#define SPI_0_ALT_2 1 -#endif #ifndef SPI_CONST #define SPI_CONST 0xff @@ -61,62 +57,107 @@ */ #if HAS_SPI_0 -#define SPI_CSR U0CSR -#define SPI_BUF U0DBUFXADDR -#define SPI_BAUD U0BAUD -#define SPI_GCR U0GCR -#define SPI_CFG_MASK PERCFG_U0CFG_ALT_MASK -#define SPI_DMA_TX DMA_CFG0_TRIGGER_UTX0 -#define SPI_DMA_RX DMA_CFG0_TRIGGER_URX0 +#define SPI_BUF_0 &U0DBUFXADDR +#define SPI_CSR_0 U0CSR +#define SPI_BAUD_0 U0BAUD +#define SPI_GCR_0 U0GCR +#define SPI_CFG_MASK_0 PERCFG_U0CFG_ALT_MASK +#define SPI_DMA_TX_0 DMA_CFG0_TRIGGER_UTX0 +#define SPI_DMA_RX_0 DMA_CFG0_TRIGGER_URX0 #if SPI_0_ALT_1 -#define SPI_CFG PERCFG_U0CFG_ALT_1 -#define SPI_SEL P0SEL -#define SPI_BITS (1 << 3) | (1 << 2) | (1 << 5) -#define SPI_CSS_BIT (1 << 4) +#define SPI_CFG_0 PERCFG_U0CFG_ALT_1 +#define SPI_SEL_0 P0SEL +#define SPI_BITS_0 (1 << 3) | (1 << 2) | (1 << 5) +#define SPI_CSS_BIT_0 (1 << 4) #endif #if SPI_0_ALT_2 -#define SPI_CFG PERCFG_U0CFG_ALT_2 -#define SPI_SEL P1SEL -#define SPI_PRI P2SEL_PRI3P1_USART0 -#define SPI_BITS (1 << 5) | (1 << 4) | (1 << 3) -#define SPI_CSS_BIT (1 << 2) +#define SPI_CFG_0 PERCFG_U0CFG_ALT_2 +#define SPI_SEL_0 P1SEL +#define SPI_PRI_0 P2SEL_PRI3P1_USART0 +#define SPI_BITS_0 (1 << 5) | (1 << 4) | (1 << 3) +#define SPI_CSS_BIT_0 (1 << 2) #endif #endif #if HAS_SPI_1 -#define SPI_CSR U1CSR -#define SPI_BUF U1DBUFXADDR -#define SPI_BAUD U1BAUD -#define SPI_GCR U1GCR -#define SPI_CFG_MASK PERCFG_U1CFG_ALT_MASK -#define SPI_DMA_TX DMA_CFG0_TRIGGER_UTX1 -#define SPI_DMA_RX DMA_CFG0_TRIGGER_URX1 +#define SPI_BUF_1 &U1DBUFXADDR +#define SPI_CSR_1 U1CSR +#define SPI_BAUD_1 U1BAUD +#define SPI_GCR_1 U1GCR +#define SPI_CFG_MASK_1 PERCFG_U1CFG_ALT_MASK +#define SPI_DMA_TX_1 DMA_CFG0_TRIGGER_UTX1 +#define SPI_DMA_RX_1 DMA_CFG0_TRIGGER_URX1 #if SPI_1_ALT_1 -#define SPI_CFG PERCFG_U1CFG_ALT_1 -#define SPI_SEL P0SEL -#define SPI_BITS (1 << 4) | (1 << 5) | (1 << 3) -#define SPI_CSS_BIT (1 << 2) +#define SPI_CFG_1 PERCFG_U1CFG_ALT_1 +#define SPI_SEL_1 P0SEL +#define SPI_BITS_1 (1 << 4) | (1 << 5) | (1 << 3) +#define SPI_CSS_BIT_1 (1 << 2) #endif #if SPI_1_ALT_2 -#define SPI_CFG PERCFG_U1CFG_ALT_2 -#define SPI_SEL P1SEL -#define SPI_PRI P2SEL_PRI3P1_USART1 -#define SPI_BITS (1 << 6) | (1 << 7) | (1 << 5) -#define SPI_CSS_BIT (1 << 4) +#define SPI_CFG_1 PERCFG_U1CFG_ALT_2 +#define SPI_SEL_1 P1SEL +#define SPI_PRI_1 P2SEL_PRI3P1_USART1 +#define SPI_BITS_1 (1 << 6) | (1 << 7) | (1 << 5) +#define SPI_CSS_BIT_1 (1 << 4) #endif #endif +#if MULTI_SPI + +#define SPI_BUF(bus) ((bus) ? SPI_BUF_1 : SPI_BUF_0) +#define SPI_CSR(bus) ((bus) ? SPI_CSR_1 : SPI_CSR_0) +#define SPI_BAUD(bus) ((bus) ? SPI_BAUD_1 : SPI_BAUD_0) +#define SPI_GCR(bus) ((bus) ? SPI_GCR_1 : SPI_GCR_0) +#define SPI_CFG_MASK(bus) ((bus) ? SPI_CFG_MASK_1 : SPI_CFG_MASK_0) +#define SPI_DMA_TX(bus) ((bus) ? SPI_DMA_TX_1 : SPI_DMA_TX_0) +#define SPI_DMA_RX(bus) ((bus) ? SPI_DMA_RX_1 : SPI_DMA_RX_0) +#define SPI_CFG(bus) ((bus) ? SPI_CFG_1 : SPI_CFG_0) +#define SPI_SEL(bus) ((bus) ? SPI_SEL_1 : SPI_SEL_0) +#define SPI_BITS(bus) ((bus) ? SPI_BITS_1 : SPI_BITS_0) +#define SPI_CSS_BIT(bus) ((bus) ? SPI_CSS_BIT_1 : SPI_CSS_BIT_0) + +#else + +#if HAS_SPI_0 +#define SPI_BUF(bus) SPI_BUF_0 +#define SPI_CSR(bus) SPI_CSR_0 +#define SPI_BAUD(bus) SPI_BAUD_0 +#define SPI_GCR(bus) SPI_GCR_0 +#define SPI_CFG_MASK(bus) SPI_CFG_MASK_0 +#define SPI_DMA_TX(bus) SPI_DMA_TX_0 +#define SPI_DMA_RX(bus) SPI_DMA_RX_0 +#define SPI_CFG(bus) SPI_CFG_0 +#define SPI_SEL(bus) SPI_SEL_0 +#define SPI_BITS(bus) SPI_BITS_0 +#define SPI_CSS_BIT(bus) SPI_CSS_BIT_0 +#endif +#if HAS_SPI_1 +#define SPI_BUF(bus) SPI_BUF_1 +#define SPI_CSR(bus) SPI_CSR_1 +#define SPI_BAUD(bus) SPI_BAUD_1 +#define SPI_GCR(bus) SPI_GCR_1 +#define SPI_CFG_MASK(bus) SPI_CFG_MASK_1 +#define SPI_DMA_TX(bus) SPI_DMA_TX_1 +#define SPI_DMA_RX(bus) SPI_DMA_RX_1 +#define SPI_CFG(bus) SPI_CFG_1 +#define SPI_SEL(bus) SPI_SEL_1 +#define SPI_BITS(bus) SPI_BITS_1 +#define SPI_CSS_BIT(bus) SPI_CSS_BIT_1 +#endif + +#endif /* MULTI_SPI */ + #if AO_SPI_SLAVE -#define CSS SPI_CSS_BIT +#define CSS(bus) SPI_CSS_BIT(bus) #define UxCSR_DIRECTION UxCSR_SLAVE #else -#define CSS 0 +#define CSS(bus) 0 #define UxCSR_DIRECTION UxCSR_MASTER #endif @@ -124,15 +165,16 @@ * operation, from CS low to CS high. This means that any SPI * user must protect the SPI bus with this mutex */ -__xdata uint8_t ao_spi_mutex; -__xdata uint8_t ao_spi_dma_in_done; -__xdata uint8_t ao_spi_dma_out_done; +__xdata uint8_t ao_spi_mutex[N_SPI]; +__xdata uint8_t ao_spi_dma_in_done[N_SPI]; +__xdata uint8_t ao_spi_dma_out_done[N_SPI]; -uint8_t ao_spi_dma_out_id; -uint8_t ao_spi_dma_in_id; +uint8_t ao_spi_dma_out_id[N_SPI]; +uint8_t ao_spi_dma_in_id[N_SPI]; static __xdata uint8_t ao_spi_const; + /* Send bytes over SPI. * * This sets up two DMA engines, one writing the data and another reading @@ -140,45 +182,52 @@ static __xdata uint8_t ao_spi_const; * is complete, as the transmit register is double buffered and hence signals * completion one byte before the transfer is actually complete */ +#if MULTI_SPI +void +ao_spi_send(void __xdata *block, uint16_t len, uint8_t bus) __reentrant +#else void ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant +#define bus 0 +#endif { - ao_dma_set_transfer(ao_spi_dma_in_id, - &SPI_BUF, + ao_dma_set_transfer(ao_spi_dma_in_id[bus], + SPI_BUF(bus), &ao_spi_const, len, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | - SPI_DMA_RX, + SPI_DMA_RX(bus), DMA_CFG1_SRCINC_0 | DMA_CFG1_DESTINC_0 | DMA_CFG1_PRIORITY_NORMAL); - ao_dma_set_transfer(ao_spi_dma_out_id, + ao_dma_set_transfer(ao_spi_dma_out_id[bus], block, - &SPI_BUF, + SPI_BUF(bus), len, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | - SPI_DMA_TX, + SPI_DMA_TX(bus), DMA_CFG1_SRCINC_1 | DMA_CFG1_DESTINC_0 | DMA_CFG1_PRIORITY_NORMAL); - ao_dma_start(ao_spi_dma_in_id); - ao_dma_start(ao_spi_dma_out_id); - ao_dma_trigger(ao_spi_dma_out_id); + ao_dma_start(ao_spi_dma_in_id[bus]); + ao_dma_start(ao_spi_dma_out_id[bus]); + ao_dma_trigger(ao_spi_dma_out_id[bus]); #if !AO_SPI_SLAVE - __critical while (!ao_spi_dma_in_done) - ao_sleep(&ao_spi_dma_in_done); + __critical while (!ao_spi_dma_in_done[bus]) + ao_sleep(&ao_spi_dma_in_done[bus]); #endif +#undef bus } #if AO_SPI_SLAVE void ao_spi_send_wait(void) { - __critical while (!ao_spi_dma_in_done) - ao_sleep(&ao_spi_dma_in_done); + __critical while (!ao_spi_dma_in_done[0]) + ao_sleep(&ao_spi_dma_in_done[0]); } #endif @@ -188,16 +237,22 @@ ao_spi_send_wait(void) * writing constant values to the SPI transmitter as that is what * clocks the data coming in. */ +#if MULTI_SPI +void +ao_spi_recv(void __xdata *block, uint16_t len, uint8_t bus) __reentrant +#else void ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant +#define bus 0 +#endif { - ao_dma_set_transfer(ao_spi_dma_in_id, - &SPI_BUF, + ao_dma_set_transfer(ao_spi_dma_in_id[bus], + SPI_BUF(bus), block, len, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | - SPI_DMA_RX, + SPI_DMA_RX(bus), DMA_CFG1_SRCINC_0 | DMA_CFG1_DESTINC_1 | DMA_CFG1_PRIORITY_NORMAL); @@ -205,24 +260,24 @@ ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant ao_spi_const = SPI_CONST; #if !AO_SPI_SLAVE - ao_dma_set_transfer(ao_spi_dma_out_id, + ao_dma_set_transfer(ao_spi_dma_out_id[bus], &ao_spi_const, - &SPI_BUF, + SPI_BUF(bus), len, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | - SPI_DMA_TX, + SPI_DMA_TX(bus), DMA_CFG1_SRCINC_0 | DMA_CFG1_DESTINC_0 | DMA_CFG1_PRIORITY_NORMAL); #endif - ao_dma_start(ao_spi_dma_in_id); + ao_dma_start(ao_spi_dma_in_id[bus]); #if !AO_SPI_SLAVE - ao_dma_start(ao_spi_dma_out_id); - ao_dma_trigger(ao_spi_dma_out_id); - __critical while (!ao_spi_dma_in_done) - ao_sleep(&ao_spi_dma_in_done); + ao_dma_start(ao_spi_dma_out_id[bus]); + ao_dma_trigger(ao_spi_dma_out_id[bus]); + __critical while (!ao_spi_dma_in_done[bus]) + ao_sleep(&ao_spi_dma_in_done[bus]); #endif } @@ -230,17 +285,43 @@ ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant void ao_spi_recv_wait(void) { - __critical while (!ao_spi_dma_in_done) - ao_sleep(&ao_spi_dma_in_done); + __critical while (!ao_spi_dma_in_done[0]) + ao_sleep(&ao_spi_dma_in_done[0]); } #endif +/* Set up the USART. + * + * SPI master/slave mode + */ +/* Set the baud rate and signal parameters + * + * The cc1111 is limited to a 24/8 MHz SPI clock. + * Every peripheral I've ever seen goes faster than that, + * so set the clock to 3MHz (BAUD_E 17, BAUD_M 0) + */ +#define SPI_INIT(bus,o) do { \ + /* Set up the USART pin assignment */ \ + PERCFG = (PERCFG & ~SPI_CFG_MASK(bus)) | SPI_CFG(bus); \ + \ + /* Make the SPI pins be controlled by the USART peripheral */ \ + SPI_SEL(bus) |= SPI_BITS(bus) | CSS(bus); \ + SPI_CSR(bus) = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_DIRECTION); \ + SPI_BAUD(bus) = 0; \ + SPI_GCR(bus) = (UxGCR_CPOL_NEGATIVE | \ + UxGCR_CPHA_FIRST_EDGE | \ + UxGCR_ORDER_MSB | \ + (17 << UxGCR_BAUD_E_SHIFT)); \ + /* Set up OUT DMA */ \ + ao_spi_dma_out_id[o] = ao_dma_alloc(&ao_spi_dma_out_done[o]); \ + \ + /* Set up IN DMA */ \ + ao_spi_dma_in_id[o] = ao_dma_alloc(&ao_spi_dma_in_done[o]); \ + } while (0) + void ao_spi_init(void) { - /* Set up the USART pin assignment */ - PERCFG = (PERCFG & ~SPI_CFG_MASK) | SPI_CFG; - /* Ensure that SPI USART takes precidence over the other USART * for pins that they share */ @@ -248,30 +329,10 @@ ao_spi_init(void) P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | SPI_PRI; #endif - /* Make the SPI pins be controlled by the USART peripheral */ - SPI_SEL |= SPI_BITS | CSS; - - /* Set up OUT DMA */ - ao_spi_dma_out_id = ao_dma_alloc(&ao_spi_dma_out_done); - - /* Set up IN DMA */ - ao_spi_dma_in_id = ao_dma_alloc(&ao_spi_dma_in_done); - - /* Set up the USART. - * - * SPI master/slave mode - */ - SPI_CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_DIRECTION); - - /* Set the baud rate and signal parameters - * - * The cc1111 is limited to a 24/8 MHz SPI clock. - * Every peripheral I've ever seen goes faster than that, - * so set the clock to 3MHz (BAUD_E 17, BAUD_M 0) - */ - SPI_BAUD = 0; - SPI_GCR = (UxGCR_CPOL_NEGATIVE | - UxGCR_CPHA_FIRST_EDGE | - UxGCR_ORDER_MSB | - (17 << UxGCR_BAUD_E_SHIFT)); +#if HAS_SPI_0 + SPI_INIT(0, 0); +#endif +#if HAS_SPI_1 + SPI_INIT(1, MULTI_SPI); +#endif } diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 4b4403a7..7c1acdd1 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -22,7 +22,7 @@ #if HAS_MS5607 || HAS_MS5611 static __xdata struct ao_ms5607_prom ms5607_prom; -static uint8_t ms5607_configured; +static __xdata uint8_t ms5607_configured; static void ao_ms5607_start(void) { diff --git a/src/telemini-v2.0/ao_pins.h b/src/telemini-v2.0/ao_pins.h index c27f47f1..9ecd076e 100644 --- a/src/telemini-v2.0/ao_pins.h +++ b/src/telemini-v2.0/ao_pins.h @@ -47,7 +47,9 @@ */ #define HAS_SPI_0 1 +#define SPI_0_ALT_1 1 #define HAS_SPI_1 1 +#define SPI_1_ALT_2 1 #define SPI_CS_PORT P1 #define SPI_CS_SEL P1SEL #define SPI_CS_DIR P1DIR @@ -55,6 +57,7 @@ /* * Flash */ +#define AO_M25_SPI_BUS 1 #define AO_M25_SPI_CS_PORT SPI_CS_PORT #define AO_M25_SPI_CS_MASK 0x04 /* cs_flash is P1_2 */ #define M25_MAX_CHIPS 1 @@ -74,6 +77,7 @@ #define AO_MS5607_MISO_PIN 2 #define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO_PIN) #define AO_MS5607_SPI_INDEX 0 +#define HAS_EXTI_0 1 /* * Igniters diff --git a/src/telemini-v2.0/ao_telemini.c b/src/telemini-v2.0/ao_telemini.c index b85ce8c8..6b7545fb 100644 --- a/src/telemini-v2.0/ao_telemini.c +++ b/src/telemini-v2.0/ao_telemini.c @@ -17,6 +17,7 @@ #include "ao.h" #include "ao_pins.h" +#include __xdata uint8_t ao_force_freq; -- cgit v1.2.3 From e72147e215a982ce701099626424b9a856ac9d09 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 25 Aug 2013 22:33:30 -0700 Subject: altos: Changes required by cc1111 multi-spi support These drivers got missed Signed-off-by: Keith Packard --- src/drivers/ao_74hc165.c | 6 +++--- src/drivers/ao_pca9922.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_74hc165.c b/src/drivers/ao_74hc165.c index f24fce37..143f4e3f 100644 --- a/src/drivers/ao_74hc165.c +++ b/src/drivers/ao_74hc165.c @@ -27,12 +27,12 @@ uint8_t ao_74hc165_read(void) { static __xdata state; - ao_mutex_get(&ao_spi_mutex); - ao_spi_set_speed(AO_SPI_SPEED_FAST); + ao_spi_get(AO_74HC165_SPI_BUS); + ao_spi_set_speed(AO_74HC165_SPI_BUS, AO_SPI_SPEED_FAST); AO_74HC165_CS = 1; ao_spi_recv(&state, 1, AO_74HC165_SPI_BUS); AO_74HC165_CS = 0; - ao_mutex_put(&ao_spi_mutex); + ao_spi_put(AO_74HC165_SPI_BUS); return state; } diff --git a/src/drivers/ao_pca9922.c b/src/drivers/ao_pca9922.c index fe070b88..d376b968 100644 --- a/src/drivers/ao_pca9922.c +++ b/src/drivers/ao_pca9922.c @@ -30,12 +30,12 @@ ao_led_apply(void) /* Don't try the SPI bus during initialization */ if (!ao_cur_task) return; - ao_mutex_get(&ao_spi_mutex); - ao_spi_set_speed(AO_SPI_SPEED_FAST); + ao_spi_get(AO_PCA9922_SPI_BUS); + ao_spi_set_speed(AO_PCA9922_SPI_BUS,AO_SPI_SPEED_FAST); AO_PCA9922_CS = 1; ao_spi_send(&ao_led_state, 1, AO_PCA9922_SPI_BUS); AO_PCA9922_CS = 0; - ao_mutex_put(&ao_spi_mutex); + ao_spi_put(AO_PCA9922_SPI_BUS); } void -- cgit v1.2.3 From 377a44cbfd5c8a659d2fecabb154726717a41900 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 25 Aug 2013 22:34:09 -0700 Subject: altos: Build more products by default We keep creating more hardware... Signed-off-by: Keith Packard --- src/Makefile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index ee76c325..af2630fc 100644 --- a/src/Makefile +++ b/src/Makefile @@ -20,7 +20,8 @@ SDCCDIRS=\ telemini-v1.0 \ telebt-v1.0 \ teleterra-v0.2 teleshield-v0.1 \ - telefire-v0.1 telefire-v0.2 + telefire-v0.1 telefire-v0.2 \ + telemini-v2.0 AVRDIRS=\ telescience-v0.1 telescience-pwm micropeak @@ -29,10 +30,11 @@ ARMDIRS=\ telemega-v0.1 telemega-v0.1/flash-loader \ telemega-v0.3 telemega-v0.3/flash-loader \ megadongle-v0.1 megadongle-v0.1/flash-loader \ - telegps-v0.1 telegps-v0.1/flash-loader \ + telegps-v0.3 telegps-v0.3/flash-loader \ stm-bringup stm-demo \ telelco-v0.2 telelco-v0.2/flash-loader \ - telescience-v0.2 telescience-v0.2/flash-loader + telescience-v0.2 telescience-v0.2/flash-loader \ + easymini-v0.1 easymini-v0.1/flash-loader ARMM0DIRS=\ easymini-v0.1 -- cgit v1.2.3 From 2380a4b9bd69629c78eec0a87ff8681a0524d8d2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Aug 2013 16:41:33 -0700 Subject: cc1111: Rework ADC configuration a bit, fix Tm V2 ADC usage The Tm v2 ADC code was not actually fetching and storing the ADC conversion values. Signed-off-by: Keith Packard --- src/cc1111/ao_adc.c | 35 +++++++++++++++++------------------ src/telemini-v2.0/ao_pins.h | 11 ++++++++--- 2 files changed, 25 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index 6cc08399..1523f94a 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -20,22 +20,22 @@ volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; volatile __data uint8_t ao_data_head; +#ifdef TELENANO_V_0_1 +# define AO_ADC_FIRST_PIN 1 +#endif + +#if HAS_ACCEL_REF +# define AO_ADC_FIRST_PIN 2 +#endif + #ifndef AO_ADC_FIRST_PIN -#define AO_ADC_FIRST_PIN 0 +# define AO_ADC_FIRST_PIN 0 #endif void ao_adc_poll(void) { -#if HAS_ACCEL_REF - ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 2; -#else -# ifdef TELENANO_V_0_1 - ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 1; -# else ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | AO_ADC_FIRST_PIN; -# endif -#endif } void @@ -141,6 +141,7 @@ ao_adc_isr(void) __interrupt 1 if (sequence) { /* Start next conversion */ ADCCON3 = sequence; + return; } #endif /* telemini || telenano */ @@ -148,8 +149,10 @@ ao_adc_isr(void) __interrupt 1 a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.sense[0] + sequence - AO_ADC_FIRST_PIN); a[0] = ADCL; a[1] = ADCH; - if (sequence < 5) + if (sequence < 5) { ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | (sequence + 1); + return; + } #define GOT_ADC #endif /* TELEFIRE_V_0_1 */ @@ -157,8 +160,6 @@ ao_adc_isr(void) __interrupt 1 a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.batt); a[0] = ADCL; a[1] = ADCH; - if (0) - ; #define GOT_ADC #endif @@ -171,12 +172,10 @@ ao_adc_isr(void) __interrupt 1 #error No known ADC configuration set #endif - else { - /* record this conversion series */ - ao_data_ring[ao_data_head].tick = ao_time(); - ao_data_head = ao_data_ring_next(ao_data_head); - ao_wakeup(DATA_TO_XDATA(&ao_data_head)); - } + /* record this conversion series */ + ao_data_ring[ao_data_head].tick = ao_time(); + ao_data_head = ao_data_ring_next(ao_data_head); + ao_wakeup(DATA_TO_XDATA(&ao_data_head)); } static void diff --git a/src/telemini-v2.0/ao_pins.h b/src/telemini-v2.0/ao_pins.h index 9ecd076e..fac6c535 100644 --- a/src/telemini-v2.0/ao_pins.h +++ b/src/telemini-v2.0/ao_pins.h @@ -31,7 +31,6 @@ #define USE_INTERNAL_FLASH 0 #define HAS_DBG 0 #define PACKET_HAS_SLAVE 1 -#define USE_FAST_ASCENT_LOG 1 #define AO_LED_GREEN 1 #define AO_LED_RED 2 @@ -127,6 +126,8 @@ struct ao_adc { printf("tick: %5u apogee: %5d main: %5d batt: %5d\n", \ (p)->tick, (p)->adc.sense_a, (p)->adc.sense_m, (p)->adc.v_batt) +#define AO_ADC_PINS ((1 << 0) | (1 << 1) | (1 << 4)) + #define FETCH_ADC() \ a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc); \ switch (sequence) { \ @@ -142,7 +143,11 @@ struct ao_adc { sequence = 1; \ break; \ } \ - if (sequence) \ - ; + a[0] = ADCL; \ + a[1] = ADCH; \ + if (sequence) { \ + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | sequence; \ + return; \ + } #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From af9f9cf0c21630562c74fae41773319229bf44d3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Aug 2013 16:42:45 -0700 Subject: cc1111: Hacky pin interrupt support. Only useful for TeleMini v2 This code is designed to support the MS5607 MISO interrupt bits. Signed-off-by: Keith Packard --- src/cc1111/ao_exti.c | 33 ++++++++++++++++++++++++++++++ src/cc1111/ao_exti.h | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 90 insertions(+) create mode 100644 src/cc1111/ao_exti.c create mode 100644 src/cc1111/ao_exti.h (limited to 'src') diff --git a/src/cc1111/ao_exti.c b/src/cc1111/ao_exti.c new file mode 100644 index 00000000..537f6252 --- /dev/null +++ b/src/cc1111/ao_exti.c @@ -0,0 +1,33 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +#if HAS_EXTI_0 +__xdata void (*ao_int_callback)(void); + +void +ao_p0_isr(void) __interrupt(13) +{ + if (P0IF && (P0IFG & (AO_MS5607_MISO_MASK))) { + (*ao_int_callback)(); + } + P0IFG = 0; + P0IF = 0; +} +#endif diff --git a/src/cc1111/ao_exti.h b/src/cc1111/ao_exti.h new file mode 100644 index 00000000..00d99a2b --- /dev/null +++ b/src/cc1111/ao_exti.h @@ -0,0 +1,57 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_EXTI_H_ +#define _AO_EXTI_H_ + +#define AO_EXTI_MODE_RISING 1 +#define AO_EXTI_MODE_FALLING 2 +#define AO_EXTI_MODE_PULL_UP 4 +#define AO_EXTI_MODE_PULL_DOWN 8 +#define AO_EXTI_PRIORITY_LOW 16 +#define AO_EXTI_PRIORITY_MED 0 +#define AO_EXTI_PRIORITY_HIGH 32 + +extern void (*ao_int_callback)(void); + +#define ao_exti_setup(gpio, pin, mode, callback) do { \ + ao_int_callback = callback; \ + } while (0) + +#define ao_exti_set_mode(gpio, pin, mode) do { \ + } while (0) + +#define ao_exti_set_callback(port, pin, callback) do { \ + ao_int_callback = callback; \ + } while (0) + +#define ao_exti_init() do { \ + IEN1 &= IEN1_P0IE; \ + PICTL |= PICTL_P0IENL; \ + } while (0) + +#define ao_exti_enable(port, pin) do { \ + P0IFG &= ~(1 << pin); \ + P0IF = 0; \ + IEN1 |= IEN1_P0IE; \ + } while (0) + +#define ao_exti_disable(port, pin) do { \ + IEN1 &= ~IEN1_P0IE; \ + } while (0) + +#endif /* _AO_EXTI_H_ */ -- cgit v1.2.3 From 8ca98dc8c868c47c372d6b666c36e691fa402824 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Aug 2013 17:15:55 -0700 Subject: altos: Get telemini to copy current MS5607 state to ring. The ADC code is responsible for actually inserting the non-ADC data into the ring, so do the copy there. Signed-off-by: Keith Packard --- src/cc1111/ao_adc.c | 2 +- src/telemini-v2.0/ao_pins.h | 48 +++++++++++++++++++++++++-------------------- 2 files changed, 28 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index 1523f94a..97a39c4d 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -164,7 +164,7 @@ ao_adc_isr(void) __interrupt 1 #endif #ifdef FETCH_ADC - FETCH_ADC() + FETCH_ADC(); #define GOT_ADC #endif diff --git a/src/telemini-v2.0/ao_pins.h b/src/telemini-v2.0/ao_pins.h index fac6c535..c1a36f8c 100644 --- a/src/telemini-v2.0/ao_pins.h +++ b/src/telemini-v2.0/ao_pins.h @@ -128,26 +128,32 @@ struct ao_adc { #define AO_ADC_PINS ((1 << 0) | (1 << 1) | (1 << 4)) -#define FETCH_ADC() \ - a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc); \ - switch (sequence) { \ - case 4: \ - a += 4; \ - sequence = 0; \ - break; \ - case 1: \ - a += 2; \ - sequence = 4; \ - break; \ - case 0: \ - sequence = 1; \ - break; \ - } \ - a[0] = ADCL; \ - a[1] = ADCH; \ - if (sequence) { \ - ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | sequence; \ - return; \ - } +#define FETCH_ADC() do { \ + a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc); \ + switch (sequence) { \ + case 4: \ + a += 4; \ + sequence = 0; \ + break; \ + case 1: \ + a += 2; \ + sequence = 4; \ + break; \ + case 0: \ + sequence = 1; \ + break; \ + } \ + a[0] = ADCL; \ + a[1] = ADCH; \ + if (sequence) { \ + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | sequence; \ + return; \ + } \ + AO_DATA_PRESENT(AO_DATA_ADC); \ + if (ao_data_present != AO_DATA_ALL) \ + return; \ + ao_data_ring[ao_data_head].ms5607_raw.pres = ao_ms5607_current.pres; \ + ao_data_ring[ao_data_head].ms5607_raw.temp = ao_ms5607_current.temp; \ + } while (0) #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 3b2f83a7d686b5fbc0aaa56d48cb734f353631c8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Aug 2013 17:16:54 -0700 Subject: altos/cc1111: Leave pin interrupts completely disabled at init time Don't even turn in the PICTL bits as that seems to cause the chip to be unhappy. Signed-off-by: Keith Packard --- src/cc1111/ao_exti.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_exti.h b/src/cc1111/ao_exti.h index 00d99a2b..49fca5d2 100644 --- a/src/cc1111/ao_exti.h +++ b/src/cc1111/ao_exti.h @@ -39,19 +39,18 @@ extern void (*ao_int_callback)(void); ao_int_callback = callback; \ } while (0) -#define ao_exti_init() do { \ - IEN1 &= IEN1_P0IE; \ - PICTL |= PICTL_P0IENL; \ - } while (0) +#define ao_exti_init() #define ao_exti_enable(port, pin) do { \ P0IFG &= ~(1 << pin); \ P0IF = 0; \ + PICTL |= PICTL_P0IENL; \ IEN1 |= IEN1_P0IE; \ } while (0) #define ao_exti_disable(port, pin) do { \ IEN1 &= ~IEN1_P0IE; \ + PICTL &= ~PICTL_P0IENL; \ } while (0) #endif /* _AO_EXTI_H_ */ -- cgit v1.2.3 From 4e3955a5b0ac125bd807920c467f959618449fbc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Aug 2013 17:17:47 -0700 Subject: altos/cc1111: Wake up non-ADC sensor code each timer tick Make sure the MS5607 code gets told to sample every tick Signed-off-by: Keith Packard --- src/cc1111/ao_timer.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/cc1111/ao_timer.c b/src/cc1111/ao_timer.c index a64b5aba..54af9605 100644 --- a/src/cc1111/ao_timer.c +++ b/src/cc1111/ao_timer.c @@ -39,6 +39,9 @@ void ao_timer_isr(void) __interrupt 9 if (++ao_adc_count == ao_adc_interval) { ao_adc_count = 0; ao_adc_poll(); +#if (AO_DATA_ALL & ~(AO_DATA_ADC)) + ao_wakeup(DATA_TO_XDATA(&ao_adc_count)); +#endif } #endif } -- cgit v1.2.3 From 7274b77666df9d2cab2854ec1a403d80e5fce73b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Aug 2013 17:18:17 -0700 Subject: altos: Use %ld and %lu for MS5607 debug output The value are 'long', so use the right printf format. Signed-off-by: Keith Packard --- src/drivers/ao_ms5607.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 7c1acdd1..8b2b6333 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -223,8 +223,8 @@ ao_ms5607_dump(void) __xdata struct ao_ms5607_value value; ao_ms5607_convert(&ao_ms5607_current, &value); - printf ("Pressure: %8u %8d\n", ao_ms5607_current.pres, value.pres); - printf ("Temperature: %8u %8d\n", ao_ms5607_current.temp, value.temp); + printf ("Pressure: %8lu %8ld\n", ao_ms5607_current.pres, value.pres); + printf ("Temperature: %8lu %8ld\n", ao_ms5607_current.temp, value.temp); printf ("Altitude: %ld\n", ao_pa_to_altitude(value.pres)); } -- cgit v1.2.3 From 9b9acb88aa97e8565cdf9342fc59a5aee08e3d34 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Aug 2013 17:18:57 -0700 Subject: altos/telemini-v2.0: Add ao_exti.h depend. Init beeper and usb. Signed-off-by: Keith Packard --- src/telemini-v2.0/Makefile | 3 ++- src/telemini-v2.0/ao_telemini.c | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/telemini-v2.0/Makefile b/src/telemini-v2.0/Makefile index adb1256c..5550e172 100644 --- a/src/telemini-v2.0/Makefile +++ b/src/telemini-v2.0/Makefile @@ -23,7 +23,8 @@ INC = \ ao_ms5607_convert_8051.c \ ao_product.h \ ao_int64.h \ - ao_sample.h + ao_sample.h \ + ao_exti.h CORE_SRC = \ ao_cmd.c \ diff --git a/src/telemini-v2.0/ao_telemini.c b/src/telemini-v2.0/ao_telemini.c index 6b7545fb..294f768a 100644 --- a/src/telemini-v2.0/ao_telemini.c +++ b/src/telemini-v2.0/ao_telemini.c @@ -40,14 +40,16 @@ main(void) ao_timer_init(); ao_adc_init(); + ao_beep_init(); ao_cmd_init(); - ao_storage_init(); - ao_exti_init(); ao_spi_init(); + ao_exti_init(); ao_ms5607_init(); + ao_storage_init(); ao_flight_init(); ao_log_init(); ao_report_init(); + ao_usb_init(); ao_telemetry_init(); ao_radio_init(); ao_packet_slave_init(TRUE); -- cgit v1.2.3 From 7e941695aa27e5eaf453ca1128b8d835472410a4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Aug 2013 18:43:20 -0700 Subject: altos: Check for MS5607 MISO low before sleeping If the MISO line goes low before we manage to configure the interrupts, we'll miss it entirely unless we check the pin explicitly. Signed-off-by: Keith Packard --- src/attiny/ao_arch_funcs.h | 2 ++ src/cc1111/ao_arch_funcs.h | 1 + src/drivers/ao_ms5607.c | 3 ++- src/telemini-v2.0/ao_pins.h | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/attiny/ao_arch_funcs.h b/src/attiny/ao_arch_funcs.h index 76dc7820..d4584a9f 100644 --- a/src/attiny/ao_arch_funcs.h +++ b/src/attiny/ao_arch_funcs.h @@ -41,6 +41,8 @@ PORTB &= ~(1 << bit); \ } while (0) +#define ao_gpio_get(port, bit, pin) ((PORTB >> (bit)) & 1) + /* * The SPI mutex must be held to call either of these * functions -- this mutex covers the entire SPI operation, diff --git a/src/cc1111/ao_arch_funcs.h b/src/cc1111/ao_arch_funcs.h index ae184108..ea340dfd 100644 --- a/src/cc1111/ao_arch_funcs.h +++ b/src/cc1111/ao_arch_funcs.h @@ -145,4 +145,5 @@ ao_spi_init(void); #define ao_enable_output(port,bit,pin,v) cc1111_enable_output(port,token_evaluator(port,DIR), token_evaluator(port,SEL), pin, bit, v) #define ao_gpio_set(port, bit, pin, v) ((pin) = (v)) +#define ao_gpio_get(port, bit, pin) (pin) diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 8b2b6333..58ab9197 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -140,7 +140,8 @@ ao_ms5607_get_sample(uint8_t cmd) { ao_spi_put(AO_MS5607_SPI_INDEX); #endif ao_arch_block_interrupts(); - while (!ao_ms5607_done) + while (!ao_gpio_get(AO_MS5607_MISO_PORT, AO_MS5607_MISO_PIN, AO_MS5607_MISO) && + !ao_ms5607_done) ao_sleep((void *) &ao_ms5607_done); ao_arch_release_interrupts(); #if AO_MS5607_PRIVATE_PINS diff --git a/src/telemini-v2.0/ao_pins.h b/src/telemini-v2.0/ao_pins.h index c1a36f8c..264ad16d 100644 --- a/src/telemini-v2.0/ao_pins.h +++ b/src/telemini-v2.0/ao_pins.h @@ -74,6 +74,7 @@ #define AO_MS5607_CS_MASK (1 << AO_MS5607_CS_PIN) #define AO_MS5607_MISO_PORT P0 #define AO_MS5607_MISO_PIN 2 +#define AO_MS5607_MISO P0_2 #define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO_PIN) #define AO_MS5607_SPI_INDEX 0 #define HAS_EXTI_0 1 -- cgit v1.2.3 From d54156caf856ab5570f050692b333a2c5d991265 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Aug 2013 18:44:23 -0700 Subject: altos: Make ao_wakeup reentrant In case we end up invoking it from two places at once. Signed-off-by: Keith Packard --- src/core/ao_task.c | 2 +- src/core/ao_task.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/ao_task.c b/src/core/ao_task.c index 0aad6508..18315b1f 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -420,7 +420,7 @@ ao_sleep(__xdata void *wchan) } void -ao_wakeup(__xdata void *wchan) +ao_wakeup(__xdata void *wchan) __reentrant { #if HAS_TASK_QUEUE struct ao_task *sleep, *next; diff --git a/src/core/ao_task.h b/src/core/ao_task.h index e3a311ed..9c56b480 100644 --- a/src/core/ao_task.h +++ b/src/core/ao_task.h @@ -70,7 +70,7 @@ ao_sleep(__xdata void *wchan); /* Wake all tasks sleeping on wchan */ void -ao_wakeup(__xdata void *wchan); +ao_wakeup(__xdata void *wchan) __reentrant; /* set an alarm to go off in 'delay' ticks */ void -- cgit v1.2.3 From a73b02518fcbc9fc0807ed8e141d3a06e8ad8214 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Aug 2013 18:46:02 -0700 Subject: altos: Don't use ao_data on cc1111 projects cc1111 ao_adc.c supplies the needed globals at this point, and linking both into the program leads to two different versions of each at different addresses (yay SDCC linker!) Signed-off-by: Keith Packard --- src/cc1111/ao_adc.c | 3 +++ src/telemini-v2.0/Makefile | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index 97a39c4d..15429677 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -19,6 +19,9 @@ volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; volatile __data uint8_t ao_data_head; +#if (AO_DATA_ALL & ~(AO_DATA_ADC)) +volatile __data uint8_t ao_data_present; +#endif #ifdef TELENANO_V_0_1 # define AO_ADC_FIRST_PIN 1 diff --git a/src/telemini-v2.0/Makefile b/src/telemini-v2.0/Makefile index 5550e172..40878778 100644 --- a/src/telemini-v2.0/Makefile +++ b/src/telemini-v2.0/Makefile @@ -24,7 +24,8 @@ INC = \ ao_product.h \ ao_int64.h \ ao_sample.h \ - ao_exti.h + ao_exti.h \ + ao_task.h CORE_SRC = \ ao_cmd.c \ @@ -58,7 +59,6 @@ CC1111_SRC = \ ao_spi.c \ ao_usb.c \ ao_convert_pa.c \ - ao_data.c \ ao_beep.c \ ao_timer.c \ ao_exti.c \ -- cgit v1.2.3 From 7b0f9b25a56fa8b4aa1c2e9d79c43e6a97cab0c0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 20 Aug 2013 11:40:17 -0700 Subject: altos: Initial TeleMetrum v2.0 bits Adds new telemetry and logging formats along with code for TeleMetrum v2.0 design. Signed-off-by: Keith Packard --- src/core/ao_gps_report_metrum.c | 110 ++++++++++++++ src/core/ao_log.h | 66 +++++++++ src/core/ao_log_metrum.c | 175 ++++++++++++++++++++++ src/core/ao_telemetry.c | 66 +++++++++ src/core/ao_telemetry.h | 44 ++++++ src/stm/ao_arch.h | 2 + src/stm/ao_beep_stm.c | 48 +++++- src/stm/stm32l.h | 2 +- src/telemetrum-v2.0/.gitignore | 2 + src/telemetrum-v2.0/Makefile | 122 ++++++++++++++++ src/telemetrum-v2.0/ao_pins.h | 282 ++++++++++++++++++++++++++++++++++++ src/telemetrum-v2.0/ao_telemetrum.c | 90 ++++++++++++ 12 files changed, 1004 insertions(+), 5 deletions(-) create mode 100644 src/core/ao_gps_report_metrum.c create mode 100644 src/core/ao_log_metrum.c create mode 100644 src/telemetrum-v2.0/.gitignore create mode 100644 src/telemetrum-v2.0/Makefile create mode 100644 src/telemetrum-v2.0/ao_pins.h create mode 100644 src/telemetrum-v2.0/ao_telemetrum.c (limited to 'src') diff --git a/src/core/ao_gps_report_metrum.c b/src/core/ao_gps_report_metrum.c new file mode 100644 index 00000000..4fefe223 --- /dev/null +++ b/src/core/ao_gps_report_metrum.c @@ -0,0 +1,110 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_log.h" + +void +ao_gps_report_metrum(void) +{ + static __xdata struct ao_log_metrum gps_log; + static __xdata struct ao_telemetry_location gps_data; + uint8_t date_reported = 0; + + for (;;) { + ao_sleep(&ao_gps_data); + ao_mutex_get(&ao_gps_mutex); + ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); + ao_mutex_put(&ao_gps_mutex); + + if (!(gps_data.flags & AO_GPS_VALID)) + continue; + + gps_log.tick = ao_gps_tick; + gps_log.type = AO_LOG_GPS_POS; + gps_log.u.gps.latitude = gps_data.latitude; + gps_log.u.gps.longitude = gps_data.longitude; + gps_log.u.gps.altitude = gps_data.altitude; + ao_log_metrum(&gps_log); + + gps_log.type = AO_LOG_GPS_TIME; + gps_log.u.gps_time.hour = gps_data.hour; + gps_log.u.gps_time.minute = gps_data.minute; + gps_log.u.gps_time.second = gps_data.second; + gps_log.u.gps_time.flags = gps_data.flags; + gps_log.u.gps_time.year = gps_data.year; + gps_log.u.gps_time.month = gps_data.month; + gps_log.u.gps_time.day = gps_data.day; + ao_log_metrum(&gps_log); + } +} + +void +ao_gps_tracking_report_metrum(void) +{ + static __xdata struct ao_log_metrum gps_log; + static __xdata struct ao_telemetry_satellite gps_tracking_data; + uint8_t c, n, i, p, valid, packets; + uint8_t svid; + + for (;;) { + ao_sleep(&ao_gps_tracking_data); + ao_mutex_get(&ao_gps_mutex); + ao_xmemcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); + ao_mutex_put(&ao_gps_mutex); + + if (!(n = gps_tracking_data.channels)) + continue; + + gps_log.type = AO_LOG_GPS_SAT; + gps_log.tick = ao_gps_tick; + i = 0; + for (c = 0; c < n; c++) { + svid = gps_tracking_data.sats[c].svid; + if (svid != 0) { + if (i == 4) { + gps_log.u.gps_sat.channels = i; + gps_log.u.gps_sat.more = 1; + ao_log_metrum(&gps_log); + i = 0; + } + gps_log.u.gps_sat.sats[i].svid = svid; + gps_log.u.gps_sat.sats[i].c_n = gps_tracking_data.sats[c].c_n_1; + i++; + } + } + if (i) { + gps_log.u.gps_sat.channels = i; + gps_log.u.gps_sat.more = 0; + ao_log_metrum(&gps_log); + } + } +} + +__xdata struct ao_task ao_gps_report_metrum_task; +__xdata struct ao_task ao_gps_tracking_report_metrum_task; + +void +ao_gps_report_metrum_init(void) +{ + ao_add_task(&ao_gps_report_metrum_task, + ao_gps_report_metrum, + "gps_report"); + ao_add_task(&ao_gps_tracking_report_metrum_task, + ao_gps_tracking_report_metrum, + "gps_tracking_report"); +} diff --git a/src/core/ao_log.h b/src/core/ao_log.h index dce12f02..f6ab4520 100644 --- a/src/core/ao_log.h +++ b/src/core/ao_log.h @@ -45,6 +45,7 @@ extern __pdata enum ao_flight_state ao_log_state; #define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ #define AO_LOG_FORMAT_TELEMEGA 5 /* 32 byte typed telemega records */ #define AO_LOG_FORMAT_MINI 6 /* 16-byte MS5607 baro only */ +#define AO_LOG_FORMAT_TELEMETRUM 7 /* 16-byte typed telemetrum records */ #define AO_LOG_FORMAT_NONE 127 /* No log at all */ extern __code uint8_t ao_log_format; @@ -135,6 +136,7 @@ ao_log_full(void); #define AO_LOG_GPS_ALT 'H' #define AO_LOG_GPS_SAT 'V' #define AO_LOG_GPS_DATE 'Y' +#define AO_LOG_GPS_POS 'P' #define AO_LOG_POS_NONE (~0UL) @@ -263,6 +265,64 @@ struct ao_log_mega { } u; }; +struct ao_log_metrum { + char type; /* 0 */ + uint8_t csum; /* 1 */ + uint16_t tick; /* 2 */ + union { /* 4 */ + /* AO_LOG_FLIGHT */ + struct { + uint16_t flight; /* 4 */ + int16_t ground_accel; /* 6 */ + uint32_t ground_pres; /* 8 */ + } flight; /* 12 */ + /* AO_LOG_STATE */ + struct { + uint16_t state; /* 4 */ + uint16_t reason; /* 6 */ + } state; /* 8 */ + /* AO_LOG_SENSOR */ + struct { + uint32_t pres; /* 4 */ + uint32_t temp; /* 8 */ + int16_t accel; /* 12 */ + } sensor; /* 14 */ + /* AO_LOG_TEMP_VOLT */ + struct { + int16_t v_batt; /* 4 */ + int16_t sense_a; /* 6 */ + int16_t sense_m; /* 8 */ + } volt; /* 10 */ + /* AO_LOG_GPS_POS */ + struct { + int32_t latitude; /* 4 */ + int32_t longitude; /* 8 */ + int16_t altitude; /* 12 */ + } gps; /* 14 */ + /* AO_LOG_GPS_TIME */ + struct { + uint8_t hour; /* 4 */ + uint8_t minute; /* 5 */ + uint8_t second; /* 6 */ + uint8_t flags; /* 7 */ + uint8_t year; /* 8 */ + uint8_t month; /* 9 */ + uint8_t day; /* 10 */ + uint8_t pad; /* 11 */ + } gps_time; /* 12 */ + /* AO_LOG_GPS_SAT (up to three packets) */ + struct { + uint8_t channels; /* 4 */ + uint8_t more; /* 5 */ + struct { + uint8_t svid; + uint8_t c_n; + } sats[4]; /* 6 */ + } gps_sat; /* 14 */ + uint8_t raw[12]; /* 4 */ + } u; /* 16 */ +}; + struct ao_log_mini { char type; /* 0 */ uint8_t csum; /* 1 */ @@ -303,10 +363,16 @@ ao_log_data(__xdata struct ao_log_record *log) __reentrant; uint8_t ao_log_mega(__xdata struct ao_log_mega *log) __reentrant; +uint8_t +ao_log_metrum(__xdata struct ao_log_metrum *log) __reentrant; + uint8_t ao_log_mini(__xdata struct ao_log_mini *log) __reentrant; void ao_log_flush(void); +void +ao_gps_report_metrum_init(void); + #endif /* _AO_LOG_H_ */ diff --git a/src/core/ao_log_metrum.c b/src/core/ao_log_metrum.c new file mode 100644 index 00000000..9c17eeed --- /dev/null +++ b/src/core/ao_log_metrum.c @@ -0,0 +1,175 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include +#include +#include + +static __xdata uint8_t ao_log_mutex; +static __xdata struct ao_log_metrum log; + +__code uint8_t ao_log_format = AO_LOG_FORMAT_TELEMETRUM; + +static uint8_t +ao_log_csum(__xdata uint8_t *b) __reentrant +{ + uint8_t sum = 0x5a; + uint8_t i; + + for (i = 0; i < sizeof (struct ao_log_metrum); i++) + sum += *b++; + return -sum; +} + +uint8_t +ao_log_metrum(__xdata struct ao_log_metrum *log) __reentrant +{ + uint8_t wrote = 0; + /* set checksum */ + log->csum = 0; + log->csum = ao_log_csum((__xdata uint8_t *) log); + ao_mutex_get(&ao_log_mutex); { + if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_stop(); + if (ao_log_running) { + wrote = 1; + ao_storage_write(ao_log_current_pos, + log, + sizeof (struct ao_log_metrum)); + ao_log_current_pos += sizeof (struct ao_log_metrum); + } + } ao_mutex_put(&ao_log_mutex); + return wrote; +} + +static uint8_t +ao_log_dump_check_data(void) +{ + if (ao_log_csum((uint8_t *) &log) != 0) + return 0; + return 1; +} + +#if HAS_ADC +static __data uint8_t ao_log_data_pos; + +/* a hack to make sure that ao_log_metrums fill the eeprom block in even units */ +typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_metrum))] ; + +#ifndef AO_SENSOR_INTERVAL_ASCENT +#define AO_SENSOR_INTERVAL_ASCENT 1 +#define AO_SENSOR_INTERVAL_DESCENT 10 +#define AO_OTHER_INTERVAL 32 +#endif + +void +ao_log(void) +{ + __pdata uint16_t next_sensor, next_other; + uint8_t i; + + ao_storage_setup(); + + ao_log_scan(); + + while (!ao_log_running) + ao_sleep(&ao_log_running); + +#if HAS_FLIGHT + log.type = AO_LOG_FLIGHT; + log.tick = ao_sample_tick; +#if HAS_ACCEL + log.u.flight.ground_accel = ao_ground_accel; +#endif + log.u.flight.ground_pres = ao_ground_pres; + log.u.flight.flight = ao_flight_number; + ao_log_metrum(&log); +#endif + + /* Write the whole contents of the ring to the log + * when starting up. + */ + ao_log_data_pos = ao_data_ring_next(ao_data_head); + next_other = next_sensor = ao_data_ring[ao_log_data_pos].tick; + ao_log_state = ao_flight_startup; + for (;;) { + /* Write samples to EEPROM */ + while (ao_log_data_pos != ao_data_head) { + log.tick = ao_data_ring[ao_log_data_pos].tick; + if ((int16_t) (log.tick - next_sensor) >= 0) { + log.type = AO_LOG_SENSOR; +#if HAS_MS5607 + log.u.sensor.pres = ao_data_ring[ao_log_data_pos].ms5607_raw.pres; + log.u.sensor.temp = ao_data_ring[ao_log_data_pos].ms5607_raw.temp; +#endif + log.u.sensor.accel = ao_data_accel(&ao_data_ring[ao_log_data_pos]); + ao_log_metrum(&log); + if (ao_log_state <= ao_flight_coast) + next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; + else + next_sensor = log.tick + AO_SENSOR_INTERVAL_DESCENT; + } + if ((int16_t) (log.tick - next_other) >= 0) { + log.type = AO_LOG_TEMP_VOLT; + log.u.volt.v_batt = ao_data_ring[ao_log_data_pos].adc.v_batt; + log.u.volt.sense_a = ao_data_ring[ao_log_data_pos].adc.sense[0]; + log.u.volt.sense_m = ao_data_ring[ao_log_data_pos].adc.sense[1]; + ao_log_metrum(&log); + next_other = log.tick + AO_OTHER_INTERVAL; + } + ao_log_data_pos = ao_data_ring_next(ao_log_data_pos); + } +#if HAS_FLIGHT + /* Write state change to EEPROM */ + if (ao_flight_state != ao_log_state) { + ao_log_state = ao_flight_state; + log.type = AO_LOG_STATE; + log.tick = ao_time(); + log.u.state.state = ao_log_state; + log.u.state.reason = 0; + ao_log_metrum(&log); + + if (ao_log_state == ao_flight_landed) + ao_log_stop(); + } +#endif + + ao_log_flush(); + + /* Wait for a while */ + ao_delay(AO_MS_TO_TICKS(100)); + + /* Stop logging when told to */ + while (!ao_log_running) + ao_sleep(&ao_log_running); + } +} +#endif + +uint16_t +ao_log_flight(uint8_t slot) +{ + if (!ao_storage_read(ao_log_pos(slot), + &log, + sizeof (struct ao_log_metrum))) + return 0; + + if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) + return log.u.flight.flight; + return 0; +} diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 03a8a273..fb40451c 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -40,6 +40,10 @@ static __pdata uint16_t ao_aprs_time; #define AO_SEND_MEGA 1 #endif +#if defined (TELEMETRUM_V_2_0) +#define AO_SEND_METRUM 1 +#endif + #if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) || defined(TELEBALLOON_V_1_1) || defined(TELEMETRUM_V_1_2) #define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMETRUM #endif @@ -171,6 +175,57 @@ ao_send_mega_data(void) } #endif /* AO_SEND_MEGA */ +#ifdef AO_SEND_METRUM +/* Send telemetrum sensor packet */ +static void +ao_send_metrum_sensor(void) +{ + __xdata struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; + + telemetry.generic.tick = packet->tick; + telemetry.generic.type = AO_TELEMETRY_METRUM_SENSOR; + + telemetry.metrum_sensor.state = ao_flight_state; + telemetry.metrum_sensor.accel = ao_data_accel(packet); + telemetry.metrum_sensor.pres = ao_data_pres(packet); + telemetry.metrum_sensor.temp = ao_data_temp(packet); + + telemetry.metrum_sensor.acceleration = ao_accel; + telemetry.metrum_sensor.speed = ao_speed; + telemetry.metrum_sensor.height = ao_height; + + telemetry.metrum_sensor.v_batt = packet->adc.v_batt; + telemetry.metrum_sensor.sense_a = packet->adc.sense[0]; + telemetry.metrum_sensor.sense_m = packet->adc.sense[1]; + + ao_radio_send(&telemetry, sizeof (telemetry)); +} + +static __pdata int8_t ao_telemetry_metrum_data_max; +static __pdata int8_t ao_telemetry_metrum_data_cur; + +/* Send telemetrum data packet */ +static void +ao_send_metrum_data(void) +{ + if (--ao_telemetry_metrum_data_cur <= 0) { + __xdata struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; + uint8_t i; + + telemetry.generic.tick = packet->tick; + telemetry.generic.type = AO_TELEMETRY_MEGA_DATA; + + telemetry.metrum_data.ground_pres = ao_ground_pres; + telemetry.metrum_data.ground_accel = ao_ground_accel; + telemetry.metrum_data.accel_plus_g = ao_config.accel_plus_g; + telemetry.metrum_data.accel_minus_g = ao_config.accel_minus_g; + + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_metrum_data_cur = ao_telemetry_metrum_data_max; + } +} +#endif /* AO_SEND_MEGA */ + #ifdef AO_SEND_ALL_BARO static uint8_t ao_baro_sample; @@ -326,10 +381,15 @@ ao_telemetry(void) #ifdef AO_SEND_MEGA ao_send_mega_sensor(); ao_send_mega_data(); +#else +#ifdef AO_SEND_METRUM + ao_send_metrum_sensor(); + ao_send_metrum_data(); #else ao_send_sensor(); #endif #endif +#endif #if HAS_COMPANION if (ao_companion_running) @@ -399,6 +459,12 @@ ao_telemetry_set_interval(uint16_t interval) cur++; ao_telemetry_mega_data_cur = cur; #endif +#if AO_SEND_METRUM + ao_telemetry_metrum_data_max = AO_SEC_TO_TICKS(1) / interval; + if (ao_telemetry_metrum_data_max > cur) + cur++; + ao_telemetry_metrum_data_cur = cur; +#endif #if HAS_COMPANION if (!ao_companion_setup.update_period) diff --git a/src/core/ao_telemetry.h b/src/core/ao_telemetry.h index f2d201de..17dc3e93 100644 --- a/src/core/ao_telemetry.h +++ b/src/core/ao_telemetry.h @@ -207,6 +207,48 @@ struct ao_telemetry_mega_data { }; +#define AO_TELEMETRY_METRUM_SENSOR 0x0A + +struct ao_telemetry_metrum_sensor { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t state; /* 5 flight state */ + int16_t accel; /* 6 Z axis */ + + int32_t pres; /* 8 Pa * 10 */ + int16_t temp; /* 12 °C * 100 */ + + int16_t acceleration; /* 14 m/s² * 16 */ + int16_t speed; /* 16 m/s * 16 */ + int16_t height; /* 18 m */ + + int16_t v_batt; /* 20 battery voltage */ + int16_t sense_a; /* 22 apogee continuity sense */ + int16_t sense_m; /* 24 main continuity sense */ + + uint8_t pad[6]; /* 26 */ + /* 32 */ +}; + +#define AO_TELEMETRY_METRUM_DATA 0x0B + +struct ao_telemetry_metrum_data { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + int32_t ground_pres; /* 8 average pres on pad */ + int16_t ground_accel; /* 12 average accel on pad */ + int16_t accel_plus_g; /* 14 accel calibration at +1g */ + int16_t accel_minus_g; /* 16 accel calibration at -1g */ + + uint8_t pad[14]; /* 18 */ + /* 32 */ +}; + + /* #define AO_SEND_ALL_BARO */ #define AO_TELEMETRY_BARO 0x80 @@ -240,6 +282,8 @@ union ao_telemetry_all { struct ao_telemetry_companion companion; struct ao_telemetry_mega_sensor mega_sensor; struct ao_telemetry_mega_data mega_data; + struct ao_telemetry_metrum_sensor metrum_sensor; + struct ao_telemetry_metrum_data metrum_data; struct ao_telemetry_baro baro; }; diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index adc288c3..42fe727a 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -34,6 +34,8 @@ #define AO_TICK_SIGNED int16_t #endif +#define AO_PORT_TYPE uint16_t + /* Various definitions to make GCC look more like SDCC */ #define ao_arch_naked_declare __attribute__((naked)) diff --git a/src/stm/ao_beep_stm.c b/src/stm/ao_beep_stm.c index 4761fbfc..a95d869b 100644 --- a/src/stm/ao_beep_stm.c +++ b/src/stm/ao_beep_stm.c @@ -17,6 +17,10 @@ #include "ao.h" +#ifndef BEEPER_CHANNEL +#define BEEPER_CHANNEL 1 +#endif + void ao_beep(uint8_t beep) { @@ -56,6 +60,7 @@ ao_beep(uint8_t beep) * is enabled and active high. */ +#if BEEPER_CHANNEL == 1 stm_tim3.ccmr1 = ((0 << STM_TIM234_CCMR1_OC2CE) | (STM_TIM234_CCMR1_OC2M_FROZEN << STM_TIM234_CCMR1_OC2M) | (0 << STM_TIM234_CCMR1_OC2PE) | @@ -68,7 +73,6 @@ ao_beep(uint8_t beep) (0 << STM_TIM234_CCMR1_OC1FE) | (STM_TIM234_CCMR1_CC1S_OUTPUT << STM_TIM234_CCMR1_CC1S)); - stm_tim3.ccer = ((0 << STM_TIM234_CCER_CC4NP) | (0 << STM_TIM234_CCER_CC4P) | (0 << STM_TIM234_CCER_CC4E) | @@ -81,6 +85,33 @@ ao_beep(uint8_t beep) (0 << STM_TIM234_CCER_CC1NP) | (0 << STM_TIM234_CCER_CC1P) | (1 << STM_TIM234_CCER_CC1E)); +#endif +#if BEEPER_CHANNEL == 4 + stm_tim3.ccmr2 = ((0 << STM_TIM234_CCMR2_OC4CE) | + (STM_TIM234_CCMR2_OC4M_TOGGLE << STM_TIM234_CCMR2_OC4M) | + (0 << STM_TIM234_CCMR2_OC4PE) | + (0 << STM_TIM234_CCMR2_OC4FE) | + (STM_TIM234_CCMR2_CC4S_OUTPUT << STM_TIM234_CCMR2_CC4S) | + + (0 << STM_TIM234_CCMR2_OC3CE) | + (STM_TIM234_CCMR2_OC3M_FROZEN << STM_TIM234_CCMR2_OC3M) | + (0 << STM_TIM234_CCMR2_OC3PE) | + (0 << STM_TIM234_CCMR2_OC3FE) | + (STM_TIM234_CCMR2_CC3S_OUTPUT << STM_TIM234_CCMR2_CC3S)); + + stm_tim3.ccer = ((0 << STM_TIM234_CCER_CC4NP) | + (0 << STM_TIM234_CCER_CC4P) | + (1 << STM_TIM234_CCER_CC4E) | + (0 << STM_TIM234_CCER_CC3NP) | + (0 << STM_TIM234_CCER_CC3P) | + (0 << STM_TIM234_CCER_CC3E) | + (0 << STM_TIM234_CCER_CC2NP) | + (0 << STM_TIM234_CCER_CC2P) | + (0 << STM_TIM234_CCER_CC2E) | + (0 << STM_TIM234_CCER_CC1NP) | + (0 << STM_TIM234_CCER_CC1P) | + (0 << STM_TIM234_CCER_CC1E)); +#endif /* 5. Enable the counter by setting the CEN bit in the TIMx_CR1 register. */ @@ -110,13 +141,22 @@ ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant void ao_beep_init(void) { - /* Our beeper is on PC6, which is hooked to TIM3_CH1, - * which is on PC6 - */ +#if BEEPER_CHANNEL == 1 + /* Our beeper is on PC6, which is hooked to TIM3_CH1. + */ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN); stm_afr_set(&stm_gpioc, 6, STM_AFR_AF2); +#endif +#if BEEPER_CHANNEL == 4 + + /* Our beeper is on PB1, which is hooked to TIM3_CH4. + */ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); + + stm_afr_set(&stm_gpiob, 1, STM_AFR_AF2); +#endif /* Leave the timer off until requested */ diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 1868468f..ff3f5336 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -1739,7 +1739,7 @@ extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4; #define STM_TIM234_CCMR1_CC1S_INPUT_TRC 3 #define STM_TIM234_CCMR1_CC1S_MASK 3 -#define STM_TIM234_CCMR2_OC2CE 15 +#define STM_TIM234_CCMR2_OC4CE 15 #define STM_TIM234_CCMR2_OC4M 12 #define STM_TIM234_CCMR2_OC4M_FROZEN 0 #define STM_TIM234_CCMR2_OC4M_SET_HIGH_ON_MATCH 1 diff --git a/src/telemetrum-v2.0/.gitignore b/src/telemetrum-v2.0/.gitignore new file mode 100644 index 00000000..35ce24d4 --- /dev/null +++ b/src/telemetrum-v2.0/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +telemetrum-*.elf diff --git a/src/telemetrum-v2.0/Makefile b/src/telemetrum-v2.0/Makefile new file mode 100644 index 00000000..c03a5539 --- /dev/null +++ b/src/telemetrum-v2.0/Makefile @@ -0,0 +1,122 @@ +# +# AltOS build +# +# + +include ../stm/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_companion.h \ + ao_data.h \ + ao_sample.h \ + ao_pins.h \ + altitude-pa.h \ + ao_kalman.h \ + ao_product.h \ + ao_ms5607.h \ + ao_mma655x.h \ + ao_cc1120_CC1120.h \ + ao_profile.h \ + ao_task.h \ + ao_whiten.h \ + ao_sample_profile.h \ + ao_mpu.h \ + stm32l.h \ + Makefile + +#PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 + +#SAMPLE_PROFILE=ao_sample_profile.c \ +# ao_sample_profile_timer.c +#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1 + +#STACK_GUARD=ao_mpu_stm.c +#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1 + +ALTOS_SRC = \ + ao_boot_chain.c \ + ao_interrupt.c \ + ao_product.c \ + ao_romconfig.c \ + ao_cmd.c \ + ao_config.c \ + ao_task.c \ + ao_led.c \ + ao_stdio.c \ + ao_panic.c \ + ao_timer.c \ + ao_mutex.c \ + ao_serial_stm.c \ + ao_gps_ublox.c \ + ao_gps_show.c \ + ao_gps_report_metrum.c \ + ao_ignite.c \ + ao_freq.c \ + ao_dma_stm.c \ + ao_spi_stm.c \ + ao_cc1120.c \ + ao_fec_tx.c \ + ao_fec_rx.c \ + ao_data.c \ + ao_ms5607.c \ + ao_mma655x.c \ + ao_adc_stm.c \ + ao_beep_stm.c \ + ao_storage.c \ + ao_m25.c \ + ao_usb_stm.c \ + ao_exti_stm.c \ + ao_report.c \ + ao_convert_pa.c \ + ao_log.c \ + ao_log_metrum.c \ + ao_sample.c \ + ao_kalman.c \ + ao_flight.c \ + ao_telemetry.c \ + ao_packet_slave.c \ + ao_packet.c \ + ao_companion.c \ + ao_aprs.c \ + $(PROFILE) \ + $(SAMPLE_PROFILE) \ + $(STACK_GUARD) + +PRODUCT=TeleMetrum-v2.0 +PRODUCT_DEF=-DTELEMETRUM_V_2_0 +IDPRODUCT=0x000b + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g + +PROGNAME=telemetrum-v2.0 +PROG=$(PROGNAME)-$(VERSION).elf + +SRC=$(ALTOS_SRC) ao_telemetrum.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) + +$(PROG): Makefile $(OBJ) altos.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + +../altitude-pa.h: make-altitude-pa + nickle $< > $@ + +$(OBJ): $(INC) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f *.o $(PROGNAME)-*.elf + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/telemetrum-v2.0/ao_pins.h b/src/telemetrum-v2.0/ao_pins.h new file mode 100644 index 00000000..36cfc7e0 --- /dev/null +++ b/src/telemetrum-v2.0/ao_pins.h @@ -0,0 +1,282 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_TASK_QUEUE 1 + +/* 8MHz High speed external crystal */ +#define AO_HSE 8000000 + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL 12 +#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12) + +/* SYSCLK = 32MHz (no need to go faster than CPU) */ +#define AO_PLLDIV 3 +#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHz (CPU clock) */ +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at 16MHz (HCLK/2) */ +#define AO_APB1_PRESCALER 2 +#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +/* Run APB2 at 16MHz (HCLK/2) */ +#define AO_APB2_PRESCALER 2 +#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +#define HAS_SERIAL_1 0 +#define USE_SERIAL_1_STDIN 0 +#define SERIAL_1_PB6_PB7 0 +#define SERIAL_1_PA9_PA10 1 + +#define HAS_SERIAL_2 0 +#define USE_SERIAL_2_STDIN 0 +#define SERIAL_2_PA2_PA3 0 +#define SERIAL_2_PD5_PD6 0 + +#define HAS_SERIAL_3 1 +#define USE_SERIAL_3_STDIN 0 +#define SERIAL_3_PB10_PB11 1 +#define SERIAL_3_PC10_PC11 0 +#define SERIAL_3_PD8_PD9 0 + +#define ao_gps_getchar ao_serial3_getchar +#define ao_gps_putchar ao_serial3_putchar +#define ao_gps_set_speed ao_serial3_set_speed +#define ao_gps_fifo (ao_stm_usart3.rx_fifo) + +#define HAS_EEPROM 1 +#define USE_INTERNAL_FLASH 0 +#define HAS_USB 1 +#define HAS_BEEP 1 +#define BEEPER_CHANNEL 4 +#define HAS_RADIO 1 +#define HAS_TELEMETRY 1 +#define HAS_APRS 1 + +#define HAS_SPI_1 1 +#define SPI_1_PA5_PA6_PA7 1 /* Barometer */ +#define SPI_1_PB3_PB4_PB5 1 /* Accelerometer */ +#define SPI_1_PE13_PE14_PE15 0 +#define SPI_1_OSPEEDR STM_OSPEEDR_10MHz + +#define HAS_SPI_2 1 +#define SPI_2_PB13_PB14_PB15 1 /* Flash, Companion, Radio */ +#define SPI_2_PD1_PD3_PD4 0 +#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz + +#define SPI_2_PORT (&stm_gpiob) +#define SPI_2_SCK_PIN 13 +#define SPI_2_MISO_PIN 14 +#define SPI_2_MOSI_PIN 15 + +#define HAS_I2C_1 0 +#define I2C_1_PB8_PB9 0 + +#define HAS_I2C_2 0 +#define I2C_2_PB10_PB11 0 + +#define PACKET_HAS_SLAVE 1 +#define PACKET_HAS_MASTER 0 + +#define LOW_LEVEL_DEBUG 0 + +#define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOCEN +#define LED_PORT (&stm_gpioc) +#define LED_PIN_RED 14 +#define LED_PIN_GREEN 15 +#define AO_LED_RED (1 << LED_PIN_RED) +#define AO_LED_GREEN (1 << LED_PIN_GREEN) + +#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN) + +#define HAS_GPS 1 +#define HAS_FLIGHT 1 +#define HAS_ADC 1 +#define HAS_ADC_TEMP 1 +#define HAS_LOG 1 + +/* + * Igniter + */ + +#define HAS_IGNITE 1 +#define HAS_IGNITE_REPORT 1 + +#define AO_SENSE_DROGUE(p) ((p)->adc.sense[0]) +#define AO_SENSE_MAIN(p) ((p)->adc.sense[1]) +#define AO_IGNITER_CLOSED 400 +#define AO_IGNITER_OPEN 60 + +/* Drogue */ +#define AO_IGNITER_DROGUE_PORT (&stm_gpioa) +#define AO_IGNITER_DROGUE_PIN 8 + +/* Main */ +#define AO_IGNITER_MAIN_PORT (&stm_gpioa) +#define AO_IGNITER_MAIN_PIN 9 + +#define AO_IGNITER_SET_DROGUE(v) stm_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, v) +#define AO_IGNITER_SET_MAIN(v) stm_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, v) + +/* + * ADC + */ +#define AO_DATA_RING 32 +#define AO_ADC_NUM_SENSE 2 + +struct ao_adc { + int16_t sense[AO_ADC_NUM_SENSE]; + int16_t v_batt; + int16_t temp; +}; + +#define AO_ADC_DUMP(p) \ + printf("tick: %5u drogue: %5d main: %5d batt: %5d pbatt: %5d temp: %5d\n", \ + (p)->tick, \ + (p)->adc.sense[0], (p)->adc.sense[1], \ + (p)->adc.v_batt, (p)->adc.temp) + +#define AO_ADC_SENSE_DROGUE 0 +#define AO_ADC_SENSE_DROGUE_PORT (&stm_gpioa) +#define AO_ADC_SENSE_DROGUE_PIN 0 + +#define AO_ADC_SENSE_MAIN 1 +#define AO_ADC_SENSE_MAIN_PORT (&stm_gpioa) +#define AO_ADC_SENSE_MAIN_PIN 1 + +#define AO_ADC_V_BATT 8 +#define AO_ADC_V_BATT_PORT (&stm_gpiob) +#define AO_ADC_V_BATT_PIN 0 + +#define AO_ADC_TEMP 16 + +#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN) | \ + (1 << STM_RCC_AHBENR_GPIOEEN) | \ + (1 << STM_RCC_AHBENR_GPIOBEN)) + +#define AO_NUM_ADC_PIN 3 + +#define AO_ADC_PIN0_PORT AO_ADC_SENSE_DROGUE_PORT +#define AO_ADC_PIN0_PIN AO_ADC_SENSE_DROGUE_PIN +#define AO_ADC_PIN1_PORT AO_ADC_SENSE_MAIN_PORT +#define AO_ADC_PIN1_PIN AO_ADC_SENSE_MAIN_PIN +#define AO_ADC_PIN2_PORT AO_ADC_V_BATT_PORT +#define AO_ADC_PIN2_PIN AO_ADC_V_BATT_PIN + +#define AO_NUM_ADC (AO_NUM_ADC_PIN + 1) + +#define AO_ADC_SQ1 AO_ADC_SENSE_DROGUE +#define AO_ADC_SQ2 AO_ADC_SENSE_MAIN +#define AO_ADC_SQ3 AO_ADC_V_BATT +#define AO_ADC_SQ4 AO_ADC_TEMP + +/* + * Pressure sensor settings + */ +#define HAS_MS5607 1 +#define HAS_MS5611 0 +#define AO_MS5607_PRIVATE_PINS 1 +#define AO_MS5607_CS_PORT (&stm_gpiob) +#define AO_MS5607_CS_PIN 12 +#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) +#define AO_MS5607_MISO_PORT (&stm_gpioa) +#define AO_MS5607_MISO_PIN 6 +#define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO) +#define AO_MS5607_SPI_INDEX AO_SPI_1_PA5_PA6_PA7 + +/* + * SPI Flash memory + */ + +#define M25_MAX_CHIPS 1 +#define AO_M25_SPI_CS_PORT (&stm_gpiob) +#define AO_M25_SPI_CS_MASK (1 << 8) +#define AO_M25_SPI_BUS AO_SPI_2_PB13_PB14_PB15 + +/* + * Radio (cc1120) + */ + +/* gets pretty close to 434.550 */ + +#define AO_RADIO_CAL_DEFAULT 0x6ca333 + +#define AO_FEC_DEBUG 0 +#define AO_CC1120_SPI_CS_PORT (&stm_gpioa) +#define AO_CC1120_SPI_CS_PIN 2 +#define AO_CC1120_SPI_BUS AO_SPI_2_PB13_PB14_PB15 +#define AO_CC1120_SPI stm_spi2 + +#define AO_CC1120_INT_PORT (&stm_gpioa) +#define AO_CC1120_INT_PIN (3) +#define AO_CC1120_MCU_WAKEUP_PORT (&stm_gpioa) +#define AO_CC1120_MCU_WAKEUP_PIN (4) + +#define AO_CC1120_INT_GPIO 2 +#define AO_CC1120_INT_GPIO_IOCFG CC1120_IOCFG2 + +#define AO_CC1120_MARC_GPIO 3 +#define AO_CC1120_MARC_GPIO_IOCFG CC1120_IOCFG3 + +#define HAS_BOOT_RADIO 0 + +#define HAS_HIGHG_ACCEL 1 + +/* + * mma655x + */ + +#define HAS_MMA655X 1 +#define AO_MMA655X_SPI_INDEX AO_SPI_1_PE13_PE14_PE15 +#define AO_MMA655X_CS_PORT (&stm_gpiod) +#define AO_MMA655X_CS_PIN 4 + +#define NUM_CMDS 16 + +/* + * Companion + */ + +#define AO_COMPANION_CS_PORT (&stm_gpiob) +#define AO_COMPANION_CS_PIN (6) +#define AO_COMPANION_SPI_BUS AO_SPI_2_PB13_PB14_PB15 + +/* + * Monitor + */ + +#define HAS_MONITOR 0 +#define LEGACY_MONITOR 0 +#define HAS_MONITOR_PUT 1 +#define AO_MONITOR_LED 0 +#define HAS_RSSI 0 + +/* + * Profiling Viterbi decoding + */ + +#ifndef AO_PROFILE +#define AO_PROFILE 0 +#endif + +#endif /* _AO_PINS_H_ */ diff --git a/src/telemetrum-v2.0/ao_telemetrum.c b/src/telemetrum-v2.0/ao_telemetrum.c new file mode 100644 index 00000000..e365417d --- /dev/null +++ b/src/telemetrum-v2.0/ao_telemetrum.c @@ -0,0 +1,90 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#if HAS_SAMPLE_PROFILE +#include +#endif +#if HAS_STACK_GUARD +#include +#endif + +int +main(void) +{ + ao_clock_init(); + +#if HAS_STACK_GUARD + ao_mpu_init(); +#endif + + ao_task_init(); + ao_serial_init(); + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_GREEN); + ao_timer_init(); + + ao_spi_init(); + ao_dma_init(); + ao_exti_init(); + + ao_adc_init(); +#if HAS_BEEP + ao_beep_init(); +#endif + ao_cmd_init(); + +#if HAS_MS5607 + ao_ms5607_init(); +#endif +#if HAS_MMA655X + ao_mma655x_init(); +#endif + + ao_storage_init(); + + ao_flight_init(); + ao_log_init(); + ao_report_init(); + + ao_usb_init(); + ao_gps_init(); + ao_gps_report_metrum_init(); + ao_telemetry_init(); + ao_radio_init(); + ao_packet_slave_init(FALSE); + ao_igniter_init(); + ao_companion_init(); + + ao_config_init(); +#if AO_PROFILE + ao_profile_init(); +#endif +#if HAS_SAMPLE_PROFILE + ao_sample_profile_init(); +#endif + + ao_start_scheduler(); + return 0; +} -- cgit v1.2.3 From 6aade70be0a7669d65a8606753d21e4eef5592cd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 20 Aug 2013 14:20:56 -0700 Subject: altos: Add TeleMetrum v2.0 boot loader Signed-off-by: Keith Packard --- src/telemetrum-v2.0/flash-loader/Makefile | 8 +++++++ src/telemetrum-v2.0/flash-loader/ao_pins.h | 34 ++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 src/telemetrum-v2.0/flash-loader/Makefile create mode 100644 src/telemetrum-v2.0/flash-loader/ao_pins.h (limited to 'src') diff --git a/src/telemetrum-v2.0/flash-loader/Makefile b/src/telemetrum-v2.0/flash-loader/Makefile new file mode 100644 index 00000000..cb99c51e --- /dev/null +++ b/src/telemetrum-v2.0/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telemetrum-v2.0 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telemetrum-v2.0/flash-loader/ao_pins.h b/src/telemetrum-v2.0/flash-loader/ao_pins.h new file mode 100644 index 00000000..304bb7c3 --- /dev/null +++ b/src/telemetrum-v2.0/flash-loader/ao_pins.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +/* External crystal at 8MHz */ +#define AO_HSE 8000000 + +#include + +/* Companion port cs_companion0 PB6 */ + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO stm_gpiob +#define AO_BOOT_APPLICATION_PIN 6 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +#endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 454a41359b94e9bcf8582420abc359bbab9d8176 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Aug 2013 11:25:56 -0700 Subject: altos: Rename TeleMetrum v2.0 ADC sense members Use sense_a and sense_m instead of sense[2] Signed-off-by: Keith Packard --- src/core/ao_log_metrum.c | 4 ++-- src/core/ao_telemetry.c | 4 ++-- src/telemetrum-v2.0/ao_pins.h | 13 +++++++------ 3 files changed, 11 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/core/ao_log_metrum.c b/src/core/ao_log_metrum.c index 9c17eeed..43441e7a 100644 --- a/src/core/ao_log_metrum.c +++ b/src/core/ao_log_metrum.c @@ -127,8 +127,8 @@ ao_log(void) if ((int16_t) (log.tick - next_other) >= 0) { log.type = AO_LOG_TEMP_VOLT; log.u.volt.v_batt = ao_data_ring[ao_log_data_pos].adc.v_batt; - log.u.volt.sense_a = ao_data_ring[ao_log_data_pos].adc.sense[0]; - log.u.volt.sense_m = ao_data_ring[ao_log_data_pos].adc.sense[1]; + log.u.volt.sense_a = ao_data_ring[ao_log_data_pos].adc.sense_a; + log.u.volt.sense_m = ao_data_ring[ao_log_data_pos].adc.sense_m; ao_log_metrum(&log); next_other = log.tick + AO_OTHER_INTERVAL; } diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index fb40451c..65d7d08f 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -195,8 +195,8 @@ ao_send_metrum_sensor(void) telemetry.metrum_sensor.height = ao_height; telemetry.metrum_sensor.v_batt = packet->adc.v_batt; - telemetry.metrum_sensor.sense_a = packet->adc.sense[0]; - telemetry.metrum_sensor.sense_m = packet->adc.sense[1]; + telemetry.metrum_sensor.sense_a = packet->adc.sense_a; + telemetry.metrum_sensor.sense_m = packet->adc.sense_m; ao_radio_send(&telemetry, sizeof (telemetry)); } diff --git a/src/telemetrum-v2.0/ao_pins.h b/src/telemetrum-v2.0/ao_pins.h index 36cfc7e0..c4f8c696 100644 --- a/src/telemetrum-v2.0/ao_pins.h +++ b/src/telemetrum-v2.0/ao_pins.h @@ -122,8 +122,8 @@ #define HAS_IGNITE 1 #define HAS_IGNITE_REPORT 1 -#define AO_SENSE_DROGUE(p) ((p)->adc.sense[0]) -#define AO_SENSE_MAIN(p) ((p)->adc.sense[1]) +#define AO_SENSE_DROGUE(p) ((p)->adc.sense_a) +#define AO_SENSE_MAIN(p) ((p)->adc.sense_m) #define AO_IGNITER_CLOSED 400 #define AO_IGNITER_OPEN 60 @@ -145,16 +145,17 @@ #define AO_ADC_NUM_SENSE 2 struct ao_adc { - int16_t sense[AO_ADC_NUM_SENSE]; + int16_t sense_a; + int16_t sense_m; int16_t v_batt; int16_t temp; }; #define AO_ADC_DUMP(p) \ - printf("tick: %5u drogue: %5d main: %5d batt: %5d pbatt: %5d temp: %5d\n", \ + printf("tick: %5u drogue: %5d main: %5d batt: %5d\n", \ (p)->tick, \ - (p)->adc.sense[0], (p)->adc.sense[1], \ - (p)->adc.v_batt, (p)->adc.temp) + (p)->adc.sense_a, (p)->adc.sense_m, \ + (p)->adc.v_batt); #define AO_ADC_SENSE_DROGUE 0 #define AO_ADC_SENSE_DROGUE_PORT (&stm_gpioa) -- cgit v1.2.3 From abde595116f6e8b60ec9ce81554c05de11fd456e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Aug 2013 21:36:02 -0600 Subject: altos/telemetrum-v2.0: Fix MMA6555 SPI pin assignment For TM v2.0, it's on PB 3-5, not PE13-15 Signed-off-by: Keith Packard --- src/telemetrum-v2.0/ao_pins.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/telemetrum-v2.0/ao_pins.h b/src/telemetrum-v2.0/ao_pins.h index c4f8c696..1ca2ddde 100644 --- a/src/telemetrum-v2.0/ao_pins.h +++ b/src/telemetrum-v2.0/ao_pins.h @@ -248,9 +248,9 @@ struct ao_adc { */ #define HAS_MMA655X 1 -#define AO_MMA655X_SPI_INDEX AO_SPI_1_PE13_PE14_PE15 -#define AO_MMA655X_CS_PORT (&stm_gpiod) -#define AO_MMA655X_CS_PIN 4 +#define AO_MMA655X_SPI_INDEX AO_SPI_1_PB3_PB4_PB5 +#define AO_MMA655X_CS_PORT (&stm_gpiob) +#define AO_MMA655X_CS_PIN 9 #define NUM_CMDS 16 -- cgit v1.2.3 From f222e8504bfd01027e3c380c239a2cde2c367d74 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Aug 2013 22:00:29 -0600 Subject: altos/telemetrum-v2.0: Use 9600 baud for ublox Something is up with the Max 7 Signed-off-by: Keith Packard --- src/telemetrum-v2.0/ao_pins.h | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/telemetrum-v2.0/ao_pins.h b/src/telemetrum-v2.0/ao_pins.h index 1ca2ddde..04cce99e 100644 --- a/src/telemetrum-v2.0/ao_pins.h +++ b/src/telemetrum-v2.0/ao_pins.h @@ -59,11 +59,6 @@ #define SERIAL_3_PC10_PC11 0 #define SERIAL_3_PD8_PD9 0 -#define ao_gps_getchar ao_serial3_getchar -#define ao_gps_putchar ao_serial3_putchar -#define ao_gps_set_speed ao_serial3_set_speed -#define ao_gps_fifo (ao_stm_usart3.rx_fifo) - #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 0 #define HAS_USB 1 @@ -191,6 +186,17 @@ struct ao_adc { #define AO_ADC_SQ3 AO_ADC_V_BATT #define AO_ADC_SQ4 AO_ADC_TEMP +/* + * GPS + */ + +#define AO_SERIAL_SPEED_UBLOX AO_SERIAL_SPEED_9600 + +#define ao_gps_getchar ao_serial3_getchar +#define ao_gps_putchar ao_serial3_putchar +#define ao_gps_set_speed ao_serial3_set_speed +#define ao_gps_fifo (ao_stm_usart3.rx_fifo) + /* * Pressure sensor settings */ -- cgit v1.2.3 From 39475c7b8da4f29936f73ffa2bff112f50ee9328 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Aug 2013 21:52:29 -0600 Subject: altos: TM v2 places the MMA6555 upside down compared to Tmega Means we need to invert the data coming out to make it work Signed-off-by: Keith Packard --- src/core/ao_data.h | 4 ++++ src/telemetrum-v2.0/ao_pins.h | 1 + 2 files changed, 5 insertions(+) (limited to 'src') diff --git a/src/core/ao_data.h b/src/core/ao_data.h index b0f086f8..c873e9d3 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -272,7 +272,11 @@ typedef int16_t accel_t; /* MMA655X is hooked up so that positive values represent negative acceleration */ #define ao_data_accel(packet) ((packet)->mma655x) +#if AO_MMA655X_INVERT +#define ao_data_accel_cook(packet) (4095 - (packet)->mma655x) +#else #define ao_data_accel_cook(packet) ((packet)->mma655x) +#endif #define ao_data_set_accel(packet, accel) ((packet)->mma655x = (accel)) #define ao_data_accel_invert(accel) (4095 - (accel)) diff --git a/src/telemetrum-v2.0/ao_pins.h b/src/telemetrum-v2.0/ao_pins.h index 04cce99e..a7236b80 100644 --- a/src/telemetrum-v2.0/ao_pins.h +++ b/src/telemetrum-v2.0/ao_pins.h @@ -257,6 +257,7 @@ struct ao_adc { #define AO_MMA655X_SPI_INDEX AO_SPI_1_PB3_PB4_PB5 #define AO_MMA655X_CS_PORT (&stm_gpiob) #define AO_MMA655X_CS_PIN 9 +#define AO_MMA655X_INVERT 1 #define NUM_CMDS 16 -- cgit v1.2.3 From 44d4c66b21d6b5a0c656fdff6d01ef1d125c1101 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Aug 2013 21:54:31 -0600 Subject: altos: Update time for next alarm each time a task is added Adding a task with a sooner timeout than existing alarm tasks was not correctly updating the time to fire the next alarm, causing tasks to be delayed by the wrong amount. Signed-off-by: Keith Packard --- src/core/ao_sample_profile.c | 6 +++--- src/core/ao_task.c | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/core/ao_sample_profile.c b/src/core/ao_sample_profile.c index 1d9ed414..e682bd98 100644 --- a/src/core/ao_sample_profile.c +++ b/src/core/ao_sample_profile.c @@ -20,15 +20,15 @@ #include #ifndef AO_SAMPLE_PROFILE_LOW_PC -#define AO_SAMPLE_PROFILE_LOW_PC 0x08000000 +#define AO_SAMPLE_PROFILE_LOW_PC 0x08002000 #endif #ifndef AO_SAMPLE_PROFILE_HIGH_PC -#define AO_SAMPLE_PROFILE_HIGH_PC (AO_SAMPLE_PROFILE_LOW_PC + 44 * 1024) +#define AO_SAMPLE_PROFILE_HIGH_PC 0x08003000 #endif #ifndef AO_SAMPLE_PROFILE_SHIFT -#define AO_SAMPLE_PROFILE_SHIFT 6 +#define AO_SAMPLE_PROFILE_SHIFT 3 #endif #define AO_SAMPLE_PROFILE_RANGE (AO_SAMPLE_PROFILE_HIGH_PC - AO_SAMPLE_PROFILE_LOW_PC) diff --git a/src/core/ao_task.c b/src/core/ao_task.c index 0aad6508..4f48e32d 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -109,6 +109,8 @@ ao_task_validate_alarm_queue(void) ao_panic(3); } } + if (ao_task_alarm_tick != ao_list_first_entry(&alarm_queue, struct ao_task, alarm_queue)->alarm) + ao_panic(4); } #else #define ao_task_validate_alarm_queue() @@ -123,6 +125,7 @@ ao_task_to_alarm_queue(struct ao_task *task) ao_list_for_each_entry(alarm, &alarm_queue, struct ao_task, alarm_queue) { if ((int16_t) (alarm->alarm - task->alarm) >= 0) { ao_list_insert(&task->alarm_queue, alarm->alarm_queue.prev); + ao_task_alarm_tick = ao_list_first_entry(&alarm_queue, struct ao_task, alarm_queue)->alarm; ao_task_validate_alarm_queue(); return; } -- cgit v1.2.3 From 61163980f096d555a843e25cd9fe1aec93bbbbba Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Aug 2013 22:02:48 -0600 Subject: altos: Add debugging to ublox GPS driver The new max 7 parts seem to be unhappy about switching baud rates, so I've added a pile of debugging to help out. Some day, I'll figure out how to make them work, this code is being left in place to help with that. Signed-off-by: Keith Packard --- src/drivers/ao_gps_ublox.c | 113 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 94 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_gps_ublox.c b/src/drivers/ao_gps_ublox.c index fa6ff0e0..a11ca3f7 100644 --- a/src/drivers/ao_gps_ublox.c +++ b/src/drivers/ao_gps_ublox.c @@ -21,6 +21,10 @@ #include "ao_gps_ublox.h" +#define AO_UBLOX_DEBUG 1 + +#include + __xdata uint8_t ao_gps_mutex; __pdata uint16_t ao_gps_tick; __xdata struct ao_telemetry_location ao_gps_data; @@ -49,7 +53,34 @@ struct ao_ublox_cksum { static __pdata struct ao_ublox_cksum ao_ublox_cksum; static __pdata uint16_t ao_ublox_len; -#define ao_ublox_byte() ((uint8_t) ao_gps_getchar()) +#if AO_UBLOX_DEBUG + +static uint8_t ao_gps_dbg_enable; + +#define DBG_PROTO 1 +#define DBG_CHAR 2 +#define DBG_INIT 4 + +static void ao_gps_dbg(int level, char *format, ...) { + va_list a; + + if (level & ao_gps_dbg_enable) { + va_start(a, format); + vprintf(format, a); + va_end(a); + flush(); + } +} + +#else +#define ao_gps_dbg(fmt, ...) +#endif + +static inline uint8_t ao_ublox_byte(void) { + uint8_t c = (uint8_t) ao_gps_getchar(); + ao_gps_dbg(DBG_CHAR, " %02x", c); + return c; +} static inline void add_cksum(struct ao_ublox_cksum *cksum, uint8_t c) { @@ -65,6 +96,7 @@ static void ao_ublox_init_cksum(void) static void ao_ublox_put_u8(uint8_t c) { add_cksum(&ao_ublox_cksum, c); + ao_gps_dbg(DBG_CHAR, " (%02x)", c); ao_gps_putchar(c); } @@ -187,6 +219,7 @@ ao_ublox_parse(void __xdata *target, const struct ublox_packet_parse *parse) __r break; } } + ao_gps_dbg(DBG_PROTO, "\n"); } /* @@ -330,6 +363,7 @@ ao_ublox_parse_nav_svinfo(void) { uint8_t nsat; nav_svinfo_nsat = 0; + ao_ublox_parse(&nav_svinfo, nav_svinfo_packet); for (nsat = 0; nsat < nav_svinfo.num_ch && ao_ublox_len >= 12; nsat++) { if (nsat < NAV_SVINFO_MAX_SAT) { @@ -338,6 +372,17 @@ ao_ublox_parse_nav_svinfo(void) ublox_discard(12); } } +#if AO_UBLOX_DEBUG + ao_gps_dbg(DBG_PROTO, "svinfo num_ch %d flags %02x\n", nav_svinfo.num_ch, nav_svinfo.flags); + for (nsat = 0; nsat < nav_svinfo.num_ch; nsat++) + ao_gps_dbg(DBG_PROTO, "\t%d: chn %d svid %d flags %02x quality %d cno %d\n", + nsat, + nav_svinfo_sat[nsat].chn, + nav_svinfo_sat[nsat].svid, + nav_svinfo_sat[nsat].flags, + nav_svinfo_sat[nsat].quality, + nav_svinfo_sat[nsat].cno); +#endif } /* @@ -406,42 +451,52 @@ ao_ublox_parse_nav_velned(void) */ static void -ao_gps_setup(void) +ao_gps_delay(void) { - uint8_t i, k; - - ao_delay(AO_SEC_TO_TICKS(3)); - - ao_gps_set_speed(AO_SERIAL_SPEED_9600); + uint8_t i; /* * A bunch of nulls so the start bit * is clear */ + for (i = 0; i < 64; i++) ao_gps_putchar(0x00); +} + +static void +ao_gps_setup(void) +{ + uint8_t i, k; + + ao_delay(AO_SEC_TO_TICKS(3)); + + ao_gps_dbg(DBG_INIT, "Set speed 9600\n"); + ao_gps_set_speed(AO_SERIAL_SPEED_9600); /* * Send the baud-rate setting and protocol-setting * command three times */ - for (k = 0; k < 3; k++) + for (k = 0; k < 3; k++) { + ao_gps_delay(); + + ao_gps_dbg(DBG_INIT, "Send initial setting\n"); for (i = 0; i < sizeof (ao_gps_set_nmea); i++) ao_gps_putchar(ao_gps_set_nmea[i]); + } + + ao_gps_delay(); #if AO_SERIAL_SPEED_UBLOX != AO_SERIAL_SPEED_9600 + ao_gps_dbg(DBG_INIT, "Set speed high\n"); /* * Increase the baud rate */ ao_gps_set_speed(AO_SERIAL_SPEED_UBLOX); #endif - /* - * Pad with nulls to give the chip - * time to see the baud rate switch - */ - for (i = 0; i < 64; i++) - ao_gps_putchar(0x00); + ao_gps_delay(); } static void @@ -556,7 +611,7 @@ ao_gps(void) __reentrant /* Enable all of the messages we want */ for (i = 0; i < sizeof (ublox_enable_nav); i++) ao_ublox_set_message_rate(UBLOX_NAV, ublox_enable_nav[i], 1); - + ao_ublox_set_navigation_settings((1 << UBLOX_CFG_NAV5_MASK_DYN) | (1 << UBLOX_CFG_NAV5_MASK_FIXMODE), UBLOX_CFG_NAV5_DYNMODEL_AIRBORNE_4G, UBLOX_CFG_NAV5_FIXMODE_3D, @@ -587,6 +642,8 @@ ao_gps(void) __reentrant ao_ublox_len = header_byte(); ao_ublox_len |= header_byte() << 8; + ao_gps_dbg(DBG_PROTO, "class %02x id %02x len %d\n", class, id, ao_ublox_len); + if (ao_ublox_len > 1023) continue; @@ -627,8 +684,10 @@ ao_gps(void) __reentrant break; } - if (ao_ublox_len != 0) + if (ao_ublox_len != 0) { + ao_gps_dbg(DBG_PROTO, "len left %d\n", ao_ublox_len); continue; + } /* verify checksum and end sequence */ cksum.a = ao_ublox_byte(); @@ -654,7 +713,7 @@ ao_gps(void) __reentrant } if (nav_timeutc.valid & (1 << NAV_TIMEUTC_VALID_UTC)) ao_gps_data.flags |= AO_GPS_DATE_VALID; - + ao_gps_data.altitude = nav_posllh.alt_msl / 1000; ao_gps_data.latitude = nav_posllh.lat; ao_gps_data.longitude = nav_posllh.lon; @@ -676,7 +735,7 @@ ao_gps(void) __reentrant ao_gps_data.ground_speed = nav_velned.g_speed; ao_gps_data.climb_rate = -nav_velned.vel_d; ao_gps_data.course = nav_velned.heading / 200000; - + ao_gps_tracking_data.channels = 0; struct ao_telemetry_satellite_info *dst = &ao_gps_tracking_data.sats[0]; @@ -704,8 +763,24 @@ ao_gps(void) __reentrant } } +#if AO_UBLOX_DEBUG +static void ao_gps_option(void) +{ + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) { + ao_cmd_status = ao_cmd_success; + ao_gps_show(); + } else { + ao_gps_dbg_enable = ao_cmd_lex_i; + printf ("gps debug set to %d\n", ao_gps_dbg_enable); + } +} +#else +#define ao_gps_option ao_gps_show +#endif + __code struct ao_cmds ao_gps_cmds[] = { - { ao_gps_show, "g\0Display GPS" }, + { ao_gps_option, "g\0Display GPS" }, { 0, NULL }, }; -- cgit v1.2.3 From 4887af0bf90661a3fdca76f1797a704888edab06 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Aug 2013 22:04:18 -0600 Subject: altos: Force u-blox to 9600 baud for now The Max-7 parts just aren't happy switching baud rates, managing only about half the time. Someday I'll figure out why, but until then, make things work by just leaving the chips at 9600 baud Signed-off-by: Keith Packard --- src/drivers/ao_gps_ublox.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_gps_ublox.c b/src/drivers/ao_gps_ublox.c index a11ca3f7..1bc2a68f 100644 --- a/src/drivers/ao_gps_ublox.c +++ b/src/drivers/ao_gps_ublox.c @@ -30,21 +30,27 @@ __pdata uint16_t ao_gps_tick; __xdata struct ao_telemetry_location ao_gps_data; __xdata struct ao_telemetry_satellite ao_gps_tracking_data; +#undef AO_SERIAL_SPEED_UBLOX + #ifndef AO_SERIAL_SPEED_UBLOX -#define AO_SERIAL_SPEED_UBLOX AO_SERIAL_SPEED_57600 +#define AO_SERIAL_SPEED_UBLOX AO_SERIAL_SPEED_9600 #endif #if AO_SERIAL_SPEED_UBLOX == AO_SERIAL_SPEED_57600 #define SERIAL_SPEED_STRING "57600" +#define SERIAL_SPEED_CHECKSUM "2d" #endif #if AO_SERIAL_SPEED_UBLOX == AO_SERIAL_SPEED_19200 #define SERIAL_SPEED_STRING "19200" +#define SERIAL_SPEED_CHECKSUM "23" #endif #if AO_SERIAL_SPEED_UBLOX == AO_SERIAL_SPEED_9600 #define SERIAL_SPEED_STRING "9600" +#define SERIAL_SPEED_CHECKSUM "16" #endif -static const char ao_gps_set_nmea[] = "\r\n$PUBX,41,1,3,1," SERIAL_SPEED_STRING ",0*2d\r\n"; +static const char ao_gps_set_nmea[] = + "\r\n$PUBX,41,1,3,1," SERIAL_SPEED_STRING ",0*" SERIAL_SPEED_CHECKSUM "\r\n"; struct ao_ublox_cksum { uint8_t a, b; -- cgit v1.2.3 From 2fa87754c5c11bb86e9b1878580c3d4f4b2463f5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Aug 2013 22:08:04 -0600 Subject: altos/stm: New compiler doesn't correctly build flash bits yet Use /opt/cortex until we make the packaged one work Signed-off-by: Keith Packard --- src/stm/Makefile-flash.defs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/Makefile-flash.defs b/src/stm/Makefile-flash.defs index 016bb7e7..86f76d46 100644 --- a/src/stm/Makefile-flash.defs +++ b/src/stm/Makefile-flash.defs @@ -6,7 +6,7 @@ vpath ao-make-product.5c $(TOPDIR)/util .elf.ihx: objcopy -O ihex $*.elf $@ -CC=arm-none-eabi-gcc +CC=/opt/cortex/bin/arm-none-eabi-gcc SAT=/opt/cortex SAT_CLIB=$(SAT)/lib/pdclib-cortex-m3.a SAT_CFLAGS=-I$(SAT)/include -- cgit v1.2.3 From 8e9ed70f50e3f535c2580820771bb1bc3cd055fe Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Aug 2013 22:08:51 -0600 Subject: altos/stm: Make sampling profiler work again Disable the separate stack as that means we can't figure out the PC from the timer interrupt. Move ao_idle_loc after the interrupt release so that we see idle tasks correctly. Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 6fe86e62..9bb2d7cd 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -338,6 +338,11 @@ static inline void ao_arch_restore_stack(void) { asm("bx lr"); } +#ifndef HAS_SAMPLE_PROFILE +#define HAS_SAMPLE_PROFILE 0 +#endif + +#if !HAS_SAMPLE_PROFILE #define HAS_ARCH_START_SCHEDULER 1 static inline void ao_arch_start_scheduler(void) { @@ -350,15 +355,17 @@ static inline void ao_arch_start_scheduler(void) { control |= (1 << 1); asm("msr control,%0" : : "r" (control)); } +#endif #define ao_arch_isr_stack() #endif -#define ao_arch_wait_interrupt() do { \ - asm(".global ao_idle_loc\n\twfi\nao_idle_loc:"); \ - ao_arch_release_interrupts(); \ - ao_arch_block_interrupts(); \ +#define ao_arch_wait_interrupt() do { \ + asm("\twfi\n"); \ + ao_arch_release_interrupts(); \ + asm(".global ao_idle_loc\nao_idle_loc:"); \ + ao_arch_block_interrupts(); \ } while (0) #define ao_arch_critical(b) do { \ -- cgit v1.2.3 From 6802b6a65b1fec06c2c873282be792c40b3c8f5e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Aug 2013 22:10:58 -0600 Subject: altos/stm: Remove stale timer defines Stuff from when we weren't using systick Signed-off-by: Keith Packard --- src/stm/ao_timer.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'src') diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index daf2f400..5cf1e4a8 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -67,20 +67,6 @@ ao_timer_set_adc_interval(uint8_t interval) } #endif -/* - * According to the STM clock-configuration, timers run - * twice as fast as the APB1 clock *if* the APB1 prescaler - * is greater than 1. - */ - -#if AO_APB1_PRESCALER > 1 -#define TIMER_23467_SCALER 2 -#else -#define TIMER_23467_SCALER 1 -#endif - -#define TIMER_10kHz ((AO_PCLK1 * TIMER_23467_SCALER) / 10000) - #define SYSTICK_RELOAD (AO_SYSTICK / 100 - 1) void -- cgit v1.2.3 From 7c82acc1c1c5b7b4da7c7ecb3b2fd90140e4c703 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Aug 2013 22:12:25 -0600 Subject: altos/stm: Make sure we switch to MSI during timer init Need to ensure that the CPU is actually using the MSI during timer init or all of the other clock changes won't work Signed-off-by: Keith Packard --- src/stm/ao_timer.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 5cf1e4a8..34f9edb9 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -90,7 +90,15 @@ ao_clock_init(void) /* Switch to MSI while messing about */ stm_rcc.cr |= (1 << STM_RCC_CR_MSION); while (!(stm_rcc.cr & (1 << STM_RCC_CR_MSIRDY))) - asm("nop"); + ao_arch_nop(); + + stm_rcc.cfgr = (stm_rcc.cfgr & ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW)) | + (STM_RCC_CFGR_SW_MSI << STM_RCC_CFGR_SW); + + /* wait for system to switch to MSI */ + while ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != + (STM_RCC_CFGR_SWS_MSI << STM_RCC_CFGR_SWS)) + ao_arch_nop(); /* reset SW, HPRE, PPRE1, PPRE2, MCOSEL and MCOPRE */ stm_rcc.cfgr &= (uint32_t)0x88FFC00C; @@ -141,7 +149,6 @@ ao_clock_init(void) stm_flash.acr |= (1 << STM_FLASH_ACR_PRFEN); /* Enable 1 wait state so the CPU can run at 32MHz */ - /* (haven't managed to run the CPU at 32MHz yet, it's at 16MHz) */ stm_flash.acr |= (1 << STM_FLASH_ACR_LATENCY); /* Enable power interface clock */ -- cgit v1.2.3 From ce1378385ef273010498e81c205f42d8e32c7dc1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 29 Aug 2013 19:22:18 -0500 Subject: altos: Split EasyMini and TeleMini log formats Same data, but EasyMini uses a 3.0V supply while TeleMini uses 3.3V, which changes the intepretation of all of the ADC values Signed-off-by: Keith Packard --- src/core/ao_log.h | 3 ++- src/core/ao_log_mini.c | 2 +- src/easymini-v0.1/ao_pins.h | 2 ++ src/telemini-v2.0/ao_pins.h | 1 + 4 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/ao_log.h b/src/core/ao_log.h index f6ab4520..a2f342d7 100644 --- a/src/core/ao_log.h +++ b/src/core/ao_log.h @@ -44,8 +44,9 @@ extern __pdata enum ao_flight_state ao_log_state; #define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */ #define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ #define AO_LOG_FORMAT_TELEMEGA 5 /* 32 byte typed telemega records */ -#define AO_LOG_FORMAT_MINI 6 /* 16-byte MS5607 baro only */ +#define AO_LOG_FORMAT_EASYMINI 6 /* 16-byte MS5607 baro only, 3.0V supply */ #define AO_LOG_FORMAT_TELEMETRUM 7 /* 16-byte typed telemetrum records */ +#define AO_LOG_FORMAT_TELEMINI 8 /* 16-byte MS5607 baro only, 3.3V supply */ #define AO_LOG_FORMAT_NONE 127 /* No log at all */ extern __code uint8_t ao_log_format; diff --git a/src/core/ao_log_mini.c b/src/core/ao_log_mini.c index 46b285f3..99a85982 100644 --- a/src/core/ao_log_mini.c +++ b/src/core/ao_log_mini.c @@ -23,7 +23,7 @@ static __xdata uint8_t ao_log_mutex; static __xdata struct ao_log_mini log; -__code uint8_t ao_log_format = AO_LOG_FORMAT_MINI; +__code uint8_t ao_log_format = AO_LOG_FORMAT; static uint8_t ao_log_csum(__xdata uint8_t *b) __reentrant diff --git a/src/easymini-v0.1/ao_pins.h b/src/easymini-v0.1/ao_pins.h index c09fb4c2..e0eb10bf 100644 --- a/src/easymini-v0.1/ao_pins.h +++ b/src/easymini-v0.1/ao_pins.h @@ -48,6 +48,8 @@ #define PACKET_HAS_SLAVE 0 +#define AO_LOG_FORMAT AO_LOG_FORMAT_EASYMINI + /* USART */ #define HAS_SERIAL 0 diff --git a/src/telemini-v2.0/ao_pins.h b/src/telemini-v2.0/ao_pins.h index 264ad16d..c4681ee2 100644 --- a/src/telemini-v2.0/ao_pins.h +++ b/src/telemini-v2.0/ao_pins.h @@ -102,6 +102,7 @@ #define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) #define AO_SEND_MINI +#define AO_LOG_FORMAT AO_LOG_FORMAT_TELEMINI /* * ADC -- cgit v1.2.3 From 4188153548fca104bb49cda2d502c708fe4b49d7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 31 Aug 2013 08:20:48 -0500 Subject: altos/lpc: Add bits for building flash loaders Signed-off-by: Keith Packard --- src/lpc/Makefile-flash.defs | 92 ++++++++++++++++++++++++++ src/lpc/ao_flash_lpc.c | 158 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 250 insertions(+) create mode 100644 src/lpc/Makefile-flash.defs create mode 100644 src/lpc/ao_flash_lpc.c (limited to 'src') diff --git a/src/lpc/Makefile-flash.defs b/src/lpc/Makefile-flash.defs new file mode 100644 index 00000000..6bdd204c --- /dev/null +++ b/src/lpc/Makefile-flash.defs @@ -0,0 +1,92 @@ +vpath % $(TOPDIR)/lpc:$(TOPDIR)/product:$(TOPDIR)/drivers:$(TOPDIR)/core:$(TOPDIR)/util:$(TOPDIR) +vpath ao-make-product.5c $(TOPDIR)/util + +.SUFFIXES: .elf .ihx + +.elf.ihx: + objcopy -O ihex $*.elf $@ + +CC=arm-none-eabi-gcc +SAT=/opt/cortex +SAT_CLIB=$(SAT)/lib/pdclib-cortex-m0.a +SAT_CFLAGS=-I$(SAT)/include + +ifndef VERSION +include $(TOPDIR)/Version +endif + +AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) +STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) + +LDFLAGS=-L$(TOPDIR)/lpc -Wl,-Taltos-loader.ld + +NICKLE=nickle + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +.c.o: + $(call quiet,CC) -c $(CFLAGS) -o $@ $< + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_flash_pins.h \ + ao_flash_lpc_pins.h \ + ao_flash_task.h \ + ao_pins.h \ + ao_product.h \ + Makefile + +# +# Common AltOS sources +# +SRC = \ + ao_interrupt.c \ + ao_romconfig.c \ + ao_boot_chain.c \ + ao_boot_pin.c \ + ao_product.c \ + ao_notask.c \ + ao_timer_lpc.c \ + ao_usb_lpc.c \ + ao_flash_lpc.c \ + ao_flash_task.c \ + ao_flash_loader_lpc.c + +OBJ=$(SRC:.c=.o) + +PRODUCT=AltosFlash-$(VERSION) +PRODUCT_DEF=-DALTOS_FLASH +IDPRODUCT=0x000a + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -g -Os + +PROGNAME=altos-flash +PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf + +$(PROG): Makefile $(OBJ) altos-loader.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + +ao_product.h: ao-make-product.5c $(TOPDIR)/Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +$(OBJ): $(INC) + +all: $(PROG) + +distclean: clean + +clean: + rm -f *.o $(PROG) + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/lpc/ao_flash_lpc.c b/src/lpc/ao_flash_lpc.c new file mode 100644 index 00000000..5a31f39f --- /dev/null +++ b/src/lpc/ao_flash_lpc.c @@ -0,0 +1,158 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +#define IAP_LOCATION 0x1fff1ff1 + +typedef void (*iap_func)(uint32_t *in, uint32_t *out); + +static void +iap(uint32_t *in, uint32_t *out) +{ + ao_arch_block_interrupts(); + lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_FLASHREG); + ((iap_func) IAP_LOCATION)(in, out); + ao_arch_release_interrupts(); +} + +#define LPC_IAP_PREPARE_WRITE 50 +#define LPC_IAP_COPY_RAM_TO_FLASH 51 +#define LPC_IAP_ERASE_SECTOR 52 +#define LPC_IAP_BLANK_CHECK 53 +#define LPC_IAP_READ_PART_ID 54 +#define LPC_IAP_READ_BOOT_CODE_VERSION 55 +#define LPC_IAP_COMPARE 56 +#define LPC_IAP_REINVOKE_ISP 57 +#define LPC_IAP_READ_UID 58 +#define LPC_IAP_ERASE_PAGE 59 +#define LPC_IAP_EEPROM_WRITE 61 +#define LPC_IAP_EEPROM_READ 62 + +#define LPC_IAP_CMD_SUCCESS 0 +#define LPC_IAP_INVALID_COMMAND 1 +#define LPC_IAP_SRC_ADDR_ERROR 2 +#define LPC_IAP_DST_ADDR_ERROR 3 +#define LPC_IAP_SRC_ADDR_NOT_MAPPED 4 +#define LPC_IAP_DST_ADDR_NOT_MAPPED 5 +#define LPC_IAP_COUNT_ERROR 6 +#define LPC_IAP_INVALID_SECTOR 7 +#define LPC_IAP_SECTOR_NOT_BLANK 8 +#define LPC_IAP_SECTOR_NOT_PREPARED_FOR_WRITE_OPERATION 9 +#define LPC_IAP_COMPARE_ERROR 10 +#define LPC_IAP_BUSY 11 +#define LPC_IAP_PARAM_ERROR 12 +#define LPC_IAP_ADDR_ERROR 13 +#define LPC_IAP_ADDR_NOT_MAPPED 14 +#define LPC_IAP_CMD_LOCKED 15 +#define LPC_IAP_INVALID_CODE 16 +#define LPC_IAP_INVALID_BAUD_RATE 17 +#define LPC_IAP_INVALID_STOP_BIT 18 +#define LPC_IAP_CODE_READ_PROTECTION_ENABLED 19 + +#define LPC_FLASH_BASE ((uint8_t *) 0x0) +#define LPC_FLASH_SECTOR 4096 +#define LPC_FLASH_SECTOR_MASK (LPC_FLASH_SECTOR - 1) +#define LPC_FLASH_SECTOR_SHIFT 12 + +static uint32_t iap_in[5], iap_out[5]; + +static uint32_t +ao_lpc_addr_to_sector(uint8_t *addr) +{ + uint32_t off = addr - LPC_FLASH_BASE; + + return off >> LPC_FLASH_SECTOR_SHIFT; +} + +static uint8_t +ao_lpc_addr_is_sector_aligned(uint8_t *addr) +{ + uint32_t off = addr - LPC_FLASH_BASE; + return (off & LPC_FLASH_SECTOR_MASK) == 0; +} + +static uint32_t +ao_lpc_prepare_write(uint32_t start_sector, uint32_t end_sector) +{ + iap_in[0] = LPC_IAP_PREPARE_WRITE; + iap_in[1] = start_sector; + iap_in[2] = end_sector; + iap(iap_in,iap_out); + return iap_out[0]; +} + +static uint32_t +ao_lpc_copy_ram_to_flash(uint8_t *dst, uint8_t *src, uint32_t len, uint32_t freq) +{ + iap_in[0] = LPC_IAP_COPY_RAM_TO_FLASH; + iap_in[1] = (uint32_t) dst; + iap_in[2] = (uint32_t) src; + iap_in[3] = len; + iap_in[4] = freq; + iap(iap_in,iap_out); + return iap_out[0]; +} + +static uint32_t +ao_lpc_erase_sector(uint32_t start_sector, uint32_t end_sector, uint32_t freq) +{ + iap_in[0] = LPC_IAP_ERASE_SECTOR; + iap_in[1] = start_sector; + iap_in[2] = end_sector; + iap_in[3] = freq; + iap(iap_in,iap_out); + return iap_out[0]; +} + +uint32_t +ao_lpc_read_part_id(void) +{ + iap_in[0] = LPC_IAP_READ_PART_ID; + iap(iap_in,iap_out); + return iap_out[1]; +} + +uint32_t +ao_flash_erase_page(uint8_t *page) +{ + uint32_t ret = LPC_IAP_CMD_SUCCESS; + if (ao_lpc_addr_is_sector_aligned(page)) { + uint32_t sector = ao_lpc_addr_to_sector(page); + ret = ao_lpc_prepare_write(sector, sector); + if (ret == LPC_IAP_CMD_SUCCESS) + ret = ao_lpc_erase_sector(sector, sector, AO_LPC_SYSCLK / 1000); + } + return ret; +} + +uint32_t +ao_flash_page(uint8_t *page, uint8_t *src) +{ + uint32_t sector = ao_lpc_addr_to_sector(page); + uint32_t ret; + + ret = ao_flash_erase_page(page); + if (ret != LPC_IAP_CMD_SUCCESS) + return ret; + ret = ao_lpc_prepare_write(sector, sector); + if (ret != LPC_IAP_CMD_SUCCESS) + return ret; + ret = ao_lpc_copy_ram_to_flash(page, src, 256, AO_LPC_SYSCLK / 1000); + return ret; +} -- cgit v1.2.3 From c781469ff907a32bd43a5d781391b6859b14cd32 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 31 Aug 2013 23:10:56 -0500 Subject: altos/telegps: Initialize logging system Otherwise, very little logging works Signed-off-by: Keith Packard --- src/telegps-v0.3/ao_telegps.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/telegps-v0.3/ao_telegps.c b/src/telegps-v0.3/ao_telegps.c index f9f62316..608817e7 100644 --- a/src/telegps-v0.3/ao_telegps.c +++ b/src/telegps-v0.3/ao_telegps.c @@ -49,6 +49,7 @@ main(void) ao_gps_init(); #if HAS_LOG ao_gps_report_mega_init(); + ao_log_init(); #endif ao_telemetry_init(); -- cgit v1.2.3 From 77dc89ed5b7bf8f5b3fa3b6131660f1a98f583ea Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 31 Aug 2013 23:11:39 -0500 Subject: altoslib/altosui: Further AltosState transition work Parses most eeprom and telem records now; altosui updated to show from AltosState info. Signed-off-by: Keith Packard --- altoslib/AltosConvert.java | 22 ++ altoslib/AltosEeprom.java | 45 +++- altoslib/AltosEepromChunk.java | 26 +++ altoslib/AltosEepromFile.java | 5 + altoslib/AltosEepromGPS.java | 178 ++++++++++++++++ altoslib/AltosEepromHeader.java | 6 +- altoslib/AltosEepromMega.java | 262 +++++++++++------------ altoslib/AltosEepromMetrum.java | 2 + altoslib/AltosEepromMetrum2.java | 178 ++++++++++++++++ altoslib/AltosEepromMini.java | 20 +- altoslib/AltosEepromTM.java | 14 +- altoslib/AltosEepromTeleScience.java | 2 + altoslib/AltosGPS.java | 10 +- altoslib/AltosLib.java | 1 + altoslib/AltosState.java | 129 +++++++++--- altoslib/AltosTelemetry.java | 44 +--- altoslib/AltosTelemetryConfiguration.java | 55 +++++ altoslib/AltosTelemetryLegacy.java | 2 +- altoslib/AltosTelemetryLocation.java | 88 ++++++++ altoslib/AltosTelemetryMegaData.java | 85 ++++++++ altoslib/AltosTelemetryMegaSensor.java | 84 ++++++++ altoslib/AltosTelemetryMetrumData.java | 42 ++++ altoslib/AltosTelemetryMetrumSensor.java | 69 ++++++ altoslib/AltosTelemetryRaw.java | 28 +++ altoslib/AltosTelemetrySatellite.java | 50 +++++ altoslib/AltosTelemetrySensor.java | 80 +++++++ altoslib/AltosTelemetryStandard.java | 106 ++++++++++ altoslib/Makefile.am | 34 ++- altosui/AltosAscent.java | 4 +- altosui/AltosDescent.java | 4 +- altosui/AltosDisplayThread.java | 2 +- altosui/AltosEepromDownload.java | 340 ++++-------------------------- altosui/AltosFlightStatus.java | 2 +- altosui/AltosFlightUI.java | 2 +- altosui/AltosIdleMonitorUI.java | 8 +- altosui/AltosInfoTable.java | 30 +-- altosui/AltosLanded.java | 5 +- altosui/AltosPad.java | 74 ++++--- altosui/AltosUI.java | 15 +- src/core/ao_log.h | 3 +- 40 files changed, 1552 insertions(+), 604 deletions(-) create mode 100644 altoslib/AltosEepromGPS.java create mode 100644 altoslib/AltosEepromMetrum2.java create mode 100644 altoslib/AltosTelemetryConfiguration.java create mode 100644 altoslib/AltosTelemetryLocation.java create mode 100644 altoslib/AltosTelemetryMegaData.java create mode 100644 altoslib/AltosTelemetryMegaSensor.java create mode 100644 altoslib/AltosTelemetryMetrumData.java create mode 100644 altoslib/AltosTelemetryMetrumSensor.java create mode 100644 altoslib/AltosTelemetryRaw.java create mode 100644 altoslib/AltosTelemetrySatellite.java create mode 100644 altoslib/AltosTelemetrySensor.java create mode 100644 altoslib/AltosTelemetryStandard.java (limited to 'src') diff --git a/altoslib/AltosConvert.java b/altoslib/AltosConvert.java index a1e2cdca..cf2bc59f 100644 --- a/altoslib/AltosConvert.java +++ b/altoslib/AltosConvert.java @@ -196,6 +196,28 @@ public class AltosConvert { return ((count / 16.0) / 2047.0 + 0.095) / 0.009 * 1000.0; } + static double + thermometer_to_temperature(double thermo) + { + return (thermo - 19791.268) / 32728.0 * 1.25 / 0.00247; + } + + static double mega_adc(int raw) { + return raw / 4095.0; + } + + static public double mega_battery_voltage(int v_batt) { + if (v_batt != AltosRecord.MISSING) + return 3.3 * mega_adc(v_batt) * (15.0 + 27.0) / 27.0; + return AltosRecord.MISSING; + } + + static double mega_pyro_voltage(int raw) { + if (raw != AltosRecord.MISSING) + return 3.3 * mega_adc(raw) * (100.0 + 27.0) / 27.0; + return AltosRecord.MISSING; + } + public static double radio_to_frequency(int freq, int setting, int cal, int channel) { double f; diff --git a/altoslib/AltosEeprom.java b/altoslib/AltosEeprom.java index 31646c7e..081b3be1 100644 --- a/altoslib/AltosEeprom.java +++ b/altoslib/AltosEeprom.java @@ -27,8 +27,26 @@ public abstract class AltosEeprom implements AltosStateUpdate { public int data8[]; public boolean valid; + public int data8(int i) { + return data8[i]; + } + + public int data16(int i) { + return ((data8[i] | (data8[i+1] << 8)) << 16) >> 16; + } + + public int data24(int i) { + return data8[i] | (data8[i+1] << 8) | (data8[i+2] << 16); + } + + public int data32(int i) { + return data8[i] | (data8[i+1] << 8) | (data8[i+2] << 16) | (data8[i+3] << 24); + } + public final static int header_length = 4; + public abstract int record_length(); + public abstract void update_state(AltosState state); public void write(PrintStream out) { @@ -40,14 +58,28 @@ public abstract class AltosEeprom implements AltosStateUpdate { out.printf ("\n"); } - void parse_chunk(AltosEepromChunk chunk, int start, int record_length) throws ParseException { + public String string() { + String s; + + s = String.format("%c %04x", cmd, tick); + if (data8 != null) { + for (int i = 0; i < data8.length; i++) { + String d = String.format(" %02x", data8[i]); + s = s.concat(d); + } + } + s = s.concat("\n"); + return s; + } + + void parse_chunk(AltosEepromChunk chunk, int start) throws ParseException { cmd = chunk.data(start); - int data_length = record_length - header_length; + int data_length = record_length() - header_length; - valid = !chunk.erased(start, record_length); + valid = !chunk.erased(start, record_length()); if (valid) { - if (AltosConvert.checksum(chunk.data, start, record_length) != 0) + if (AltosConvert.checksum(chunk.data, start, record_length()) != 0) throw new ParseException(String.format("invalid checksum at 0x%x", chunk.address + start), 0); } else { @@ -61,12 +93,12 @@ public abstract class AltosEeprom implements AltosStateUpdate { data8[i] = chunk.data(start + header_length + i); } - void parse_string(String line, int record_length) { + void parse_string(String line) { valid = false; tick = 0; cmd = AltosLib.AO_LOG_INVALID; - int data_length = record_length - header_length; + int data_length = record_length() - header_length; if (line == null) return; @@ -79,6 +111,7 @@ public abstract class AltosEeprom implements AltosStateUpdate { tick = Integer.parseInt(tokens[1],16); valid = true; data8 = new int[data_length]; + for (int i = 0; i < data_length; i++) data8[i] = Integer.parseInt(tokens[2 + i],16); } diff --git a/altoslib/AltosEepromChunk.java b/altoslib/AltosEepromChunk.java index b1bba3bb..1709352b 100644 --- a/altoslib/AltosEepromChunk.java +++ b/altoslib/AltosEepromChunk.java @@ -62,6 +62,32 @@ public class AltosEepromChunk { return true; } + public AltosEeprom eeprom(int offset, int log_format) { + AltosEeprom eeprom = null; + try { + switch (log_format) { + case AltosLib.AO_LOG_FORMAT_FULL: + eeprom = new AltosEepromTM(this, offset); + break; + case AltosLib.AO_LOG_FORMAT_TINY: + case AltosLib.AO_LOG_FORMAT_TELEMETRY: + case AltosLib.AO_LOG_FORMAT_TELESCIENCE: + case AltosLib.AO_LOG_FORMAT_TELEMEGA: + eeprom = new AltosEepromMega(this, offset); + break; + case AltosLib.AO_LOG_FORMAT_TELEMETRUM: + eeprom = new AltosEepromMetrum2(this, offset); + break; + case AltosLib.AO_LOG_FORMAT_TELEMINI: + case AltosLib.AO_LOG_FORMAT_EASYMINI: + eeprom = new AltosEepromMini(this, offset); + break; + } + } catch (ParseException e) { + } + return eeprom; + } + public AltosEepromChunk(AltosLink link, int block, boolean flush) throws TimeoutException, InterruptedException { diff --git a/altoslib/AltosEepromFile.java b/altoslib/AltosEepromFile.java index 2f4c54d7..367b6791 100644 --- a/altoslib/AltosEepromFile.java +++ b/altoslib/AltosEepromFile.java @@ -72,6 +72,7 @@ public class AltosEepromFile extends AltosStateIterable { headers = new AltosEepromIterable(AltosEepromHeader.read(input)); start = headers.state(); + start.set_state(AltosLib.ao_flight_pad); switch (start.log_format) { case AltosLib.AO_LOG_FORMAT_FULL: @@ -81,6 +82,10 @@ public class AltosEepromFile extends AltosStateIterable { case AltosLib.AO_LOG_FORMAT_TELEMETRY: case AltosLib.AO_LOG_FORMAT_TELESCIENCE: case AltosLib.AO_LOG_FORMAT_TELEMEGA: + body = new AltosEepromIterable(AltosEepromMega.read(input)); + break; + case AltosLib.AO_LOG_FORMAT_TELEMETRUM: + body = new AltosEepromIterable(AltosEepromMetrum2.read(input)); break; case AltosLib.AO_LOG_FORMAT_TELEMINI: case AltosLib.AO_LOG_FORMAT_EASYMINI: diff --git a/altoslib/AltosEepromGPS.java b/altoslib/AltosEepromGPS.java new file mode 100644 index 00000000..d8e47a6e --- /dev/null +++ b/altoslib/AltosEepromGPS.java @@ -0,0 +1,178 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_1; + +import java.io.*; +import java.util.*; +import java.text.*; + +public class AltosEepromGPS extends AltosEeprom { + public static final int record_length = 16; + + public int record_length() { return record_length; } + + /* AO_LOG_FLIGHT elements */ + public int flight() { return data16(0); } + public int ground_accel() { return data16(2); } + public int ground_pres() { return data32(4); } + public int ground_temp() { return data32(8); } + + /* AO_LOG_STATE elements */ + public int state() { return data16(0); } + public int reason() { return data16(2); } + + /* AO_LOG_SENSOR elements */ + public int pres() { return data32(0); } + public int temp() { return data32(4); } + public int accel() { return data16(8); } + + /* AO_LOG_TEMP_VOLT elements */ + public int v_batt() { return data16(0); } + public int sense_a() { return data16(2); } + public int sense_m() { return data16(4); } + + /* AO_LOG_GPS_POS elements */ + public int latitude() { return data32(0); } + public int longitude() { return data32(4); } + public int altitude() { return data16(8); } + + /* AO_LOG_GPS_TIME elements */ + public int hour() { return data8(0); } + public int minute() { return data8(1); } + public int second() { return data8(2); } + public int flags() { return data8(3); } + public int year() { return data8(4); } + public int month() { return data8(5); } + public int day() { return data8(6); } + + /* AO_LOG_GPS_SAT elements */ + public int nsat() { return data8(0); } + public int more() { return data8(1); } + public int svid(int n) { return data8(2 + n * 2); } + public int c_n(int n) { return data8(2 + n * 2 + 1); } + + public AltosEepromMetrum2 (AltosEepromChunk chunk, int start) throws ParseException { + parse_chunk(chunk, start); + } + + public void update_state(AltosState state) { + AltosGPS gps; + + /* Flush any pending GPS changes */ + if (state.gps_pending) { + switch (cmd) { + case AltosLib.AO_LOG_GPS_POS: + case AltosLib.AO_LOG_GPS_LAT: + case AltosLib.AO_LOG_GPS_LON: + case AltosLib.AO_LOG_GPS_ALT: + case AltosLib.AO_LOG_GPS_SAT: + case AltosLib.AO_LOG_GPS_DATE: + break; + default: + state.set_temp_gps(); + break; + } + } + + if (cmd != AltosLib.AO_LOG_FLIGHT) + state.set_tick(tick); + switch (cmd) { + case AltosLib.AO_LOG_FLIGHT: + state.set_boost_tick(tick); + state.set_flight(flight()); + state.set_ground_accel(ground_accel()); + state.set_ground_pressure(ground_pres()); +// state.set_temperature(ground_temp() / 100.0); + break; + case AltosLib.AO_LOG_STATE: + state.set_state(state()); + break; + case AltosLib.AO_LOG_SENSOR: + state.set_ms5607(pres(), temp()); + state.set_accel(accel()); + + break; + case AltosLib.AO_LOG_TEMP_VOLT: + state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); + + state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a())); + state.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m())); + + break; + case AltosLib.AO_LOG_GPS_POS: + gps = state.make_temp_gps(); + gps.lat = latitude() / 1e7; + gps.lon = longitude() / 1e7; + gps.alt = altitude(); + break; + case AltosLib.AO_LOG_GPS_TIME: + gps = state.make_temp_gps(); + + gps.hour = hour(); + gps.minute = minute(); + gps.second = second(); + + int flags = flags(); + + gps.connected = (flags & AltosLib.AO_GPS_RUNNING) != 0; + gps.locked = (flags & AltosLib.AO_GPS_VALID) != 0; + gps.nsat = (flags & AltosLib.AO_GPS_NUM_SAT_MASK) >> + AltosLib.AO_GPS_NUM_SAT_SHIFT; + + gps.year = year(); + gps.month = month(); + gps.day = day(); + break; + case AltosLib.AO_LOG_GPS_SAT: + state.set_tick(tick); + gps = state.make_temp_gps(); + + int n = nsat(); + for (int i = 0; i < n; i++) + gps.add_sat(svid(i), c_n(i)); + break; + } + } + + public AltosEepromMetrum2 (String line) { + parse_string(line); + } + + static public LinkedList read(FileInputStream input) { + LinkedList megas = new LinkedList(); + + for (;;) { + try { + String line = AltosLib.gets(input); + if (line == null) + break; + try { + AltosEepromMetrum2 mega = new AltosEepromMetrum2(line); + if (mega.cmd != AltosLib.AO_LOG_INVALID) + megas.add(mega); + } catch (Exception e) { + System.out.printf ("exception\n"); + } + } catch (IOException ie) { + break; + } + } + + return megas; + } +} diff --git a/altoslib/AltosEepromHeader.java b/altoslib/AltosEepromHeader.java index a06f05ed..35a03a12 100644 --- a/altoslib/AltosEepromHeader.java +++ b/altoslib/AltosEepromHeader.java @@ -29,6 +29,9 @@ public class AltosEepromHeader extends AltosEeprom { public boolean last; public boolean valid; + public int record_length () { return 0; } + + /* XXX pull rest of config data to state */ public void update_state(AltosState state) { switch (cmd) { case AltosLib.AO_LOG_CONFIG_VERSION: @@ -40,7 +43,7 @@ public class AltosEepromHeader extends AltosEeprom { case AltosLib.AO_LOG_RADIO_CHANNEL: break; case AltosLib.AO_LOG_CALLSIGN: - state.callsign = data; + state.set_callsign(data); break; case AltosLib.AO_LOG_ACCEL_CAL: state.set_accel_g(config_a, config_b); @@ -90,6 +93,7 @@ public class AltosEepromHeader extends AltosEeprom { state.baro.crc = config_a; break; case AltosLib.AO_LOG_SOFTWARE_VERSION: + state.set_firmware_version(data); break; } } diff --git a/altoslib/AltosEepromMega.java b/altoslib/AltosEepromMega.java index 0804c392..e8f9b1fc 100644 --- a/altoslib/AltosEepromMega.java +++ b/altoslib/AltosEepromMega.java @@ -17,32 +17,14 @@ package org.altusmetrum.altoslib_1; +import java.io.*; +import java.util.*; import java.text.*; -public class AltosEepromMega { - public int cmd; - public int tick; - public boolean valid; - public String data; - public int config_a, config_b; - - public int data8[]; - +public class AltosEepromMega extends AltosEeprom { public static final int record_length = 32; - static final int header_length = 4; - static final int data_length = record_length - header_length; - - public int data8(int i) { - return data8[i]; - } - public int data16(int i) { - return ((data8[i] | (data8[i+1] << 8)) << 16) >> 16; - } - - public int data32(int i) { - return data8[i] | (data8[i+1] << 8) | (data8[i+2] << 16) | (data8[i+3] << 24); - } + public int record_length() { return record_length; } /* AO_LOG_FLIGHT elements */ public int flight() { return data16(0); } @@ -68,7 +50,7 @@ public class AltosEepromMega { public int mag_z() { return data16(24); } public int accel() { return data16(26); } - /* AO_LOG_VOLT elements */ + /* AO_LOG_TEMP_VOLT elements */ public int v_batt() { return data16(0); } public int v_pbatt() { return data16(2); } public int nsense() { return data16(4); } @@ -91,131 +73,137 @@ public class AltosEepromMega { public int nsat() { return data16(0); } public int svid(int n) { return data8(2 + n * 2); } public int c_n(int n) { return data8(2 + n * 2 + 1); } + public AltosEepromMega (AltosEepromChunk chunk, int start) throws ParseException { - cmd = chunk.data(start); - - valid = !chunk.erased(start, record_length); - if (valid) { - if (AltosConvert.checksum(chunk.data, start, record_length) != 0) - throw new ParseException(String.format("invalid checksum at 0x%x", - chunk.address + start), 0); - } else { - cmd = AltosLib.AO_LOG_INVALID; - } + parse_chunk(chunk, start); + } - tick = chunk.data16(start+2); + public void update_state(AltosState state) { + AltosGPS gps; + + /* Flush any pending GPS changes */ + if (state.gps_pending) { + switch (cmd) { + case AltosLib.AO_LOG_GPS_LAT: + case AltosLib.AO_LOG_GPS_LON: + case AltosLib.AO_LOG_GPS_ALT: + case AltosLib.AO_LOG_GPS_SAT: + case AltosLib.AO_LOG_GPS_DATE: + break; + default: + state.set_temp_gps(); + break; + } + } - data8 = new int[data_length]; - for (int i = 0; i < data_length; i++) - data8[i] = chunk.data(start + header_length + i); + switch (cmd) { + case AltosLib.AO_LOG_FLIGHT: + state.set_boost_tick(tick); + state.set_flight(flight()); + state.set_ground_accel(ground_accel()); + state.set_ground_pressure(ground_pres()); + state.set_temperature(ground_temp() / 100.0); + break; + case AltosLib.AO_LOG_STATE: + state.set_tick(tick); + state.set_state(state()); + break; + case AltosLib.AO_LOG_SENSOR: + state.set_tick(tick); + state.set_ms5607(pres(), temp()); + + AltosIMU imu = new AltosIMU(); + imu.accel_x = accel_x(); + imu.accel_y = accel_y(); + imu.accel_z = accel_z(); + + imu.gyro_x = gyro_x(); + imu.gyro_y = gyro_y(); + imu.gyro_z = gyro_z(); + state.imu = imu; + + AltosMag mag = new AltosMag(); + mag.x = mag_x(); + mag.y = mag_y(); + mag.z = mag_z(); + + state.mag = mag; + + state.set_accel(accel()); + + break; + case AltosLib.AO_LOG_TEMP_VOLT: + state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); + state.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pbatt())); + + int nsense = nsense(); + + state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-2))); + state.set_main_voltage(AltosConvert.mega_pyro_voltage(sense(nsense-1))); + + double voltages[] = new double[nsense-2]; + for (int i = 0; i < nsense-2; i++) + voltages[i] = AltosConvert.mega_pyro_voltage(sense(i)); + + state.set_ignitor_voltage(voltages); + break; + case AltosLib.AO_LOG_GPS_TIME: + state.set_tick(tick); + gps = state.make_temp_gps(); + gps.lat = latitude() / 1e7; + gps.lon = longitude() / 1e7; + gps.alt = altitude(); + + gps.hour = hour(); + gps.minute = minute(); + gps.second = second(); + + int flags = flags(); + + gps.connected = (flags & AltosLib.AO_GPS_RUNNING) != 0; + gps.locked = (flags & AltosLib.AO_GPS_VALID) != 0; + gps.nsat = (flags & AltosLib.AO_GPS_NUM_SAT_MASK) >> + AltosLib.AO_GPS_NUM_SAT_SHIFT; + + gps.year = year(); + gps.month = month(); + gps.day = day(); + break; + case AltosLib.AO_LOG_GPS_SAT: + state.set_tick(tick); + gps = state.make_temp_gps(); + + int n = nsat(); + for (int i = 0; i < n; i++) + gps.add_sat(svid(i), c_n(i)); + break; + } } public AltosEepromMega (String line) { - valid = false; - tick = 0; + parse_string(line); + } - if (line == null) { - cmd = AltosLib.AO_LOG_INVALID; - line = ""; - } else { + static public LinkedList read(FileInputStream input) { + LinkedList megas = new LinkedList(); + + for (;;) { try { - String[] tokens = line.split("\\s+"); - - if (tokens[0].length() == 1) { - if (tokens.length != 2 + data_length) { - cmd = AltosLib.AO_LOG_INVALID; - data = line; - } else { - cmd = tokens[0].codePointAt(0); - tick = Integer.parseInt(tokens[1],16); - valid = true; - data8 = new int[data_length]; - for (int i = 0; i < data_length; i++) - data8[i] = Integer.parseInt(tokens[2 + i],16); - } - } else if (tokens[0].equals("Config") && tokens[1].equals("version:")) { - cmd = AltosLib.AO_LOG_CONFIG_VERSION; - data = tokens[2]; - } else if (tokens[0].equals("Main") && tokens[1].equals("deploy:")) { - cmd = AltosLib.AO_LOG_MAIN_DEPLOY; - config_a = Integer.parseInt(tokens[2]); - } else if (tokens[0].equals("Apogee") && tokens[1].equals("delay:")) { - cmd = AltosLib.AO_LOG_APOGEE_DELAY; - config_a = Integer.parseInt(tokens[2]); - } else if (tokens[0].equals("Radio") && tokens[1].equals("channel:")) { - cmd = AltosLib.AO_LOG_RADIO_CHANNEL; - config_a = Integer.parseInt(tokens[2]); - } else if (tokens[0].equals("Callsign:")) { - cmd = AltosLib.AO_LOG_CALLSIGN; - data = tokens[1].replaceAll("\"",""); - } else if (tokens[0].equals("Accel") && tokens[1].equals("cal")) { - cmd = AltosLib.AO_LOG_ACCEL_CAL; - config_a = Integer.parseInt(tokens[3]); - config_b = Integer.parseInt(tokens[5]); - } else if (tokens[0].equals("Radio") && tokens[1].equals("cal:")) { - cmd = AltosLib.AO_LOG_RADIO_CAL; - config_a = Integer.parseInt(tokens[2]); - } else if (tokens[0].equals("Max") && tokens[1].equals("flight") && tokens[2].equals("log:")) { - cmd = AltosLib.AO_LOG_MAX_FLIGHT_LOG; - config_a = Integer.parseInt(tokens[3]); - } else if (tokens[0].equals("manufacturer")) { - cmd = AltosLib.AO_LOG_MANUFACTURER; - data = tokens[1]; - } else if (tokens[0].equals("product")) { - cmd = AltosLib.AO_LOG_PRODUCT; - data = tokens[1]; - } else if (tokens[0].equals("serial-number")) { - cmd = AltosLib.AO_LOG_SERIAL_NUMBER; - config_a = Integer.parseInt(tokens[1]); - } else if (tokens[0].equals("log-format")) { - cmd = AltosLib.AO_LOG_LOG_FORMAT; - config_a = Integer.parseInt(tokens[1]); - } else if (tokens[0].equals("software-version")) { - cmd = AltosLib.AO_LOG_SOFTWARE_VERSION; - data = tokens[1]; - } else if (tokens[0].equals("ms5607")) { - if (tokens[1].equals("reserved:")) { - cmd = AltosLib.AO_LOG_BARO_RESERVED; - config_a = Integer.parseInt(tokens[2]); - } else if (tokens[1].equals("sens:")) { - cmd = AltosLib.AO_LOG_BARO_SENS; - config_a = Integer.parseInt(tokens[2]); - } else if (tokens[1].equals("off:")) { - cmd = AltosLib.AO_LOG_BARO_OFF; - config_a = Integer.parseInt(tokens[2]); - } else if (tokens[1].equals("tcs:")) { - cmd = AltosLib.AO_LOG_BARO_TCS; - config_a = Integer.parseInt(tokens[2]); - } else if (tokens[1].equals("tco:")) { - cmd = AltosLib.AO_LOG_BARO_TCO; - config_a = Integer.parseInt(tokens[2]); - } else if (tokens[1].equals("tref:")) { - cmd = AltosLib.AO_LOG_BARO_TREF; - config_a = Integer.parseInt(tokens[2]); - } else if (tokens[1].equals("tempsens:")) { - cmd = AltosLib.AO_LOG_BARO_TEMPSENS; - config_a = Integer.parseInt(tokens[2]); - } else if (tokens[1].equals("crc:")) { - cmd = AltosLib.AO_LOG_BARO_CRC; - config_a = Integer.parseInt(tokens[2]); - } else { - cmd = AltosLib.AO_LOG_INVALID; - data = line; - } - } else { - cmd = AltosLib.AO_LOG_INVALID; - data = line; + String line = AltosLib.gets(input); + if (line == null) + break; + try { + AltosEepromMega mega = new AltosEepromMega(line); + if (mega.cmd != AltosLib.AO_LOG_INVALID) + megas.add(mega); + } catch (Exception e) { + System.out.printf ("exception\n"); } - } catch (NumberFormatException ne) { - cmd = AltosLib.AO_LOG_INVALID; - data = line; + } catch (IOException ie) { + break; } } - } - public AltosEepromMega(int in_cmd, int in_tick) { - cmd = in_cmd; - tick = in_tick; - valid = true; + return megas; } } diff --git a/altoslib/AltosEepromMetrum.java b/altoslib/AltosEepromMetrum.java index 72887032..e035e5fd 100644 --- a/altoslib/AltosEepromMetrum.java +++ b/altoslib/AltosEepromMetrum.java @@ -32,6 +32,8 @@ public class AltosEepromMetrum { static final int header_length = 4; static final int data_length = record_length - header_length; + public int record_length() { return record_length; } + public int data8(int i) { return data8[i]; } diff --git a/altoslib/AltosEepromMetrum2.java b/altoslib/AltosEepromMetrum2.java new file mode 100644 index 00000000..5a616e6c --- /dev/null +++ b/altoslib/AltosEepromMetrum2.java @@ -0,0 +1,178 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_1; + +import java.io.*; +import java.util.*; +import java.text.*; + +public class AltosEepromMetrum2 extends AltosEeprom { + public static final int record_length = 16; + + public int record_length() { return record_length; } + + /* AO_LOG_FLIGHT elements */ + public int flight() { return data16(0); } + public int ground_accel() { return data16(2); } + public int ground_pres() { return data32(4); } + public int ground_temp() { return data32(8); } + + /* AO_LOG_STATE elements */ + public int state() { return data16(0); } + public int reason() { return data16(2); } + + /* AO_LOG_SENSOR elements */ + public int pres() { return data32(0); } + public int temp() { return data32(4); } + public int accel() { return data16(8); } + + /* AO_LOG_TEMP_VOLT elements */ + public int v_batt() { return data16(0); } + public int sense_a() { return data16(2); } + public int sense_m() { return data16(4); } + + /* AO_LOG_GPS_POS elements */ + public int latitude() { return data32(0); } + public int longitude() { return data32(4); } + public int altitude() { return data16(8); } + + /* AO_LOG_GPS_TIME elements */ + public int hour() { return data8(0); } + public int minute() { return data8(1); } + public int second() { return data8(2); } + public int flags() { return data8(3); } + public int year() { return data8(4); } + public int month() { return data8(5); } + public int day() { return data8(6); } + + /* AO_LOG_GPS_SAT elements */ + public int nsat() { return data8(0); } + public int more() { return data8(1); } + public int svid(int n) { return data8(2 + n * 2); } + public int c_n(int n) { return data8(2 + n * 2 + 1); } + + public AltosEepromMetrum2 (AltosEepromChunk chunk, int start) throws ParseException { + parse_chunk(chunk, start); + } + + public void update_state(AltosState state) { + AltosGPS gps; + + /* Flush any pending GPS changes */ + if (state.gps_pending) { + switch (cmd) { + case AltosLib.AO_LOG_GPS_POS: + case AltosLib.AO_LOG_GPS_LAT: + case AltosLib.AO_LOG_GPS_LON: + case AltosLib.AO_LOG_GPS_ALT: + case AltosLib.AO_LOG_GPS_SAT: + case AltosLib.AO_LOG_GPS_DATE: + break; + default: + state.set_temp_gps(); + break; + } + } + + if (cmd != AltosLib.AO_LOG_FLIGHT) + state.set_tick(tick); + switch (cmd) { + case AltosLib.AO_LOG_FLIGHT: + state.set_boost_tick(tick); + state.set_flight(flight()); + state.set_ground_accel(ground_accel()); + state.set_ground_pressure(ground_pres()); +// state.set_temperature(ground_temp() / 100.0); + break; + case AltosLib.AO_LOG_STATE: + state.set_state(state()); + break; + case AltosLib.AO_LOG_SENSOR: + state.set_ms5607(pres(), temp()); + state.set_accel(accel()); + + break; + case AltosLib.AO_LOG_TEMP_VOLT: + state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt())); + + state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a())); + state.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m())); + + break; + case AltosLib.AO_LOG_GPS_POS: + gps = state.make_temp_gps(); + gps.lat = latitude() / 1e7; + gps.lon = longitude() / 1e7; + gps.alt = altitude(); + break; + case AltosLib.AO_LOG_GPS_TIME: + gps = state.make_temp_gps(); + + gps.hour = hour(); + gps.minute = minute(); + gps.second = second(); + + int flags = flags(); + + gps.connected = (flags & AltosLib.AO_GPS_RUNNING) != 0; + gps.locked = (flags & AltosLib.AO_GPS_VALID) != 0; + gps.nsat = (flags & AltosLib.AO_GPS_NUM_SAT_MASK) >> + AltosLib.AO_GPS_NUM_SAT_SHIFT; + + gps.year = year(); + gps.month = month(); + gps.day = day(); + break; + case AltosLib.AO_LOG_GPS_SAT: + state.set_tick(tick); + gps = state.make_temp_gps(); + + int n = nsat(); + for (int i = 0; i < n; i++) + gps.add_sat(svid(i), c_n(i)); + break; + } + } + + public AltosEepromMetrum2 (String line) { + parse_string(line); + } + + static public LinkedList read(FileInputStream input) { + LinkedList megas = new LinkedList(); + + for (;;) { + try { + String line = AltosLib.gets(input); + if (line == null) + break; + try { + AltosEepromMetrum2 mega = new AltosEepromMetrum2(line); + if (mega.cmd != AltosLib.AO_LOG_INVALID) + megas.add(mega); + } catch (Exception e) { + System.out.printf ("exception\n"); + } + } catch (IOException ie) { + break; + } + } + + return megas; + } +} diff --git a/altoslib/AltosEepromMini.java b/altoslib/AltosEepromMini.java index 1e0ff1b9..15ec1929 100644 --- a/altoslib/AltosEepromMini.java +++ b/altoslib/AltosEepromMini.java @@ -24,21 +24,7 @@ import java.text.*; public class AltosEepromMini extends AltosEeprom { public static final int record_length = 16; - public int data8(int i) { - return data8[i]; - } - - public int data16(int i) { - return ((data8[i] | (data8[i+1] << 8)) << 16) >> 16; - } - - public int data24(int i) { - return data8[i] | (data8[i+1] << 8) | (data8[i+2] << 16); - } - - public int data32(int i) { - return data8[i] | (data8[i+1] << 8) | (data8[i+2] << 16) | (data8[i+3] << 24); - } + public int record_length() { return record_length; } /* AO_LOG_FLIGHT elements */ public int flight() { return data16(0); } @@ -84,11 +70,11 @@ public class AltosEepromMini extends AltosEeprom { } public AltosEepromMini (AltosEepromChunk chunk, int start) throws ParseException { - parse_chunk(chunk, start, record_length); + parse_chunk(chunk, start); } public AltosEepromMini (String line) { - parse_string(line, record_length); + parse_string(line); } public AltosEepromMini(int in_cmd, int in_tick) { diff --git a/altoslib/AltosEepromTM.java b/altoslib/AltosEepromTM.java index 6945468b..461a7a9c 100644 --- a/altoslib/AltosEepromTM.java +++ b/altoslib/AltosEepromTM.java @@ -30,16 +30,16 @@ public class AltosEepromTM extends AltosEeprom { public static final int record_length = 8; - static double - thermometer_to_temperature(double thermo) - { - return (thermo - 19791.268) / 32728.0 * 1.25 / 0.00247; - } - public void write(PrintStream out) { out.printf("%c %4x %4x %4x\n", cmd, tick, a, b); } + public int record_length() { return record_length; } + + public String string() { + return String.format("%c %4x %4x %4x\n", cmd, tick, a, b); + } + public void update_state(AltosState state) { AltosGPS gps; @@ -77,7 +77,7 @@ public class AltosEepromTM extends AltosEeprom { break; case AltosLib.AO_LOG_TEMP_VOLT: state.set_tick(tick); - state.set_temperature(thermometer_to_temperature(a)); + state.set_temperature(AltosConvert.thermometer_to_temperature(a)); state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(b)); break; case AltosLib.AO_LOG_DEPLOY: diff --git a/altoslib/AltosEepromTeleScience.java b/altoslib/AltosEepromTeleScience.java index 2a828cf3..bacd66b5 100644 --- a/altoslib/AltosEepromTeleScience.java +++ b/altoslib/AltosEepromTeleScience.java @@ -33,6 +33,8 @@ public class AltosEepromTeleScience { static final int max_data = 12; public static final int record_length = 32; + public int record_length() { return record_length; } + public AltosEepromTeleScience (AltosEepromChunk chunk, int start) throws ParseException { type = chunk.data(start); diff --git a/altoslib/AltosGPS.java b/altoslib/AltosGPS.java index 399e95b1..a8c19e4a 100644 --- a/altoslib/AltosGPS.java +++ b/altoslib/AltosGPS.java @@ -65,8 +65,8 @@ public class AltosGPS implements Cloneable { } public void ClearGPSTime() { - year = month = day = 0; - hour = minute = second = 0; + year = month = day = AltosRecord.MISSING; + hour = minute = second = AltosRecord.MISSING; } public AltosGPS(AltosTelemetryMap map) throws ParseException { @@ -212,6 +212,9 @@ public class AltosGPS implements Cloneable { } public AltosGPS() { + lat = AltosRecord.MISSING; + lon = AltosRecord.MISSING; + alt = AltosRecord.MISSING; ClearGPSTime(); cc_gps_sat = null; } @@ -280,6 +283,9 @@ public class AltosGPS implements Cloneable { } } } else { + lat = AltosRecord.MISSING; + lon = AltosRecord.MISSING; + alt = AltosRecord.MISSING; ClearGPSTime(); cc_gps_sat = null; } diff --git a/altoslib/AltosLib.java b/altoslib/AltosLib.java index 4ca8ad9d..d6d78ca8 100644 --- a/altoslib/AltosLib.java +++ b/altoslib/AltosLib.java @@ -28,6 +28,7 @@ public class AltosLib { public static final int AO_LOG_TEMP_VOLT = 'T'; public static final int AO_LOG_DEPLOY = 'D'; public static final int AO_LOG_STATE = 'S'; + public static final int AO_LOG_GPS_POS = 'P'; public static final int AO_LOG_GPS_TIME = 'G'; public static final int AO_LOG_GPS_LAT = 'N'; public static final int AO_LOG_GPS_LON = 'W'; diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index aa3de432..b80d7b2e 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -32,7 +32,7 @@ public class AltosState implements Cloneable { /* derived data */ - public long report_time; + public long received_time; public double time; public double prev_time; @@ -48,6 +48,12 @@ public class AltosState implements Cloneable { public boolean boost; /* under power */ public int rssi; public int status; + public int device_type; + public int config_major; + public int config_minor; + public int apogee_delay; + public int main_deploy; + public int flight_log_max; public double ground_altitude; public double ground_pressure; @@ -61,11 +67,16 @@ public class AltosState implements Cloneable { public double apogee_voltage; public double main_voltage; public double speed; + public double ignitor_voltage[]; public double prev_height; public double prev_speed; public double prev_acceleration; + public double prev_max_height; + public double prev_max_acceleration; + public double prev_max_speed; + public double max_height; public double max_acceleration; public double max_speed; @@ -100,6 +111,8 @@ public class AltosState implements Cloneable { public double speak_altitude; public String callsign; + public String firmware_version; + public double accel_plus_g; public double accel_minus_g; public double accel; @@ -133,7 +146,7 @@ public class AltosState implements Cloneable { set = 0; - report_time = System.currentTimeMillis(); + received_time = System.currentTimeMillis(); time = AltosRecord.MISSING; time_change = AltosRecord.MISSING; prev_time = AltosRecord.MISSING; @@ -145,6 +158,12 @@ public class AltosState implements Cloneable { boost = false; rssi = AltosRecord.MISSING; status = 0; + device_type = AltosRecord.MISSING; + config_major = AltosRecord.MISSING; + config_minor = AltosRecord.MISSING; + apogee_delay = AltosRecord.MISSING; + main_deploy = AltosRecord.MISSING; + flight_log_max = AltosRecord.MISSING; ground_altitude = AltosRecord.MISSING; ground_pressure = AltosRecord.MISSING; @@ -158,10 +177,15 @@ public class AltosState implements Cloneable { prev_speed = AltosRecord.MISSING; prev_acceleration = AltosRecord.MISSING; + prev_max_height = 0; + prev_max_speed = 0; + prev_max_acceleration = 0; + battery_voltage = AltosRecord.MISSING; pyro_voltage = AltosRecord.MISSING; apogee_voltage = AltosRecord.MISSING; main_voltage = AltosRecord.MISSING; + ignitor_voltage = null; speed = AltosRecord.MISSING; @@ -219,7 +243,7 @@ public class AltosState implements Cloneable { return; } - report_time = old.report_time; + received_time = old.received_time; time = old.time; time_change = 0; tick = old.tick; @@ -232,6 +256,12 @@ public class AltosState implements Cloneable { boost = old.boost; rssi = old.rssi; status = old.status; + device_type = old.device_type; + config_major = old.config_major; + config_minor = old.config_minor; + apogee_delay = old.apogee_delay; + main_deploy = old.main_deploy; + flight_log_max = old.flight_log_max; set = 0; @@ -245,11 +275,16 @@ public class AltosState implements Cloneable { temperature = old.temperature; apogee_voltage = old.apogee_voltage; main_voltage = old.main_voltage; + ignitor_voltage = old.ignitor_voltage; speed = old.speed; prev_height = old.height; prev_speed = old.speed; prev_acceleration = old.acceleration; + + prev_max_height = old.max_height; + prev_max_speed = old.max_speed; + prev_max_acceleration = old.max_acceleration; prev_time = old.time; max_height = old.max_height; @@ -343,7 +378,7 @@ public class AltosState implements Cloneable { else height = AltosRecord.MISSING; - if (height != AltosRecord.MISSING && height > max_height) + if (height != AltosRecord.MISSING && height > prev_max_height) max_height = height; update_speed(); @@ -394,31 +429,34 @@ public class AltosState implements Cloneable { } } } - if (boost && speed != AltosRecord.MISSING && speed > max_speed) + if (boost && speed != AltosRecord.MISSING && speed > prev_max_speed) max_speed = speed; } void update_accel() { - double ground = ground_accel; - - if (ground == AltosRecord.MISSING) - ground = ground_accel_avg; - if (accel == AltosRecord.MISSING) - return; - if (ground == AltosRecord.MISSING) - return; - if (accel_plus_g == AltosRecord.MISSING) - return; - if (accel_minus_g == AltosRecord.MISSING) - return; - - double counts_per_g = (accel_minus_g - accel_plus_g) / 2.0; - double counts_per_mss = counts_per_g / 9.80665; - - acceleration = (ground - accel) / counts_per_mss; + if (kalman_acceleration != AltosRecord.MISSING) { + acceleration = kalman_acceleration; + } else { + double ground = ground_accel; + + if (ground == AltosRecord.MISSING) + ground = ground_accel_avg; + if (accel == AltosRecord.MISSING) + return; + if (ground == AltosRecord.MISSING) + return; + if (accel_plus_g == AltosRecord.MISSING) + return; + if (accel_minus_g == AltosRecord.MISSING) + return; + + double counts_per_g = (accel_minus_g - accel_plus_g) / 2.0; + double counts_per_mss = counts_per_g / 9.80665; + acceleration = (ground - accel) / counts_per_mss; + } /* Only look at accelerometer data under boost */ - if (boost && acceleration != AltosRecord.MISSING && (max_acceleration == AltosRecord.MISSING || acceleration > max_acceleration)) + if (boost && acceleration != AltosRecord.MISSING && acceleration > prev_max_acceleration) max_acceleration = acceleration; update_speed(); } @@ -502,6 +540,26 @@ public class AltosState implements Cloneable { } + public void set_device_type(int device_type) { + this.device_type = device_type; + } + + public void set_config(int major, int minor, int apogee_delay, int main_deploy, int flight_log_max) { + config_major = major; + config_minor = minor; + this.apogee_delay = apogee_delay; + this.main_deploy = main_deploy; + this.flight_log_max = flight_log_max; + } + + public void set_callsign(String callsign) { + this.callsign = callsign; + } + + public void set_firmware_version(String version) { + firmware_version = version; + } + public void set_flight(int flight) { /* When the flight changes, reset the state */ @@ -538,6 +596,10 @@ public class AltosState implements Cloneable { } } + public void set_received_time(long ms) { + received_time = ms; + } + public void set_altitude(double altitude) { if (altitude != AltosRecord.MISSING) { this.altitude = altitude; @@ -577,6 +639,8 @@ public class AltosState implements Cloneable { kalman_speed = speed; kalman_acceleration = acceleration; update_vertical_pos(); + update_speed(); + update_accel(); } } @@ -672,6 +736,9 @@ public class AltosState implements Cloneable { } } + public void set_ignitor_voltage(double[] voltage) { + this.ignitor_voltage = voltage; + } public double time_since_boost() { if (tick == AltosRecord.MISSING) @@ -702,6 +769,13 @@ public class AltosState implements Cloneable { temp_gps = null; } + public AltosState clone() { + AltosState s = new AltosState(); + s.copy(this); + return s; + } + + public void init (AltosRecord cur, AltosState prev_state) { System.out.printf ("init\n"); @@ -721,7 +795,7 @@ public class AltosState implements Cloneable { set_kalman(cur.kalman_height, cur.kalman_speed, cur.kalman_acceleration); - report_time = System.currentTimeMillis(); + received_time = System.currentTimeMillis(); set_temperature(cur.temperature()); set_apogee_voltage(cur.drogue_voltage()); @@ -742,12 +816,6 @@ public class AltosState implements Cloneable { } - public AltosState clone() { - AltosState s = new AltosState(); - s.copy(this); - return s; - } - public AltosState(AltosRecord cur) { init(cur, null); } @@ -756,6 +824,7 @@ public class AltosState implements Cloneable { init(cur, prev); } + public AltosState () { init(); } diff --git a/altoslib/AltosTelemetry.java b/altoslib/AltosTelemetry.java index b84455d3..82e5400e 100644 --- a/altoslib/AltosTelemetry.java +++ b/altoslib/AltosTelemetry.java @@ -43,6 +43,10 @@ public abstract class AltosTelemetry implements AltosStateUpdate { } public void update_state(AltosState state) { + state.set_serial(serial); + state.set_tick(tick); + state.set_rssi(rssi, status); + state.set_received_time(received_time); } final static int PKT_APPEND_STATUS_1_CRC_OK = (1 << 7); @@ -56,9 +60,11 @@ public abstract class AltosTelemetry implements AltosStateUpdate { final static int packet_type_location = 0x05; final static int packet_type_satellite = 0x06; final static int packet_type_companion = 0x07; - final static int packet_type_MM_sensor = 0x08; - final static int packet_type_MM_data = 0x09; - final static int packet_type_Mini = 0x10; + final static int packet_type_mega_sensor = 0x08; + final static int packet_type_mega_data = 0x09; + final static int packet_type_metrum_sensor = 0x0a; + final static int packet_type_metrum_data = 0x0b; + final static int packet_type_mini = 0x10; static AltosTelemetry parse_hex(String hex) throws ParseException, AltosCRCException { AltosTelemetry telem = null; @@ -87,37 +93,7 @@ public abstract class AltosTelemetry implements AltosStateUpdate { /* length, data ..., rssi, status, checksum -- 4 bytes extra */ switch (bytes.length) { case AltosLib.ao_telemetry_standard_len + 4: - int type = AltosLib.uint8(bytes, 4 + 1); -/* - switch (type) { - case packet_type_TM_sensor: - case packet_type_Tm_sensor: - case packet_type_Tn_sensor: - telem = new AltosTelemetrySensor(bytes); - break; - case packet_type_configuration: - telem = new AltosTelemetryConfiguration(bytes); - break; - case packet_type_location: - telem = new AltosTelemetryLocation(bytes); - break; - case packet_type_satellite: - telem = new AltosTelemetrySatellite(bytes); - break; - case packet_type_companion: - telem = new AltosTelemetryCompanion(bytes); - break; - case packet_type_MM_sensor: - telem = new AltosTelemetryMegaSensor(bytes); - break; - case packet_type_MM_data: - telem = new AltosTelemetryMegaData(bytes); - break; - default: - telem = new AltosTelemetryRaw(bytes); - break; - } -*/ + telem = AltosTelemetryStandard.parse_hex(bytes); break; case AltosLib.ao_telemetry_0_9_len + 4: telem = new AltosTelemetryLegacy(bytes); diff --git a/altoslib/AltosTelemetryConfiguration.java b/altoslib/AltosTelemetryConfiguration.java new file mode 100644 index 00000000..4c9bdd1f --- /dev/null +++ b/altoslib/AltosTelemetryConfiguration.java @@ -0,0 +1,55 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_1; + + +public class AltosTelemetryConfiguration extends AltosTelemetryStandard { + int device_type; + int flight; + int config_major; + int config_minor; + int apogee_delay; + int main_deploy; + int flight_log_max; + String callsign; + String version; + + public AltosTelemetryConfiguration(int[] bytes) { + super(bytes); + + device_type = uint8(5); + flight = uint16(6); + config_major = uint8(8); + config_minor = uint8(9); + apogee_delay = uint16(10); + main_deploy = uint16(12); + flight_log_max = uint16(14); + callsign = string(16, 8); + version = string(24, 8); + } + + public void update_state(AltosState state) { + super.update_state(state); + state.set_device_type(device_type); + state.set_flight(flight); + state.set_config(config_major, config_minor, apogee_delay, main_deploy, flight_log_max); + + state.set_callsign(callsign); + state.set_firmware_version(version); + } +} diff --git a/altoslib/AltosTelemetryLegacy.java b/altoslib/AltosTelemetryLegacy.java index 45e5c315..95cbbeed 100644 --- a/altoslib/AltosTelemetryLegacy.java +++ b/altoslib/AltosTelemetryLegacy.java @@ -546,7 +546,7 @@ public class AltosTelemetryLegacy extends AltosTelemetry { state.set_accel(accel); if (kalman_height != AltosRecord.MISSING) state.set_kalman(kalman_height, kalman_speed, kalman_acceleration); - state.set_temperature(AltosEepromTM.thermometer_to_temperature(temp)); + state.set_temperature(AltosConvert.thermometer_to_temperature(temp)); state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(batt)); state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(apogee)); state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(main)); diff --git a/altoslib/AltosTelemetryLocation.java b/altoslib/AltosTelemetryLocation.java new file mode 100644 index 00000000..fa3c24d0 --- /dev/null +++ b/altoslib/AltosTelemetryLocation.java @@ -0,0 +1,88 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_1; + + +public class AltosTelemetryLocation extends AltosTelemetryStandard { + int flags; + int altitude; + int latitude; + int longitude; + int year; + int month; + int day; + int hour; + int minute; + int second; + int pdop; + int hdop; + int vdop; + int mode; + int ground_speed; + int climb_rate; + int course; + + public AltosTelemetryLocation(int[] bytes) { + super(bytes); + + flags = uint8(5); + altitude = int16(6); + latitude = uint32(8); + longitude = uint32(12); + year = uint8(16); + month = uint8(17); + day = uint8(18); + hour = uint8(19); + minute = uint8(20); + second = uint8(21); + pdop = uint8(22); + hdop = uint8(23); + vdop = uint8(24); + mode = uint8(25); + ground_speed = uint16(26); + climb_rate = int16(28); + course = uint8(30); + } + + public void update_state(AltosState state) { + super.update_state(state); + AltosGPS gps = state.make_temp_gps(); + + gps.nsat = flags & 0xf; + gps.locked = (flags & (1 << 4)) != 0; + gps.connected = (flags & (1 << 5)) != 0; + + if (gps.locked) { + gps.lat = latitude * 1.0e-7; + gps.lon = longitude * 1.0e-7; + gps.alt = altitude; + gps.year = 2000 + year; + gps.month = month; + gps.day = day; + gps.hour = hour; + gps.minute = minute; + gps.second = second; + gps.ground_speed = ground_speed * 1.0e-2; + gps.course = course * 2; + gps.climb_rate = climb_rate * 1.0e-2; + gps.hdop = hdop; + gps.vdop = vdop; + } + state.set_temp_gps(); + } +} diff --git a/altoslib/AltosTelemetryMegaData.java b/altoslib/AltosTelemetryMegaData.java new file mode 100644 index 00000000..5e6cd580 --- /dev/null +++ b/altoslib/AltosTelemetryMegaData.java @@ -0,0 +1,85 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_1; + +public class AltosTelemetryMegaData extends AltosTelemetryStandard { + int state; + + int v_batt; + int v_pyro; + int sense[]; + + int ground_pres; + int ground_accel; + int accel_plus_g; + int accel_minus_g; + + int acceleration; + int speed; + int height; + + public AltosTelemetryMegaData(int[] bytes) { + super(bytes); + + state = int8(5); + + v_batt = int16(6); + v_pyro = int16(8); + + sense = new int[6]; + + for (int i = 0; i < 6; i++) { + sense[i] = int8(10 + i) << 4; + sense[i] |= sense[i] >> 8; + } + + ground_pres = int32(16); + ground_accel = int16(20); + accel_plus_g = int16(22); + accel_minus_g = int16(24); + + acceleration = int16(26); + speed = int16(28); + height = int16(30); + } + + public void update_state(AltosState state) { + super.update_state(state); + + state.set_state(this.state); + + state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt)); + state.set_pyro_voltage(AltosConvert.mega_pyro_voltage(v_pyro)); + + state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense[4])); + state.set_main_voltage(AltosConvert.mega_pyro_voltage(sense[5])); + + double voltages[] = new double[4]; + for (int i = 0; i < 4; i++) + voltages[i] = AltosConvert.mega_pyro_voltage(sense[i]); + + state.set_ignitor_voltage(voltages); + + state.set_ground_accel(ground_accel); + state.set_ground_pressure(ground_pres); + state.set_accel_g(accel_plus_g, accel_minus_g); + + state.set_kalman(height, speed/16.0, acceleration / 16.0); + } +} + diff --git a/altoslib/AltosTelemetryMegaSensor.java b/altoslib/AltosTelemetryMegaSensor.java new file mode 100644 index 00000000..7c385cfd --- /dev/null +++ b/altoslib/AltosTelemetryMegaSensor.java @@ -0,0 +1,84 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_1; + +public class AltosTelemetryMegaSensor extends AltosTelemetryStandard { + int accel; + int pres; + int temp; + + int accel_x; + int accel_y; + int accel_z; + + int gyro_x; + int gyro_y; + int gyro_z; + + int mag_x; + int mag_y; + int mag_z; + + public AltosTelemetryMegaSensor(int[] bytes) { + super(bytes); + + accel = int16(6); + pres = int32(8); + temp = int16(12); + + accel_x = int16(14); + accel_y = int16(16); + accel_z = int16(18); + + gyro_x = int16(20); + gyro_y = int16(22); + gyro_z = int16(24); + + mag_x = int16(26); + mag_y = int16(28); + mag_z = int16(30); + } + + public void update_state(AltosState state) { + super.update_state(state); + + state.set_accel(accel); + state.set_pressure(pres); + state.set_temperature(temp / 100.0); + + AltosIMU imu = new AltosIMU(); + + imu.accel_x = accel_x; + imu.accel_y = accel_y; + imu.accel_z = accel_z; + + imu.gyro_x = gyro_x; + imu.gyro_y = gyro_y; + imu.gyro_z = gyro_z; + + state.imu = imu; + + AltosMag mag = new AltosMag(); + + mag.x = mag_x; + mag.y = mag_y; + mag.z = mag_z; + + state.mag = mag; + } +} diff --git a/altoslib/AltosTelemetryMetrumData.java b/altoslib/AltosTelemetryMetrumData.java new file mode 100644 index 00000000..d419ab80 --- /dev/null +++ b/altoslib/AltosTelemetryMetrumData.java @@ -0,0 +1,42 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_1; + + +public class AltosTelemetryMetrumData extends AltosTelemetryStandard { + + int ground_pres; + int ground_accel; + int accel_plus_g; + int accel_minus_g; + + public AltosTelemetryMetrumData(int[] bytes) { + super(bytes); + + ground_pres = int32(8); + ground_accel = int16(12); + accel_plus_g = int16(14); + accel_minus_g = int16(16); + } + + public void update_state(AltosState state) { + state.set_ground_accel(ground_accel); + state.set_accel_g(accel_plus_g, accel_minus_g); + state.set_ground_pressure(ground_pres); + } +} diff --git a/altoslib/AltosTelemetryMetrumSensor.java b/altoslib/AltosTelemetryMetrumSensor.java new file mode 100644 index 00000000..59d34dba --- /dev/null +++ b/altoslib/AltosTelemetryMetrumSensor.java @@ -0,0 +1,69 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_1; + + +public class AltosTelemetryMetrumSensor extends AltosTelemetryStandard { + int state; + + int accel; + int pres; + int temp; + + int acceleration; + int speed; + int height; + + int v_batt; + int sense_a; + int sense_m; + + public AltosTelemetryMetrumSensor(int[] bytes) { + super(bytes); + + state = int8(5); + accel = int16(6); + pres = int32(8); + temp = int16(12); + + acceleration = int16(14); + speed = int16(16); + height = int16(18); + + v_batt = int16(20); + sense_a = int16(22); + sense_m = int16(24); + } + + public void update_state(AltosState state) { + super.update_state(state); + + state.set_state(this.state); + + state.set_accel(accel); + state.set_ms5607(pres, temp); + + state.set_kalman(height, speed/16.0, acceleration/16.0); + + state.set_battery_voltage(AltosConvert.mega_battery_voltage(v_batt)); + + state.set_apogee_voltage(AltosConvert.mega_pyro_voltage(sense_a)); + state.set_main_voltage(AltosConvert.mega_pyro_voltage(sense_m)); + System.out.printf ("sense_a %d apogee voltage %g\n", sense_a, state.apogee_voltage); + } +} diff --git a/altoslib/AltosTelemetryRaw.java b/altoslib/AltosTelemetryRaw.java new file mode 100644 index 00000000..9ef7787e --- /dev/null +++ b/altoslib/AltosTelemetryRaw.java @@ -0,0 +1,28 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_1; + +public class AltosTelemetryRaw extends AltosTelemetryStandard { + public AltosTelemetryRaw(int[] bytes) { + super(bytes); + } + + public void update_state(AltosState state) { + super.update_state(state); + } +} diff --git a/altoslib/AltosTelemetrySatellite.java b/altoslib/AltosTelemetrySatellite.java new file mode 100644 index 00000000..3f70f212 --- /dev/null +++ b/altoslib/AltosTelemetrySatellite.java @@ -0,0 +1,50 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_1; + +public class AltosTelemetrySatellite extends AltosTelemetryStandard { + int channels; + AltosGPSSat[] sats; + + public AltosTelemetrySatellite(int[] bytes) { + super(bytes); + + channels = uint8(5); + if (channels > 12) + channels = 12; + if (channels == 0) + sats = null; + else { + sats = new AltosGPSSat[channels]; + for (int i = 0; i < channels; i++) { + int svid = uint8(6 + i * 2 + 0); + int c_n_1 = uint8(6 + i * 2 + 1); + sats[i] = new AltosGPSSat(svid, c_n_1); + } + } + } + + public void update_state(AltosState state) { + super.update_state(state); + + AltosGPS gps = state.make_temp_gps(); + + gps.cc_gps_sat = sats; + state.set_temp_gps(); + } +} diff --git a/altoslib/AltosTelemetrySensor.java b/altoslib/AltosTelemetrySensor.java new file mode 100644 index 00000000..f89e56c3 --- /dev/null +++ b/altoslib/AltosTelemetrySensor.java @@ -0,0 +1,80 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_1; + + +public class AltosTelemetrySensor extends AltosTelemetryStandard { + int state; + int accel; + int pres; + int temp; + int v_batt; + int sense_d; + int sense_m; + + int acceleration; + int speed; + int height; + + int ground_accel; + int ground_pres; + int accel_plus_g; + int accel_minus_g; + + public AltosTelemetrySensor(int[] bytes) { + super(bytes); + state = uint8(5); + + accel = int16(6); + pres = int16(8); + temp = int16(10); + v_batt = int16(12); + sense_d = int16(14); + sense_m = int16(16); + + acceleration = int16(18); + speed = int16(20); + height = int16(22); + + ground_pres = int16(24); + ground_accel = int16(26); + accel_plus_g = int16(28); + accel_minus_g = int16(30); + } + + public void update_state(AltosState state) { + super.update_state(state); + + state.set_state(this.state); + if (type == packet_type_TM_sensor) { + state.set_ground_accel(ground_accel); + state.set_accel_g(accel_plus_g, accel_minus_g); + state.set_accel(accel); + } + state.set_ground_pressure(AltosConvert.barometer_to_pressure(ground_pres)); + state.set_pressure(AltosConvert.barometer_to_pressure(pres)); + state.set_temperature(AltosConvert.thermometer_to_temperature(temp)); + state.set_battery_voltage(AltosConvert.cc_battery_to_voltage(v_batt)); + if (type == packet_type_TM_sensor || type == packet_type_Tm_sensor) { + state.set_apogee_voltage(AltosConvert.cc_ignitor_to_voltage(sense_d)); + state.set_main_voltage(AltosConvert.cc_ignitor_to_voltage(sense_m)); + } + + state.set_kalman(height, speed/16.0, acceleration / 16.0); + } +} diff --git a/altoslib/AltosTelemetryStandard.java b/altoslib/AltosTelemetryStandard.java new file mode 100644 index 00000000..fa86bf8e --- /dev/null +++ b/altoslib/AltosTelemetryStandard.java @@ -0,0 +1,106 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package org.altusmetrum.altoslib_1; + +public abstract class AltosTelemetryStandard extends AltosTelemetry { + int[] bytes; + int type; + + public int int8(int off) { + return AltosLib.int8(bytes, off + 1); + } + + public int uint8(int off) { + return AltosLib.uint8(bytes, off + 1); + } + + public int int16(int off) { + return AltosLib.int16(bytes, off + 1); + } + + public int uint16(int off) { + return AltosLib.uint16(bytes, off + 1); + } + + public int uint32(int off) { + return AltosLib.uint32(bytes, off + 1); + } + + public int int32(int off) { + return AltosLib.int32(bytes, off + 1); + } + + public String string(int off, int l) { + return AltosLib.string(bytes, off + 1, l); + } + + public static AltosTelemetry parse_hex(int[] bytes) { + int type = AltosLib.uint8(bytes, 4 + 1); + + AltosTelemetry telem; + switch (type) { + case packet_type_TM_sensor: + case packet_type_Tm_sensor: + case packet_type_Tn_sensor: + telem = new AltosTelemetrySensor(bytes); + break; + case packet_type_configuration: + telem = new AltosTelemetryConfiguration(bytes); + break; + case packet_type_location: + telem = new AltosTelemetryLocation(bytes); + break; + case packet_type_satellite: + telem = new AltosTelemetrySatellite(bytes); + break; +/* + case packet_type_companion: + telem = new AltosTelemetryCompanion(bytes); + break; +*/ + case packet_type_mega_sensor: + telem = new AltosTelemetryMegaSensor(bytes); + break; + case packet_type_mega_data: + telem = new AltosTelemetryMegaData(bytes); + break; + case packet_type_metrum_sensor: + telem = new AltosTelemetryMetrumSensor(bytes); + break; + case packet_type_metrum_data: + telem = new AltosTelemetryMetrumData(bytes); + break; + default: + telem = new AltosTelemetryRaw(bytes); + break; + } + return telem; + } + + public AltosTelemetryStandard(int[] bytes) { + this.bytes = bytes; + + serial = uint16(0); + tick = uint16(2); + type = uint8(4); + } + + public void update_state(AltosState state) { + super.update_state(state); + } +} diff --git a/altoslib/Makefile.am b/altoslib/Makefile.am index 59e0ec1c..87d4d898 100644 --- a/altoslib/Makefile.am +++ b/altoslib/Makefile.am @@ -10,7 +10,19 @@ SRC=. altoslibdir = $(datadir)/java +record_files = \ + AltosEepromRecord.java \ + AltosEepromTeleScience.java \ + AltosRecordCompanion.java \ + AltosRecordIterable.java \ + AltosRecord.java \ + AltosRecordNone.java \ + AltosRecordTM.java \ + AltosRecordMM.java \ + AltosRecordMini.java + altoslib_JAVA = \ + $(record_files) \ AltosLib.java \ AltosConfigData.java \ AltosConfigValues.java \ @@ -25,11 +37,8 @@ altoslib_JAVA = \ AltosEepromIterable.java \ AltosEepromLog.java \ AltosEepromMega.java \ - AltosEepromMegaIterable.java \ - AltosEepromRecord.java \ - AltosEepromTeleScience.java \ + AltosEepromMetrum2.java \ AltosEepromMini.java \ - AltosEepromOldIterable.java \ AltosFile.java \ AltosFlash.java \ AltosFlashListener.java \ @@ -57,13 +66,6 @@ altoslib_JAVA = \ AltosParse.java \ AltosPreferences.java \ AltosPreferencesBackend.java \ - AltosRecordCompanion.java \ - AltosRecordIterable.java \ - AltosRecord.java \ - AltosRecordNone.java \ - AltosRecordTM.java \ - AltosRecordMM.java \ - AltosRecordMini.java \ AltosReplayReader.java \ AltosRomconfig.java \ AltosSensorMM.java \ @@ -72,11 +74,21 @@ altoslib_JAVA = \ AltosStateIterable.java \ AltosStateUpdate.java \ AltosTelemetry.java \ + AltosTelemetryConfiguration.java \ AltosTelemetryFile.java \ AltosTelemetryIterable.java \ AltosTelemetryLegacy.java \ + AltosTelemetryLocation.java \ AltosTelemetryMap.java \ + AltosTelemetryMegaSensor.java \ + AltosTelemetryMegaData.java \ + AltosTelemetryMetrumSensor.java \ + AltosTelemetryMetrumData.java \ AltosTelemetryReader.java \ + AltosTelemetryRaw.java \ + AltosTelemetrySensor.java \ + AltosTelemetrySatellite.java \ + AltosTelemetryStandard.java \ AltosUnitsListener.java \ AltosMs5607.java \ AltosIMU.java \ diff --git a/altosui/AltosAscent.java b/altosui/AltosAscent.java index f8435037..ceba2d1d 100644 --- a/altosui/AltosAscent.java +++ b/altosui/AltosAscent.java @@ -308,7 +308,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { class Lat extends AscentValue { void show (AltosState state, AltosListenerState listener_state) { - if (state.gps != null) + if (state.gps != null && state.gps.connected && state.gps.lat != AltosRecord.MISSING) show(pos(state.gps.lat,"N", "S")); else show("???"); @@ -322,7 +322,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { class Lon extends AscentValue { void show (AltosState state, AltosListenerState listener_state) { - if (state.gps != null) + if (state.gps != null && state.gps.connected && state.gps.lon != AltosRecord.MISSING) show(pos(state.gps.lon,"E", "W")); else show("???"); diff --git a/altosui/AltosDescent.java b/altosui/AltosDescent.java index 2b6575cb..35efce16 100644 --- a/altosui/AltosDescent.java +++ b/altosui/AltosDescent.java @@ -278,7 +278,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { class Lat extends DescentValue { void show (AltosState state, AltosListenerState listener_state) { - if (state.gps != null && state.gps.connected) + if (state.gps != null && state.gps.connected && state.gps.lat != AltosRecord.MISSING) show(pos(state.gps.lat,"N", "S")); else show("???"); @@ -292,7 +292,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { class Lon extends DescentValue { void show (AltosState state, AltosListenerState listener_state) { - if (state.gps != null && state.gps.connected) + if (state.gps != null && state.gps.connected && state.gps.lon != AltosRecord.MISSING) show(pos(state.gps.lon,"W", "E")); else show("???"); diff --git a/altosui/AltosDisplayThread.java b/altosui/AltosDisplayThread.java index 70144fb2..7a750c86 100644 --- a/altosui/AltosDisplayThread.java +++ b/altosui/AltosDisplayThread.java @@ -110,7 +110,7 @@ public class AltosDisplayThread extends Thread { */ if (state.state >= Altos.ao_flight_drogue && (last || - System.currentTimeMillis() - state.report_time >= 15000 || + System.currentTimeMillis() - state.received_time >= 15000 || state.state == Altos.ao_flight_landed)) { if (Math.abs(state.speed) < 20 && state.height < 100) diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index 95b17e2a..931b55fd 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -33,9 +33,6 @@ public class AltosEepromDownload implements Runnable { Thread eeprom_thread; AltosEepromMonitor monitor; - int flight; - int serial; - int year, month, day; boolean want_file; FileWriter eeprom_file; LinkedList eeprom_pending; @@ -44,7 +41,7 @@ public class AltosEepromDownload implements Runnable { ActionListener listener; boolean success; ParseException parse_exception; - String extension; + AltosState state; private void FlushPending() throws IOException { for (String s : flights.config_data) { @@ -59,15 +56,19 @@ public class AltosEepromDownload implements Runnable { private void CheckFile(boolean force) throws IOException { if (eeprom_file != null) return; - if (force || (flight != 0 && want_file)) { + if (force || (state.flight != 0 && want_file)) { AltosFile eeprom_name; - - if (extension == null) - extension = "data"; - if (year != 0 && month != 0 && day != 0) - eeprom_name = new AltosFile(year, month, day, serial, flight, extension); - else - eeprom_name = new AltosFile(serial, flight, extension); + AltosGPS gps = state.gps; + + if (gps != null && + gps.year != AltosRecord.MISSING && + gps.month != AltosRecord.MISSING && + gps.day != AltosRecord.MISSING) + { + eeprom_name = new AltosFile(gps.year, gps.month, gps.day, + state.serial, state.flight, "eeprom"); + } else + eeprom_name = new AltosFile(state.serial, state.flight, "eeprom"); eeprom_file = new FileWriter(eeprom_name); if (eeprom_file != null) { @@ -78,270 +79,49 @@ public class AltosEepromDownload implements Runnable { } } - void Log(AltosEepromRecord r) throws IOException { + boolean done; + boolean start; + + void LogEeprom(AltosEeprom r) throws IOException { if (r.cmd != Altos.AO_LOG_INVALID) { - String log_line = String.format("%c %4x %4x %4x\n", - r.cmd, r.tick, r.a, r.b); + String line = r.string(); if (eeprom_file != null) - eeprom_file.write(log_line); + eeprom_file.write(line); else - eeprom_pending.add(log_line); + eeprom_pending.add(line); } } - void set_serial(int in_serial) { - serial = in_serial; - monitor.set_serial(serial); - } - - void set_flight(int in_flight) { - flight = in_flight; - monitor.set_flight(flight); - } - - boolean done; - int state; - - void CaptureFull(AltosEepromChunk eechunk) throws IOException { - boolean any_valid = false; - - extension = "eeprom"; - set_serial(flights.config_data.serial); - for (int i = 0; i < AltosEepromChunk.chunk_size && !done; i += AltosEepromRecord.record_length) { - try { - AltosEepromRecord r = new AltosEepromRecord(eechunk, i); - if (r.cmd == Altos.AO_LOG_FLIGHT) - set_flight(r.b); - - /* Monitor state transitions to update display */ - if (r.cmd == Altos.AO_LOG_STATE && r.a <= Altos.ao_flight_landed) { - state = r.a; - if (state > Altos.ao_flight_pad) - want_file = true; - } - - if (r.cmd == Altos.AO_LOG_GPS_DATE) { - year = 2000 + (r.a & 0xff); - month = (r.a >> 8) & 0xff; - day = (r.b & 0xff); - want_file = true; - } - if (r.cmd == Altos.AO_LOG_STATE && r.a == Altos.ao_flight_landed) - done = true; - if (r.cmd != AltosLib.AO_LOG_INVALID) - any_valid = true; - Log(r); - } catch (ParseException pe) { - if (parse_exception == null) - parse_exception = pe; - } - } - - if (!any_valid) - done = true; - - CheckFile(false); - } - - boolean start; - int tiny_tick; - - void CaptureTiny (AltosEepromChunk eechunk) throws IOException { + void CaptureEeprom(AltosEepromChunk eechunk, int log_format) throws IOException { boolean any_valid = false; - extension = "eeprom"; - set_serial(flights.config_data.serial); - for (int i = 0; i < eechunk.data.length && !done; i += 2) { - int v = eechunk.data16(i); - AltosEepromRecord r; - - if (i == 0 && start) { - tiny_tick = 0; - start = false; - set_flight(v); - r = new AltosEepromRecord(Altos.AO_LOG_FLIGHT, tiny_tick, 0, v); - any_valid = true; - } else { - int s = v ^ 0x8000; - - if (Altos.ao_flight_startup <= s && s <= Altos.ao_flight_invalid) { - state = s; - r = new AltosEepromRecord(Altos.AO_LOG_STATE, tiny_tick, state, 0); - if (state == Altos.ao_flight_landed) - done = true; - state = s; - any_valid = true; - } else { - if (v != 0xffff) - any_valid = true; - - r = new AltosEepromRecord(Altos.AO_LOG_PRESSURE, tiny_tick, 0, v); - - /* - * The flight software records ascent data every 100ms, and descent - * data every 1s. - */ - if (state < Altos.ao_flight_drogue) - tiny_tick += 10; - else - tiny_tick += 100; - } - } - Log(r); - } - CheckFile(false); - if (!any_valid) - done = true; - } - - void LogTeleScience(AltosEepromTeleScience r) throws IOException { - if (r.type != Altos.AO_LOG_INVALID) { - String log_line = String.format("%c %4x %4x %d %5d %5d %5d %5d %5d %5d %5d %5d %5d %5d %5d %5d\n", - r.type, r.tick, r.tm_tick, r.tm_state, - r.data[0], r.data[1], r.data[2], r.data[3], - r.data[4], r.data[5], r.data[6], r.data[7], - r.data[8], r.data[9], r.data[10], r.data[11]); - if (eeprom_file != null) - eeprom_file.write(log_line); - else - eeprom_pending.add(log_line); - } - } - - boolean telescience_start; - - void CaptureTeleScience (AltosEepromChunk eechunk) throws IOException { - boolean any_valid = false; - - extension = "science"; - for (int i = 0; i < AltosEepromChunk.chunk_size && !done; i += AltosEepromTeleScience.record_length) { - try { - AltosEepromTeleScience r = new AltosEepromTeleScience(eechunk, i); - if (r.type == AltosEepromTeleScience.AO_LOG_TELESCIENCE_START) { - if (telescience_start) { - done = true; - break; - } - set_serial(r.data[0]); - set_flight(r.data[1]); - telescience_start = true; - } else { - if (!telescience_start) - break; - } - state = r.tm_state; - want_file =true; - any_valid = true; - LogTeleScience(r); - } catch (ParseException pe) { - if (parse_exception == null) - parse_exception = pe; - } - } + int record_length = 8; - CheckFile(false); - if (!any_valid) - done = true; - } + state.set_serial(flights.config_data.serial); - void LogMega(AltosEepromMega r) throws IOException { - if (r.cmd != Altos.AO_LOG_INVALID) { - String log_line = String.format("%c %4x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x\n", - r.cmd, r.tick, - r.data8[0], r.data8[1], r.data8[2], r.data8[3], - r.data8[4], r.data8[5], r.data8[6], r.data8[7], - r.data8[8], r.data8[9], r.data8[10], r.data8[11], - r.data8[12], r.data8[13], r.data8[14], r.data8[15], - r.data8[16], r.data8[17], r.data8[18], r.data8[19], - r.data8[20], r.data8[21], r.data8[22], r.data8[23], - r.data8[24], r.data8[25], r.data8[26], r.data8[27]); - if (eeprom_file != null) - eeprom_file.write(log_line); - else - eeprom_pending.add(log_line); - } - } + for (int i = 0; i < AltosEepromChunk.chunk_size && !done; i += record_length) { + AltosEeprom r = eechunk.eeprom(i, log_format); - void CaptureMega(AltosEepromChunk eechunk) throws IOException { - boolean any_valid = false; + record_length = r.record_length(); - extension = "mega"; - set_serial(flights.config_data.serial); - for (int i = 0; i < AltosEepromChunk.chunk_size && !done; i += AltosEepromMega.record_length) { - try { - AltosEepromMega r = new AltosEepromMega(eechunk, i); - if (r.cmd == Altos.AO_LOG_FLIGHT) - set_flight(r.data16(0)); - - /* Monitor state transitions to update display */ - if (r.cmd == Altos.AO_LOG_STATE && r.data16(0) <= Altos.ao_flight_landed) { - state = r.data16(0); - if (state > Altos.ao_flight_pad) - want_file = true; - } + r.update_state(state); - if (r.cmd == Altos.AO_LOG_GPS_TIME) { - year = 2000 + r.data8(14); - month = r.data8(15); - day = r.data8(16); + /* Monitor state transitions to update display */ + if (state.state != AltosLib.ao_flight_invalid && + state.state <= AltosLib.ao_flight_landed) + { + if (state.state > Altos.ao_flight_pad) want_file = true; - } - - if (r.cmd == Altos.AO_LOG_STATE && r.data16(0) == Altos.ao_flight_landed) + if (state.state == AltosLib.ao_flight_landed) done = true; - if (r.cmd != AltosLib.AO_LOG_INVALID) - any_valid = true; - LogMega(r); - } catch (ParseException pe) { - if (parse_exception == null) - parse_exception = pe; } - } - if (!any_valid) - done = true; - CheckFile(false); - } - - void LogMini(AltosEepromMini r) throws IOException { - if (r.cmd != Altos.AO_LOG_INVALID) { - String log_line = String.format("%c %4x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x\n", - r.cmd, r.tick, - r.data8[0], r.data8[1], r.data8[2], r.data8[3], - r.data8[4], r.data8[5], r.data8[6], r.data8[7], - r.data8[8], r.data8[9], r.data8[10], r.data8[11]); - if (eeprom_file != null) - eeprom_file.write(log_line); - else - eeprom_pending.add(log_line); - } - } + if (state.gps != null) + want_file = true; - void CaptureMini(AltosEepromChunk eechunk) throws IOException { - boolean any_valid = false; - - extension = "mini"; - set_serial(flights.config_data.serial); - for (int i = 0; i < AltosEepromChunk.chunk_size && !done; i += AltosEepromMini.record_length) { - try { - AltosEepromMini r = new AltosEepromMini(eechunk, i); - if (r.cmd == Altos.AO_LOG_FLIGHT) - set_flight(r.data16(0)); - - /* Monitor state transitions to update display */ - if (r.cmd == Altos.AO_LOG_STATE && r.data16(0) <= Altos.ao_flight_landed) { - state = r.data16(0); - if (state > Altos.ao_flight_pad) - want_file = true; - } - - if (r.cmd == Altos.AO_LOG_STATE && r.data16(0) == Altos.ao_flight_landed) - done = true; + if (r.valid) { any_valid = true; - LogMini(r); - } catch (ParseException pe) { - if (parse_exception == null) - parse_exception = pe; + LogEeprom(r); } } if (!any_valid) @@ -350,15 +130,12 @@ public class AltosEepromDownload implements Runnable { CheckFile(false); } - void CaptureTelemetry(AltosEepromChunk eechunk) throws IOException { - - } - void CaptureLog(AltosEepromLog log) throws IOException, InterruptedException, TimeoutException { int block, state_block = 0; int log_format = flights.config_data.log_format; - state = 0; + state = new AltosState(); + done = false; start = true; @@ -366,10 +143,6 @@ public class AltosEepromDownload implements Runnable { throw new IOException("no serial number found"); /* Reset per-capture variables */ - flight = 0; - year = 0; - month = 0; - day = 0; want_file = false; eeprom_file = null; eeprom_pending = new LinkedList(); @@ -377,9 +150,12 @@ public class AltosEepromDownload implements Runnable { /* Set serial number in the monitor dialog window */ /* Now scan the eeprom, reading blocks of data and converting to .eeprom file form */ - state = 0; state_block = log.start_block; + state_block = log.start_block; for (block = log.start_block; !done && block < log.end_block; block++) { - monitor.set_value(AltosLib.state_name(state), state, block - state_block, block - log.start_block); + monitor.set_value(state.state_name(), + state.state, + block - state_block, + block - log.start_block); AltosEepromChunk eechunk = new AltosEepromChunk(serial_line, block, block == log.start_block); @@ -397,33 +173,7 @@ public class AltosEepromDownload implements Runnable { } } - switch (log_format) { - case AltosLib.AO_LOG_FORMAT_FULL: - extension = "eeprom"; - CaptureFull(eechunk); - break; - case AltosLib.AO_LOG_FORMAT_TINY: - extension = "eeprom"; - CaptureTiny(eechunk); - break; - case AltosLib.AO_LOG_FORMAT_TELEMETRY: - extension = "telem"; - CaptureTelemetry(eechunk); - break; - case AltosLib.AO_LOG_FORMAT_TELESCIENCE: - extension = "science"; - CaptureTeleScience(eechunk); - break; - case AltosLib.AO_LOG_FORMAT_TELEMEGA: - extension = "mega"; - CaptureMega(eechunk); - break; - case AltosLib.AO_LOG_FORMAT_EASYMINI: - case AltosLib.AO_LOG_FORMAT_TELEMINI: - extension = "eeprom"; - CaptureMini(eechunk); - break; - } + CaptureEeprom (eechunk, log_format); } CheckFile(true); if (eeprom_file != null) { diff --git a/altosui/AltosFlightStatus.java b/altosui/AltosFlightStatus.java index 0be7bb51..6383e5b9 100644 --- a/altosui/AltosFlightStatus.java +++ b/altosui/AltosFlightStatus.java @@ -126,7 +126,7 @@ public class AltosFlightStatus extends JComponent implements AltosFlightDisplay class LastPacket extends FlightValue { void show(AltosState state, AltosListenerState listener_state) { - long secs = (System.currentTimeMillis() - state.report_time + 500) / 1000; + long secs = (System.currentTimeMillis() - state.received_time + 500) / 1000; value.setText(String.format("%d", secs)); } public LastPacket(GridBagLayout layout, int x) { diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index 423cf10c..1c450ce3 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -102,7 +102,7 @@ public class AltosFlightUI extends AltosUIFrame implements AltosFlightDisplay, A status_update.saved_state = state; if (state == null) - state = new AltosState(new AltosRecord()); + state = new AltosState(); pad.show(state, listener_state); diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index bbab017f..f6a91de8 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -65,13 +65,13 @@ public class AltosIdleMonitorUI extends AltosUIFrame implements AltosFlightDispl public void show(AltosState state, AltosListenerState listener_state) { status_update.saved_state = state; - try { +// try { pad.show(state, listener_state); flightStatus.show(state, listener_state); flightInfo.show(state, listener_state); - } catch (Exception e) { - System.out.print("Show exception" + e); - } +// } catch (Exception e) { +// System.out.print("Show exception " + e); +// } } public void update(final AltosState state, final AltosListenerState listener_state) { diff --git a/altosui/AltosInfoTable.java b/altosui/AltosInfoTable.java index 8601d76f..8906920b 100644 --- a/altosui/AltosInfoTable.java +++ b/altosui/AltosInfoTable.java @@ -155,10 +155,14 @@ public class AltosInfoTable extends JTable { else info_add_row(1, "GPS", " missing"); info_add_row(1, "Satellites", "%6d", state.gps.nsat); - info_add_deg(1, "Latitude", state.gps.lat, 'N', 'S'); - info_add_deg(1, "Longitude", state.gps.lon, 'E', 'W'); - info_add_row(1, "GPS altitude", "%6d", state.gps.alt); - info_add_row(1, "GPS height", "%6.0f", state.gps_height); + if (state.gps.lat != AltosRecord.MISSING) + info_add_deg(1, "Latitude", state.gps.lat, 'N', 'S'); + if (state.gps.lon != AltosRecord.MISSING) + info_add_deg(1, "Longitude", state.gps.lon, 'E', 'W'); + if (state.gps.alt != AltosRecord.MISSING) + info_add_row(1, "GPS altitude", "%8.1f", state.gps.alt); + if (state.gps_height != AltosRecord.MISSING) + info_add_row(1, "GPS height", "%8.1f", state.gps_height); /* The SkyTraq GPS doesn't report these values */ /* @@ -195,14 +199,16 @@ public class AltosInfoTable extends JTable { info_add_deg(1, "Pad longitude", state.pad_lon, 'E', 'W'); info_add_row(1, "Pad GPS alt", "%6.0f m", state.pad_alt); } - info_add_row(1, "GPS date", "%04d-%02d-%02d", - state.gps.year, - state.gps.month, - state.gps.day); - info_add_row(1, "GPS time", " %02d:%02d:%02d", - state.gps.hour, - state.gps.minute, - state.gps.second); + if (state.gps.year != AltosRecord.MISSING) + info_add_row(1, "GPS date", "%04d-%02d-%02d", + state.gps.year, + state.gps.month, + state.gps.day); + if (state.gps.hour != AltosRecord.MISSING) + info_add_row(1, "GPS time", " %02d:%02d:%02d", + state.gps.hour, + state.gps.minute, + state.gps.second); //int nsat_vis = 0; int c; diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java index 38f273cf..4cdaa3df 100644 --- a/altosui/AltosLanded.java +++ b/altosui/AltosLanded.java @@ -103,7 +103,8 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio class Lat extends LandedValue { void show (AltosState state, AltosListenerState listener_state) { - if (state.gps != null && state.gps.connected) + show(); + if (state.gps != null && state.gps.connected && state.gps.lat != AltosRecord.MISSING) show(pos(state.gps.lat,"N", "S")); else show("???"); @@ -118,7 +119,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay, Actio class Lon extends LandedValue { void show (AltosState state, AltosListenerState listener_state) { show(); - if (state.gps != null && state.gps.connected) + if (state.gps != null && state.gps.connected && state.gps.lon != AltosRecord.MISSING) show(pos(state.gps.lon,"E", "W")); else show("???"); diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java index fed009cc..e9c973de 100644 --- a/altosui/AltosPad.java +++ b/altosui/AltosPad.java @@ -310,17 +310,23 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { class PadLat extends LaunchValue { void show (AltosState state, AltosListenerState listener_state) { - if (state == null || state.gps == null) { - hide(); - } else { - if (state.state < AltosLib.ao_flight_pad) { - show(pos(state.gps.lat,"N", "S")); - set_label("Latitude"); - } else { - show(pos(state.pad_lat,"N", "S")); - set_label("Pad Latitude"); + double lat = AltosRecord.MISSING; + String label = null; + + if (state != null) { + if (state.state < AltosLib.ao_flight_pad && state.gps != null && state.gps.lat != AltosRecord.MISSING) { + lat = state.gps.lat; + label = "Latitude"; + } else { + lat = state.pad_lat; + label = "Pad Latitude"; } } + if (lat != AltosRecord.MISSING) { + show(pos(lat,"E", "W")); + set_label(label); + } else + hide(); } public PadLat (GridBagLayout layout, int y) { super (layout, y, "Pad Latitude"); @@ -331,17 +337,23 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { class PadLon extends LaunchValue { void show (AltosState state, AltosListenerState listener_state) { - if (state == null || state.gps == null) { - hide(); - } else { - if (state.state < AltosLib.ao_flight_pad) { - show(pos(state.gps.lon,"E", "W")); - set_label("Longitude"); - } else { - show(pos(state.pad_lon,"E", "W")); - set_label("Pad Longitude"); + double lon = AltosRecord.MISSING; + String label = null; + + if (state != null) { + if (state.state < AltosLib.ao_flight_pad && state.gps != null && state.gps.lon != AltosRecord.MISSING) { + lon = state.gps.lon; + label = "Longitude"; + } else { + lon = state.pad_lon; + label = "Pad Longitude"; } } + if (lon != AltosRecord.MISSING) { + show(pos(lon,"E", "W")); + set_label(label); + } else + hide(); } public PadLon (GridBagLayout layout, int y) { super (layout, y, "Pad Longitude"); @@ -352,21 +364,23 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { class PadAlt extends LaunchValue { void show (AltosState state, AltosListenerState listener_state) { - if (state == null) - hide(); - else { - if (state.state < AltosLib.ao_flight_pad && state.gps != null) { - show("%4.0f m", state.gps.alt); - set_label("Altitude"); + double alt = AltosRecord.MISSING; + String label = null; + + if (state != null) { + if (state.state < AltosLib.ao_flight_pad && state.gps != null && state.gps.alt != AltosRecord.MISSING) { + alt = state.gps.alt; + label = "Altitude"; } else { - if (state.pad_alt == AltosRecord.MISSING) - hide(); - else { - show("%4.0f m", state.pad_alt); - set_label("Pad Altitude"); - } + alt = state.pad_alt; + label = "Pad Altitude"; } } + if (alt != AltosRecord.MISSING) { + show("%4.0f m", state.gps.alt); + set_label(label); + } else + hide(); } public PadAlt (GridBagLayout layout, int y) { super (layout, y, "Pad Altitude"); diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index b47df0d9..151f68fd 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -350,10 +350,10 @@ public class AltosUI extends AltosUIFrame { FileInputStream in; in = new FileInputStream(file); - if (file.getName().endsWith("eeprom")) - return new AltosEepromFile(in); - else + if (file.getName().endsWith("telem")) return new AltosTelemetryFile(in); + else + return new AltosEepromFile(in); } catch (FileNotFoundException fe) { System.out.printf("%s\n", fe.getMessage()); return null; @@ -434,11 +434,10 @@ public class AltosUI extends AltosUIFrame { System.out.printf("Failed to open file '%s'\n", file); return null; } - if (file.getName().endsWith("eeprom")) { - return new AltosEepromFile(in); - } else { + if (file.getName().endsWith("telem")) return new AltosTelemetryFile(in); - } + else + return new AltosEepromFile(in); } static AltosReplayReader replay_file(File file) { @@ -521,6 +520,8 @@ public class AltosUI extends AltosUIFrame { System.out.printf ("process cat\n"); for (AltosState state : eef) { + System.out.printf ("tick %d state %d height %g\n", + state.tick, state.state, state.height); if ((state.set & AltosState.set_gps) != 0) System.out.printf ("time %g lat %g lon %g alt %g\n", state.time_since_boost(), diff --git a/src/core/ao_log.h b/src/core/ao_log.h index a2f342d7..4b09faeb 100644 --- a/src/core/ao_log.h +++ b/src/core/ao_log.h @@ -276,7 +276,8 @@ struct ao_log_metrum { uint16_t flight; /* 4 */ int16_t ground_accel; /* 6 */ uint32_t ground_pres; /* 8 */ - } flight; /* 12 */ + uint32_t ground_temp; /* 12 */ + } flight; /* 16 */ /* AO_LOG_STATE */ struct { uint16_t state; /* 4 */ -- cgit v1.2.3 From 224a1e01bacb7db0076129906ed58e1c785e1b14 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Sep 2013 23:08:34 -0600 Subject: altos: Not all products have pins to control flash loader TeleGPS has no exposed pins for this function Signed-off-by: Keith Packard --- src/product/ao_flash_pins.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/product/ao_flash_pins.h b/src/product/ao_flash_pins.h index 439ba75c..dd67d820 100644 --- a/src/product/ao_flash_pins.h +++ b/src/product/ao_flash_pins.h @@ -35,7 +35,6 @@ #define HAS_VERSION 0 #define AO_BOOT_CHAIN 1 -#define AO_BOOT_PIN 1 #define IS_FLASH_LOADER 1 -- cgit v1.2.3 From 7f4650990e8a7cfcf8461e8928dfc426c9a563cc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Sep 2013 22:57:19 -0700 Subject: altos: Set tick value in new TeleMetrum v2 sensor packets Was getting left with the old value, which wasn't very useful Signed-off-by: Keith Packard --- src/core/ao_telemetry.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index cd95aa6b..6b47a06a 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -182,6 +182,7 @@ ao_send_metrum_sensor(void) { __xdata struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; + telemetry.generic.tick = packet->tick; telemetry.generic.type = AO_TELEMETRY_METRUM_SENSOR; telemetry.metrum_sensor.state = ao_flight_state; -- cgit v1.2.3 From 690094e2d7d9cfe5eb4edb478fd79e5d133c6b4b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 15 Sep 2013 14:11:50 -0700 Subject: altos: Move micropeak sources around This sticks the micropeak sources in appropriate directories, rather than in the micropeak product directory so that they can be shared with future micropeak-style products. Signed-off-by: Keith Packard --- src/attiny/ao_async.c | 71 ++++++++++++++++++++ src/attiny/ao_async.h | 30 +++++++++ src/core/ao_log_micro.c | 121 ++++++++++++++++++++++++++++++++++ src/core/ao_log_micro.h | 39 +++++++++++ src/core/ao_microflight.c | 143 +++++++++++++++++++++++++++++++++++++++++ src/core/ao_microkalman.c | 74 +++++++++++++++++++++ src/core/ao_report_micro.c | 57 ++++++++++++++++ src/micropeak/Makefile | 6 +- src/micropeak/ao_async.c | 71 -------------------- src/micropeak/ao_async.h | 30 --------- src/micropeak/ao_log_micro.c | 121 ---------------------------------- src/micropeak/ao_log_micro.h | 39 ----------- src/micropeak/ao_microflight.c | 143 ----------------------------------------- src/micropeak/ao_microkalman.c | 74 --------------------- src/micropeak/ao_micropeak.c | 89 ------------------------- src/micropeak/ao_micropeak.h | 78 ---------------------- src/micropeak/ao_report_tiny.c | 57 ---------------- src/product/ao_micropeak.c | 89 +++++++++++++++++++++++++ src/product/ao_micropeak.h | 78 ++++++++++++++++++++++ 19 files changed, 705 insertions(+), 705 deletions(-) create mode 100644 src/attiny/ao_async.c create mode 100644 src/attiny/ao_async.h create mode 100644 src/core/ao_log_micro.c create mode 100644 src/core/ao_log_micro.h create mode 100644 src/core/ao_microflight.c create mode 100644 src/core/ao_microkalman.c create mode 100644 src/core/ao_report_micro.c delete mode 100644 src/micropeak/ao_async.c delete mode 100644 src/micropeak/ao_async.h delete mode 100644 src/micropeak/ao_log_micro.c delete mode 100644 src/micropeak/ao_log_micro.h delete mode 100644 src/micropeak/ao_microflight.c delete mode 100644 src/micropeak/ao_microkalman.c delete mode 100644 src/micropeak/ao_micropeak.c delete mode 100644 src/micropeak/ao_micropeak.h delete mode 100644 src/micropeak/ao_report_tiny.c create mode 100644 src/product/ao_micropeak.c create mode 100644 src/product/ao_micropeak.h (limited to 'src') diff --git a/src/attiny/ao_async.c b/src/attiny/ao_async.c new file mode 100644 index 00000000..3556f54c --- /dev/null +++ b/src/attiny/ao_async.c @@ -0,0 +1,71 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +#define AO_ASYNC_BAUD 38400l +#define AO_ASYNC_DELAY (uint8_t) (1000000l / AO_ASYNC_BAUD) + +#define LED_PORT PORTB + +void +ao_async_start(void) +{ + LED_PORT |= (1 << AO_LED_SERIAL); +} + +void +ao_async_stop(void) +{ + LED_PORT &= ~(1 << AO_LED_SERIAL); +} + +void +ao_async_byte(uint8_t byte) +{ + uint8_t b; + uint16_t w; + + /* start data stop */ + w = (0x000 << 0) | (byte << 1) | (0x001 << 9); + + ao_arch_block_interrupts(); + for (b = 0; b < 10; b++) { + uint8_t v = LED_PORT & ~(1 << AO_LED_SERIAL); + v |= (w & 1) << AO_LED_SERIAL; + LED_PORT = v; + w >>= 1; + + /* Carefully timed to hit around 9600 baud */ + asm volatile ("nop"); + asm volatile ("nop"); + + asm volatile ("nop"); + asm volatile ("nop"); + asm volatile ("nop"); + asm volatile ("nop"); + asm volatile ("nop"); + + asm volatile ("nop"); + asm volatile ("nop"); + asm volatile ("nop"); + asm volatile ("nop"); + asm volatile ("nop"); + } + ao_arch_release_interrupts(); +} diff --git a/src/attiny/ao_async.h b/src/attiny/ao_async.h new file mode 100644 index 00000000..1b239712 --- /dev/null +++ b/src/attiny/ao_async.h @@ -0,0 +1,30 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_ASYNC_H_ +#define _AO_ASYNC_H_ + +void +ao_async_start(void); + +void +ao_async_stop(void); + +void +ao_async_byte(uint8_t byte); + +#endif /* _AO_ASYNC_H_ */ diff --git a/src/core/ao_log_micro.c b/src/core/ao_log_micro.c new file mode 100644 index 00000000..d665efb5 --- /dev/null +++ b/src/core/ao_log_micro.c @@ -0,0 +1,121 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include + +static uint16_t ao_log_offset = STARTING_LOG_OFFSET; + +void +ao_log_micro_save(void) +{ + uint16_t n_samples = (ao_log_offset - STARTING_LOG_OFFSET) / sizeof (uint16_t); + ao_eeprom_write(PA_GROUND_OFFSET, &pa_ground, sizeof (pa_ground)); + ao_eeprom_write(PA_MIN_OFFSET, &pa_min, sizeof (pa_min)); + ao_eeprom_write(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples)); +} + +void +ao_log_micro_restore(void) +{ + ao_eeprom_read(PA_GROUND_OFFSET, &pa_ground, sizeof (pa_ground)); + ao_eeprom_read(PA_MIN_OFFSET, &pa_min, sizeof (pa_min)); +} + +void +ao_log_micro_data(void) +{ + uint16_t low_bits = pa; + + if (ao_log_offset < MAX_LOG_OFFSET) { + ao_eeprom_write(ao_log_offset, &low_bits, sizeof (low_bits)); + ao_log_offset += sizeof (low_bits); + } +} + +#define POLY 0x8408 + +static uint16_t +ao_log_micro_crc(uint16_t crc, uint8_t byte) +{ + uint8_t i; + + for (i = 0; i < 8; i++) { + if ((crc & 0x0001) ^ (byte & 0x0001)) + crc = (crc >> 1) ^ POLY; + else + crc = crc >> 1; + byte >>= 1; + } + return crc; +} + +static void +ao_log_hex_nibble(uint8_t b) +{ + if (b < 10) + ao_async_byte('0' + b); + else + ao_async_byte('a' - 10 + b); +} + +static void +ao_log_hex(uint8_t b) +{ + ao_log_hex_nibble(b>>4); + ao_log_hex_nibble(b&0xf); +} + +static void +ao_log_newline(void) +{ + ao_async_byte('\r'); + ao_async_byte('\n'); +} + +void +ao_log_micro_dump(void) +{ + uint16_t n_samples; + uint16_t nbytes; + uint8_t byte; + uint16_t b; + uint16_t crc = 0xffff; + + ao_eeprom_read(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples)); + if (n_samples == 0xffff) + n_samples = 0; + nbytes = STARTING_LOG_OFFSET + sizeof (uint16_t) * n_samples; + ao_async_start(); + ao_async_byte('M'); + ao_async_byte('P'); + for (b = 0; b < nbytes; b++) { + if ((b & 0xf) == 0) + ao_log_newline(); + ao_eeprom_read(b, &byte, 1); + ao_log_hex(byte); + crc = ao_log_micro_crc(crc, byte); + } + ao_log_newline(); + crc = ~crc; + ao_log_hex(crc >> 8); + ao_log_hex(crc); + ao_log_newline(); + ao_async_stop(); +} diff --git a/src/core/ao_log_micro.h b/src/core/ao_log_micro.h new file mode 100644 index 00000000..976852ee --- /dev/null +++ b/src/core/ao_log_micro.h @@ -0,0 +1,39 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_LOG_MICRO_H_ +#define _AO_LOG_MICRO_H_ + +#define PA_GROUND_OFFSET 0 +#define PA_MIN_OFFSET 4 +#define N_SAMPLES_OFFSET 8 +#define STARTING_LOG_OFFSET 10 +#define MAX_LOG_OFFSET 512 + +void +ao_log_micro_save(void); + +void +ao_log_micro_restore(void); + +void +ao_log_micro_data(void); + +void +ao_log_micro_dump(void); + +#endif /* _AO_LOG_MICRO_H_ */ diff --git a/src/core/ao_microflight.c b/src/core/ao_microflight.c new file mode 100644 index 00000000..714bb90a --- /dev/null +++ b/src/core/ao_microflight.c @@ -0,0 +1,143 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_FLIGHT_TEST +#include +#endif +#include +#include + +uint32_t pa; +uint32_t pa_ground; +uint32_t pa_min; + +static void +ao_microsample(void) +{ + ao_pa_get(); + ao_microkalman_predict(); + ao_microkalman_correct(); +} + +#define NUM_PA_HIST 16 + +#define SKIP_PA_HIST(i,j) (((i) + (j)) & (NUM_PA_HIST - 1)) + +static uint32_t pa_hist[NUM_PA_HIST]; + +void +ao_microflight(void) +{ + int16_t sample_count; + uint16_t time; + uint32_t pa_interval_min, pa_interval_max; + int32_t pa_diff; + uint8_t h, i; + uint8_t accel_lock = 0; + uint32_t pa_sum = 0; + + /* Wait for motion, averaging values to get ground pressure */ + + time = ao_time(); + ao_pa_get(); + ao_microkalman_init(); + pa_ground = pa; + sample_count = 0; + h = 0; + for (;;) { + time += SAMPLE_SLEEP; + if (sample_count == 0) + ao_led_on(AO_LED_REPORT); + ao_delay_until(time); + ao_microsample(); + if (sample_count == 0) + ao_led_off(AO_LED_REPORT); + pa_hist[h] = pa; + h = SKIP_PA_HIST(h,1); + pa_diff = pa_ground - ao_pa; + + /* Check for a significant pressure change */ + if (pa_diff > BOOST_DETECT) + break; + + if (sample_count < GROUND_AVG * 2) { + if (sample_count < GROUND_AVG) + pa_sum += pa; + ++sample_count; + } else { + pa_ground = pa_sum >> GROUND_AVG_SHIFT; + pa_sum = 0; + sample_count = 0; + } + } + + /* Go back and find the first sample a decent interval above the ground */ + pa_min = pa_ground - LAND_DETECT; + for (i = SKIP_PA_HIST(h,2); i != h; i = SKIP_PA_HIST(i,2)) { + if (pa_hist[i] < pa_min) + break; + } + + /* Log the remaining samples so we get a complete history since leaving the ground */ + for (; i != h; i = SKIP_PA_HIST(i,2)) { + pa = pa_hist[i]; + ao_log_micro_data(); + } + + /* Now sit around until the pressure is stable again and record the max */ + + sample_count = 0; + pa_min = ao_pa; + pa_interval_min = ao_pa; + pa_interval_max = ao_pa; + for (;;) { + time += SAMPLE_SLEEP; + ao_delay_until(time); + if ((sample_count & 3) == 0) + ao_led_on(AO_LED_REPORT); + ao_microsample(); + if ((sample_count & 3) == 0) + ao_led_off(AO_LED_REPORT); + if (sample_count & 1) + ao_log_micro_data(); + + /* If accelerating upwards, don't look for min pressure */ + if (ao_pa_accel < ACCEL_LOCK_PA) + accel_lock = ACCEL_LOCK_TIME; + else if (accel_lock) + --accel_lock; + else if (ao_pa < pa_min) + pa_min = ao_pa; + + if (sample_count == (GROUND_AVG - 1)) { + pa_diff = pa_interval_max - pa_interval_min; + + /* Check to see if the pressure is now stable */ + if (pa_diff < LAND_DETECT) + break; + sample_count = 0; + pa_interval_min = ao_pa; + pa_interval_max = ao_pa; + } else { + if (ao_pa < pa_interval_min) + pa_interval_min = ao_pa; + if (ao_pa > pa_interval_max) + pa_interval_max = ao_pa; + ++sample_count; + } + } +} diff --git a/src/core/ao_microkalman.c b/src/core/ao_microkalman.c new file mode 100644 index 00000000..0684ea2b --- /dev/null +++ b/src/core/ao_microkalman.c @@ -0,0 +1,74 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_FLIGHT_TEST +#include +#endif +#include + +#define FIX_BITS 16 + +#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) +#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) +#define from_fix8(x) ((x) >> 8) +#define from_fix(x) ((x) >> 16) +#define fix8_to_fix16(x) ((x) << 8) +#define fix16_to_fix8(x) ((x) >> 8) + +#include + +/* Basic time step (96ms) */ +#define AO_MK_STEP to_fix16(0.096) +/* step ** 2 / 2 */ +#define AO_MK_STEP_2_2 to_fix16(0.004608) + +uint32_t ao_k_pa; /* 24.8 fixed point */ +int32_t ao_k_pa_speed; /* 16.16 fixed point */ +int32_t ao_k_pa_accel; /* 16.16 fixed point */ + +uint32_t ao_pa; /* integer portion */ +int16_t ao_pa_speed; /* integer portion */ +int16_t ao_pa_accel; /* integer portion */ + +void +ao_microkalman_init(void) +{ + ao_pa = pa; + ao_k_pa = pa << 8; +} + +void +ao_microkalman_predict(void) +{ + ao_k_pa += fix16_to_fix8((int32_t) ao_pa_speed * AO_MK_STEP + (int32_t) ao_pa_accel * AO_MK_STEP_2_2); + ao_k_pa_speed += (int32_t) ao_pa_accel * AO_MK_STEP; +} + +void +ao_microkalman_correct(void) +{ + int16_t e; /* Height error in Pa */ + + e = pa - from_fix8(ao_k_pa); + + ao_k_pa += fix16_to_fix8((int32_t) e * AO_MK_BARO_K0_10); + ao_k_pa_speed += (int32_t) e * AO_MK_BARO_K1_10; + ao_k_pa_accel += (int32_t) e * AO_MK_BARO_K2_10; + ao_pa = from_fix8(ao_k_pa); + ao_pa_speed = from_fix(ao_k_pa_speed); + ao_pa_accel = from_fix(ao_k_pa_accel); +} diff --git a/src/core/ao_report_micro.c b/src/core/ao_report_micro.c new file mode 100644 index 00000000..0e8e287f --- /dev/null +++ b/src/core/ao_report_micro.c @@ -0,0 +1,57 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include + +#define mid(time) ao_led_for(AO_LED_REPORT, time) +#define pause(time) ao_delay(time) + +static void +ao_report_digit(uint8_t digit) __reentrant +{ + if (!digit) { + mid(AO_MS_TO_TICKS(1000)); + pause(AO_MS_TO_TICKS(300)); + } else { + while (digit--) { + mid(AO_MS_TO_TICKS(300)); + pause(AO_MS_TO_TICKS(300)); + } + } + pause(AO_MS_TO_TICKS(1000)); +} + +void +ao_report_altitude(void) +{ + __pdata alt_t agl = ao_max_height; + static __xdata uint8_t digits[11]; + __pdata uint8_t ndigits, i; + + if (agl < 0) + agl = 0; + ndigits = 0; + do { + digits[ndigits++] = agl % 10; + agl /= 10; + } while (agl); + + i = ndigits; + do + ao_report_digit(digits[--i]); + while (i != 0); +} diff --git a/src/micropeak/Makefile b/src/micropeak/Makefile index 44e0b873..e51b2847 100644 --- a/src/micropeak/Makefile +++ b/src/micropeak/Makefile @@ -2,7 +2,7 @@ # Tiny AltOS build # # -vpath % ../attiny:../drivers:../core:.. +vpath % ../attiny:../drivers:../core:../product:.. vpath ao-make-product.5c ../util vpath make-altitude-pa ../util @@ -30,7 +30,7 @@ ALTOS_SRC = \ ao_ms5607.c \ ao_exti.c \ ao_convert_pa.c \ - ao_report_tiny.c \ + ao_report_micro.c \ ao_notask.c \ ao_eeprom_tiny.c \ ao_panic.c \ @@ -53,7 +53,7 @@ INC=\ IDPRODUCT=0 PRODUCT=MicroPeak-v0.1 PRODUCT_DEF=-DMICROPEAK -CFLAGS = $(PRODUCT_DEF) -I. -I../attiny -I../core -I.. -I../drivers +CFLAGS = $(PRODUCT_DEF) -I. -I../attiny -I../core -I.. -I../drivers -I../product CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O2 -mcall-prologues -DATTINY NICKLE=nickle diff --git a/src/micropeak/ao_async.c b/src/micropeak/ao_async.c deleted file mode 100644 index 3556f54c..00000000 --- a/src/micropeak/ao_async.c +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include -#include - -#define AO_ASYNC_BAUD 38400l -#define AO_ASYNC_DELAY (uint8_t) (1000000l / AO_ASYNC_BAUD) - -#define LED_PORT PORTB - -void -ao_async_start(void) -{ - LED_PORT |= (1 << AO_LED_SERIAL); -} - -void -ao_async_stop(void) -{ - LED_PORT &= ~(1 << AO_LED_SERIAL); -} - -void -ao_async_byte(uint8_t byte) -{ - uint8_t b; - uint16_t w; - - /* start data stop */ - w = (0x000 << 0) | (byte << 1) | (0x001 << 9); - - ao_arch_block_interrupts(); - for (b = 0; b < 10; b++) { - uint8_t v = LED_PORT & ~(1 << AO_LED_SERIAL); - v |= (w & 1) << AO_LED_SERIAL; - LED_PORT = v; - w >>= 1; - - /* Carefully timed to hit around 9600 baud */ - asm volatile ("nop"); - asm volatile ("nop"); - - asm volatile ("nop"); - asm volatile ("nop"); - asm volatile ("nop"); - asm volatile ("nop"); - asm volatile ("nop"); - - asm volatile ("nop"); - asm volatile ("nop"); - asm volatile ("nop"); - asm volatile ("nop"); - asm volatile ("nop"); - } - ao_arch_release_interrupts(); -} diff --git a/src/micropeak/ao_async.h b/src/micropeak/ao_async.h deleted file mode 100644 index 1b239712..00000000 --- a/src/micropeak/ao_async.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_ASYNC_H_ -#define _AO_ASYNC_H_ - -void -ao_async_start(void); - -void -ao_async_stop(void); - -void -ao_async_byte(uint8_t byte); - -#endif /* _AO_ASYNC_H_ */ diff --git a/src/micropeak/ao_log_micro.c b/src/micropeak/ao_log_micro.c deleted file mode 100644 index d665efb5..00000000 --- a/src/micropeak/ao_log_micro.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include -#include -#include -#include - -static uint16_t ao_log_offset = STARTING_LOG_OFFSET; - -void -ao_log_micro_save(void) -{ - uint16_t n_samples = (ao_log_offset - STARTING_LOG_OFFSET) / sizeof (uint16_t); - ao_eeprom_write(PA_GROUND_OFFSET, &pa_ground, sizeof (pa_ground)); - ao_eeprom_write(PA_MIN_OFFSET, &pa_min, sizeof (pa_min)); - ao_eeprom_write(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples)); -} - -void -ao_log_micro_restore(void) -{ - ao_eeprom_read(PA_GROUND_OFFSET, &pa_ground, sizeof (pa_ground)); - ao_eeprom_read(PA_MIN_OFFSET, &pa_min, sizeof (pa_min)); -} - -void -ao_log_micro_data(void) -{ - uint16_t low_bits = pa; - - if (ao_log_offset < MAX_LOG_OFFSET) { - ao_eeprom_write(ao_log_offset, &low_bits, sizeof (low_bits)); - ao_log_offset += sizeof (low_bits); - } -} - -#define POLY 0x8408 - -static uint16_t -ao_log_micro_crc(uint16_t crc, uint8_t byte) -{ - uint8_t i; - - for (i = 0; i < 8; i++) { - if ((crc & 0x0001) ^ (byte & 0x0001)) - crc = (crc >> 1) ^ POLY; - else - crc = crc >> 1; - byte >>= 1; - } - return crc; -} - -static void -ao_log_hex_nibble(uint8_t b) -{ - if (b < 10) - ao_async_byte('0' + b); - else - ao_async_byte('a' - 10 + b); -} - -static void -ao_log_hex(uint8_t b) -{ - ao_log_hex_nibble(b>>4); - ao_log_hex_nibble(b&0xf); -} - -static void -ao_log_newline(void) -{ - ao_async_byte('\r'); - ao_async_byte('\n'); -} - -void -ao_log_micro_dump(void) -{ - uint16_t n_samples; - uint16_t nbytes; - uint8_t byte; - uint16_t b; - uint16_t crc = 0xffff; - - ao_eeprom_read(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples)); - if (n_samples == 0xffff) - n_samples = 0; - nbytes = STARTING_LOG_OFFSET + sizeof (uint16_t) * n_samples; - ao_async_start(); - ao_async_byte('M'); - ao_async_byte('P'); - for (b = 0; b < nbytes; b++) { - if ((b & 0xf) == 0) - ao_log_newline(); - ao_eeprom_read(b, &byte, 1); - ao_log_hex(byte); - crc = ao_log_micro_crc(crc, byte); - } - ao_log_newline(); - crc = ~crc; - ao_log_hex(crc >> 8); - ao_log_hex(crc); - ao_log_newline(); - ao_async_stop(); -} diff --git a/src/micropeak/ao_log_micro.h b/src/micropeak/ao_log_micro.h deleted file mode 100644 index 976852ee..00000000 --- a/src/micropeak/ao_log_micro.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_LOG_MICRO_H_ -#define _AO_LOG_MICRO_H_ - -#define PA_GROUND_OFFSET 0 -#define PA_MIN_OFFSET 4 -#define N_SAMPLES_OFFSET 8 -#define STARTING_LOG_OFFSET 10 -#define MAX_LOG_OFFSET 512 - -void -ao_log_micro_save(void); - -void -ao_log_micro_restore(void); - -void -ao_log_micro_data(void); - -void -ao_log_micro_dump(void); - -#endif /* _AO_LOG_MICRO_H_ */ diff --git a/src/micropeak/ao_microflight.c b/src/micropeak/ao_microflight.c deleted file mode 100644 index 714bb90a..00000000 --- a/src/micropeak/ao_microflight.c +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright © 2013 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef AO_FLIGHT_TEST -#include -#endif -#include -#include - -uint32_t pa; -uint32_t pa_ground; -uint32_t pa_min; - -static void -ao_microsample(void) -{ - ao_pa_get(); - ao_microkalman_predict(); - ao_microkalman_correct(); -} - -#define NUM_PA_HIST 16 - -#define SKIP_PA_HIST(i,j) (((i) + (j)) & (NUM_PA_HIST - 1)) - -static uint32_t pa_hist[NUM_PA_HIST]; - -void -ao_microflight(void) -{ - int16_t sample_count; - uint16_t time; - uint32_t pa_interval_min, pa_interval_max; - int32_t pa_diff; - uint8_t h, i; - uint8_t accel_lock = 0; - uint32_t pa_sum = 0; - - /* Wait for motion, averaging values to get ground pressure */ - - time = ao_time(); - ao_pa_get(); - ao_microkalman_init(); - pa_ground = pa; - sample_count = 0; - h = 0; - for (;;) { - time += SAMPLE_SLEEP; - if (sample_count == 0) - ao_led_on(AO_LED_REPORT); - ao_delay_until(time); - ao_microsample(); - if (sample_count == 0) - ao_led_off(AO_LED_REPORT); - pa_hist[h] = pa; - h = SKIP_PA_HIST(h,1); - pa_diff = pa_ground - ao_pa; - - /* Check for a significant pressure change */ - if (pa_diff > BOOST_DETECT) - break; - - if (sample_count < GROUND_AVG * 2) { - if (sample_count < GROUND_AVG) - pa_sum += pa; - ++sample_count; - } else { - pa_ground = pa_sum >> GROUND_AVG_SHIFT; - pa_sum = 0; - sample_count = 0; - } - } - - /* Go back and find the first sample a decent interval above the ground */ - pa_min = pa_ground - LAND_DETECT; - for (i = SKIP_PA_HIST(h,2); i != h; i = SKIP_PA_HIST(i,2)) { - if (pa_hist[i] < pa_min) - break; - } - - /* Log the remaining samples so we get a complete history since leaving the ground */ - for (; i != h; i = SKIP_PA_HIST(i,2)) { - pa = pa_hist[i]; - ao_log_micro_data(); - } - - /* Now sit around until the pressure is stable again and record the max */ - - sample_count = 0; - pa_min = ao_pa; - pa_interval_min = ao_pa; - pa_interval_max = ao_pa; - for (;;) { - time += SAMPLE_SLEEP; - ao_delay_until(time); - if ((sample_count & 3) == 0) - ao_led_on(AO_LED_REPORT); - ao_microsample(); - if ((sample_count & 3) == 0) - ao_led_off(AO_LED_REPORT); - if (sample_count & 1) - ao_log_micro_data(); - - /* If accelerating upwards, don't look for min pressure */ - if (ao_pa_accel < ACCEL_LOCK_PA) - accel_lock = ACCEL_LOCK_TIME; - else if (accel_lock) - --accel_lock; - else if (ao_pa < pa_min) - pa_min = ao_pa; - - if (sample_count == (GROUND_AVG - 1)) { - pa_diff = pa_interval_max - pa_interval_min; - - /* Check to see if the pressure is now stable */ - if (pa_diff < LAND_DETECT) - break; - sample_count = 0; - pa_interval_min = ao_pa; - pa_interval_max = ao_pa; - } else { - if (ao_pa < pa_interval_min) - pa_interval_min = ao_pa; - if (ao_pa > pa_interval_max) - pa_interval_max = ao_pa; - ++sample_count; - } - } -} diff --git a/src/micropeak/ao_microkalman.c b/src/micropeak/ao_microkalman.c deleted file mode 100644 index 0684ea2b..00000000 --- a/src/micropeak/ao_microkalman.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright © 2013 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef AO_FLIGHT_TEST -#include -#endif -#include - -#define FIX_BITS 16 - -#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) -#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) -#define from_fix8(x) ((x) >> 8) -#define from_fix(x) ((x) >> 16) -#define fix8_to_fix16(x) ((x) << 8) -#define fix16_to_fix8(x) ((x) >> 8) - -#include - -/* Basic time step (96ms) */ -#define AO_MK_STEP to_fix16(0.096) -/* step ** 2 / 2 */ -#define AO_MK_STEP_2_2 to_fix16(0.004608) - -uint32_t ao_k_pa; /* 24.8 fixed point */ -int32_t ao_k_pa_speed; /* 16.16 fixed point */ -int32_t ao_k_pa_accel; /* 16.16 fixed point */ - -uint32_t ao_pa; /* integer portion */ -int16_t ao_pa_speed; /* integer portion */ -int16_t ao_pa_accel; /* integer portion */ - -void -ao_microkalman_init(void) -{ - ao_pa = pa; - ao_k_pa = pa << 8; -} - -void -ao_microkalman_predict(void) -{ - ao_k_pa += fix16_to_fix8((int32_t) ao_pa_speed * AO_MK_STEP + (int32_t) ao_pa_accel * AO_MK_STEP_2_2); - ao_k_pa_speed += (int32_t) ao_pa_accel * AO_MK_STEP; -} - -void -ao_microkalman_correct(void) -{ - int16_t e; /* Height error in Pa */ - - e = pa - from_fix8(ao_k_pa); - - ao_k_pa += fix16_to_fix8((int32_t) e * AO_MK_BARO_K0_10); - ao_k_pa_speed += (int32_t) e * AO_MK_BARO_K1_10; - ao_k_pa_accel += (int32_t) e * AO_MK_BARO_K2_10; - ao_pa = from_fix8(ao_k_pa); - ao_pa_speed = from_fix(ao_k_pa_speed); - ao_pa_accel = from_fix(ao_k_pa_accel); -} diff --git a/src/micropeak/ao_micropeak.c b/src/micropeak/ao_micropeak.c deleted file mode 100644 index 10f0d192..00000000 --- a/src/micropeak/ao_micropeak.c +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include -#include -#include -#include -#include - -static struct ao_ms5607_sample sample; -static struct ao_ms5607_value value; - -alt_t ground_alt, max_alt; -alt_t ao_max_height; - -void -ao_pa_get(void) -{ - ao_ms5607_sample(&sample); - ao_ms5607_convert(&sample, &value); - pa = value.pres; -} - -static void -ao_compute_height(void) -{ - ground_alt = ao_pa_to_altitude(pa_ground); - max_alt = ao_pa_to_altitude(pa_min); - ao_max_height = max_alt - ground_alt; -} - -static void -ao_pips(void) -{ - uint8_t i; - for (i = 0; i < 10; i++) { - ao_led_toggle(AO_LED_REPORT); - ao_delay(AO_MS_TO_TICKS(80)); - } - ao_delay(AO_MS_TO_TICKS(200)); -} - -int -main(void) -{ - ao_led_init(LEDS_AVAILABLE); - ao_timer_init(); - - /* Init external hardware */ - ao_spi_init(); - ao_ms5607_init(); - ao_ms5607_setup(); - - /* Give the person a second to get their finger out of the way */ - ao_delay(AO_MS_TO_TICKS(1000)); - - ao_log_micro_restore(); - ao_compute_height(); - ao_report_altitude(); - ao_pips(); - ao_log_micro_dump(); - - ao_delay(BOOST_DELAY); - - ao_microflight(); - - ao_log_micro_save(); - ao_compute_height(); - ao_report_altitude(); - for (;;) { - cli(); - set_sleep_mode(SLEEP_MODE_PWR_DOWN); - sleep_mode(); - } -} diff --git a/src/micropeak/ao_micropeak.h b/src/micropeak/ao_micropeak.h deleted file mode 100644 index 382b98d9..00000000 --- a/src/micropeak/ao_micropeak.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_MICROPEAK_H_ -#define _AO_MICROPEAK_H_ - -#define SAMPLE_SLEEP AO_MS_TO_TICKS(96) - -/* 16 sample, or about two seconds worth */ -#define GROUND_AVG_SHIFT 4 -#define GROUND_AVG (1 << GROUND_AVG_SHIFT) - -/* Pressure change (in Pa) to detect boost */ -#define BOOST_DETECT 120 /* 10m at sea level, 12m at 2000m */ - -/* Wait after power on before doing anything to give the user time to assemble the rocket */ -#define BOOST_DELAY AO_SEC_TO_TICKS(30) - -/* Pressure change (in Pa) to detect landing */ -#define LAND_DETECT 24 /* 2m at sea level, 2.4m at 2000m */ - -/* Current sensor pressure value */ -extern uint32_t pa; - -/* Average pressure value on ground */ -extern uint32_t pa_ground; - -/* Minimum recorded filtered pressure value */ -extern uint32_t pa_min; - -/* Pressure values converted to altitudes */ -extern alt_t ground_alt, max_alt; - -/* max_alt - ground_alt */ -extern alt_t ao_max_height; - -void -ao_pa_get(void); - -void -ao_microflight(void); - -#define ACCEL_LOCK_PA -20 -#define ACCEL_LOCK_TIME 10 - -extern uint32_t ao_k_pa; /* 24.8 fixed point */ -extern int32_t ao_k_pa_speed; /* 16.16 fixed point */ -extern int32_t ao_k_pa_accel; /* 16.16 fixed point */ - -extern uint32_t ao_pa; /* integer portion */ -extern int16_t ao_pa_speed; /* integer portion */ -extern int16_t ao_pa_accel; /* integer portion */ - -void -ao_microkalman_init(void); - -void -ao_microkalman_predict(void); - -void -ao_microkalman_correct(void); - -#endif - diff --git a/src/micropeak/ao_report_tiny.c b/src/micropeak/ao_report_tiny.c deleted file mode 100644 index 0e8e287f..00000000 --- a/src/micropeak/ao_report_tiny.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include - -#define mid(time) ao_led_for(AO_LED_REPORT, time) -#define pause(time) ao_delay(time) - -static void -ao_report_digit(uint8_t digit) __reentrant -{ - if (!digit) { - mid(AO_MS_TO_TICKS(1000)); - pause(AO_MS_TO_TICKS(300)); - } else { - while (digit--) { - mid(AO_MS_TO_TICKS(300)); - pause(AO_MS_TO_TICKS(300)); - } - } - pause(AO_MS_TO_TICKS(1000)); -} - -void -ao_report_altitude(void) -{ - __pdata alt_t agl = ao_max_height; - static __xdata uint8_t digits[11]; - __pdata uint8_t ndigits, i; - - if (agl < 0) - agl = 0; - ndigits = 0; - do { - digits[ndigits++] = agl % 10; - agl /= 10; - } while (agl); - - i = ndigits; - do - ao_report_digit(digits[--i]); - while (i != 0); -} diff --git a/src/product/ao_micropeak.c b/src/product/ao_micropeak.c new file mode 100644 index 00000000..10f0d192 --- /dev/null +++ b/src/product/ao_micropeak.c @@ -0,0 +1,89 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include +#include + +static struct ao_ms5607_sample sample; +static struct ao_ms5607_value value; + +alt_t ground_alt, max_alt; +alt_t ao_max_height; + +void +ao_pa_get(void) +{ + ao_ms5607_sample(&sample); + ao_ms5607_convert(&sample, &value); + pa = value.pres; +} + +static void +ao_compute_height(void) +{ + ground_alt = ao_pa_to_altitude(pa_ground); + max_alt = ao_pa_to_altitude(pa_min); + ao_max_height = max_alt - ground_alt; +} + +static void +ao_pips(void) +{ + uint8_t i; + for (i = 0; i < 10; i++) { + ao_led_toggle(AO_LED_REPORT); + ao_delay(AO_MS_TO_TICKS(80)); + } + ao_delay(AO_MS_TO_TICKS(200)); +} + +int +main(void) +{ + ao_led_init(LEDS_AVAILABLE); + ao_timer_init(); + + /* Init external hardware */ + ao_spi_init(); + ao_ms5607_init(); + ao_ms5607_setup(); + + /* Give the person a second to get their finger out of the way */ + ao_delay(AO_MS_TO_TICKS(1000)); + + ao_log_micro_restore(); + ao_compute_height(); + ao_report_altitude(); + ao_pips(); + ao_log_micro_dump(); + + ao_delay(BOOST_DELAY); + + ao_microflight(); + + ao_log_micro_save(); + ao_compute_height(); + ao_report_altitude(); + for (;;) { + cli(); + set_sleep_mode(SLEEP_MODE_PWR_DOWN); + sleep_mode(); + } +} diff --git a/src/product/ao_micropeak.h b/src/product/ao_micropeak.h new file mode 100644 index 00000000..3e3dec15 --- /dev/null +++ b/src/product/ao_micropeak.h @@ -0,0 +1,78 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_MICROPEAK_H_ +#define _AO_MICROPEAK_H_ + +#define SAMPLE_SLEEP AO_MS_TO_TICKS(96) + +/* 16 sample, or about two seconds worth */ +#define GROUND_AVG_SHIFT 4 +#define GROUND_AVG (1 << GROUND_AVG_SHIFT) + +/* Pressure change (in Pa) to detect boost */ +#define BOOST_DETECT 120 /* 10m at sea level, 12m at 2000m */ + +/* Wait after power on before doing anything to give the user time to assemble the rocket */ +#define BOOST_DELAY AO_SEC_TO_TICKS(60) + +/* Pressure change (in Pa) to detect landing */ +#define LAND_DETECT 24 /* 2m at sea level, 2.4m at 2000m */ + +/* Current sensor pressure value */ +extern uint32_t pa; + +/* Average pressure value on ground */ +extern uint32_t pa_ground; + +/* Minimum recorded filtered pressure value */ +extern uint32_t pa_min; + +/* Pressure values converted to altitudes */ +extern alt_t ground_alt, max_alt; + +/* max_alt - ground_alt */ +extern alt_t ao_max_height; + +void +ao_pa_get(void); + +void +ao_microflight(void); + +#define ACCEL_LOCK_PA -20 +#define ACCEL_LOCK_TIME 10 + +extern uint32_t ao_k_pa; /* 24.8 fixed point */ +extern int32_t ao_k_pa_speed; /* 16.16 fixed point */ +extern int32_t ao_k_pa_accel; /* 16.16 fixed point */ + +extern uint32_t ao_pa; /* integer portion */ +extern int16_t ao_pa_speed; /* integer portion */ +extern int16_t ao_pa_accel; /* integer portion */ + +void +ao_microkalman_init(void); + +void +ao_microkalman_predict(void); + +void +ao_microkalman_correct(void); + +#endif + -- cgit v1.2.3 From b86c69d56261da54745076b1f5a9c8e8e44787c2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 15 Sep 2013 14:13:59 -0700 Subject: altos: Add nanopeak-v0.1 The same as micropeak, just a few different pins Signed-off-by: Keith Packard --- src/Makefile | 2 +- src/nanopeak-v0.1/.gitignore | 2 + src/nanopeak-v0.1/Makefile | 114 +++++++++++++++++++++++++++++++++++++++++++ src/nanopeak-v0.1/ao_pins.h | 65 ++++++++++++++++++++++++ 4 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 src/nanopeak-v0.1/.gitignore create mode 100644 src/nanopeak-v0.1/Makefile create mode 100644 src/nanopeak-v0.1/ao_pins.h (limited to 'src') diff --git a/src/Makefile b/src/Makefile index af2630fc..9a8cb837 100644 --- a/src/Makefile +++ b/src/Makefile @@ -24,7 +24,7 @@ SDCCDIRS=\ telemini-v2.0 AVRDIRS=\ - telescience-v0.1 telescience-pwm micropeak + telescience-v0.1 telescience-pwm micropeak nanopeak-v0.1 ARMDIRS=\ telemega-v0.1 telemega-v0.1/flash-loader \ diff --git a/src/nanopeak-v0.1/.gitignore b/src/nanopeak-v0.1/.gitignore new file mode 100644 index 00000000..27cd0a7c --- /dev/null +++ b/src/nanopeak-v0.1/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +nanopeak-* diff --git a/src/nanopeak-v0.1/Makefile b/src/nanopeak-v0.1/Makefile new file mode 100644 index 00000000..cb468a06 --- /dev/null +++ b/src/nanopeak-v0.1/Makefile @@ -0,0 +1,114 @@ +# +# Tiny AltOS build +# +# +vpath % ../attiny:../drivers:../core:../product:.. +vpath ao-make-product.5c ../util +vpath make-altitude-pa ../util + +MCU=attiny85 +DUDECPUTYPE=t85 +#PROGRAMMER=stk500v2 -P usb +PROGRAMMER=usbtiny +LOADCMD=avrdude +LOADSLOW=-i 32 -B 32 +LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: +CC=avr-gcc +OBJCOPY=avr-objcopy + +LDFLAGS=-L/usr/lib/ldscripts -Tavr25.x + +ifndef VERSION +include ../Version +endif + +ALTOS_SRC = \ + ao_micropeak.c \ + ao_spi_attiny.c \ + ao_led.c \ + ao_clock.c \ + ao_ms5607.c \ + ao_exti.c \ + ao_convert_pa.c \ + ao_report_micro.c \ + ao_notask.c \ + ao_eeprom_tiny.c \ + ao_panic.c \ + ao_log_micro.c \ + ao_async.c \ + ao_microflight.c \ + ao_microkalman.c + +INC=\ + ao.h \ + ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_exti.h \ + ao_ms5607.h \ + ao_log_micro.h \ + ao_micropeak.h \ + altitude-pa.h + +IDPRODUCT=0 +PRODUCT=NanoPeak-v0.1 +PRODUCT_DEF=-DNANOPEAK +CFLAGS = $(PRODUCT_DEF) -I. -I../attiny -I../core -I.. -I../drivers -I../product +CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O2 -mcall-prologues -DATTINY + +NICKLE=nickle + +PROG=nanopeak-v0.1 + +SRC=$(ALTOS_SRC) +OBJ=$(SRC:.c=.o) + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: $(PROG) $(PROG).hex + +CHECK=sh ../util/check-avr-mem + +$(PROG): Makefile $(OBJ) + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) + $(call quiet,CHECK) $(PROG) || ($(RM) -f $(PROG); exit 1) + +$(PROG).hex: $(PROG) + avr-size $(PROG) + $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@ + + +load: $(PROG).hex + $(LOADCMD) $(LOADARG)$(PROG).hex + +load-slow: $(PROG).hex + $(LOADCMD) $(LOADSLOW) $(LOADARG)$(PROG).hex + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +ao_product.o: ao_product.c ao_product.h + +%.o : %.c $(INC) + $(call quiet,CC) -c $(CFLAGS) $< + +distclean: clean + +clean: + rm -f *.o $(PROG) $(PROG).hex + rm -f ao_product.h + +../altitude-pa.h: make-altitude-pa + nickle $< > $@ + +install: + +uninstall: + +$(OBJ): ao_product.h $(INC) diff --git a/src/nanopeak-v0.1/ao_pins.h b/src/nanopeak-v0.1/ao_pins.h new file mode 100644 index 00000000..bd4a06d1 --- /dev/null +++ b/src/nanopeak-v0.1/ao_pins.h @@ -0,0 +1,65 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ +#include + +#define AO_LED_ORANGE (1<<3) +#define AO_LED_SERIAL 3 +#define AO_LED_PANIC AO_LED_ORANGE +#define AO_LED_REPORT AO_LED_ORANGE +#define LEDS_AVAILABLE (AO_LED_ORANGE) +#define USE_SERIAL_1_STDIN 0 +#define HAS_USB 0 +#define PACKET_HAS_SLAVE 0 +#define HAS_SERIAL_1 0 +#define HAS_TASK 0 +#define HAS_MS5607 1 +#define HAS_MS5611 0 +#define HAS_EEPROM 0 +#define HAS_BEEP 0 +#define AVR_CLOCK 250000UL + +/* SPI */ +#define SPI_PORT PORTB +#define SPI_PIN PINB +#define SPI_DIR DDRB +#define AO_MS5607_CS_PORT PORTB +#define AO_MS5607_CS_PIN 4 + +/* MS5607 */ +#define AO_MS5607_SPI_INDEX 0 +#define AO_MS5607_MISO_PORT PORTB +#define AO_MS5607_MISO_PIN 0 +#define AO_MS5607_BARO_OVERSAMPLE 4096 +#define AO_MS5607_TEMP_OVERSAMPLE 1024 + +/* I2C */ +#define I2C_PORT PORTB +#define I2C_PIN PINB +#define I2C_DIR DDRB +#define I2C_PIN_SCL PINB2 +#define I2C_PIN_SDA PINB0 + +#define AO_CONST_ATTRIB PROGMEM +typedef int32_t alt_t; +#define FETCH_ALT(o) ((alt_t) pgm_read_dword(&altitude_table[o])) + +#define AO_ALT_VALUE(x) ((x) * (alt_t) 10) + +#endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 0ff5f0fbc4900ad45bb7910ffc0c5a4e4cc4b857 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 15 Sep 2013 14:21:08 -0700 Subject: altos: Stop copying cc1111 binaries to the altos/src dir Just clutters up that directory. Signed-off-by: Keith Packard --- src/product/Makefile.teledongle | 4 ++-- src/product/Makefile.telelaunch | 4 ++-- src/product/Makefile.telemetrum | 6 +++--- src/product/Makefile.telemini | 6 +++--- src/product/Makefile.telenano | 4 ++-- src/spiradio-v0.1/Makefile | 6 +++--- src/teleballoon-v1.1/Makefile | 2 +- src/telebt-v1.0/Makefile | 2 +- src/telefire-v0.1/Makefile | 6 +++--- src/telefire-v0.2/Makefile | 6 +++--- src/telemini-v2.0/Makefile | 6 +++--- src/teleshield-v0.1/Makefile | 6 +++--- src/teleterra-v0.2/Makefile | 6 +++--- src/tidongle/Makefile | 6 +++--- 14 files changed, 35 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle index 3101b777..da9bcba0 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -80,9 +80,9 @@ endif # Otherwise, print the full command line. quiet ?= $($1) -all: ../$(PROG) +all: $(PROG) -../$(PROG): $(REL) Makefile +$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch index 1e55989c..a5e2eb7f 100644 --- a/src/product/Makefile.telelaunch +++ b/src/product/Makefile.telelaunch @@ -82,9 +82,9 @@ endif # Otherwise, print the full command line. quiet ?= $($1) -all: ../$(PROG) +all: $(PROG) -../$(PROG): $(REL) Makefile +$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index 5e3eed7f..c740a483 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -94,10 +94,10 @@ endif # Otherwise, print the full command line. quiet ?= $($1) -all: ../$(PROG) +all: $(PROG) -../$(PROG): $(REL) Makefile - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. +$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini index ef8906ba..0884079e 100644 --- a/src/product/Makefile.telemini +++ b/src/product/Makefile.telemini @@ -83,10 +83,10 @@ endif # Otherwise, print the full command line. quiet ?= $($1) -all: ../$(PROG) +all: $(PROG) -../$(PROG): $(REL) Makefile - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. +$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index 67410ae0..c31989ee 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -82,9 +82,9 @@ endif # Otherwise, print the full command line. quiet ?= $($1) -all: ../$(PROG) +all: $(PROG) -../$(PROG): $(REL) Makefile +$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ diff --git a/src/spiradio-v0.1/Makefile b/src/spiradio-v0.1/Makefile index a207d34f..e644bc49 100644 --- a/src/spiradio-v0.1/Makefile +++ b/src/spiradio-v0.1/Makefile @@ -73,10 +73,10 @@ endif # Otherwise, print the full command line. quiet ?= $($1) -all: ../$(PROG) +all: $(PROG) -../$(PROG): $(REL) Makefile - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. +$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version diff --git a/src/teleballoon-v1.1/Makefile b/src/teleballoon-v1.1/Makefile index 2eea996e..6ff076a9 100644 --- a/src/teleballoon-v1.1/Makefile +++ b/src/teleballoon-v1.1/Makefile @@ -103,7 +103,7 @@ quiet ?= $($1) all: $(PROG) $(PROG): $(REL) Makefile - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version diff --git a/src/telebt-v1.0/Makefile b/src/telebt-v1.0/Makefile index 911a8b09..40853fc3 100644 --- a/src/telebt-v1.0/Makefile +++ b/src/telebt-v1.0/Makefile @@ -82,7 +82,7 @@ quiet ?= $($1) all: $(PROG) $(PROG): $(REL) Makefile - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version diff --git a/src/telefire-v0.1/Makefile b/src/telefire-v0.1/Makefile index 712b2e8b..f9e11698 100644 --- a/src/telefire-v0.1/Makefile +++ b/src/telefire-v0.1/Makefile @@ -84,10 +84,10 @@ endif # Otherwise, print the full command line. quiet ?= $($1) -all: ../$(PROG) +all: $(PROG) -../$(PROG): $(REL) Makefile - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. +$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version diff --git a/src/telefire-v0.2/Makefile b/src/telefire-v0.2/Makefile index 3353bc1a..a820990a 100644 --- a/src/telefire-v0.2/Makefile +++ b/src/telefire-v0.2/Makefile @@ -84,10 +84,10 @@ endif # Otherwise, print the full command line. quiet ?= $($1) -all: ../$(PROG) +all: $(PROG) -../$(PROG): $(REL) Makefile - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. +$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version diff --git a/src/telemini-v2.0/Makefile b/src/telemini-v2.0/Makefile index 40878778..ed90f30f 100644 --- a/src/telemini-v2.0/Makefile +++ b/src/telemini-v2.0/Makefile @@ -96,10 +96,10 @@ endif # Otherwise, print the full command line. quiet ?= $($1) -all: ../$(PROG) +all: $(PROG) -../$(PROG): $(REL) Makefile - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. +$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version diff --git a/src/teleshield-v0.1/Makefile b/src/teleshield-v0.1/Makefile index ab2a025f..e8b262ef 100644 --- a/src/teleshield-v0.1/Makefile +++ b/src/teleshield-v0.1/Makefile @@ -92,10 +92,10 @@ endif # Otherwise, print the full command line. quiet ?= $($1) -all: ../$(PROG) +all: $(PROG) -../$(PROG): $(REL) Makefile - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. +$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile index 68a8d1b6..88637360 100644 --- a/src/teleterra-v0.2/Makefile +++ b/src/teleterra-v0.2/Makefile @@ -86,10 +86,10 @@ endif # Otherwise, print the full command line. quiet ?= $($1) -all: ../$(PROG) +all: $(PROG) -../$(PROG): $(REL) Makefile - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. +$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile index 1514c4df..b2ba537b 100644 --- a/src/tidongle/Makefile +++ b/src/tidongle/Makefile @@ -72,10 +72,10 @@ endif # Otherwise, print the full command line. quiet ?= $($1) -all: ../$(PROG) +all: $(PROG) -../$(PROG): $(REL) Makefile - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. +$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version -- cgit v1.2.3 From 1fa3ff9ba6d04303b3de6952675532492c85182f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 15 Sep 2013 14:29:09 -0700 Subject: altos/telemini-v2.0: Change initialization order Make sure busses are running before devices are initialized Signed-off-by: Keith Packard --- src/telemini-v2.0/ao_telemini.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/telemini-v2.0/ao_telemini.c b/src/telemini-v2.0/ao_telemini.c index 294f768a..0d8dd1cb 100644 --- a/src/telemini-v2.0/ao_telemini.c +++ b/src/telemini-v2.0/ao_telemini.c @@ -24,36 +24,42 @@ __xdata uint8_t ao_force_freq; void main(void) { - /* - * Reduce the transient on the ignite pins at startup by - * pulling the pins low as soon as possible at power up - */ - ao_ignite_set_pins(); - ao_clock_init(); +#if HAS_STACK_GUARD + ao_mpu_init(); +#endif + ao_task_init(); + /* Turn on the red LED until the system is stable */ ao_led_init(LEDS_AVAILABLE); ao_led_on(AO_LED_RED); - ao_task_init(); - ao_timer_init(); + + ao_spi_init(); + ao_exti_init(); ao_adc_init(); +#if HAS_BEEP ao_beep_init(); +#endif ao_cmd_init(); - ao_spi_init(); - ao_exti_init(); +#if HAS_MS5607 ao_ms5607_init(); +#endif ao_storage_init(); + ao_flight_init(); ao_log_init(); ao_report_init(); + ao_usb_init(); ao_telemetry_init(); ao_radio_init(); ao_packet_slave_init(TRUE); + ao_igniter_init(); + ao_config_init(); ao_start_scheduler(); } -- cgit v1.2.3 From 56b577e55c264c8e3152bb2b2cca02fa8836ac1e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 15 Sep 2013 14:29:46 -0700 Subject: altos/telemetrum-v2.0: Use red LED during boot time If the LED is stuck on, then the board has failed to initialize, so use red instead of green as a warning indicator. Signed-off-by: Keith Packard --- src/telemetrum-v2.0/ao_telemetrum.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/telemetrum-v2.0/ao_telemetrum.c b/src/telemetrum-v2.0/ao_telemetrum.c index e365417d..d79aba54 100644 --- a/src/telemetrum-v2.0/ao_telemetrum.c +++ b/src/telemetrum-v2.0/ao_telemetrum.c @@ -42,7 +42,7 @@ main(void) ao_task_init(); ao_serial_init(); ao_led_init(LEDS_AVAILABLE); - ao_led_on(AO_LED_GREEN); + ao_led_on(AO_LED_RED); ao_timer_init(); ao_spi_init(); -- cgit v1.2.3 From 8bd218854e968d2b9407489359be0c4a1aefd2c8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 19 Sep 2013 00:29:25 -0500 Subject: altos: Set TeleMini v2.0 USB ID correctly Uses 0x0027 Signed-off-by: Keith Packard --- src/telemini-v2.0/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/telemini-v2.0/Makefile b/src/telemini-v2.0/Makefile index ed90f30f..fcac2c48 100644 --- a/src/telemini-v2.0/Makefile +++ b/src/telemini-v2.0/Makefile @@ -81,7 +81,7 @@ PROGNAME = telemini-v$(TELEMINI_VER) PROG = $(PROGNAME)-$(VERSION).ihx PRODUCT=TeleMini-v$(TELEMINI_VER) PRODUCT_DEF=-DTELEMINI_V_$(TELEMINI_DEF) -IDPRODUCT=0x000a +IDPRODUCT=0x0027 include ../cc1111/Makefile.cc1111 -- cgit v1.2.3 From 4254de22864de2ed7ae5928c6b8bfd9df1c8a3fb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 Oct 2013 21:51:30 -0700 Subject: altos: Don't require an LED for ao_flight EasyMini has no LEDs. Deal with it. Signed-off-by: Keith Packard --- src/core/ao_flight.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index 1322195b..88dc816d 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -134,8 +134,10 @@ ao_flight(void) ao_rdf_set(1); ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); #endif +#if HAS_LED /* signal successful initialization by turning off the LED */ ao_led_off(AO_LED_RED); +#endif } else { /* Set idle mode */ ao_flight_state = ao_flight_idle; @@ -145,8 +147,10 @@ ao_flight(void) ao_packet_slave_start(); #endif +#if HAS_LED /* signal successful initialization by turning off the LED */ ao_led_off(AO_LED_RED); +#endif } /* wakeup threads due to state change */ ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); -- cgit v1.2.3 From 8f7edcee2db30652ce0b147f282de3396c3786ad Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 Oct 2013 21:53:53 -0700 Subject: altos/lpc, altos/stm: ARM requires ISB after switching stack pointers This sticks a barrier in the CPU to prevent using the wrong stack register past the change. Signed-off-by: Keith Packard --- src/lpc/ao_arch_funcs.h | 1 + src/stm/ao_arch_funcs.h | 1 + 2 files changed, 2 insertions(+) (limited to 'src') diff --git a/src/lpc/ao_arch_funcs.h b/src/lpc/ao_arch_funcs.h index 9a3219a2..0891903e 100644 --- a/src/lpc/ao_arch_funcs.h +++ b/src/lpc/ao_arch_funcs.h @@ -235,6 +235,7 @@ static inline void ao_arch_start_scheduler(void) { asm("mrs %0,control" : "=&r" (control)); control |= (1 << 1); asm("msr control,%0" : : "r" (control)); + asm("isb"); } #endif /* _AO_ARCH_FUNCS_H_ */ diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 9bb2d7cd..4bcc1023 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -354,6 +354,7 @@ static inline void ao_arch_start_scheduler(void) { asm("mrs %0,control" : "=&r" (control)); control |= (1 << 1); asm("msr control,%0" : : "r" (control)); + asm("isb"); } #endif -- cgit v1.2.3 From 258d225df1f4afe1cfdc9c43208bcd75d18cdf2d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 Oct 2013 22:00:15 -0700 Subject: altos: Rename easymini-v0.1 to easymini-v1.0 The production boards are the same as the modified v0.1 boards Signed-off-by: Keith Packard --- src/Makefile | 5 +- src/easymini-v0.1/.gitignore | 2 - src/easymini-v0.1/Makefile | 85 ------------------ src/easymini-v0.1/ao_easymini.c | 46 ---------- src/easymini-v0.1/ao_pins.h | 143 ------------------------------- src/easymini-v0.1/flash-loader/Makefile | 8 -- src/easymini-v0.1/flash-loader/ao_pins.h | 33 ------- src/easymini-v1.0/.gitignore | 2 + src/easymini-v1.0/Makefile | 84 ++++++++++++++++++ src/easymini-v1.0/ao_easymini.c | 46 ++++++++++ src/easymini-v1.0/ao_pins.h | 136 +++++++++++++++++++++++++++++ src/easymini-v1.0/flash-loader/Makefile | 8 ++ src/easymini-v1.0/flash-loader/ao_pins.h | 33 +++++++ src/lpc/Makefile.defs | 8 +- 14 files changed, 314 insertions(+), 325 deletions(-) delete mode 100644 src/easymini-v0.1/.gitignore delete mode 100644 src/easymini-v0.1/Makefile delete mode 100644 src/easymini-v0.1/ao_easymini.c delete mode 100644 src/easymini-v0.1/ao_pins.h delete mode 100644 src/easymini-v0.1/flash-loader/Makefile delete mode 100644 src/easymini-v0.1/flash-loader/ao_pins.h create mode 100644 src/easymini-v1.0/.gitignore create mode 100644 src/easymini-v1.0/Makefile create mode 100644 src/easymini-v1.0/ao_easymini.c create mode 100644 src/easymini-v1.0/ao_pins.h create mode 100644 src/easymini-v1.0/flash-loader/Makefile create mode 100644 src/easymini-v1.0/flash-loader/ao_pins.h (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 9a8cb837..23cd2920 100644 --- a/src/Makefile +++ b/src/Makefile @@ -33,11 +33,10 @@ ARMDIRS=\ telegps-v0.3 telegps-v0.3/flash-loader \ stm-bringup stm-demo \ telelco-v0.2 telelco-v0.2/flash-loader \ - telescience-v0.2 telescience-v0.2/flash-loader \ - easymini-v0.1 easymini-v0.1/flash-loader + telescience-v0.2 telescience-v0.2/flash-loader ARMM0DIRS=\ - easymini-v0.1 + easymini-v1.0 easymini-v1.0/flash-loader ifneq ($(shell which sdcc),) SUBDIRS += $(SDCCDIRS) diff --git a/src/easymini-v0.1/.gitignore b/src/easymini-v0.1/.gitignore deleted file mode 100644 index e5f7d586..00000000 --- a/src/easymini-v0.1/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -ao_product.h -*.elf diff --git a/src/easymini-v0.1/Makefile b/src/easymini-v0.1/Makefile deleted file mode 100644 index 9847656c..00000000 --- a/src/easymini-v0.1/Makefile +++ /dev/null @@ -1,85 +0,0 @@ -# -# AltOS build -# -# - -include ../lpc/Makefile.defs - -INC = \ - ao.h \ - ao_arch.h \ - ao_arch_funcs.h \ - ao_pins.h \ - ao_product.h \ - lpc.h - -# -# Common AltOS sources -# -ALTOS_SRC = \ - ao_interrupt.c \ - ao_boot_chain.c \ - ao_romconfig.c \ - ao_product.c \ - ao_mutex.c \ - ao_panic.c \ - ao_stdio.c \ - ao_storage.c \ - ao_report.c \ - ao_ignite.c \ - ao_flight.c \ - ao_kalman.c \ - ao_sample.c \ - ao_data.c \ - ao_convert_pa.c \ - ao_led_lpc.c \ - ao_task.c \ - ao_log.c \ - ao_log_mini.c \ - ao_cmd.c \ - ao_config.c \ - ao_timer_lpc.c \ - ao_exti_lpc.c \ - ao_usb_lpc.c \ - ao_spi_lpc.c \ - ao_adc_lpc.c \ - ao_beep_lpc.c \ - ao_m25.c \ - ao_ms5607.c - -PRODUCT=EasyMini-v0.1 -PRODUCT_DEF=-DEASYMINI_V_0_1 -IDPRODUCT=0x0026 - -CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -g -Os - -PROGNAME=easymini-v0.1 -PROG=$(PROGNAME)-$(VERSION).elf - -SRC=$(ALTOS_SRC) ao_easymini.c -OBJ=$(SRC:.c=.o) - -all: $(PROG) - -LDFLAGS=-L../lpc -Wl,-Taltos.ld - -$(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc - -ao_product.h: ao-make-product.5c ../Version - $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ - -$(OBJ): $(INC) - -load: $(PROG) - lpc-load $(PROG) - -distclean: clean - -clean: - rm -f *.o $(PROG) - rm -f ao_product.h - -install: - -uninstall: diff --git a/src/easymini-v0.1/ao_easymini.c b/src/easymini-v0.1/ao_easymini.c deleted file mode 100644 index 97230b61..00000000 --- a/src/easymini-v0.1/ao_easymini.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include -#include - -void -main(void) -{ - ao_clock_init(); - ao_task_init(); - ao_timer_init(); - ao_exti_init(); - - ao_beep_init(); - - ao_adc_init(); - ao_spi_init(); - ao_storage_init(); - - ao_usb_init(); - - ao_cmd_init(); - ao_flight_init(); - ao_ms5607_init(); - ao_log_init(); - ao_report_init(); - ao_igniter_init(); - ao_config_init(); - - ao_start_scheduler(); -} diff --git a/src/easymini-v0.1/ao_pins.h b/src/easymini-v0.1/ao_pins.h deleted file mode 100644 index e0eb10bf..00000000 --- a/src/easymini-v0.1/ao_pins.h +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright © 2013 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#define HAS_BEEP 1 -#define HAS_LED 1 - -#define AO_STACK_SIZE 384 - -#define IS_FLASH_LOADER 0 - -/* Crystal on the board */ -#define AO_LPC_CLKIN 12000000 - -/* Main clock frequency. 48MHz for USB so we don't use the USB PLL */ -#define AO_LPC_CLKOUT 48000000 - -/* System clock frequency */ -#define AO_LPC_SYSCLK 24000000 - -#define LED_PORT 0 -#define LED_PIN_RED 7 - -#define AO_LED_RED (1 << LED_PIN_RED) - -#define LEDS_AVAILABLE AO_LED_RED - -#define HAS_USB 1 - -#define HAS_USB_CONNECT 0 -#define HAS_USB_VBUS 0 -#define HAS_USB_PULLUP 1 -#define AO_USB_PULLUP_PORT 0 -#define AO_USB_PULLUP_PIN 20 - -#define PACKET_HAS_SLAVE 0 - -#define AO_LOG_FORMAT AO_LOG_FORMAT_EASYMINI - -/* USART */ - -#define HAS_SERIAL 0 -#define USE_SERIAL_0_STDIN 1 -#define SERIAL_0_18_19 1 -#define SERIAL_0_14_15 0 -#define SERIAL_0_17_18 0 -#define SERIAL_0_26_27 0 - -/* SPI */ - -#define HAS_SPI_0 1 -#define SPI_SCK0_P0_6 1 -#define HAS_SPI_1 1 -#define SPI_SCK1_P1_15 1 -#define SPI_MISO1_P0_22 1 -#define SPI_MOSI1_P0_21 1 - -/* M25 */ - -#define M25_MAX_CHIPS 1 -#define AO_M25_SPI_CS_PORT 0 -#define AO_M25_SPI_CS_MASK (1 << 23) -#define AO_M25_SPI_BUS 1 - -/* MS5607 */ - -#define HAS_MS5607 1 -#define HAS_MS5611 0 -#define AO_MS5607_PRIVATE_PINS 0 -#define AO_MS5607_CS_PORT 0 -#define AO_MS5607_CS_PIN 7 -#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS_PIN) -#define AO_MS5607_MISO_PORT 0 -#define AO_MS5607_MISO_PIN 8 -#define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO_PIN) -#define AO_MS5607_SPI_INDEX 0 - -#define HAS_ACCEL 0 -#define HAS_GPS 0 -#define HAS_RADIO 0 -#define HAS_FLIGHT 1 -#define HAS_EEPROM 1 -#define HAS_TELEMETRY 0 -#define HAS_APRS 0 -#define HAS_LOG 1 -#define USE_INTERNAL_FLASH 0 -#define HAS_IGNITE 1 -#define HAS_IGNITE_REPORT 1 - -#define AO_DATA_RING 16 - -/* - * ADC - */ - -#define HAS_ADC 1 - -#define AO_NUM_ADC 3 - -#define AO_ADC_0 1 -#define AO_ADC_1 1 -#define AO_ADC_2 1 - -struct ao_adc { - int16_t sense_a; - int16_t sense_m; - int16_t v_batt; -}; - -/* - * Igniter - */ - -#define AO_IGNITER_CLOSED 400 -#define AO_IGNITER_OPEN 60 - -#define AO_IGNITER_DROGUE_PORT 0 -#define AO_IGNITER_DROGUE_PIN 2 -#define AO_IGNITER_SET_DROGUE(v) ao_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, AO_IGNITER_DROGUE, v) - -#define AO_IGNITER_MAIN_PORT 0 -#define AO_IGNITER_MAIN_PIN 3 -#define AO_IGNITER_SET_MAIN(v) ao_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, AO_IGNITER_MAIN, v) - -#define AO_SENSE_DROGUE(p) ((p)->adc.sense_a) -#define AO_SENSE_MAIN(p) ((p)->adc.sense_m) - -#define AO_ADC_DUMP(p) \ - printf("tick: %5u apogee: %5d main: %5d batt: %5d\n", \ - (p)->tick, (p)->adc.sense_a, (p)->adc.sense_m, (p)->adc.v_batt) diff --git a/src/easymini-v0.1/flash-loader/Makefile b/src/easymini-v0.1/flash-loader/Makefile deleted file mode 100644 index ab828b22..00000000 --- a/src/easymini-v0.1/flash-loader/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# AltOS flash loader build -# -# - -TOPDIR=../.. -HARDWARE=easymini-v0.1 -include $(TOPDIR)/lpc/Makefile-flash.defs diff --git a/src/easymini-v0.1/flash-loader/ao_pins.h b/src/easymini-v0.1/flash-loader/ao_pins.h deleted file mode 100644 index 4330151d..00000000 --- a/src/easymini-v0.1/flash-loader/ao_pins.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright © 2013 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_PINS_H_ -#define _AO_PINS_H_ - -#include - -#define AO_BOOT_PIN 1 -#define AO_BOOT_APPLICATION_GPIO 0 -#define AO_BOOT_APPLICATION_PIN 19 -#define AO_BOOT_APPLICATION_VALUE 1 -#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP - -#define HAS_USB_PULLUP 1 -#define AO_USB_PULLUP_PORT 0 -#define AO_USB_PULLUP_PIN 20 - -#endif /* _AO_PINS_H_ */ diff --git a/src/easymini-v1.0/.gitignore b/src/easymini-v1.0/.gitignore new file mode 100644 index 00000000..e5f7d586 --- /dev/null +++ b/src/easymini-v1.0/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +*.elf diff --git a/src/easymini-v1.0/Makefile b/src/easymini-v1.0/Makefile new file mode 100644 index 00000000..ec305c94 --- /dev/null +++ b/src/easymini-v1.0/Makefile @@ -0,0 +1,84 @@ +# +# AltOS build +# +# + +include ../lpc/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_pins.h \ + ao_product.h \ + lpc.h + +# +# Common AltOS sources +# +ALTOS_SRC = \ + ao_interrupt.c \ + ao_boot_chain.c \ + ao_romconfig.c \ + ao_product.c \ + ao_mutex.c \ + ao_panic.c \ + ao_stdio.c \ + ao_storage.c \ + ao_report.c \ + ao_ignite.c \ + ao_flight.c \ + ao_kalman.c \ + ao_sample.c \ + ao_data.c \ + ao_convert_pa.c \ + ao_task.c \ + ao_log.c \ + ao_log_mini.c \ + ao_cmd.c \ + ao_config.c \ + ao_timer_lpc.c \ + ao_exti_lpc.c \ + ao_usb_lpc.c \ + ao_spi_lpc.c \ + ao_adc_lpc.c \ + ao_beep_lpc.c \ + ao_m25.c \ + ao_ms5607.c + +PRODUCT=EasyMini-v1.0 +PRODUCT_DEF=-DEASYMINI_V_1_0 +IDPRODUCT=0x0026 + +CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -g -Os + +PROGNAME=easymini-v1.0 +PROG=$(PROGNAME)-$(VERSION).elf + +SRC=$(ALTOS_SRC) ao_easymini.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) + +LDFLAGS=-L../lpc -Wl,-Taltos.ld + +$(PROG): Makefile $(OBJ) altos.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +$(OBJ): $(INC) + +load: $(PROG) + lpc-load $(PROG) + +distclean: clean + +clean: + rm -f *.o $(PROG) + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/easymini-v1.0/ao_easymini.c b/src/easymini-v1.0/ao_easymini.c new file mode 100644 index 00000000..97230b61 --- /dev/null +++ b/src/easymini-v1.0/ao_easymini.c @@ -0,0 +1,46 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +void +main(void) +{ + ao_clock_init(); + ao_task_init(); + ao_timer_init(); + ao_exti_init(); + + ao_beep_init(); + + ao_adc_init(); + ao_spi_init(); + ao_storage_init(); + + ao_usb_init(); + + ao_cmd_init(); + ao_flight_init(); + ao_ms5607_init(); + ao_log_init(); + ao_report_init(); + ao_igniter_init(); + ao_config_init(); + + ao_start_scheduler(); +} diff --git a/src/easymini-v1.0/ao_pins.h b/src/easymini-v1.0/ao_pins.h new file mode 100644 index 00000000..e721030d --- /dev/null +++ b/src/easymini-v1.0/ao_pins.h @@ -0,0 +1,136 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#define HAS_BEEP 1 +#define HAS_LED 0 + +#define AO_STACK_SIZE 384 + +#define IS_FLASH_LOADER 0 + +/* Crystal on the board */ +#define AO_LPC_CLKIN 12000000 + +/* Main clock frequency. 48MHz for USB so we don't use the USB PLL */ +#define AO_LPC_CLKOUT 48000000 + +/* System clock frequency */ +#define AO_LPC_SYSCLK 24000000 + +#define HAS_USB 1 + +#define HAS_USB_CONNECT 0 +#define HAS_USB_VBUS 0 +#define HAS_USB_PULLUP 1 +#define AO_USB_PULLUP_PORT 0 +#define AO_USB_PULLUP_PIN 20 + +#define PACKET_HAS_SLAVE 0 + +#define AO_LOG_FORMAT AO_LOG_FORMAT_EASYMINI + +/* USART */ + +#define HAS_SERIAL 0 +#define USE_SERIAL_0_STDIN 1 +#define SERIAL_0_18_19 1 +#define SERIAL_0_14_15 0 +#define SERIAL_0_17_18 0 +#define SERIAL_0_26_27 0 + +/* SPI */ + +#define HAS_SPI_0 1 +#define SPI_SCK0_P0_6 1 +#define HAS_SPI_1 1 +#define SPI_SCK1_P1_15 1 +#define SPI_MISO1_P0_22 1 +#define SPI_MOSI1_P0_21 1 + +/* M25 */ + +#define M25_MAX_CHIPS 1 +#define AO_M25_SPI_CS_PORT 0 +#define AO_M25_SPI_CS_MASK (1 << 23) +#define AO_M25_SPI_BUS 1 + +/* MS5607 */ + +#define HAS_MS5607 1 +#define HAS_MS5611 0 +#define AO_MS5607_PRIVATE_PINS 0 +#define AO_MS5607_CS_PORT 0 +#define AO_MS5607_CS_PIN 7 +#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS_PIN) +#define AO_MS5607_MISO_PORT 0 +#define AO_MS5607_MISO_PIN 8 +#define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO_PIN) +#define AO_MS5607_SPI_INDEX 0 + +#define HAS_ACCEL 0 +#define HAS_GPS 0 +#define HAS_RADIO 0 +#define HAS_FLIGHT 1 +#define HAS_EEPROM 1 +#define HAS_TELEMETRY 0 +#define HAS_APRS 0 +#define HAS_LOG 1 +#define USE_INTERNAL_FLASH 0 +#define HAS_IGNITE 1 +#define HAS_IGNITE_REPORT 1 + +#define AO_DATA_RING 16 + +/* + * ADC + */ + +#define HAS_ADC 1 + +#define AO_NUM_ADC 3 + +#define AO_ADC_0 1 +#define AO_ADC_1 1 +#define AO_ADC_2 1 + +struct ao_adc { + int16_t sense_a; + int16_t sense_m; + int16_t v_batt; +}; + +/* + * Igniter + */ + +#define AO_IGNITER_CLOSED 400 +#define AO_IGNITER_OPEN 60 + +#define AO_IGNITER_DROGUE_PORT 0 +#define AO_IGNITER_DROGUE_PIN 2 +#define AO_IGNITER_SET_DROGUE(v) ao_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, AO_IGNITER_DROGUE, v) + +#define AO_IGNITER_MAIN_PORT 0 +#define AO_IGNITER_MAIN_PIN 3 +#define AO_IGNITER_SET_MAIN(v) ao_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, AO_IGNITER_MAIN, v) + +#define AO_SENSE_DROGUE(p) ((p)->adc.sense_a) +#define AO_SENSE_MAIN(p) ((p)->adc.sense_m) + +#define AO_ADC_DUMP(p) \ + printf("tick: %5u apogee: %5d main: %5d batt: %5d\n", \ + (p)->tick, (p)->adc.sense_a, (p)->adc.sense_m, (p)->adc.v_batt) diff --git a/src/easymini-v1.0/flash-loader/Makefile b/src/easymini-v1.0/flash-loader/Makefile new file mode 100644 index 00000000..78bb4092 --- /dev/null +++ b/src/easymini-v1.0/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=easymini-v1.0 +include $(TOPDIR)/lpc/Makefile-flash.defs diff --git a/src/easymini-v1.0/flash-loader/ao_pins.h b/src/easymini-v1.0/flash-loader/ao_pins.h new file mode 100644 index 00000000..4330151d --- /dev/null +++ b/src/easymini-v1.0/flash-loader/ao_pins.h @@ -0,0 +1,33 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#include + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO 0 +#define AO_BOOT_APPLICATION_PIN 19 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +#define HAS_USB_PULLUP 1 +#define AO_USB_PULLUP_PORT 0 +#define AO_USB_PULLUP_PIN 20 + +#endif /* _AO_PINS_H_ */ diff --git a/src/lpc/Makefile.defs b/src/lpc/Makefile.defs index 9e87cee1..2873d5e8 100644 --- a/src/lpc/Makefile.defs +++ b/src/lpc/Makefile.defs @@ -7,13 +7,11 @@ vpath load_csv.5c ../kalman vpath matrix.5c ../kalman vpath ao-make-product.5c ../util -CC=/usr/bin/arm-none-eabi-gcc +CC=arm-none-eabi-gcc SAT=/opt/cortex SAT_CLIB=$(SAT)/lib/pdclib-cortex-m0.a SAT_CFLAGS=-I$(SAT)/include -#CC=/opt/arm-gcc-bits/bin/arm-none-eabi-gcc - ifndef VERSION include ../Version endif @@ -21,7 +19,7 @@ endif AO_CFLAGS=-I. -I../lpc -I../core -I../drivers -I.. LPC_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) -LDFLAGS=-L../stm -Wl,-Taltos.ld +LDFLAGS=$(LPC_CFLAGS) -L../stm -Wl,-Taltos.ld NICKLE=nickle @@ -34,7 +32,7 @@ endif quiet ?= $($1) .c.o: - $(call quiet,CC) -c $(CFLAGS) -o $@ $< + $(call quiet,CC) -c $(CFLAGS) $< ao_serial_lpc.h: ../lpc/baud_rate ao_pins.h nickle ../lpc/baud_rate `awk '/AO_LPC_CLKOUT/{print $$3}' ao_pins.h` > $@ -- cgit v1.2.3 From 16965716c02eb79b449d9d3b264814d775660134 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 8 Oct 2013 09:20:12 -0700 Subject: altos/stm: New GAS version requires flags in APSR assignment Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 4bcc1023..b461cd3f 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -329,7 +329,7 @@ static inline void ao_arch_restore_stack(void) { /* Restore APSR */ asm("pop {r0}"); - asm("msr apsr,r0"); + asm("msr apsr_nczvq,r0"); /* Restore general registers */ asm("pop {r0-r12,lr}\n"); -- cgit v1.2.3 From 6a1e398e590121458176758858bb4210f3eb5a55 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 8 Oct 2013 09:22:03 -0700 Subject: Add --with parameters to configure for compiler selection This allows the user to specify which compiler to use for each target CPU. Also checks to make sure the arm compiler supports -m0 and -m3 cpu type flags. The build now actually uses the specified compilers too. Signed-off-by: Keith Packard --- configure.ac | 155 +++++++++++++++++++++++++++++++++++++++--- src/Makedefs.in | 10 +++ src/Makefile | 25 +++---- src/avr-demo/Makefile | 10 +-- src/avr/Makefile.defs | 16 +++++ src/cc1111/Makefile.cc1111 | 3 +- src/lpc/Makefile-flash.defs | 10 +-- src/lpc/Makefile.defs | 23 ++++--- src/micropeak/Makefile | 12 +--- src/nanopeak-v0.1/Makefile | 12 +--- src/stm/Makefile-flash.defs | 11 +-- src/stm/Makefile.defs | 15 ++-- src/telepyro-v0.1/Makefile | 10 +-- src/telescience-pwm/Makefile | 12 +--- src/telescience-v0.1/Makefile | 12 +--- 15 files changed, 238 insertions(+), 98 deletions(-) create mode 100644 src/Makedefs.in create mode 100644 src/avr/Makefile.defs (limited to 'src') diff --git a/configure.ac b/configure.ac index e88109f9..729149da 100644 --- a/configure.ac +++ b/configure.ac @@ -180,21 +180,151 @@ if test "x$GCC" = "xyes"; then fi AC_SUBST(WARN_CFLAGS) -AC_CHECK_PROG([HAVE_SDCC], [sdcc], yes, no) +# +# Configure SDCC +# + +AC_ARG_WITH([sdcc], + [AS_HELP_STRING([--with-sdcc], + [Name of SDCC])], + [], + [with_sdcc=auto]) + +if test "x$with_sdcc" != "xno"; then + if test "x$with_sdcc" = "xauto"; then + with_sdcc="sdcc" + AC_CHECK_PROG([HAVE_SDCC],[$with_sdcc], yes, no) + else + HAVE_SDCC=yes + fi +else + HAVE_SDCC=no +fi + if test "x$HAVE_SDCC" = "xno"; then - AC_MSG_WARN([No sdcc found, cc1111 binaries will not be built]) + AC_MSG_WARN([SDCC not found, cc1111 binaries will not be built]) +else + SDCC=$with_sdcc +fi + +AC_SUBST(SDCC) +AC_SUBST(HAVE_SDCC) + +# +# Configure ARM compiler for STM32L and LPC11U14 +# + +AC_ARG_WITH([arm-cc], + [AS_HELP_STRING([--with-arm-cc], + [Name of ARM C compiler])], + [], + [with_arm_cc=auto]) + +if test "x$with_arm_cc" != "xno"; then + if test "x$with_arm_cc" = "xauto"; then + with_arm_cc="arm-none-eabi-gcc" + AC_CHECK_PROG([HAVE_ARM_CC],[$with_arm_cc], yes, no) + else + HAVE_ARM_CC=yes + fi +else + HAVE_ARM_CC=no fi -AC_CHECK_PROG([HAVE_ARM_GCC],[arm-none-eabi-gcc], yes, no,[/opt/cortex/bin]) -if test "x$HAVE_ARM_GCC" = "xno"; then - AC_MSG_WARN([No summon toolchain arm compiler found, STM32L binaries will not be built]) +if test "x$HAVE_ARM_CC" = "xno"; then + AC_MSG_WARN([Arm compiler not found, ARM binaries will not be built]) +else + ARM_CC=$with_arm_cc +fi +AC_SUBST(HAVE_ARM_CC) +AC_SUBST(ARM_CC) + +if test "x$HAVE_ARM_CC" = "xyes"; then + save_CC="$CC" + save_CFLAGS="$CFLAGS" + CC="$ARM_CC" + CFLAGS="-mthumb -mcpu=cortex-m0" + AC_LANG_PUSH([C]) + + AC_MSG_CHECKING([if ]$ARM_CC[ supports cortex-m0]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int i;])], + [HAVE_ARM_M0_CC=yes], + [HAVE_ARM_M0_CC=no]) + AC_MSG_RESULT([$HAVE_ARM_M0]) + CFLAGS="-mthumb -mcpu=cortex-m3" + AC_MSG_CHECKING([if ]$ARM_CC[ supports cortex-m3]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int i;])], + [HAVE_ARM_M3_CC=yes], + [HAVE_ARM_M3_CC=no]) + AC_MSG_RESULT([$HAVE_ARM_M3]) + AC_LANG_POP([C]) + CFLAGS="$save_CFLAGS" + CC="$save_CC" +else + HAVE_ARM_M3_CC=no + HAVE_ARM_M0_CC=no +fi +AC_SUBST(HAVE_ARM_M3_CC) +AC_SUBST(HAVE_ARM_M0_CC) + +if test "x$HAVE_ARM_M3_CC" = "xno"; then + AC_MSG_WARN([No cortex-m3 arm compiler found, STM32L binaries will not be built]) fi -AC_CHECK_PROG([HAVE_ARM_M0_GCC], [arm-none-eabi-gcc], yes, no,[/usr/bin]) -if test "x$HAVE_ARM_M0_GCC" = "xno"; then - AC_MSG_WARN([No linaro toolchain arm cortex-m0 compiler found, LPC11U14 binaries will not be built]) +if test "x$HAVE_ARM_M0_CC" = "xno"; then + AC_MSG_WARN([No cortex-m0 arm compiler found, LPC11U14 binaries will not be built]) fi +# +# Configure AVR compiler +# + +AC_ARG_WITH([avr-cc], + [AS_HELP_STRING([--with-avr-cc], + [Name of AVR C compiler])], + [], + [with_avr_cc=auto]) + +if test "x$with_avr_cc" != "xno"; then + if test "x$with_avr_cc" = "xauto"; then + with_avr_cc="avr-gcc" + AC_CHECK_PROG([HAVE_AVR_CC],[$with_avr_cc], yes, no) + else + HAVE_AVR_CC=yes + fi +else + HAVE_AVR_CC=no +fi + +AC_ARG_WITH([avr-objcopy], + [AS_HELP_STRING([--with-avr-objcopy], + [Name of AVR objcopy])], + [], + [with_avr_objcopy=auto]) + +if test "x$with_avr_objcopy" != "xno"; then + if test "x$with_avr_objcopy" = "xauto"; then + with_avr_objcopy="avr-objcopy" + AC_CHECK_PROG([HAVE_AVR_OBJCOPY],[$with_avr_objcopy], yes, no) + else + HAVE_AVR_OBJCOPY=yes + fi +else + HAVE_AVR_OBJCOPY=no +fi + +if test "x$HAVE_AVR_CC" = "xno" -o "x$HAVE_AVR_OBJCOPY" = "xno"; then + AC_MSG_WARN([AVR compiler and objcopy not found, atmel binaries will not be built]) + HAVE_AVR_CC=no +else + AVR_CC=$with_avr_cc + AVR_OBJCOPY=$with_avr_objcopy +fi + +AC_SUBST(AVR_CC) +AC_SUBST(AVR_OBJCOPY) +AC_SUBST(HAVE_AVR_CC) + AC_CHECK_PROG([HAVE_NICKLE], [nickle], yes, no) if test "x$HAVE_NICKLE" = "xno"; then AC_MSG_ERROR([Please install nickle to build AltOs]) @@ -213,6 +343,7 @@ AM_CONDITIONAL([LIBSTLINK], [test x$HAVE_STLINK != xno]) AC_OUTPUT([ Makefile +src/Makedefs altoslib/Makefile altosuilib/Makefile altosuilib/AltosUIVersion.java @@ -248,9 +379,13 @@ echo "" echo " Package: ${PACKAGE_NAME} ${PACKAGE_VERSION}" echo "" echo " Configuration" -echo " STM32L support..............: ${HAVE_ARM_GCC}" -echo " LPC11U14 support............: ${HAVE_ARM_M0_GCC}" +echo " Arm compiler................: ${ARM_CC}" +echo " STM32L support..............: ${HAVE_ARM_M3_CC}" +echo " LPC11U14 support............: ${HAVE_ARM_M0_CC}" +echo " SDCC........................: ${SDCC}" echo " CC1111 support..............: ${HAVE_SDCC}" +echo " AVR compiler................: ${AVR_CC} ${AVR_OBJCOPY}" +echo " AVR support.................: ${HAVE_AVR_CC}" echo " Android support.............: ${HAVE_ANDROID_SDK}" echo " STlink support..............: ${HAVE_STLINK}" echo "" diff --git a/src/Makedefs.in b/src/Makedefs.in new file mode 100644 index 00000000..6dc9ab0f --- /dev/null +++ b/src/Makedefs.in @@ -0,0 +1,10 @@ +ARM_CC=@ARM_CC@ +HAVE_ARM_M3_CC=@HAVE_ARM_M3_CC@ +HAVE_ARM_M0_CC=@HAVE_ARM_M0_CC@ + +SDCC=@SDCC@ +HAVE_SDCC=@HAVE_SDCC@ + +AVR_CC=@AVR_CC@ +AVR_OBJCOPY=@AVR_OBJCOPY@ +HAVE_AVR_CC=@HAVE_AVR_CC@ diff --git a/src/Makefile b/src/Makefile index 23cd2920..ae231c64 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,6 +13,7 @@ vpath load_csv.5c kalman vpath matrix.5c kalman include Version +include Makedefs SDCCDIRS=\ telemetrum-v1.2 telemetrum-v1.1 telemetrum-v1.0 \ @@ -23,10 +24,7 @@ SDCCDIRS=\ telefire-v0.1 telefire-v0.2 \ telemini-v2.0 -AVRDIRS=\ - telescience-v0.1 telescience-pwm micropeak nanopeak-v0.1 - -ARMDIRS=\ +ARMM3DIRS=\ telemega-v0.1 telemega-v0.1/flash-loader \ telemega-v0.3 telemega-v0.3/flash-loader \ megadongle-v0.1 megadongle-v0.1/flash-loader \ @@ -38,23 +36,26 @@ ARMDIRS=\ ARMM0DIRS=\ easymini-v1.0 easymini-v1.0/flash-loader -ifneq ($(shell which sdcc),) +AVRDIRS=\ + telescience-v0.1 telescience-pwm micropeak nanopeak-v0.1 + +ifeq ($(strip $(HAVE_SDCC)),yes) SUBDIRS += $(SDCCDIRS) endif -ifneq ($(shell which avr-gcc),) - SUBDIRS += $(AVRDIRS) +ifeq ($(strip ($HAVE_ARM_M3_CC)),yes) + SUBDIRS += $(ARMM3DIRS) endif -ifneq ($(shell which /opt/cortex/bin/arm-none-eabi-gcc),) - SUBDIRS += $(ARMDIRS) +ifneq ($(strip ($HAVE_ARM_M0_CC)),yes) + SUBDIRS += $(ARMM0DIRS) endif -ifneq ($(shell which /usr/bin/arm-none-eabi-gcc),) - SUBDIRS += $(ARMM0DIRS) +ifeq ($(strip $(HAVE_AVR_CC)),yes) + SUBDIRS += $(AVRDIRS) endif -ALLDIRS=$(SDCCDIRS) $(AVRDIRS) $(ARMDIRS) +ALLDIRS=$(SDCCDIRS) $(ARMM3DIRS) $(ARMM0DIRS) $(AVRDIRS) all: all-local all-recursive diff --git a/src/avr-demo/Makefile b/src/avr-demo/Makefile index 93295166..6d9bfea2 100644 --- a/src/avr-demo/Makefile +++ b/src/avr-demo/Makefile @@ -11,18 +11,12 @@ vpath load_csv.5c ../kalman vpath matrix.5c ../kalman vpath ao-make-product.5c ../util +include ../avr/Makefile.defs + MCU=atmega32u4 DUDECPUTYPE=m32u4 #PROGRAMMER=stk500v2 -P usb -PROGRAMMER=usbtiny -LOADCMD=avrdude LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: -CC=avr-gcc -OBJCOPY=avr-objcopy - -ifndef VERSION -include ../Version -endif INC = \ ao.h \ diff --git a/src/avr/Makefile.defs b/src/avr/Makefile.defs new file mode 100644 index 00000000..eeb9a881 --- /dev/null +++ b/src/avr/Makefile.defs @@ -0,0 +1,16 @@ +ifndef TOPDIR +TOPDIR=.. +endif + +ifndef VERSION +include $(TOPDIR)/Version +endif + +include $(TOPDIR)/Makedefs + +CC=$(AVR_CC) +OBJCOPY=$(AVR_OBJCOPY) +LDSCRIPTS=/usr/lib/avr/lib/ldscripts + +PROGRAMMER=usbtiny +LOADCMD=avrdude diff --git a/src/cc1111/Makefile.cc1111 b/src/cc1111/Makefile.cc1111 index 0e19603b..78b653b3 100644 --- a/src/cc1111/Makefile.cc1111 +++ b/src/cc1111/Makefile.cc1111 @@ -1,4 +1,5 @@ -CC=sdcc +include ../Makedefs +CC=$(SDCC) CFLAGS=--model-small --debug --opt-code-speed -DCODESIZE=$(CODESIZE) diff --git a/src/lpc/Makefile-flash.defs b/src/lpc/Makefile-flash.defs index 6bdd204c..ab7181b9 100644 --- a/src/lpc/Makefile-flash.defs +++ b/src/lpc/Makefile-flash.defs @@ -6,14 +6,16 @@ vpath ao-make-product.5c $(TOPDIR)/util .elf.ihx: objcopy -O ihex $*.elf $@ -CC=arm-none-eabi-gcc -SAT=/opt/cortex -SAT_CLIB=$(SAT)/lib/pdclib-cortex-m0.a -SAT_CFLAGS=-I$(SAT)/include ifndef VERSION include $(TOPDIR)/Version endif +include $(TOPDIR)/Makedefs + +CC=$(ARM_CC) +SAT=/opt/cortex +SAT_CLIB=$(SAT)/lib/pdclib-cortex-m0.a +SAT_CFLAGS=-I$(SAT)/include AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) diff --git a/src/lpc/Makefile.defs b/src/lpc/Makefile.defs index 2873d5e8..d541230a 100644 --- a/src/lpc/Makefile.defs +++ b/src/lpc/Makefile.defs @@ -7,19 +7,24 @@ vpath load_csv.5c ../kalman vpath matrix.5c ../kalman vpath ao-make-product.5c ../util -CC=arm-none-eabi-gcc -SAT=/opt/cortex -SAT_CLIB=$(SAT)/lib/pdclib-cortex-m0.a -SAT_CFLAGS=-I$(SAT)/include +ifndef TOPDIR +TOPDIR=.. +endif ifndef VERSION -include ../Version +include $(TOPDIR)/Version endif +include $(TOPDIR)/Makedefs + +CC=$(ARM_CC) +SAT=/opt/cortex +SAT_CLIB=$(SAT)/lib/pdclib-cortex-m0.a +SAT_CFLAGS=-I$(SAT)/include -AO_CFLAGS=-I. -I../lpc -I../core -I../drivers -I.. +AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR) LPC_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) -LDFLAGS=$(LPC_CFLAGS) -L../stm -Wl,-Taltos.ld +LDFLAGS=$(LPC_CFLAGS) -L$(TOPDIR)/stm -Wl,-Taltos.ld NICKLE=nickle @@ -34,8 +39,8 @@ quiet ?= $($1) .c.o: $(call quiet,CC) -c $(CFLAGS) $< -ao_serial_lpc.h: ../lpc/baud_rate ao_pins.h - nickle ../lpc/baud_rate `awk '/AO_LPC_CLKOUT/{print $$3}' ao_pins.h` > $@ +ao_serial_lpc.h: $(TOPDIR)/lpc/baud_rate ao_pins.h + nickle $(TOPDIR)/lpc/baud_rate `awk '/AO_LPC_CLKOUT/{print $$3}' ao_pins.h` > $@ ao_serial_lpc.o: ao_serial_lpc.h diff --git a/src/micropeak/Makefile b/src/micropeak/Makefile index e51b2847..35dfaab8 100644 --- a/src/micropeak/Makefile +++ b/src/micropeak/Makefile @@ -6,21 +6,15 @@ vpath % ../attiny:../drivers:../core:../product:.. vpath ao-make-product.5c ../util vpath make-altitude-pa ../util +include ../avr/Makefile.defs + MCU=attiny85 DUDECPUTYPE=t85 #PROGRAMMER=stk500v2 -P usb -PROGRAMMER=usbtiny -LOADCMD=avrdude LOADSLOW=-i 32 -B 32 LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: -CC=avr-gcc -OBJCOPY=avr-objcopy - -LDFLAGS=-L/usr/lib/ldscripts -Tavr25.x -ifndef VERSION -include ../Version -endif +LDFLAGS=-L$(LDSCRIPTS) -Tavr25.x ALTOS_SRC = \ ao_micropeak.c \ diff --git a/src/nanopeak-v0.1/Makefile b/src/nanopeak-v0.1/Makefile index cb468a06..154d78f6 100644 --- a/src/nanopeak-v0.1/Makefile +++ b/src/nanopeak-v0.1/Makefile @@ -6,21 +6,15 @@ vpath % ../attiny:../drivers:../core:../product:.. vpath ao-make-product.5c ../util vpath make-altitude-pa ../util +include ../avr/Makefile.defs + MCU=attiny85 DUDECPUTYPE=t85 #PROGRAMMER=stk500v2 -P usb -PROGRAMMER=usbtiny -LOADCMD=avrdude LOADSLOW=-i 32 -B 32 LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: -CC=avr-gcc -OBJCOPY=avr-objcopy - -LDFLAGS=-L/usr/lib/ldscripts -Tavr25.x -ifndef VERSION -include ../Version -endif +LDFLAGS=-L$(LDSCRIPTS) -Tavr25.x ALTOS_SRC = \ ao_micropeak.c \ diff --git a/src/stm/Makefile-flash.defs b/src/stm/Makefile-flash.defs index 86f76d46..f429d9bd 100644 --- a/src/stm/Makefile-flash.defs +++ b/src/stm/Makefile-flash.defs @@ -6,14 +6,15 @@ vpath ao-make-product.5c $(TOPDIR)/util .elf.ihx: objcopy -O ihex $*.elf $@ -CC=/opt/cortex/bin/arm-none-eabi-gcc -SAT=/opt/cortex -SAT_CLIB=$(SAT)/lib/pdclib-cortex-m3.a -SAT_CFLAGS=-I$(SAT)/include - ifndef VERSION include $(TOPDIR)/Version endif +include $(TOPDIR)/Makedefs + +CC=$(ARM_CC) +SAT=/opt/cortex +SAT_CLIB=$(SAT)/lib/pdclib-cortex-m3.a +SAT_CFLAGS=-I$(SAT)/include AO_CFLAGS=-I. -I$(TOPDIR)/stm -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index 8ef30521..ede75f80 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -12,14 +12,19 @@ vpath ao-make-product.5c ../util .elf.ihx: objcopy -O ihex $*.elf $@ -SAT=/opt/cortex -CC=$(SAT)/bin/arm-none-eabi-gcc -SAT_CLIB=$(SAT)/lib/pdclib-cortex-m3.a -SAT_CFLAGS=-I$(SAT)/include +ifndef TOPDIR +TOPDIR=.. +endif ifndef VERSION -include ../Version +include $(TOPDIR)/Version endif +include $(TOPDIR)/Makedefs + +CC=$(ARM_CC) +SAT=/opt/cortex +SAT_CLIB=$(SAT)/lib/pdclib-cortex-m3.a +SAT_CFLAGS=-I$(SAT)/include AO_CFLAGS=-I. -I../stm -I../core -I../drivers -I.. STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) diff --git a/src/telepyro-v0.1/Makefile b/src/telepyro-v0.1/Makefile index 6743ba66..025b324a 100644 --- a/src/telepyro-v0.1/Makefile +++ b/src/telepyro-v0.1/Makefile @@ -5,18 +5,12 @@ vpath % .:..:../core:../product:../drivers:../avr vpath ao-make-product.5c ../util +include ../avr/Makefile.defs + MCU=atmega32u4 DUDECPUTYPE=m32u4 #PROGRAMMER=stk500v2 -P usb -PROGRAMMER=usbtiny -LOADCMD=avrdude LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: -CC=avr-gcc -OBJCOPY=avr-objcopy - -ifndef VERSION -include ../Version -endif INC = \ ao.h \ diff --git a/src/telescience-pwm/Makefile b/src/telescience-pwm/Makefile index ce2a8fde..7f39d3f1 100644 --- a/src/telescience-pwm/Makefile +++ b/src/telescience-pwm/Makefile @@ -5,20 +5,14 @@ vpath % ..:../core:../product:../drivers:../avr vpath ao-make-product.5c ../util +include ../avr/Makefile.defs + MCU=atmega32u4 DUDECPUTYPE=m32u4 #PROGRAMMER=stk500v2 -P usb -PROGRAMMER=usbtiny -LOADCMD=avrdude LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: -CC=avr-gcc -OBJCOPY=avr-objcopy - -LDFLAGS=-L/usr/lib/ldscripts -Tavr5.x -ifndef VERSION -include ../Version -endif +LDFLAGS=-L$(LDSCRIPTS) -Tavr5.x INC = \ ao.h \ diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index 81054a75..a65b3ad0 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -5,20 +5,14 @@ vpath % ..:../core:../product:../drivers:../avr vpath ao-make-product.5c ../util +include ../avr/Makefile.defs + MCU=atmega32u4 DUDECPUTYPE=m32u4 #PROGRAMMER=stk500v2 -P usb -PROGRAMMER=usbtiny -LOADCMD=avrdude LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: -CC=avr-gcc -OBJCOPY=avr-objcopy - -LDFLAGS=-L/usr/lib/ldscripts -Tavr5.x -ifndef VERSION -include ../Version -endif +LDFLAGS=-L$(LDSCRIPTS) -Tavr5.x INC = \ ao.h \ -- cgit v1.2.3 From f7cccbb7a624a2a47b21682f416a135a28319b41 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 8 Oct 2013 09:39:29 -0700 Subject: altos: Broken test for M0 compiler in src/Makefile Was causing it to try to compiler M0 progs only when *no* compiler was found. Signed-off-by: Keith Packard --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index ae231c64..3e4ed68d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -47,7 +47,7 @@ ifeq ($(strip ($HAVE_ARM_M3_CC)),yes) SUBDIRS += $(ARMM3DIRS) endif -ifneq ($(strip ($HAVE_ARM_M0_CC)),yes) +ifeq ($(strip ($HAVE_ARM_M0_CC)),yes) SUBDIRS += $(ARMM0DIRS) endif -- cgit v1.2.3 From 0e5d1f3ce39495e3702ecd22cb45972e13a5c986 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 8 Oct 2013 09:50:21 -0700 Subject: altos: avr-gcc appears to find the loader scripts without help now At some point, avr-gcc lost its ability to find the loader scripts necessary to link programs. That appears to be fixed now, at least on my machine. Signed-off-by: Keith Packard --- src/micropeak/Makefile | 2 +- src/nanopeak-v0.1/Makefile | 2 +- src/telescience-pwm/Makefile | 2 +- src/telescience-v0.1/Makefile | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/micropeak/Makefile b/src/micropeak/Makefile index 35dfaab8..dcc32874 100644 --- a/src/micropeak/Makefile +++ b/src/micropeak/Makefile @@ -14,7 +14,7 @@ DUDECPUTYPE=t85 LOADSLOW=-i 32 -B 32 LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: -LDFLAGS=-L$(LDSCRIPTS) -Tavr25.x +#LDFLAGS=-L$(LDSCRIPTS) -Tavr25.x ALTOS_SRC = \ ao_micropeak.c \ diff --git a/src/nanopeak-v0.1/Makefile b/src/nanopeak-v0.1/Makefile index 154d78f6..04eea902 100644 --- a/src/nanopeak-v0.1/Makefile +++ b/src/nanopeak-v0.1/Makefile @@ -14,7 +14,7 @@ DUDECPUTYPE=t85 LOADSLOW=-i 32 -B 32 LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: -LDFLAGS=-L$(LDSCRIPTS) -Tavr25.x +#LDFLAGS=-L$(LDSCRIPTS) -Tavr25.x ALTOS_SRC = \ ao_micropeak.c \ diff --git a/src/telescience-pwm/Makefile b/src/telescience-pwm/Makefile index 7f39d3f1..de81b8d7 100644 --- a/src/telescience-pwm/Makefile +++ b/src/telescience-pwm/Makefile @@ -12,7 +12,7 @@ DUDECPUTYPE=m32u4 #PROGRAMMER=stk500v2 -P usb LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: -LDFLAGS=-L$(LDSCRIPTS) -Tavr5.x +#LDFLAGS=-L$(LDSCRIPTS) -Tavr5.x INC = \ ao.h \ diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index a65b3ad0..6e4eb6de 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -12,7 +12,7 @@ DUDECPUTYPE=m32u4 #PROGRAMMER=stk500v2 -P usb LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: -LDFLAGS=-L$(LDSCRIPTS) -Tavr5.x +#LDFLAGS=-L$(LDSCRIPTS) -Tavr5.x INC = \ ao.h \ -- cgit v1.2.3 From c584b5fc1128c7bfd7fb921ddc3a8ec498803b53 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 9 Oct 2013 12:37:30 -0700 Subject: altos: Messed up the ifeq syntax a bit so ARM bits weren't getting built $(x) is not the same as ($x) Signed-off-by: Keith Packard --- src/Makefile | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 3e4ed68d..a0a271c6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -39,20 +39,24 @@ ARMM0DIRS=\ AVRDIRS=\ telescience-v0.1 telescience-pwm micropeak nanopeak-v0.1 +SUBDIRS= + ifeq ($(strip $(HAVE_SDCC)),yes) - SUBDIRS += $(SDCCDIRS) +SUBDIRS+=$(SDCCDIRS) endif -ifeq ($(strip ($HAVE_ARM_M3_CC)),yes) - SUBDIRS += $(ARMM3DIRS) +ifeq ($(strip $(HAVE_ARM_M3_CC)),yes) +SUBDIRS+=$(ARMM3DIRS) +foo=bar endif -ifeq ($(strip ($HAVE_ARM_M0_CC)),yes) - SUBDIRS += $(ARMM0DIRS) +ifeq ($(strip $(HAVE_ARM_M0_CC)),yes) +SUBDIRS+=$(ARMM0DIRS) +baz=bletch endif ifeq ($(strip $(HAVE_AVR_CC)),yes) - SUBDIRS += $(AVRDIRS) +SUBDIRS += $(AVRDIRS) endif ALLDIRS=$(SDCCDIRS) $(ARMM3DIRS) $(ARMM0DIRS) $(AVRDIRS) -- cgit v1.2.3 From d8d3835fedf9b7c4d203f321e72c2b086ebb3b97 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 10 Oct 2013 00:00:05 -0700 Subject: altos: Use installed pdclib Switch over to the installed pdclib everywhere Signed-off-by: Keith Packard --- configure.ac | 17 +++++++++++++++-- src/easymini-v1.0/Makefile | 4 +--- src/lpc/Makefile-flash.defs | 43 +++++------------------------------------- src/lpc/Makefile-lpc.defs | 44 +++++++++++++++++++++++++++++++++++++++++++ src/lpc/Makefile.defs | 36 ++--------------------------------- src/lpcxpresso/Makefile | 2 +- src/megadongle-v0.1/Makefile | 2 +- src/stm-demo/Makefile | 2 +- src/stm-flash/Makefile | 2 +- src/stm/Makefile-flash.defs | 6 ++---- src/stm/Makefile.defs | 6 ++---- src/telegps-v0.1/Makefile | 2 +- src/telegps-v0.3/Makefile | 2 +- src/telelco-v0.1/Makefile | 2 +- src/telelco-v0.2/Makefile | 2 +- src/telemega-v0.1/Makefile | 2 +- src/telemega-v0.3/Makefile | 2 +- src/telemetrum-v2.0/Makefile | 2 +- src/telescience-v0.2/Makefile | 2 +- 19 files changed, 83 insertions(+), 97 deletions(-) create mode 100644 src/lpc/Makefile-lpc.defs (limited to 'src') diff --git a/configure.ac b/configure.ac index de344335..8024b7c6 100644 --- a/configure.ac +++ b/configure.ac @@ -242,22 +242,35 @@ AC_SUBST(ARM_CC) if test "x$HAVE_ARM_CC" = "xyes"; then save_CC="$CC" save_CFLAGS="$CFLAGS" + save_LIBS="$LIBS" CC="$ARM_CC" CFLAGS="-mthumb -mcpu=cortex-m0" + LIBS="-ffreestanding -nostdlib" AC_LANG_PUSH([C]) AC_MSG_CHECKING([if ]$ARM_CC[ supports cortex-m0]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int i;])], [HAVE_ARM_M0_CC=yes], [HAVE_ARM_M0_CC=no]) - AC_MSG_RESULT([$HAVE_ARM_M0]) + AC_MSG_RESULT([$HAVE_ARM_M0_CC]) + + AC_CHECK_LIB(pdclib-cortex-m0,memcpy, + [], + [HAVE_ARM_M0_CC=no]) + CFLAGS="-mthumb -mcpu=cortex-m3" AC_MSG_CHECKING([if ]$ARM_CC[ supports cortex-m3]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int i;])], [HAVE_ARM_M3_CC=yes], [HAVE_ARM_M3_CC=no]) - AC_MSG_RESULT([$HAVE_ARM_M3]) + AC_MSG_RESULT([$HAVE_ARM_M3_CC]) + + AC_CHECK_LIB(pdclib-cortex-m3,memcpy, + [], + [HAVE_ARM_M3_CC=no]) + AC_LANG_POP([C]) + LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" CC="$save_CC" else diff --git a/src/easymini-v1.0/Makefile b/src/easymini-v1.0/Makefile index ec305c94..6ab79425 100644 --- a/src/easymini-v1.0/Makefile +++ b/src/easymini-v1.0/Makefile @@ -60,10 +60,8 @@ OBJ=$(SRC:.c=.o) all: $(PROG) -LDFLAGS=-L../lpc -Wl,-Taltos.ld - $(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/lpc/Makefile-flash.defs b/src/lpc/Makefile-flash.defs index ab7181b9..bb90b0d7 100644 --- a/src/lpc/Makefile-flash.defs +++ b/src/lpc/Makefile-flash.defs @@ -1,39 +1,4 @@ -vpath % $(TOPDIR)/lpc:$(TOPDIR)/product:$(TOPDIR)/drivers:$(TOPDIR)/core:$(TOPDIR)/util:$(TOPDIR) -vpath ao-make-product.5c $(TOPDIR)/util - -.SUFFIXES: .elf .ihx - -.elf.ihx: - objcopy -O ihex $*.elf $@ - - -ifndef VERSION -include $(TOPDIR)/Version -endif -include $(TOPDIR)/Makedefs - -CC=$(ARM_CC) -SAT=/opt/cortex -SAT_CLIB=$(SAT)/lib/pdclib-cortex-m0.a -SAT_CFLAGS=-I$(SAT)/include - -AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) -STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) - -LDFLAGS=-L$(TOPDIR)/lpc -Wl,-Taltos-loader.ld - -NICKLE=nickle - -V=0 -# The user has explicitly enabled quiet compilation. -ifeq ($(V),0) -quiet = @printf " $1 $2 $@\n"; $($1) -endif -# Otherwise, print the full command line. -quiet ?= $($1) - -.c.o: - $(call quiet,CC) -c $(CFLAGS) -o $@ $< +include $(TOPDIR)/lpc/Makefile-lpc.defs INC = \ ao.h \ @@ -68,13 +33,15 @@ PRODUCT=AltosFlash-$(VERSION) PRODUCT_DEF=-DALTOS_FLASH IDPRODUCT=0x000a -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -g -Os +CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -g -Os + +LDFLAGS=$(CFLAGS) -L$(TOPDIR)/lpc -Wl,-Taltos-loader.ld PROGNAME=altos-flash PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf $(PROG): Makefile $(OBJ) altos-loader.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) ao_product.h: ao-make-product.5c $(TOPDIR)/Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/lpc/Makefile-lpc.defs b/src/lpc/Makefile-lpc.defs new file mode 100644 index 00000000..32a02a4c --- /dev/null +++ b/src/lpc/Makefile-lpc.defs @@ -0,0 +1,44 @@ +ifndef TOPDIR +TOPDIR=.. +endif + +include $(TOPDIR)/Makedefs + +vpath % $(TOPDIR)/lpc:$(TOPDIR)/product:$(TOPDIR)/drivers:$(TOPDIR)/core:$(TOPDIR)/util:$(TOPDIR)/kalman:$(TOPDIR/aes):$(TOPDIR) +vpath make-altitude $(TOPDIR)/util +vpath make-kalman $(TOPDIR)/util +vpath kalman.5c $(TOPDIR)/kalman +vpath kalman_filter.5c $(TOPDIR)/kalman +vpath load_csv.5c $(TOPDIR)/kalman +vpath matrix.5c $(TOPDIR)/kalman +vpath ao-make-product.5c $(TOPDIR)/util + +.SUFFIXES: .elf .ihx + +.elf.ihx: + objcopy -O ihex $*.elf $@ + + +ifndef VERSION +include $(TOPDIR)/Version +endif + +CC=$(ARM_CC) + +AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) +LPC_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) + +NICKLE=nickle + +LIBS=-lpdclib-cortex-m0 -lgcc + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +.c.o: + $(call quiet,CC) -c $(CFLAGS) -o $@ $< diff --git a/src/lpc/Makefile.defs b/src/lpc/Makefile.defs index d541230a..b6d739c2 100644 --- a/src/lpc/Makefile.defs +++ b/src/lpc/Makefile.defs @@ -1,43 +1,11 @@ -vpath % ../lpc:../product:../drivers:../core:../util:../kalman:../aes:.. -vpath make-altitude ../util -vpath make-kalman ../util -vpath kalman.5c ../kalman -vpath kalman_filter.5c ../kalman -vpath load_csv.5c ../kalman -vpath matrix.5c ../kalman -vpath ao-make-product.5c ../util - ifndef TOPDIR TOPDIR=.. endif -ifndef VERSION -include $(TOPDIR)/Version -endif +include $(TOPDIR)/lpc/Makefile-lpc.defs include $(TOPDIR)/Makedefs -CC=$(ARM_CC) -SAT=/opt/cortex -SAT_CLIB=$(SAT)/lib/pdclib-cortex-m0.a -SAT_CFLAGS=-I$(SAT)/include - -AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR) -LPC_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) - -LDFLAGS=$(LPC_CFLAGS) -L$(TOPDIR)/stm -Wl,-Taltos.ld - -NICKLE=nickle - -V=0 -# The user has explicitly enabled quiet compilation. -ifeq ($(V),0) -quiet = @printf " $1 $2 $@\n"; $($1) -endif -# Otherwise, print the full command line. -quiet ?= $($1) - -.c.o: - $(call quiet,CC) -c $(CFLAGS) $< +LDFLAGS=$(CFLAGS) -L$(TOPDIR)/lpc -Wl,-Taltos.ld ao_serial_lpc.h: $(TOPDIR)/lpc/baud_rate ao_pins.h nickle $(TOPDIR)/lpc/baud_rate `awk '/AO_LPC_CLKOUT/{print $$3}' ao_pins.h` > $@ diff --git a/src/lpcxpresso/Makefile b/src/lpcxpresso/Makefile index 3745f283..374c052f 100644 --- a/src/lpcxpresso/Makefile +++ b/src/lpcxpresso/Makefile @@ -45,7 +45,7 @@ all: $(PROG) LDFLAGS=-L../lpc -Wl,-Taltos.ld $(PROG): Makefile $(OBJ) - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/megadongle-v0.1/Makefile b/src/megadongle-v0.1/Makefile index 7f12963f..268f186f 100644 --- a/src/megadongle-v0.1/Makefile +++ b/src/megadongle-v0.1/Makefile @@ -69,7 +69,7 @@ OBJ=$(SRC:.c=.o) all: $(PROG) $(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) $(OBJ): $(INC) diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 48fa07eb..990968c2 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -56,7 +56,7 @@ all: $(ELF) $(IHX) LDFLAGS=-L../stm -Wl,-Taltos.ld $(ELF): Makefile $(OBJ) - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $@ $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $@ $(OBJ) $(LIBS) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/stm-flash/Makefile b/src/stm-flash/Makefile index 1ea35581..5c0699e1 100644 --- a/src/stm-flash/Makefile +++ b/src/stm-flash/Makefile @@ -41,7 +41,7 @@ all: $(PROG) LDFLAGS=-L../stm -Wl,-Taltos-loader.ld $(PROG): Makefile $(OBJ) - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/stm/Makefile-flash.defs b/src/stm/Makefile-flash.defs index f429d9bd..159f8b9c 100644 --- a/src/stm/Makefile-flash.defs +++ b/src/stm/Makefile-flash.defs @@ -12,9 +12,7 @@ endif include $(TOPDIR)/Makedefs CC=$(ARM_CC) -SAT=/opt/cortex -SAT_CLIB=$(SAT)/lib/pdclib-cortex-m3.a -SAT_CFLAGS=-I$(SAT)/include +LIBS=-lpdclib-cortex-m3 -lgcc AO_CFLAGS=-I. -I$(TOPDIR)/stm -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) @@ -73,7 +71,7 @@ PROGNAME=altos-flash PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf $(PROG): Makefile $(OBJ) altos-loader.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) ao_product.h: ao-make-product.5c $(TOPDIR)/Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index ede75f80..ee1cb658 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -22,12 +22,10 @@ endif include $(TOPDIR)/Makedefs CC=$(ARM_CC) -SAT=/opt/cortex -SAT_CLIB=$(SAT)/lib/pdclib-cortex-m3.a -SAT_CFLAGS=-I$(SAT)/include +LIBS=-lpdclib-cortex-m3 -lgcc AO_CFLAGS=-I. -I../stm -I../core -I../drivers -I.. -STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) +STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) LDFLAGS=-L../stm -Wl,-Taltos.ld diff --git a/src/telegps-v0.1/Makefile b/src/telegps-v0.1/Makefile index 64deddc6..170294e6 100644 --- a/src/telegps-v0.1/Makefile +++ b/src/telegps-v0.1/Makefile @@ -82,7 +82,7 @@ OBJ=$(SRC:.c=.o) all: $(PROG) $(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) $(OBJ): $(INC) diff --git a/src/telegps-v0.3/Makefile b/src/telegps-v0.3/Makefile index ca7d7c2b..d129d295 100644 --- a/src/telegps-v0.3/Makefile +++ b/src/telegps-v0.3/Makefile @@ -66,7 +66,7 @@ all: $(PROG) LDFLAGS=-L../lpc -Wl,-Taltos.ld $(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) $(OBJ): $(INC) diff --git a/src/telelco-v0.1/Makefile b/src/telelco-v0.1/Makefile index 24083308..0f61788c 100644 --- a/src/telelco-v0.1/Makefile +++ b/src/telelco-v0.1/Makefile @@ -76,7 +76,7 @@ OBJ=$(SRC:.c=.o) all: $(PROG) $(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) ../altitude.h: make-altitude nickle $< > $@ diff --git a/src/telelco-v0.2/Makefile b/src/telelco-v0.2/Makefile index f78ca9e2..bc5f8571 100644 --- a/src/telelco-v0.2/Makefile +++ b/src/telelco-v0.2/Makefile @@ -85,7 +85,7 @@ OBJ=$(SRC:.c=.o) all: $(PROG) $(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) ../altitude.h: make-altitude nickle $< > $@ diff --git a/src/telemega-v0.1/Makefile b/src/telemega-v0.1/Makefile index bf756e96..bbf46f3c 100644 --- a/src/telemega-v0.1/Makefile +++ b/src/telemega-v0.1/Makefile @@ -112,7 +112,7 @@ OBJ=$(SRC:.c=.o) all: $(PROG) $(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) ../altitude-pa.h: make-altitude-pa nickle $< > $@ diff --git a/src/telemega-v0.3/Makefile b/src/telemega-v0.3/Makefile index f2c0625f..6e5da721 100644 --- a/src/telemega-v0.3/Makefile +++ b/src/telemega-v0.3/Makefile @@ -112,7 +112,7 @@ OBJ=$(SRC:.c=.o) all: $(PROG) $(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) ../altitude-pa.h: make-altitude-pa nickle $< > $@ diff --git a/src/telemetrum-v2.0/Makefile b/src/telemetrum-v2.0/Makefile index c03a5539..be72d493 100644 --- a/src/telemetrum-v2.0/Makefile +++ b/src/telemetrum-v2.0/Makefile @@ -101,7 +101,7 @@ OBJ=$(SRC:.c=.o) all: $(PROG) $(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) ../altitude-pa.h: make-altitude-pa nickle $< > $@ diff --git a/src/telescience-v0.2/Makefile b/src/telescience-v0.2/Makefile index f16ef268..c53a6cc3 100644 --- a/src/telescience-v0.2/Makefile +++ b/src/telescience-v0.2/Makefile @@ -68,7 +68,7 @@ OBJ=$(SRC:.c=.o) all: $(PROG) $(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) $(OBJ): $(INC) -- cgit v1.2.3 From aa169b80039728e35b0dec3be66a8483d48a3458 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 10 Oct 2013 08:04:22 -0700 Subject: altos: Fix stm-bringup demo build to use installed pdclib Signed-off-by: Keith Packard --- autogen.sh | 3 +-- src/stm-bringup/Makefile | 10 ++++------ 2 files changed, 5 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/autogen.sh b/autogen.sh index c838c5b3..4e8b11ba 100755 --- a/autogen.sh +++ b/autogen.sh @@ -9,5 +9,4 @@ cd $srcdir autoreconf --force -v --install || exit 1 cd $ORIGDIR || exit $? -PKG_CONFIG_PATH=/opt/cortex/lib/pkgconfig \ - $srcdir/configure --enable-maintainer-mode "$@" +$srcdir/configure --enable-maintainer-mode "$@" diff --git a/src/stm-bringup/Makefile b/src/stm-bringup/Makefile index 1bc5aaad..33ecd710 100644 --- a/src/stm-bringup/Makefile +++ b/src/stm-bringup/Makefile @@ -8,11 +8,9 @@ endif CC=arm-none-eabi-gcc OBJCOPY=arm-none-eabi-objcopy -PDCLIB=/opt/cortex -C_LIB=$(PDCLIB)/lib/pdclib-cortex-m3.a -C_INC=-I$(PDCLIB)/include +C_LIB=-lpdclib-cortex-m3 -DEF_CFLAGS=-g -std=gnu99 -Os -mlittle-endian -mthumb -ffreestanding -nostdlib -I. -I../../src/stm $(C_INC) +DEF_CFLAGS=-g -std=gnu99 -Os -mlittle-endian -mthumb -ffreestanding -nostdlib -I. -I../stm # to run from SRAM LD_FLAGS_RAM=-L../stm -Wl,-Taltos-ram.ld @@ -28,10 +26,10 @@ all: bringup-ram.elf bringup.elf %.bin: %.elf $(OBJCOPY) -O binary $^ $@ -bringup.elf: $(OBJ) $(C_LIB) bringup.ld +bringup.elf: $(OBJ) bringup.ld $(CC) $(CFLAGS) $(LD_FLAGS) -o $@ $(OBJ) $(C_LIB) -lgcc -bringup-ram.elf: $(OBJ) $(C_LIB) altos-ram.ld +bringup-ram.elf: $(OBJ) altos-ram.ld $(CC) $(CFLAGS) $(LD_FLAGS_RAM) -o $@ $(OBJ) $(C_LIB) -lgcc clean: -- cgit v1.2.3 From 1bd9786802751391cca3b83ac3045029e00e39ee Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 13 Oct 2013 22:05:20 -0700 Subject: altos/micropeak: Increase boost detect to 30m This meant increasing the data buffering as well so that we could reliably capture the flight data back to the ground, even for slow flights. And, with the buffer extra large, we work backwards from the current buffer location to find the last ground location rather than working forwards from the first buffered location. This ensures that we don't capture noise before boost and instead capture a nice flight curve instead. Signed-off-by: Keith Packard --- src/core/ao_microflight.c | 12 ++++++------ src/product/ao_micropeak.h | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/core/ao_microflight.c b/src/core/ao_microflight.c index 714bb90a..f680e400 100644 --- a/src/core/ao_microflight.c +++ b/src/core/ao_microflight.c @@ -33,7 +33,7 @@ ao_microsample(void) ao_microkalman_correct(); } -#define NUM_PA_HIST 16 +#define NUM_PA_HIST (GROUND_AVG) #define SKIP_PA_HIST(i,j) (((i) + (j)) & (NUM_PA_HIST - 1)) @@ -60,11 +60,11 @@ ao_microflight(void) h = 0; for (;;) { time += SAMPLE_SLEEP; - if (sample_count == 0) + if ((sample_count & 0x1f) == 0) ao_led_on(AO_LED_REPORT); ao_delay_until(time); ao_microsample(); - if (sample_count == 0) + if ((sample_count & 0x1f) == 0) ao_led_off(AO_LED_REPORT); pa_hist[h] = pa; h = SKIP_PA_HIST(h,1); @@ -85,10 +85,10 @@ ao_microflight(void) } } - /* Go back and find the first sample a decent interval above the ground */ + /* Go back and find the last sample close to the ground */ pa_min = pa_ground - LAND_DETECT; - for (i = SKIP_PA_HIST(h,2); i != h; i = SKIP_PA_HIST(i,2)) { - if (pa_hist[i] < pa_min) + for (i = SKIP_PA_HIST(h,-2); i != SKIP_PA_HIST(h,2); i = SKIP_PA_HIST(i,-2)) { + if (pa_hist[i] >= pa_min) break; } diff --git a/src/product/ao_micropeak.h b/src/product/ao_micropeak.h index 3e3dec15..0cefca6f 100644 --- a/src/product/ao_micropeak.h +++ b/src/product/ao_micropeak.h @@ -20,12 +20,12 @@ #define SAMPLE_SLEEP AO_MS_TO_TICKS(96) -/* 16 sample, or about two seconds worth */ -#define GROUND_AVG_SHIFT 4 +/* 64 sample, or about six seconds worth */ +#define GROUND_AVG_SHIFT 6 #define GROUND_AVG (1 << GROUND_AVG_SHIFT) /* Pressure change (in Pa) to detect boost */ -#define BOOST_DETECT 120 /* 10m at sea level, 12m at 2000m */ +#define BOOST_DETECT 360 /* 30m at sea level, 36m at 2000m */ /* Wait after power on before doing anything to give the user time to assemble the rocket */ #define BOOST_DELAY AO_SEC_TO_TICKS(60) -- cgit v1.2.3 From 5c4b3658a96f1a64ccebf7bddda06b15b4ac4a6f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 14 Oct 2013 21:49:39 -0700 Subject: altos: Use #define values for ublox packet types One case was using hex values instead of the #define equivalents. Signed-off-by: Keith Packard --- src/drivers/ao_gps_ublox.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_gps_ublox.c b/src/drivers/ao_gps_ublox.c index 1bc2a68f..e9168348 100644 --- a/src/drivers/ao_gps_ublox.c +++ b/src/drivers/ao_gps_ublox.c @@ -702,9 +702,9 @@ ao_gps(void) __reentrant continue; switch (class) { - case 0x01: + case UBLOX_NAV: switch (id) { - case 0x21: + case UBLOX_NAV_TIMEUTC: ao_mutex_get(&ao_gps_mutex); ao_gps_tick = ao_time(); -- cgit v1.2.3 From 039446f54ef6968a3f0b37ce32ca6bdcdbe62546 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 14 Oct 2013 22:41:43 -0700 Subject: altos: Merge GPS logging into a single function Create a new global, ao_gps_new, which indicates new GPS position and satellite data. Use ao_gps_new as the new sleep/wakeup address. Merge the separate gps position/satellite logging tasks into a single function which waits for new data and writes out the changed values. Signed-off-by: Keith Packard --- src/core/ao.h | 4 ++ src/core/ao_flight.c | 4 +- src/core/ao_gps_report.c | 102 ++++++++++++++++------------------- src/core/ao_gps_report_mega.c | 88 +++++++++++++------------------ src/core/ao_gps_report_metrum.c | 108 +++++++++++++++++--------------------- src/drivers/ao_gps_sirf.c | 7 ++- src/drivers/ao_gps_skytraq.c | 7 ++- src/drivers/ao_gps_ublox.c | 5 +- src/product/ao_terraui.c | 2 +- src/teleballoon-v1.1/ao_balloon.c | 4 +- src/test/ao_gps_test.c | 13 +++-- src/test/ao_gps_test_skytraq.c | 2 +- src/test/ao_gps_test_ublox.c | 2 +- 13 files changed, 164 insertions(+), 184 deletions(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index e7320327..ea37885e 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -342,6 +342,10 @@ ao_spi_slave(void); #define AO_GPS_DATE_VALID (1 << 6) #define AO_GPS_COURSE_VALID (1 << 7) +#define AO_GPS_NEW_DATA 1 +#define AO_GPS_NEW_TRACKING 2 + +extern __xdata uint8_t ao_gps_new; extern __pdata uint16_t ao_gps_tick; extern __xdata uint8_t ao_gps_mutex; extern __xdata struct ao_telemetry_location ao_gps_data; diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index 88dc816d..2495a44b 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -194,8 +194,8 @@ ao_flight(void) #if HAS_GPS /* Record current GPS position by waking up GPS log tasks */ - ao_wakeup(&ao_gps_data); - ao_wakeup(&ao_gps_tracking_data); + ao_gps_new = AO_GPS_NEW_DATA | AO_GPS_NEW_TRACKING; + ao_wakeup(&ao_gps_new); #endif ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); diff --git a/src/core/ao_gps_report.c b/src/core/ao_gps_report.c index c52ef621..8d15c083 100644 --- a/src/core/ao_gps_report.c +++ b/src/core/ao_gps_report.c @@ -22,78 +22,68 @@ ao_gps_report(void) { static __xdata struct ao_log_record gps_log; static __xdata struct ao_telemetry_location gps_data; + static __xdata struct ao_telemetry_satellite gps_tracking_data; uint8_t date_reported = 0; + uint8_t new; for (;;) { - ao_sleep(&ao_gps_data); ao_mutex_get(&ao_gps_mutex); - ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); + while ((new = ao_gps_new) == 0) + ao_sleep(&ao_gps_new); + if (new & AO_GPS_NEW_DATA) + ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); + if (new & AO_GPS_NEW_TRACKING) + ao_xmemcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); + ao_gps_new = 0; ao_mutex_put(&ao_gps_mutex); - if (!(gps_data.flags & AO_GPS_VALID)) - continue; - - gps_log.tick = ao_gps_tick; - gps_log.type = AO_LOG_GPS_TIME; - gps_log.u.gps_time.hour = gps_data.hour; - gps_log.u.gps_time.minute = gps_data.minute; - gps_log.u.gps_time.second = gps_data.second; - gps_log.u.gps_time.flags = gps_data.flags; - ao_log_data(&gps_log); - gps_log.type = AO_LOG_GPS_LAT; - gps_log.u.gps_latitude = gps_data.latitude; - ao_log_data(&gps_log); - gps_log.type = AO_LOG_GPS_LON; - gps_log.u.gps_longitude = gps_data.longitude; - ao_log_data(&gps_log); - gps_log.type = AO_LOG_GPS_ALT; - gps_log.u.gps_altitude.altitude = gps_data.altitude; - gps_log.u.gps_altitude.unused = 0xffff; - ao_log_data(&gps_log); - if (!date_reported && (gps_data.flags & AO_GPS_DATE_VALID)) { - gps_log.type = AO_LOG_GPS_DATE; - gps_log.u.gps_date.year = gps_data.year; - gps_log.u.gps_date.month = gps_data.month; - gps_log.u.gps_date.day = gps_data.day; - gps_log.u.gps_date.extra = 0; - date_reported = ao_log_data(&gps_log); + if ((new & AO_GPS_NEW_DATA) && (gps_data.flags & AO_GPS_VALID)) { + gps_log.tick = ao_gps_tick; + gps_log.type = AO_LOG_GPS_TIME; + gps_log.u.gps_time.hour = gps_data.hour; + gps_log.u.gps_time.minute = gps_data.minute; + gps_log.u.gps_time.second = gps_data.second; + gps_log.u.gps_time.flags = gps_data.flags; + ao_log_data(&gps_log); + gps_log.type = AO_LOG_GPS_LAT; + gps_log.u.gps_latitude = gps_data.latitude; + ao_log_data(&gps_log); + gps_log.type = AO_LOG_GPS_LON; + gps_log.u.gps_longitude = gps_data.longitude; + ao_log_data(&gps_log); + gps_log.type = AO_LOG_GPS_ALT; + gps_log.u.gps_altitude.altitude = gps_data.altitude; + gps_log.u.gps_altitude.unused = 0xffff; + ao_log_data(&gps_log); + if (!date_reported && (gps_data.flags & AO_GPS_DATE_VALID)) { + gps_log.type = AO_LOG_GPS_DATE; + gps_log.u.gps_date.year = gps_data.year; + gps_log.u.gps_date.month = gps_data.month; + gps_log.u.gps_date.day = gps_data.day; + gps_log.u.gps_date.extra = 0; + date_reported = ao_log_data(&gps_log); + } } - } -} - -void -ao_gps_tracking_report(void) -{ - static __xdata struct ao_log_record gps_log; - static __xdata struct ao_telemetry_satellite gps_tracking_data; - uint8_t c, n; - - for (;;) { - ao_sleep(&ao_gps_tracking_data); - ao_mutex_get(&ao_gps_mutex); - gps_log.tick = ao_gps_tick; - ao_xmemcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); - ao_mutex_put(&ao_gps_mutex); + if (new & AO_GPS_NEW_TRACKING) { + uint8_t c, n; - if (!(n = gps_tracking_data.channels)) - continue; - - gps_log.type = AO_LOG_GPS_SAT; - for (c = 0; c < n; c++) - if ((gps_log.u.gps_sat.svid = gps_tracking_data.sats[c].svid)) - { - gps_log.u.gps_sat.c_n = gps_tracking_data.sats[c].c_n_1; - ao_log_data(&gps_log); + if ((n = gps_tracking_data.channels) != 0) { + gps_log.type = AO_LOG_GPS_SAT; + for (c = 0; c < n; c++) + if ((gps_log.u.gps_sat.svid = gps_tracking_data.sats[c].svid)) + { + gps_log.u.gps_sat.c_n = gps_tracking_data.sats[c].c_n_1; + ao_log_data(&gps_log); + } } + } } } __xdata struct ao_task ao_gps_report_task; -__xdata struct ao_task ao_gps_tracking_report_task; void ao_gps_report_init(void) { ao_add_task(&ao_gps_report_task, ao_gps_report, "gps_report"); - ao_add_task(&ao_gps_tracking_report_task, ao_gps_tracking_report, "gps_tracking_report"); } diff --git a/src/core/ao_gps_report_mega.c b/src/core/ao_gps_report_mega.c index e3af4307..e2adbfbc 100644 --- a/src/core/ao_gps_report_mega.c +++ b/src/core/ao_gps_report_mega.c @@ -23,66 +23,55 @@ ao_gps_report_mega(void) { static __xdata struct ao_log_mega gps_log; static __xdata struct ao_telemetry_location gps_data; - uint8_t date_reported = 0; - - for (;;) { - ao_sleep(&ao_gps_data); - ao_mutex_get(&ao_gps_mutex); - ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); - ao_mutex_put(&ao_gps_mutex); - - if (!(gps_data.flags & AO_GPS_VALID)) - continue; - - gps_log.tick = ao_gps_tick; - gps_log.type = AO_LOG_GPS_TIME; - gps_log.u.gps.latitude = gps_data.latitude; - gps_log.u.gps.longitude = gps_data.longitude; - gps_log.u.gps.altitude = gps_data.altitude; - - gps_log.u.gps.hour = gps_data.hour; - gps_log.u.gps.minute = gps_data.minute; - gps_log.u.gps.second = gps_data.second; - gps_log.u.gps.flags = gps_data.flags; - gps_log.u.gps.year = gps_data.year; - gps_log.u.gps.month = gps_data.month; - gps_log.u.gps.day = gps_data.day; - ao_log_mega(&gps_log); - } -} - -void -ao_gps_tracking_report_mega(void) -{ - static __xdata struct ao_log_mega gps_log; static __xdata struct ao_telemetry_satellite gps_tracking_data; + uint8_t date_reported = 0; + uint8_t new; uint8_t c, n, i; for (;;) { - ao_sleep(&ao_gps_tracking_data); ao_mutex_get(&ao_gps_mutex); - ao_xmemcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); + while (!(new = ao_gps_new)) + ao_sleep(&ao_gps_new); + if (new & AO_GPS_NEW_DATA) + ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); + if (new & AO_GPS_NEW_TRACKING) + ao_xmemcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); + ao_gps_new = 0; ao_mutex_put(&ao_gps_mutex); - if (!(n = gps_tracking_data.channels)) - continue; + if ((new & AO_GPS_NEW_DATA) && (gps_data.flags & AO_GPS_VALID)) { + gps_log.tick = ao_gps_tick; + gps_log.type = AO_LOG_GPS_TIME; + gps_log.u.gps.latitude = gps_data.latitude; + gps_log.u.gps.longitude = gps_data.longitude; + gps_log.u.gps.altitude = gps_data.altitude; - gps_log.type = AO_LOG_GPS_SAT; - gps_log.tick = ao_gps_tick; - i = 0; - for (c = 0; c < n; c++) - if ((gps_log.u.gps_sat.sats[i].svid = gps_tracking_data.sats[c].svid)) - { - gps_log.u.gps_sat.sats[i].c_n = gps_tracking_data.sats[c].c_n_1; - i++; - } - gps_log.u.gps_sat.channels = i; - ao_log_mega(&gps_log); + gps_log.u.gps.hour = gps_data.hour; + gps_log.u.gps.minute = gps_data.minute; + gps_log.u.gps.second = gps_data.second; + gps_log.u.gps.flags = gps_data.flags; + gps_log.u.gps.year = gps_data.year; + gps_log.u.gps.month = gps_data.month; + gps_log.u.gps.day = gps_data.day; + ao_log_mega(&gps_log); + } + if ((new & AO_GPS_NEW_TRACKING) && (n = gps_tracking_data.channels) != 0) { + gps_log.tick = ao_gps_tick; + gps_log.type = AO_LOG_GPS_SAT; + i = 0; + for (c = 0; c < n; c++) + if ((gps_log.u.gps_sat.sats[i].svid = gps_tracking_data.sats[c].svid)) + { + gps_log.u.gps_sat.sats[i].c_n = gps_tracking_data.sats[c].c_n_1; + i++; + } + gps_log.u.gps_sat.channels = i; + ao_log_mega(&gps_log); + } } } __xdata struct ao_task ao_gps_report_mega_task; -__xdata struct ao_task ao_gps_tracking_report_mega_task; void ao_gps_report_mega_init(void) @@ -90,7 +79,4 @@ ao_gps_report_mega_init(void) ao_add_task(&ao_gps_report_mega_task, ao_gps_report_mega, "gps_report"); - ao_add_task(&ao_gps_tracking_report_mega_task, - ao_gps_tracking_report_mega, - "gps_tracking_report"); } diff --git a/src/core/ao_gps_report_metrum.c b/src/core/ao_gps_report_metrum.c index 4fefe223..b82936dd 100644 --- a/src/core/ao_gps_report_metrum.c +++ b/src/core/ao_gps_report_metrum.c @@ -23,80 +23,69 @@ ao_gps_report_metrum(void) { static __xdata struct ao_log_metrum gps_log; static __xdata struct ao_telemetry_location gps_data; - uint8_t date_reported = 0; - - for (;;) { - ao_sleep(&ao_gps_data); - ao_mutex_get(&ao_gps_mutex); - ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); - ao_mutex_put(&ao_gps_mutex); - - if (!(gps_data.flags & AO_GPS_VALID)) - continue; - - gps_log.tick = ao_gps_tick; - gps_log.type = AO_LOG_GPS_POS; - gps_log.u.gps.latitude = gps_data.latitude; - gps_log.u.gps.longitude = gps_data.longitude; - gps_log.u.gps.altitude = gps_data.altitude; - ao_log_metrum(&gps_log); - - gps_log.type = AO_LOG_GPS_TIME; - gps_log.u.gps_time.hour = gps_data.hour; - gps_log.u.gps_time.minute = gps_data.minute; - gps_log.u.gps_time.second = gps_data.second; - gps_log.u.gps_time.flags = gps_data.flags; - gps_log.u.gps_time.year = gps_data.year; - gps_log.u.gps_time.month = gps_data.month; - gps_log.u.gps_time.day = gps_data.day; - ao_log_metrum(&gps_log); - } -} - -void -ao_gps_tracking_report_metrum(void) -{ - static __xdata struct ao_log_metrum gps_log; static __xdata struct ao_telemetry_satellite gps_tracking_data; uint8_t c, n, i, p, valid, packets; uint8_t svid; + uint8_t date_reported = 0; for (;;) { - ao_sleep(&ao_gps_tracking_data); ao_mutex_get(&ao_gps_mutex); - ao_xmemcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); + while (!(new = ao_gps_new)) + ao_sleep(&ao_gps_new); + if (new & AO_GPS_NEW_DATA) + ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); + if (new & AO_GPS_NEW_TRACKING) + ao_xmemcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); + ao_gps_new = 0; ao_mutex_put(&ao_gps_mutex); - if (!(n = gps_tracking_data.channels)) - continue; + if ((new & AO_GPS_NEW_DATA) && (gps_data.flags & AO_GPS_VALID)) { + gps_log.tick = ao_gps_tick; + gps_log.type = AO_LOG_GPS_POS; + gps_log.u.gps.latitude = gps_data.latitude; + gps_log.u.gps.longitude = gps_data.longitude; + gps_log.u.gps.altitude = gps_data.altitude; + ao_log_metrum(&gps_log); - gps_log.type = AO_LOG_GPS_SAT; - gps_log.tick = ao_gps_tick; - i = 0; - for (c = 0; c < n; c++) { - svid = gps_tracking_data.sats[c].svid; - if (svid != 0) { - if (i == 4) { - gps_log.u.gps_sat.channels = i; - gps_log.u.gps_sat.more = 1; - ao_log_metrum(&gps_log); - i = 0; + gps_log.type = AO_LOG_GPS_TIME; + gps_log.u.gps_time.hour = gps_data.hour; + gps_log.u.gps_time.minute = gps_data.minute; + gps_log.u.gps_time.second = gps_data.second; + gps_log.u.gps_time.flags = gps_data.flags; + gps_log.u.gps_time.year = gps_data.year; + gps_log.u.gps_time.month = gps_data.month; + gps_log.u.gps_time.day = gps_data.day; + ao_log_metrum(&gps_log); + } + + if ((new & AO_GPS_NEW_TRACKING) && (n = gps_tracking_data.channels)) { + gps_log.type = AO_LOG_GPS_SAT; + gps_log.tick = ao_gps_tick; + i = 0; + for (c = 0; c < n; c++) { + svid = gps_tracking_data.sats[c].svid; + if (svid != 0) { + if (i == 4) { + gps_log.u.gps_sat.channels = i; + gps_log.u.gps_sat.more = 1; + ao_log_metrum(&gps_log); + i = 0; + } + gps_log.u.gps_sat.sats[i].svid = svid; + gps_log.u.gps_sat.sats[i].c_n = gps_tracking_data.sats[c].c_n_1; + i++; } - gps_log.u.gps_sat.sats[i].svid = svid; - gps_log.u.gps_sat.sats[i].c_n = gps_tracking_data.sats[c].c_n_1; - i++; } - } - if (i) { - gps_log.u.gps_sat.channels = i; - gps_log.u.gps_sat.more = 0; - ao_log_metrum(&gps_log); + if (i) { + gps_log.u.gps_sat.channels = i; + gps_log.u.gps_sat.more = 0; + ao_log_metrum(&gps_log); + } } } } __xdata struct ao_task ao_gps_report_metrum_task; -__xdata struct ao_task ao_gps_tracking_report_metrum_task; void ao_gps_report_metrum_init(void) @@ -104,7 +93,4 @@ ao_gps_report_metrum_init(void) ao_add_task(&ao_gps_report_metrum_task, ao_gps_report_metrum, "gps_report"); - ao_add_task(&ao_gps_tracking_report_metrum_task, - ao_gps_tracking_report_metrum, - "gps_tracking_report"); } diff --git a/src/drivers/ao_gps_sirf.c b/src/drivers/ao_gps_sirf.c index 91fc948b..d89435b9 100644 --- a/src/drivers/ao_gps_sirf.c +++ b/src/drivers/ao_gps_sirf.c @@ -19,6 +19,7 @@ #include "ao.h" #endif +__xdata uint8_t ao_gps_new; __xdata uint8_t ao_gps_mutex; __pdata uint16_t ao_gps_tick; __xdata struct ao_telemetry_location ao_gps_data; @@ -422,8 +423,9 @@ ao_gps(void) __reentrant else ao_gps_data.v_error = ao_sirf_data.v_error / 100; #endif + ao_gps_new |= AO_GPS_NEW_DATA; ao_mutex_put(&ao_gps_mutex); - ao_wakeup(&ao_gps_data); + ao_wakeup(&ao_gps_new); break; case 4: ao_mutex_get(&ao_gps_mutex); @@ -432,8 +434,9 @@ ao_gps(void) __reentrant ao_gps_tracking_data.sats[i].svid = ao_sirf_tracker_data.sats[i].svid; ao_gps_tracking_data.sats[i].c_n_1 = ao_sirf_tracker_data.sats[i].c_n_1; } + ao_gps_new |= AO_GPS_NEW_TRACKING; ao_mutex_put(&ao_gps_mutex); - ao_wakeup(&ao_gps_tracking_data); + ao_wakeup(&ao_gps_new); break; } } diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index 9a9dff75..944a37f9 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -32,6 +32,7 @@ #define ao_gps_set_speed ao_serial1_set_speed #endif +__xdata uint8_t ao_gps_new; __xdata uint8_t ao_gps_mutex; static __data char ao_gps_char; static __data uint8_t ao_gps_cksum; @@ -293,10 +294,11 @@ ao_nmea_gga(void) if (!ao_gps_error) { ao_mutex_get(&ao_gps_mutex); + ao_gps_new |= AO_GPS_NEW_DATA; ao_gps_tick = ao_gps_next_tick; ao_xmemcpy(&ao_gps_data, PDATA_TO_XDATA(&ao_gps_next), sizeof (ao_gps_data)); ao_mutex_put(&ao_gps_mutex); - ao_wakeup(&ao_gps_data); + ao_wakeup(&ao_gps_new); } } @@ -352,9 +354,10 @@ ao_nmea_gsv(void) ao_gps_tracking_next.channels = 0; else if (done) { ao_mutex_get(&ao_gps_mutex); + ao_gps_new |= AO_GPS_NEW_TRACKING; ao_xmemcpy(&ao_gps_tracking_data, PDATA_TO_XDATA(&ao_gps_tracking_next), sizeof(ao_gps_tracking_data)); ao_mutex_put(&ao_gps_mutex); - ao_wakeup(&ao_gps_tracking_data); + ao_wakeup(&ao_gps_new); } } diff --git a/src/drivers/ao_gps_ublox.c b/src/drivers/ao_gps_ublox.c index e9168348..3582d6e0 100644 --- a/src/drivers/ao_gps_ublox.c +++ b/src/drivers/ao_gps_ublox.c @@ -25,6 +25,7 @@ #include +__xdata uint8_t ao_gps_new; __xdata uint8_t ao_gps_mutex; __pdata uint16_t ao_gps_tick; __xdata struct ao_telemetry_location ao_gps_data; @@ -760,8 +761,8 @@ ao_gps(void) __reentrant } ao_mutex_put(&ao_gps_mutex); - ao_wakeup(&ao_gps_data); - ao_wakeup(&ao_gps_tracking_data); + ao_gps_new = AO_GPS_NEW_DATA | AO_GPS_NEW_TRACKING; + ao_wakeup(&ao_gps_new); break; } break; diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c index 1866eb0c..8fd97033 100644 --- a/src/product/ao_terraui.c +++ b/src/product/ao_terraui.c @@ -629,7 +629,7 @@ ao_terragps(void) for (;;) { while (ao_gps_tick == gps_tick) - ao_sleep(&ao_gps_data); + ao_sleep(&ao_gps_new); gps_tick = ao_gps_tick; ao_gps_progress = (ao_gps_progress + 1) & 3; } diff --git a/src/teleballoon-v1.1/ao_balloon.c b/src/teleballoon-v1.1/ao_balloon.c index e8972655..12752d1f 100644 --- a/src/teleballoon-v1.1/ao_balloon.c +++ b/src/teleballoon-v1.1/ao_balloon.c @@ -105,8 +105,8 @@ ao_flight(void) #if HAS_GPS /* Record current GPS position by waking up GPS log tasks */ - ao_wakeup(&ao_gps_data); - ao_wakeup(&ao_gps_tracking_data); + ao_gps_new = AO_GPS_NEW_DATA | AO_GPS_NEW_TRACKING; + ao_wakeup(&ao_gps_new); #endif ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); diff --git a/src/test/ao_gps_test.c b/src/test/ao_gps_test.c index 3844a326..b6cc9ba7 100644 --- a/src/test/ao_gps_test.c +++ b/src/test/ao_gps_test.c @@ -427,11 +427,18 @@ void ao_dump_state(void *wchan) { int i; - if (wchan == &ao_gps_data) + + if (wchan != &ao_gps_new) + return; + + if (ao_gps_new & AO_GPS_NEW_DATA) { ao_gps_print(&ao_gps_data); - else + putchar('\n'); + } + if (ao_gps_new & AO_GPS_NEW_TRACKING) { ao_gps_tracking_print(&ao_gps_tracking_data); - putchar('\n'); + putchar('\n'); + } return; printf ("%02d:%02d:%02d", ao_gps_data.hour, ao_gps_data.minute, diff --git a/src/test/ao_gps_test_skytraq.c b/src/test/ao_gps_test_skytraq.c index 89cbd767..bf2ab5b8 100644 --- a/src/test/ao_gps_test_skytraq.c +++ b/src/test/ao_gps_test_skytraq.c @@ -443,7 +443,7 @@ uint8_t ao_task_minimize_latency; void ao_dump_state(void *wchan) { - if (wchan == &ao_gps_data) + if (wchan == &ao_gps_new) ao_gps_show(); } diff --git a/src/test/ao_gps_test_ublox.c b/src/test/ao_gps_test_ublox.c index a0e04cb6..31c7af60 100644 --- a/src/test/ao_gps_test_ublox.c +++ b/src/test/ao_gps_test_ublox.c @@ -347,7 +347,7 @@ check_ublox_message(char *which, uint8_t *msg) void ao_dump_state(void *wchan) { - if (wchan == &ao_gps_data) + if (wchan == &ao_gps_new) ao_gps_show(); return; } -- cgit v1.2.3 From b83876718b1a535ee04ca0351ad57814454ec646 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 25 Oct 2013 04:00:49 -0700 Subject: altos: Add floating point math functions from newlib These are all BSD licensed, so we can simply include them directly Signed-off-by: Keith Packard --- src/math/ef_acos.c | 84 ++++++++++ src/math/ef_rem_pio2.c | 193 ++++++++++++++++++++++ src/math/ef_sqrt.c | 89 ++++++++++ src/math/fdlibm.h | 413 ++++++++++++++++++++++++++++++++++++++++++++++ src/math/ieeefp.h | 256 ++++++++++++++++++++++++++++ src/math/kf_cos.c | 59 +++++++ src/math/kf_rem_pio2.c | 208 +++++++++++++++++++++++ src/math/kf_sin.c | 49 ++++++ src/math/machine/ieeefp.h | 382 ++++++++++++++++++++++++++++++++++++++++++ src/math/math.h | 35 ++++ src/math/sf_copysign.c | 50 ++++++ src/math/sf_cos.c | 68 ++++++++ src/math/sf_fabs.c | 47 ++++++ src/math/sf_floor.c | 80 +++++++++ src/math/sf_scalbn.c | 86 ++++++++++ 15 files changed, 2099 insertions(+) create mode 100644 src/math/ef_acos.c create mode 100644 src/math/ef_rem_pio2.c create mode 100644 src/math/ef_sqrt.c create mode 100644 src/math/fdlibm.h create mode 100644 src/math/ieeefp.h create mode 100644 src/math/kf_cos.c create mode 100644 src/math/kf_rem_pio2.c create mode 100644 src/math/kf_sin.c create mode 100644 src/math/machine/ieeefp.h create mode 100644 src/math/math.h create mode 100644 src/math/sf_copysign.c create mode 100644 src/math/sf_cos.c create mode 100644 src/math/sf_fabs.c create mode 100644 src/math/sf_floor.c create mode 100644 src/math/sf_scalbn.c (limited to 'src') diff --git a/src/math/ef_acos.c b/src/math/ef_acos.c new file mode 100644 index 00000000..f73f97de --- /dev/null +++ b/src/math/ef_acos.c @@ -0,0 +1,84 @@ +/* ef_acos.c -- float version of e_acos.c. + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include "fdlibm.h" + +#ifdef __STDC__ +static const float +#else +static float +#endif +one = 1.0000000000e+00, /* 0x3F800000 */ +pi = 3.1415925026e+00, /* 0x40490fda */ +pio2_hi = 1.5707962513e+00, /* 0x3fc90fda */ +pio2_lo = 7.5497894159e-08, /* 0x33a22168 */ +pS0 = 1.6666667163e-01, /* 0x3e2aaaab */ +pS1 = -3.2556581497e-01, /* 0xbea6b090 */ +pS2 = 2.0121252537e-01, /* 0x3e4e0aa8 */ +pS3 = -4.0055535734e-02, /* 0xbd241146 */ +pS4 = 7.9153501429e-04, /* 0x3a4f7f04 */ +pS5 = 3.4793309169e-05, /* 0x3811ef08 */ +qS1 = -2.4033949375e+00, /* 0xc019d139 */ +qS2 = 2.0209457874e+00, /* 0x4001572d */ +qS3 = -6.8828397989e-01, /* 0xbf303361 */ +qS4 = 7.7038154006e-02; /* 0x3d9dc62e */ + +#ifdef __STDC__ + float __ieee754_acosf(float x) +#else + float __ieee754_acosf(x) + float x; +#endif +{ + float z,p,q,r,w,s,c,df; + __int32_t hx,ix; + GET_FLOAT_WORD(hx,x); + ix = hx&0x7fffffff; + if(ix==0x3f800000) { /* |x|==1 */ + if(hx>0) return 0.0; /* acos(1) = 0 */ + else return pi+(float)2.0*pio2_lo; /* acos(-1)= pi */ + } else if(ix>0x3f800000) { /* |x| >= 1 */ + return (x-x)/(x-x); /* acos(|x|>1) is NaN */ + } + if(ix<0x3f000000) { /* |x| < 0.5 */ + if(ix<=0x23000000) return pio2_hi+pio2_lo;/*if|x|<2**-57*/ + z = x*x; + p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); + q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4))); + r = p/q; + return pio2_hi - (x - (pio2_lo-x*r)); + } else if (hx<0) { /* x < -0.5 */ + z = (one+x)*(float)0.5; + p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); + q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4))); + s = __ieee754_sqrtf(z); + r = p/q; + w = r*s-pio2_lo; + return pi - (float)2.0*(s+w); + } else { /* x > 0.5 */ + __int32_t idf; + z = (one-x)*(float)0.5; + s = __ieee754_sqrtf(z); + df = s; + GET_FLOAT_WORD(idf,df); + SET_FLOAT_WORD(df,idf&0xfffff000); + c = (z-df*df)/(s+df); + p = z*(pS0+z*(pS1+z*(pS2+z*(pS3+z*(pS4+z*pS5))))); + q = one+z*(qS1+z*(qS2+z*(qS3+z*qS4))); + r = p/q; + w = r*s+c; + return (float)2.0*(df+w); + } +} diff --git a/src/math/ef_rem_pio2.c b/src/math/ef_rem_pio2.c new file mode 100644 index 00000000..f1191d09 --- /dev/null +++ b/src/math/ef_rem_pio2.c @@ -0,0 +1,193 @@ +/* ef_rem_pio2.c -- float version of e_rem_pio2.c + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + * + */ + +/* __ieee754_rem_pio2f(x,y) + * + * return the remainder of x rem pi/2 in y[0]+y[1] + * use __kernel_rem_pio2f() + */ + +#include "fdlibm.h" + +/* + * Table of constants for 2/pi, 396 Hex digits (476 decimal) of 2/pi + */ +#ifdef __STDC__ +static const __int32_t two_over_pi[] = { +#else +static __int32_t two_over_pi[] = { +#endif +0xA2, 0xF9, 0x83, 0x6E, 0x4E, 0x44, 0x15, 0x29, 0xFC, +0x27, 0x57, 0xD1, 0xF5, 0x34, 0xDD, 0xC0, 0xDB, 0x62, +0x95, 0x99, 0x3C, 0x43, 0x90, 0x41, 0xFE, 0x51, 0x63, +0xAB, 0xDE, 0xBB, 0xC5, 0x61, 0xB7, 0x24, 0x6E, 0x3A, +0x42, 0x4D, 0xD2, 0xE0, 0x06, 0x49, 0x2E, 0xEA, 0x09, +0xD1, 0x92, 0x1C, 0xFE, 0x1D, 0xEB, 0x1C, 0xB1, 0x29, +0xA7, 0x3E, 0xE8, 0x82, 0x35, 0xF5, 0x2E, 0xBB, 0x44, +0x84, 0xE9, 0x9C, 0x70, 0x26, 0xB4, 0x5F, 0x7E, 0x41, +0x39, 0x91, 0xD6, 0x39, 0x83, 0x53, 0x39, 0xF4, 0x9C, +0x84, 0x5F, 0x8B, 0xBD, 0xF9, 0x28, 0x3B, 0x1F, 0xF8, +0x97, 0xFF, 0xDE, 0x05, 0x98, 0x0F, 0xEF, 0x2F, 0x11, +0x8B, 0x5A, 0x0A, 0x6D, 0x1F, 0x6D, 0x36, 0x7E, 0xCF, +0x27, 0xCB, 0x09, 0xB7, 0x4F, 0x46, 0x3F, 0x66, 0x9E, +0x5F, 0xEA, 0x2D, 0x75, 0x27, 0xBA, 0xC7, 0xEB, 0xE5, +0xF1, 0x7B, 0x3D, 0x07, 0x39, 0xF7, 0x8A, 0x52, 0x92, +0xEA, 0x6B, 0xFB, 0x5F, 0xB1, 0x1F, 0x8D, 0x5D, 0x08, +0x56, 0x03, 0x30, 0x46, 0xFC, 0x7B, 0x6B, 0xAB, 0xF0, +0xCF, 0xBC, 0x20, 0x9A, 0xF4, 0x36, 0x1D, 0xA9, 0xE3, +0x91, 0x61, 0x5E, 0xE6, 0x1B, 0x08, 0x65, 0x99, 0x85, +0x5F, 0x14, 0xA0, 0x68, 0x40, 0x8D, 0xFF, 0xD8, 0x80, +0x4D, 0x73, 0x27, 0x31, 0x06, 0x06, 0x15, 0x56, 0xCA, +0x73, 0xA8, 0xC9, 0x60, 0xE2, 0x7B, 0xC0, 0x8C, 0x6B, +}; + +/* This array is like the one in e_rem_pio2.c, but the numbers are + single precision and the last 8 bits are forced to 0. */ +#ifdef __STDC__ +static const __int32_t npio2_hw[] = { +#else +static __int32_t npio2_hw[] = { +#endif +0x3fc90f00, 0x40490f00, 0x4096cb00, 0x40c90f00, 0x40fb5300, 0x4116cb00, +0x412fed00, 0x41490f00, 0x41623100, 0x417b5300, 0x418a3a00, 0x4196cb00, +0x41a35c00, 0x41afed00, 0x41bc7e00, 0x41c90f00, 0x41d5a000, 0x41e23100, +0x41eec200, 0x41fb5300, 0x4203f200, 0x420a3a00, 0x42108300, 0x4216cb00, +0x421d1400, 0x42235c00, 0x4229a500, 0x422fed00, 0x42363600, 0x423c7e00, +0x4242c700, 0x42490f00 +}; + +/* + * invpio2: 24 bits of 2/pi + * pio2_1: first 17 bit of pi/2 + * pio2_1t: pi/2 - pio2_1 + * pio2_2: second 17 bit of pi/2 + * pio2_2t: pi/2 - (pio2_1+pio2_2) + * pio2_3: third 17 bit of pi/2 + * pio2_3t: pi/2 - (pio2_1+pio2_2+pio2_3) + */ + +#ifdef __STDC__ +static const float +#else +static float +#endif +zero = 0.0000000000e+00, /* 0x00000000 */ +half = 5.0000000000e-01, /* 0x3f000000 */ +two8 = 2.5600000000e+02, /* 0x43800000 */ +invpio2 = 6.3661980629e-01, /* 0x3f22f984 */ +pio2_1 = 1.5707855225e+00, /* 0x3fc90f80 */ +pio2_1t = 1.0804334124e-05, /* 0x37354443 */ +pio2_2 = 1.0804273188e-05, /* 0x37354400 */ +pio2_2t = 6.0770999344e-11, /* 0x2e85a308 */ +pio2_3 = 6.0770943833e-11, /* 0x2e85a300 */ +pio2_3t = 6.1232342629e-17; /* 0x248d3132 */ + +#ifdef __STDC__ + __int32_t __ieee754_rem_pio2f(float x, float *y) +#else + __int32_t __ieee754_rem_pio2f(x,y) + float x,y[]; +#endif +{ + float z,w,t,r,fn; + float tx[3]; + __int32_t i,j,n,ix,hx; + int e0,nx; + + GET_FLOAT_WORD(hx,x); + ix = hx&0x7fffffff; + if(ix<=0x3f490fd8) /* |x| ~<= pi/4 , no need for reduction */ + {y[0] = x; y[1] = 0; return 0;} + if(ix<0x4016cbe4) { /* |x| < 3pi/4, special case with n=+-1 */ + if(hx>0) { + z = x - pio2_1; + if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */ + y[0] = z - pio2_1t; + y[1] = (z-y[0])-pio2_1t; + } else { /* near pi/2, use 24+24+24 bit pi */ + z -= pio2_2; + y[0] = z - pio2_2t; + y[1] = (z-y[0])-pio2_2t; + } + return 1; + } else { /* negative x */ + z = x + pio2_1; + if((ix&0xfffffff0)!=0x3fc90fd0) { /* 24+24 bit pi OK */ + y[0] = z + pio2_1t; + y[1] = (z-y[0])+pio2_1t; + } else { /* near pi/2, use 24+24+24 bit pi */ + z += pio2_2; + y[0] = z + pio2_2t; + y[1] = (z-y[0])+pio2_2t; + } + return -1; + } + } + if(ix<=0x43490f80) { /* |x| ~<= 2^7*(pi/2), medium size */ + t = fabsf(x); + n = (__int32_t) (t*invpio2+half); + fn = (float)n; + r = t-fn*pio2_1; + w = fn*pio2_1t; /* 1st round good to 40 bit */ + if(n<32&&(ix&0xffffff00)!=npio2_hw[n-1]) { + y[0] = r-w; /* quick check no cancellation */ + } else { + __uint32_t high; + j = ix>>23; + y[0] = r-w; + GET_FLOAT_WORD(high,y[0]); + i = j-((high>>23)&0xff); + if(i>8) { /* 2nd iteration needed, good to 57 */ + t = r; + w = fn*pio2_2; + r = t-w; + w = fn*pio2_2t-((t-r)-w); + y[0] = r-w; + GET_FLOAT_WORD(high,y[0]); + i = j-((high>>23)&0xff); + if(i>25) { /* 3rd iteration need, 74 bits acc */ + t = r; /* will cover all possible cases */ + w = fn*pio2_3; + r = t-w; + w = fn*pio2_3t-((t-r)-w); + y[0] = r-w; + } + } + } + y[1] = (r-y[0])-w; + if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} + else return n; + } + /* + * all other (large) arguments + */ + if(!FLT_UWORD_IS_FINITE(ix)) { + y[0]=y[1]=x-x; return 0; + } + /* set z = scalbn(|x|,ilogb(x)-7) */ + e0 = (int)((ix>>23)-134); /* e0 = ilogb(z)-7; */ + SET_FLOAT_WORD(z, ix - ((__int32_t)e0<<23)); + for(i=0;i<2;i++) { + tx[i] = (float)((__int32_t)(z)); + z = (z-tx[i])*two8; + } + tx[2] = z; + nx = 3; + while(tx[nx-1]==zero) nx--; /* skip zero term */ + n = __kernel_rem_pio2f(tx,y,e0,nx,2,two_over_pi); + if(hx<0) {y[0] = -y[0]; y[1] = -y[1]; return -n;} + return n; +} diff --git a/src/math/ef_sqrt.c b/src/math/ef_sqrt.c new file mode 100644 index 00000000..80e7f360 --- /dev/null +++ b/src/math/ef_sqrt.c @@ -0,0 +1,89 @@ +/* ef_sqrtf.c -- float version of e_sqrt.c. + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include "fdlibm.h" + +#ifdef __STDC__ +static const float one = 1.0, tiny=1.0e-30; +#else +static float one = 1.0, tiny=1.0e-30; +#endif + +#ifdef __STDC__ + float __ieee754_sqrtf(float x) +#else + float __ieee754_sqrtf(x) + float x; +#endif +{ + float z; + __uint32_t r,hx; + __int32_t ix,s,q,m,t,i; + + GET_FLOAT_WORD(ix,x); + hx = ix&0x7fffffff; + + /* take care of Inf and NaN */ + if(!FLT_UWORD_IS_FINITE(hx)) + return x*x+x; /* sqrt(NaN)=NaN, sqrt(+inf)=+inf + sqrt(-inf)=sNaN */ + /* take care of zero and -ves */ + if(FLT_UWORD_IS_ZERO(hx)) return x;/* sqrt(+-0) = +-0 */ + if(ix<0) return (x-x)/(x-x); /* sqrt(-ve) = sNaN */ + + /* normalize x */ + m = (ix>>23); + if(FLT_UWORD_IS_SUBNORMAL(hx)) { /* subnormal x */ + for(i=0;(ix&0x00800000L)==0;i++) ix<<=1; + m -= i-1; + } + m -= 127; /* unbias exponent */ + ix = (ix&0x007fffffL)|0x00800000L; + if(m&1) /* odd m, double x to make it even */ + ix += ix; + m >>= 1; /* m = [m/2] */ + + /* generate sqrt(x) bit by bit */ + ix += ix; + q = s = 0; /* q = sqrt(x) */ + r = 0x01000000L; /* r = moving bit from right to left */ + + while(r!=0) { + t = s+r; + if(t<=ix) { + s = t+r; + ix -= t; + q += r; + } + ix += ix; + r>>=1; + } + + /* use floating add to find out rounding direction */ + if(ix!=0) { + z = one-tiny; /* trigger inexact flag */ + if (z>=one) { + z = one+tiny; + if (z>one) + q += 2; + else + q += (q&1); + } + } + ix = (q>>1)+0x3f000000L; + ix += (m <<23); + SET_FLOAT_WORD(z,ix); + return z; +} diff --git a/src/math/fdlibm.h b/src/math/fdlibm.h new file mode 100644 index 00000000..821619ad --- /dev/null +++ b/src/math/fdlibm.h @@ -0,0 +1,413 @@ + +/* @(#)fdlibm.h 5.1 93/09/24 */ +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* AltOS local */ +#include +#include +#define __int32_t int32_t +#define __uint32_t uint32_t + +#define __ieee754_acosf acosf +#define __ieee754_sqrtf sqrtf + +/* REDHAT LOCAL: Include files. */ +#include +/* #include */ +#include + +/* REDHAT LOCAL: Default to XOPEN_MODE. */ +#define _XOPEN_MODE + +/* Most routines need to check whether a float is finite, infinite, or not a + number, and many need to know whether the result of an operation will + overflow. These conditions depend on whether the largest exponent is + used for NaNs & infinities, or whether it's used for finite numbers. The + macros below wrap up that kind of information: + + FLT_UWORD_IS_FINITE(X) + True if a positive float with bitmask X is finite. + + FLT_UWORD_IS_NAN(X) + True if a positive float with bitmask X is not a number. + + FLT_UWORD_IS_INFINITE(X) + True if a positive float with bitmask X is +infinity. + + FLT_UWORD_MAX + The bitmask of FLT_MAX. + + FLT_UWORD_HALF_MAX + The bitmask of FLT_MAX/2. + + FLT_UWORD_EXP_MAX + The bitmask of the largest finite exponent (129 if the largest + exponent is used for finite numbers, 128 otherwise). + + FLT_UWORD_LOG_MAX + The bitmask of log(FLT_MAX), rounded down. This value is the largest + input that can be passed to exp() without producing overflow. + + FLT_UWORD_LOG_2MAX + The bitmask of log(2*FLT_MAX), rounded down. This value is the + largest input than can be passed to cosh() without producing + overflow. + + FLT_LARGEST_EXP + The largest biased exponent that can be used for finite numbers + (255 if the largest exponent is used for finite numbers, 254 + otherwise) */ + +#ifdef _FLT_LARGEST_EXPONENT_IS_NORMAL +#define FLT_UWORD_IS_FINITE(x) 1 +#define FLT_UWORD_IS_NAN(x) 0 +#define FLT_UWORD_IS_INFINITE(x) 0 +#define FLT_UWORD_MAX 0x7fffffff +#define FLT_UWORD_EXP_MAX 0x43010000 +#define FLT_UWORD_LOG_MAX 0x42b2d4fc +#define FLT_UWORD_LOG_2MAX 0x42b437e0 +#define HUGE ((float)0X1.FFFFFEP128) +#else +#define FLT_UWORD_IS_FINITE(x) ((x)<0x7f800000L) +#define FLT_UWORD_IS_NAN(x) ((x)>0x7f800000L) +#define FLT_UWORD_IS_INFINITE(x) ((x)==0x7f800000L) +#define FLT_UWORD_MAX 0x7f7fffffL +#define FLT_UWORD_EXP_MAX 0x43000000 +#define FLT_UWORD_LOG_MAX 0x42b17217 +#define FLT_UWORD_LOG_2MAX 0x42b2d4fc +#define HUGE ((float)3.40282346638528860e+38) +#endif +#define FLT_UWORD_HALF_MAX (FLT_UWORD_MAX-(1L<<23)) +#define FLT_LARGEST_EXP (FLT_UWORD_MAX>>23) + +/* Many routines check for zero and subnormal numbers. Such things depend + on whether the target supports denormals or not: + + FLT_UWORD_IS_ZERO(X) + True if a positive float with bitmask X is +0. Without denormals, + any float with a zero exponent is a +0 representation. With + denormals, the only +0 representation is a 0 bitmask. + + FLT_UWORD_IS_SUBNORMAL(X) + True if a non-zero positive float with bitmask X is subnormal. + (Routines should check for zeros first.) + + FLT_UWORD_MIN + The bitmask of the smallest float above +0. Call this number + REAL_FLT_MIN... + + FLT_UWORD_EXP_MIN + The bitmask of the float representation of REAL_FLT_MIN's exponent. + + FLT_UWORD_LOG_MIN + The bitmask of |log(REAL_FLT_MIN)|, rounding down. + + FLT_SMALLEST_EXP + REAL_FLT_MIN's exponent - EXP_BIAS (1 if denormals are not supported, + -22 if they are). +*/ + +#ifdef _FLT_NO_DENORMALS +#define FLT_UWORD_IS_ZERO(x) ((x)<0x00800000L) +#define FLT_UWORD_IS_SUBNORMAL(x) 0 +#define FLT_UWORD_MIN 0x00800000 +#define FLT_UWORD_EXP_MIN 0x42fc0000 +#define FLT_UWORD_LOG_MIN 0x42aeac50 +#define FLT_SMALLEST_EXP 1 +#else +#define FLT_UWORD_IS_ZERO(x) ((x)==0) +#define FLT_UWORD_IS_SUBNORMAL(x) ((x)<0x00800000L) +#define FLT_UWORD_MIN 0x00000001 +#define FLT_UWORD_EXP_MIN 0x43160000 +#define FLT_UWORD_LOG_MIN 0x42cff1b5 +#define FLT_SMALLEST_EXP -22 +#endif + +#ifdef __STDC__ +#undef __P +#define __P(p) p +#else +#define __P(p) () +#endif + +/* + * set X_TLOSS = pi*2**52, which is possibly defined in + * (one may replace the following line by "#include ") + */ + +#define X_TLOSS 1.41484755040568800000e+16 + +/* Functions that are not documented, and are not in . */ + +#ifdef _SCALB_INT +extern double scalb __P((double, int)); +#else +extern double scalb __P((double, double)); +#endif +extern double significand __P((double)); + +/* ieee style elementary functions */ +extern double __ieee754_sqrt __P((double)); +extern double __ieee754_acos __P((double)); +extern double __ieee754_acosh __P((double)); +extern double __ieee754_log __P((double)); +extern double __ieee754_atanh __P((double)); +extern double __ieee754_asin __P((double)); +extern double __ieee754_atan2 __P((double,double)); +extern double __ieee754_exp __P((double)); +extern double __ieee754_cosh __P((double)); +extern double __ieee754_fmod __P((double,double)); +extern double __ieee754_pow __P((double,double)); +extern double __ieee754_lgamma_r __P((double,int *)); +extern double __ieee754_gamma_r __P((double,int *)); +extern double __ieee754_log10 __P((double)); +extern double __ieee754_sinh __P((double)); +extern double __ieee754_hypot __P((double,double)); +extern double __ieee754_j0 __P((double)); +extern double __ieee754_j1 __P((double)); +extern double __ieee754_y0 __P((double)); +extern double __ieee754_y1 __P((double)); +extern double __ieee754_jn __P((int,double)); +extern double __ieee754_yn __P((int,double)); +extern double __ieee754_remainder __P((double,double)); +extern __int32_t __ieee754_rem_pio2 __P((double,double*)); +#ifdef _SCALB_INT +extern double __ieee754_scalb __P((double,int)); +#else +extern double __ieee754_scalb __P((double,double)); +#endif + +/* fdlibm kernel function */ +extern double __kernel_standard __P((double,double,int)); +extern double __kernel_sin __P((double,double,int)); +extern double __kernel_cos __P((double,double)); +extern double __kernel_tan __P((double,double,int)); +extern int __kernel_rem_pio2 __P((double*,double*,int,int,int,const __int32_t*)); + +/* Undocumented float functions. */ +#ifdef _SCALB_INT +extern float scalbf __P((float, int)); +#else +extern float scalbf __P((float, float)); +#endif +extern float significandf __P((float)); + +/* ieee style elementary float functions */ +extern float __ieee754_sqrtf __P((float)); +extern float __ieee754_acosf __P((float)); +extern float __ieee754_acoshf __P((float)); +extern float __ieee754_logf __P((float)); +extern float __ieee754_atanhf __P((float)); +extern float __ieee754_asinf __P((float)); +extern float __ieee754_atan2f __P((float,float)); +extern float __ieee754_expf __P((float)); +extern float __ieee754_coshf __P((float)); +extern float __ieee754_fmodf __P((float,float)); +extern float __ieee754_powf __P((float,float)); +extern float __ieee754_lgammaf_r __P((float,int *)); +extern float __ieee754_gammaf_r __P((float,int *)); +extern float __ieee754_log10f __P((float)); +extern float __ieee754_sinhf __P((float)); +extern float __ieee754_hypotf __P((float,float)); +extern float __ieee754_j0f __P((float)); +extern float __ieee754_j1f __P((float)); +extern float __ieee754_y0f __P((float)); +extern float __ieee754_y1f __P((float)); +extern float __ieee754_jnf __P((int,float)); +extern float __ieee754_ynf __P((int,float)); +extern float __ieee754_remainderf __P((float,float)); +extern __int32_t __ieee754_rem_pio2f __P((float,float*)); +#ifdef _SCALB_INT +extern float __ieee754_scalbf __P((float,int)); +#else +extern float __ieee754_scalbf __P((float,float)); +#endif + +/* float versions of fdlibm kernel functions */ +extern float __kernel_sinf __P((float,float,int)); +extern float __kernel_cosf __P((float,float)); +extern float __kernel_tanf __P((float,float,int)); +extern int __kernel_rem_pio2f __P((float*,float*,int,int,int,const __int32_t*)); + +/* The original code used statements like + n0 = ((*(int*)&one)>>29)^1; * index of high word * + ix0 = *(n0+(int*)&x); * high word of x * + ix1 = *((1-n0)+(int*)&x); * low word of x * + to dig two 32 bit words out of the 64 bit IEEE floating point + value. That is non-ANSI, and, moreover, the gcc instruction + scheduler gets it wrong. We instead use the following macros. + Unlike the original code, we determine the endianness at compile + time, not at run time; I don't see much benefit to selecting + endianness at run time. */ + +#ifndef __IEEE_BIG_ENDIAN +#ifndef __IEEE_LITTLE_ENDIAN + #error Must define endianness +#endif +#endif + +/* A union which permits us to convert between a double and two 32 bit + ints. */ + +#ifdef __IEEE_BIG_ENDIAN + +typedef union +{ + double value; + struct + { + __uint32_t msw; + __uint32_t lsw; + } parts; +} ieee_double_shape_type; + +#endif + +#ifdef __IEEE_LITTLE_ENDIAN + +typedef union +{ + double value; + struct + { + __uint32_t lsw; + __uint32_t msw; + } parts; +} ieee_double_shape_type; + +#endif + +/* Get two 32 bit ints from a double. */ + +#define EXTRACT_WORDS(ix0,ix1,d) \ +do { \ + ieee_double_shape_type ew_u; \ + ew_u.value = (d); \ + (ix0) = ew_u.parts.msw; \ + (ix1) = ew_u.parts.lsw; \ +} while (0) + +/* Get the more significant 32 bit int from a double. */ + +#define GET_HIGH_WORD(i,d) \ +do { \ + ieee_double_shape_type gh_u; \ + gh_u.value = (d); \ + (i) = gh_u.parts.msw; \ +} while (0) + +/* Get the less significant 32 bit int from a double. */ + +#define GET_LOW_WORD(i,d) \ +do { \ + ieee_double_shape_type gl_u; \ + gl_u.value = (d); \ + (i) = gl_u.parts.lsw; \ +} while (0) + +/* Set a double from two 32 bit ints. */ + +#define INSERT_WORDS(d,ix0,ix1) \ +do { \ + ieee_double_shape_type iw_u; \ + iw_u.parts.msw = (ix0); \ + iw_u.parts.lsw = (ix1); \ + (d) = iw_u.value; \ +} while (0) + +/* Set the more significant 32 bits of a double from an int. */ + +#define SET_HIGH_WORD(d,v) \ +do { \ + ieee_double_shape_type sh_u; \ + sh_u.value = (d); \ + sh_u.parts.msw = (v); \ + (d) = sh_u.value; \ +} while (0) + +/* Set the less significant 32 bits of a double from an int. */ + +#define SET_LOW_WORD(d,v) \ +do { \ + ieee_double_shape_type sl_u; \ + sl_u.value = (d); \ + sl_u.parts.lsw = (v); \ + (d) = sl_u.value; \ +} while (0) + +/* A union which permits us to convert between a float and a 32 bit + int. */ + +typedef union +{ + float value; + __uint32_t word; +} ieee_float_shape_type; + +/* Get a 32 bit int from a float. */ + +#define GET_FLOAT_WORD(i,d) \ +do { \ + ieee_float_shape_type gf_u; \ + gf_u.value = (d); \ + (i) = gf_u.word; \ +} while (0) + +/* Set a float from a 32 bit int. */ + +#define SET_FLOAT_WORD(d,i) \ +do { \ + ieee_float_shape_type sf_u; \ + sf_u.word = (i); \ + (d) = sf_u.value; \ +} while (0) + +/* Macros to avoid undefined behaviour that can arise if the amount + of a shift is exactly equal to the size of the shifted operand. */ + +#define SAFE_LEFT_SHIFT(op,amt) \ + (((amt) < 8 * sizeof(op)) ? ((op) << (amt)) : 0) + +#define SAFE_RIGHT_SHIFT(op,amt) \ + (((amt) < 8 * sizeof(op)) ? ((op) >> (amt)) : 0) + +#ifdef _COMPLEX_H + +/* + * Quoting from ISO/IEC 9899:TC2: + * + * 6.2.5.13 Types + * Each complex type has the same representation and alignment requirements as + * an array type containing exactly two elements of the corresponding real type; + * the first element is equal to the real part, and the second element to the + * imaginary part, of the complex number. + */ +typedef union { + float complex z; + float parts[2]; +} float_complex; + +typedef union { + double complex z; + double parts[2]; +} double_complex; + +typedef union { + long double complex z; + long double parts[2]; +} long_double_complex; + +#define REAL_PART(z) ((z).parts[0]) +#define IMAG_PART(z) ((z).parts[1]) + +#endif /* _COMPLEX_H */ + diff --git a/src/math/ieeefp.h b/src/math/ieeefp.h new file mode 100644 index 00000000..0b06fb78 --- /dev/null +++ b/src/math/ieeefp.h @@ -0,0 +1,256 @@ +#ifndef _IEEE_FP_H_ +#define _IEEE_FP_H_ + +#include "_ansi.h" + +#include + +_BEGIN_STD_C + +/* FIXME FIXME FIXME: + Neither of __ieee_{float,double}_shape_tape seem to be used anywhere + except in libm/test. If that is the case, please delete these from here. + If that is not the case, please insert documentation here describing why + they're needed. */ + +#ifdef __IEEE_BIG_ENDIAN + +typedef union +{ + double value; + struct + { + unsigned int sign : 1; + unsigned int exponent: 11; + unsigned int fraction0:4; + unsigned int fraction1:16; + unsigned int fraction2:16; + unsigned int fraction3:16; + + } number; + struct + { + unsigned int sign : 1; + unsigned int exponent: 11; + unsigned int quiet:1; + unsigned int function0:3; + unsigned int function1:16; + unsigned int function2:16; + unsigned int function3:16; + } nan; + struct + { + unsigned long msw; + unsigned long lsw; + } parts; + long aslong[2]; +} __ieee_double_shape_type; + +#endif + +#ifdef __IEEE_LITTLE_ENDIAN + +typedef union +{ + double value; + struct + { +#ifdef __SMALL_BITFIELDS + unsigned int fraction3:16; + unsigned int fraction2:16; + unsigned int fraction1:16; + unsigned int fraction0: 4; +#else + unsigned int fraction1:32; + unsigned int fraction0:20; +#endif + unsigned int exponent :11; + unsigned int sign : 1; + } number; + struct + { +#ifdef __SMALL_BITFIELDS + unsigned int function3:16; + unsigned int function2:16; + unsigned int function1:16; + unsigned int function0:3; +#else + unsigned int function1:32; + unsigned int function0:19; +#endif + unsigned int quiet:1; + unsigned int exponent: 11; + unsigned int sign : 1; + } nan; + struct + { + unsigned long lsw; + unsigned long msw; + } parts; + + long aslong[2]; + +} __ieee_double_shape_type; + +#endif + +#ifdef __IEEE_BIG_ENDIAN + +typedef union +{ + float value; + struct + { + unsigned int sign : 1; + unsigned int exponent: 8; + unsigned int fraction0: 7; + unsigned int fraction1: 16; + } number; + struct + { + unsigned int sign:1; + unsigned int exponent:8; + unsigned int quiet:1; + unsigned int function0:6; + unsigned int function1:16; + } nan; + long p1; + +} __ieee_float_shape_type; + +#endif + +#ifdef __IEEE_LITTLE_ENDIAN + +typedef union +{ + float value; + struct + { + unsigned int fraction0: 7; + unsigned int fraction1: 16; + unsigned int exponent: 8; + unsigned int sign : 1; + } number; + struct + { + unsigned int function1:16; + unsigned int function0:6; + unsigned int quiet:1; + unsigned int exponent:8; + unsigned int sign:1; + } nan; + long p1; + +} __ieee_float_shape_type; + +#endif + + + + + +/* FLOATING ROUNDING */ + +typedef int fp_rnd; +#define FP_RN 0 /* Round to nearest */ +#define FP_RM 1 /* Round down */ +#define FP_RP 2 /* Round up */ +#define FP_RZ 3 /* Round to zero (trunate) */ + +fp_rnd _EXFUN(fpgetround,(void)); +fp_rnd _EXFUN(fpsetround, (fp_rnd)); + +/* EXCEPTIONS */ + +typedef int fp_except; +#define FP_X_INV 0x10 /* Invalid operation */ +#define FP_X_DX 0x80 /* Divide by zero */ +#define FP_X_OFL 0x04 /* Overflow exception */ +#define FP_X_UFL 0x02 /* Underflow exception */ +#define FP_X_IMP 0x01 /* imprecise exception */ + +fp_except _EXFUN(fpgetmask,(void)); +fp_except _EXFUN(fpsetmask,(fp_except)); +fp_except _EXFUN(fpgetsticky,(void)); +fp_except _EXFUN(fpsetsticky, (fp_except)); + +/* INTEGER ROUNDING */ + +typedef int fp_rdi; +#define FP_RDI_TOZ 0 /* Round to Zero */ +#define FP_RDI_RD 1 /* Follow float mode */ + +fp_rdi _EXFUN(fpgetroundtoi,(void)); +fp_rdi _EXFUN(fpsetroundtoi,(fp_rdi)); + +#undef isnan +#undef isinf + +int _EXFUN(isnan, (double)); +int _EXFUN(isinf, (double)); +int _EXFUN(finite, (double)); + + + +int _EXFUN(isnanf, (float)); +int _EXFUN(isinff, (float)); +int _EXFUN(finitef, (float)); + +#define __IEEE_DBL_EXPBIAS 1023 +#define __IEEE_FLT_EXPBIAS 127 + +#define __IEEE_DBL_EXPLEN 11 +#define __IEEE_FLT_EXPLEN 8 + + +#define __IEEE_DBL_FRACLEN (64 - (__IEEE_DBL_EXPLEN + 1)) +#define __IEEE_FLT_FRACLEN (32 - (__IEEE_FLT_EXPLEN + 1)) + +#define __IEEE_DBL_MAXPOWTWO ((double)(1L << 32 - 2) * (1L << (32-11) - 32 + 1)) +#define __IEEE_FLT_MAXPOWTWO ((float)(1L << (32-8) - 1)) + +#define __IEEE_DBL_NAN_EXP 0x7ff +#define __IEEE_FLT_NAN_EXP 0xff + +#ifndef __ieeefp_isnanf +#define __ieeefp_isnanf(x) (((*(long *)&(x) & 0x7f800000L)==0x7f800000L) && \ + ((*(long *)&(x) & 0x007fffffL)!=0000000000L)) +#endif +#define isnanf(x) __ieeefp_isnanf(x) + +#ifndef __ieeefp_isinff +#define __ieeefp_isinff(x) (((*(long *)&(x) & 0x7f800000L)==0x7f800000L) && \ + ((*(long *)&(x) & 0x007fffffL)==0000000000L)) +#endif +#define isinff(x) __ieeefp_isinff(x) + +#ifndef __ieeefp_finitef +#define __ieeefp_finitef(x) (((*(long *)&(x) & 0x7f800000L)!=0x7f800000L)) +#endif +#define finitef(x) __ieeefp_finitef(x) + +#ifdef _DOUBLE_IS_32BITS +#undef __IEEE_DBL_EXPBIAS +#define __IEEE_DBL_EXPBIAS __IEEE_FLT_EXPBIAS + +#undef __IEEE_DBL_EXPLEN +#define __IEEE_DBL_EXPLEN __IEEE_FLT_EXPLEN + +#undef __IEEE_DBL_FRACLEN +#define __IEEE_DBL_FRACLEN __IEEE_FLT_FRACLEN + +#undef __IEEE_DBL_MAXPOWTWO +#define __IEEE_DBL_MAXPOWTWO __IEEE_FLT_MAXPOWTWO + +#undef __IEEE_DBL_NAN_EXP +#define __IEEE_DBL_NAN_EXP __IEEE_FLT_NAN_EXP + +#undef __ieee_double_shape_type +#define __ieee_double_shape_type __ieee_float_shape_type + +#endif /* _DOUBLE_IS_32BITS */ + +_END_STD_C + +#endif /* _IEEE_FP_H_ */ diff --git a/src/math/kf_cos.c b/src/math/kf_cos.c new file mode 100644 index 00000000..4f71af23 --- /dev/null +++ b/src/math/kf_cos.c @@ -0,0 +1,59 @@ +/* kf_cos.c -- float version of k_cos.c + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include "fdlibm.h" + +#ifdef __STDC__ +static const float +#else +static float +#endif +one = 1.0000000000e+00, /* 0x3f800000 */ +C1 = 4.1666667908e-02, /* 0x3d2aaaab */ +C2 = -1.3888889225e-03, /* 0xbab60b61 */ +C3 = 2.4801587642e-05, /* 0x37d00d01 */ +C4 = -2.7557314297e-07, /* 0xb493f27c */ +C5 = 2.0875723372e-09, /* 0x310f74f6 */ +C6 = -1.1359647598e-11; /* 0xad47d74e */ + +#ifdef __STDC__ + float __kernel_cosf(float x, float y) +#else + float __kernel_cosf(x, y) + float x,y; +#endif +{ + float a,hz,z,r,qx; + __int32_t ix; + GET_FLOAT_WORD(ix,x); + ix &= 0x7fffffff; /* ix = |x|'s high word*/ + if(ix<0x32000000) { /* if x < 2**27 */ + if(((int)x)==0) return one; /* generate inexact */ + } + z = x*x; + r = z*(C1+z*(C2+z*(C3+z*(C4+z*(C5+z*C6))))); + if(ix < 0x3e99999a) /* if |x| < 0.3 */ + return one - ((float)0.5*z - (z*r - x*y)); + else { + if(ix > 0x3f480000) { /* x > 0.78125 */ + qx = (float)0.28125; + } else { + SET_FLOAT_WORD(qx,ix-0x01000000); /* x/4 */ + } + hz = (float)0.5*z-qx; + a = one-qx; + return a - (hz - (z*r-x*y)); + } +} diff --git a/src/math/kf_rem_pio2.c b/src/math/kf_rem_pio2.c new file mode 100644 index 00000000..261c4812 --- /dev/null +++ b/src/math/kf_rem_pio2.c @@ -0,0 +1,208 @@ +/* kf_rem_pio2.c -- float version of k_rem_pio2.c + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include "fdlibm.h" + +/* In the float version, the input parameter x contains 8 bit + integers, not 24 bit integers. 113 bit precision is not supported. */ + +#ifdef __STDC__ +static const int init_jk[] = {4,7,9}; /* initial value for jk */ +#else +static int init_jk[] = {4,7,9}; +#endif + +#ifdef __STDC__ +static const float PIo2[] = { +#else +static float PIo2[] = { +#endif + 1.5703125000e+00, /* 0x3fc90000 */ + 4.5776367188e-04, /* 0x39f00000 */ + 2.5987625122e-05, /* 0x37da0000 */ + 7.5437128544e-08, /* 0x33a20000 */ + 6.0026650317e-11, /* 0x2e840000 */ + 7.3896444519e-13, /* 0x2b500000 */ + 5.3845816694e-15, /* 0x27c20000 */ + 5.6378512969e-18, /* 0x22d00000 */ + 8.3009228831e-20, /* 0x1fc40000 */ + 3.2756352257e-22, /* 0x1bc60000 */ + 6.3331015649e-25, /* 0x17440000 */ +}; + +#ifdef __STDC__ +static const float +#else +static float +#endif +zero = 0.0, +one = 1.0, +two8 = 2.5600000000e+02, /* 0x43800000 */ +twon8 = 3.9062500000e-03; /* 0x3b800000 */ + +#ifdef __STDC__ + int __kernel_rem_pio2f(float *x, float *y, int e0, int nx, int prec, const __int32_t *ipio2) +#else + int __kernel_rem_pio2f(x,y,e0,nx,prec,ipio2) + float x[], y[]; int e0,nx,prec; __int32_t ipio2[]; +#endif +{ + __int32_t jz,jx,jv,jp,jk,carry,n,iq[20],i,j,k,m,q0,ih; + float z,fw,f[20],fq[20],q[20]; + + /* initialize jk*/ + jk = init_jk[prec]; + jp = jk; + + /* determine jx,jv,q0, note that 3>q0 */ + jx = nx-1; + jv = (e0-3)/8; if(jv<0) jv=0; + q0 = e0-8*(jv+1); + + /* set up f[0] to f[jx+jk] where f[jx+jk] = ipio2[jv+jk] */ + j = jv-jx; m = jx+jk; + for(i=0;i<=m;i++,j++) f[i] = (j<0)? zero : (float) ipio2[j]; + + /* compute q[0],q[1],...q[jk] */ + for (i=0;i<=jk;i++) { + for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; q[i] = fw; + } + + jz = jk; +recompute: + /* distill q[] into iq[] reversingly */ + for(i=0,j=jz,z=q[jz];j>0;i++,j--) { + fw = (float)((__int32_t)(twon8* z)); + iq[i] = (__int32_t)(z-two8*fw); + z = q[j-1]+fw; + } + + /* compute n */ + z = scalbnf(z,(int)q0); /* actual value of z */ + z -= (float)8.0*floorf(z*(float)0.125); /* trim off integer >= 8 */ + n = (__int32_t) z; + z -= (float)n; + ih = 0; + if(q0>0) { /* need iq[jz-1] to determine n */ + i = (iq[jz-1]>>(8-q0)); n += i; + iq[jz-1] -= i<<(8-q0); + ih = iq[jz-1]>>(7-q0); + } + else if(q0==0) ih = iq[jz-1]>>8; + else if(z>=(float)0.5) ih=2; + + if(ih>0) { /* q > 0.5 */ + n += 1; carry = 0; + for(i=0;i0) { /* rare case: chance is 1 in 12 */ + switch(q0) { + case 1: + iq[jz-1] &= 0x7f; break; + case 2: + iq[jz-1] &= 0x3f; break; + } + } + if(ih==2) { + z = one - z; + if(carry!=0) z -= scalbnf(one,(int)q0); + } + } + + /* check if recomputation is needed */ + if(z==zero) { + j = 0; + for (i=jz-1;i>=jk;i--) j |= iq[i]; + if(j==0) { /* need recomputation */ + for(k=1;iq[jk-k]==0;k++); /* k = no. of terms needed */ + + for(i=jz+1;i<=jz+k;i++) { /* add q[jz+1] to q[jz+k] */ + f[jx+i] = (float) ipio2[jv+i]; + for(j=0,fw=0.0;j<=jx;j++) fw += x[j]*f[jx+i-j]; + q[i] = fw; + } + jz += k; + goto recompute; + } + } + + /* chop off zero terms */ + if(z==(float)0.0) { + jz -= 1; q0 -= 8; + while(iq[jz]==0) { jz--; q0-=8;} + } else { /* break z into 8-bit if necessary */ + z = scalbnf(z,-(int)q0); + if(z>=two8) { + fw = (float)((__int32_t)(twon8*z)); + iq[jz] = (__int32_t)(z-two8*fw); + jz += 1; q0 += 8; + iq[jz] = (__int32_t) fw; + } else iq[jz] = (__int32_t) z ; + } + + /* convert integer "bit" chunk to floating-point value */ + fw = scalbnf(one,(int)q0); + for(i=jz;i>=0;i--) { + q[i] = fw*(float)iq[i]; fw*=twon8; + } + + /* compute PIo2[0,...,jp]*q[jz,...,0] */ + for(i=jz;i>=0;i--) { + for(fw=0.0,k=0;k<=jp&&k<=jz-i;k++) fw += PIo2[k]*q[i+k]; + fq[jz-i] = fw; + } + + /* compress fq[] into y[] */ + switch(prec) { + case 0: + fw = 0.0; + for (i=jz;i>=0;i--) fw += fq[i]; + y[0] = (ih==0)? fw: -fw; + break; + case 1: + case 2: + fw = 0.0; + for (i=jz;i>=0;i--) fw += fq[i]; + y[0] = (ih==0)? fw: -fw; + fw = fq[0]-fw; + for (i=1;i<=jz;i++) fw += fq[i]; + y[1] = (ih==0)? fw: -fw; + break; + case 3: /* painful */ + for (i=jz;i>0;i--) { + fw = fq[i-1]+fq[i]; + fq[i] += fq[i-1]-fw; + fq[i-1] = fw; + } + for (i=jz;i>1;i--) { + fw = fq[i-1]+fq[i]; + fq[i] += fq[i-1]-fw; + fq[i-1] = fw; + } + for (fw=0.0,i=jz;i>=2;i--) fw += fq[i]; + if(ih==0) { + y[0] = fq[0]; y[1] = fq[1]; y[2] = fw; + } else { + y[0] = -fq[0]; y[1] = -fq[1]; y[2] = -fw; + } + } + return n&7; +} diff --git a/src/math/kf_sin.c b/src/math/kf_sin.c new file mode 100644 index 00000000..e81fa0bd --- /dev/null +++ b/src/math/kf_sin.c @@ -0,0 +1,49 @@ +/* kf_sin.c -- float version of k_sin.c + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include "fdlibm.h" + +#ifdef __STDC__ +static const float +#else +static float +#endif +half = 5.0000000000e-01,/* 0x3f000000 */ +S1 = -1.6666667163e-01, /* 0xbe2aaaab */ +S2 = 8.3333337680e-03, /* 0x3c088889 */ +S3 = -1.9841270114e-04, /* 0xb9500d01 */ +S4 = 2.7557314297e-06, /* 0x3638ef1b */ +S5 = -2.5050759689e-08, /* 0xb2d72f34 */ +S6 = 1.5896910177e-10; /* 0x2f2ec9d3 */ + +#ifdef __STDC__ + float __kernel_sinf(float x, float y, int iy) +#else + float __kernel_sinf(x, y, iy) + float x,y; int iy; /* iy=0 if y is zero */ +#endif +{ + float z,r,v; + __int32_t ix; + GET_FLOAT_WORD(ix,x); + ix &= 0x7fffffff; /* high word of x */ + if(ix<0x32000000) /* |x| < 2**-27 */ + {if((int)x==0) return x;} /* generate inexact */ + z = x*x; + v = z*x; + r = S2+z*(S3+z*(S4+z*(S5+z*S6))); + if(iy==0) return x+v*(S1+z*r); + else return x-((z*(half*y-v*r)-y)-v*S1); +} diff --git a/src/math/machine/ieeefp.h b/src/math/machine/ieeefp.h new file mode 100644 index 00000000..fffa3804 --- /dev/null +++ b/src/math/machine/ieeefp.h @@ -0,0 +1,382 @@ +#ifndef __IEEE_BIG_ENDIAN +#ifndef __IEEE_LITTLE_ENDIAN + +/* This file can define macros to choose variations of the IEEE float + format: + + _FLT_LARGEST_EXPONENT_IS_NORMAL + + Defined if the float format uses the largest exponent for finite + numbers rather than NaN and infinity representations. Such a + format cannot represent NaNs or infinities at all, but it's FLT_MAX + is twice the IEEE value. + + _FLT_NO_DENORMALS + + Defined if the float format does not support IEEE denormals. Every + float with a zero exponent is taken to be a zero representation. + + ??? At the moment, there are no equivalent macros above for doubles and + the macros are not fully supported by --enable-newlib-hw-fp. + + __IEEE_BIG_ENDIAN + + Defined if the float format is big endian. This is mutually exclusive + with __IEEE_LITTLE_ENDIAN. + + __IEEE_LITTLE_ENDIAN + + Defined if the float format is little endian. This is mutually exclusive + with __IEEE_BIG_ENDIAN. + + Note that one of __IEEE_BIG_ENDIAN or __IEEE_LITTLE_ENDIAN must be specified for a + platform or error will occur. + + __IEEE_BYTES_LITTLE_ENDIAN + + This flag is used in conjunction with __IEEE_BIG_ENDIAN to describe a situation + whereby multiple words of an IEEE floating point are in big endian order, but the + words themselves are little endian with respect to the bytes. + + _DOUBLE_IS_32BITS + + This is used on platforms that support double by using the 32-bit IEEE + float type. + + _FLOAT_ARG + + This represents what type a float arg is passed as. It is used when the type is + not promoted to double. + +*/ + +#if (defined(__arm__) || defined(__thumb__)) && !defined(__MAVERICK__) +/* ARM traditionally used big-endian words; and within those words the + byte ordering was big or little endian depending upon the target. + Modern floating-point formats are naturally ordered; in this case + __VFP_FP__ will be defined, even if soft-float. */ +#ifdef __VFP_FP__ +# ifdef __ARMEL__ +# define __IEEE_LITTLE_ENDIAN +# else +# define __IEEE_BIG_ENDIAN +# endif +#else +# define __IEEE_BIG_ENDIAN +# ifdef __ARMEL__ +# define __IEEE_BYTES_LITTLE_ENDIAN +# endif +#endif +#endif + +#ifdef __hppa__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __SPU__ +#define __IEEE_BIG_ENDIAN + +#define isfinite(__y) \ + (__extension__ ({int __cy; \ + (sizeof (__y) == sizeof (float)) ? (1) : \ + (__cy = fpclassify(__y)) != FP_INFINITE && __cy != FP_NAN;})) + +#define isinf(__x) ((sizeof (__x) == sizeof (float)) ? (0) : __isinfd(__x)) +#define isnan(__x) ((sizeof (__x) == sizeof (float)) ? (0) : __isnand(__x)) + +/* + * Macros for use in ieeefp.h. We can't just define the real ones here + * (like those above) as we have name space issues when this is *not* + * included via generic the ieeefp.h. + */ +#define __ieeefp_isnanf(x) 0 +#define __ieeefp_isinff(x) 0 +#define __ieeefp_finitef(x) 1 +#endif + +#ifdef __sparc__ +#ifdef __LITTLE_ENDIAN_DATA__ +#define __IEEE_LITTLE_ENDIAN +#else +#define __IEEE_BIG_ENDIAN +#endif +#endif + +#if defined(__m68k__) || defined(__mc68000__) +#define __IEEE_BIG_ENDIAN +#endif + +#if defined(__mc68hc11__) || defined(__mc68hc12__) || defined(__mc68hc1x__) +#define __IEEE_BIG_ENDIAN +#ifdef __HAVE_SHORT_DOUBLE__ +# define _DOUBLE_IS_32BITS +#endif +#endif + +#if defined (__H8300__) || defined (__H8300H__) || defined (__H8300S__) || defined (__H8500__) || defined (__H8300SX__) +#define __IEEE_BIG_ENDIAN +#define _FLOAT_ARG float +#define _DOUBLE_IS_32BITS +#endif + +#if defined (__xc16x__) || defined (__xc16xL__) || defined (__xc16xS__) +#define __IEEE_LITTLE_ENDIAN +#define _FLOAT_ARG float +#define _DOUBLE_IS_32BITS +#endif + + +#ifdef __sh__ +#ifdef __LITTLE_ENDIAN__ +#define __IEEE_LITTLE_ENDIAN +#else +#define __IEEE_BIG_ENDIAN +#endif +#if defined(__SH2E__) || defined(__SH3E__) || defined(__SH4_SINGLE_ONLY__) || defined(__SH2A_SINGLE_ONLY__) +#define _DOUBLE_IS_32BITS +#endif +#endif + +#ifdef _AM29K +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef _WIN32 +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __i386__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __i960__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __lm32__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __M32R__ +#define __IEEE_BIG_ENDIAN +#endif + +#if defined(_C4x) || defined(_C3x) +#define __IEEE_BIG_ENDIAN +#define _DOUBLE_IS_32BITS +#endif + +#ifdef __TMS320C6X__ +#ifdef _BIG_ENDIAN +#define __IEEE_BIG_ENDIAN +#else +#define __IEEE_LITTLE_ENDIAN +#endif +#endif + +#ifdef __TIC80__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __MIPSEL__ +#define __IEEE_LITTLE_ENDIAN +#endif +#ifdef __MIPSEB__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __MMIX__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __D30V__ +#define __IEEE_BIG_ENDIAN +#endif + +/* necv70 was __IEEE_LITTLE_ENDIAN. */ + +#ifdef __W65__ +#define __IEEE_LITTLE_ENDIAN +#define _DOUBLE_IS_32BITS +#endif + +#if defined(__Z8001__) || defined(__Z8002__) +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __m88k__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __mn10300__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __mn10200__ +#define __IEEE_LITTLE_ENDIAN +#define _DOUBLE_IS_32BITS +#endif + +#ifdef __v800 +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __v850 +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __D10V__ +#define __IEEE_BIG_ENDIAN +#if __DOUBLE__ == 32 +#define _DOUBLE_IS_32BITS +#endif +#endif + +#ifdef __PPC__ +#if (defined(_BIG_ENDIAN) && _BIG_ENDIAN) || (defined(_AIX) && _AIX) +#define __IEEE_BIG_ENDIAN +#else +#if (defined(_LITTLE_ENDIAN) && _LITTLE_ENDIAN) || (defined(__sun__) && __sun__) || (defined(_WIN32) && _WIN32) +#define __IEEE_LITTLE_ENDIAN +#endif +#endif +#endif + +#ifdef __xstormy16__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __arc__ +#ifdef __big_endian__ +#define __IEEE_BIG_ENDIAN +#else +#define __IEEE_LITTLE_ENDIAN +#endif +#endif + +#ifdef __CRX__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __fr30__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __mcore__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __mt__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __frv__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __moxie__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __ia64__ +#ifdef __BIG_ENDIAN__ +#define __IEEE_BIG_ENDIAN +#else +#define __IEEE_LITTLE_ENDIAN +#endif +#endif + +#ifdef __AVR__ +#define __IEEE_LITTLE_ENDIAN +#define _DOUBLE_IS_32BITS +#endif + +#if defined(__or32__) || defined(__or1k__) || defined(__or16__) +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __IP2K__ +#define __IEEE_BIG_ENDIAN +#define __SMALL_BITFIELDS +#define _DOUBLE_IS_32BITS +#endif + +#ifdef __iq2000__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __MAVERICK__ +#ifdef __ARMEL__ +# define __IEEE_LITTLE_ENDIAN +#else /* must be __ARMEB__ */ +# define __IEEE_BIG_ENDIAN +#endif /* __ARMEL__ */ +#endif /* __MAVERICK__ */ + +#ifdef __m32c__ +#define __IEEE_LITTLE_ENDIAN +#define __SMALL_BITFIELDS +#endif + +#ifdef __CRIS__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __BFIN__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __x86_64__ +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifdef __mep__ +#ifdef __LITTLE_ENDIAN__ +#define __IEEE_LITTLE_ENDIAN +#else +#define __IEEE_BIG_ENDIAN +#endif +#endif + +#ifdef __MICROBLAZE__ +#define __IEEE_BIG_ENDIAN +#endif + +#ifdef __RL78__ +#define __IEEE_LITTLE_ENDIAN +#define __SMALL_BITFIELDS /* 16 Bit INT */ +#define _DOUBLE_IS_32BITS +#endif + +#ifdef __RX__ + +#ifdef __RX_BIG_ENDIAN__ +#define __IEEE_BIG_ENDIAN +#else +#define __IEEE_LITTLE_ENDIAN +#endif + +#ifndef __RX_64BIT_DOUBLES__ +#define _DOUBLE_IS_32BITS +#endif + +#ifdef __RX_16BIT_INTS__ +#define __SMALL_BITFIELDS +#endif + +#endif + +#if (defined(__CR16__) || defined(__CR16C__) ||defined(__CR16CP__)) +#define __IEEE_LITTLE_ENDIAN +#define __SMALL_BITFIELDS /* 16 Bit INT */ +#endif + +#ifndef __IEEE_BIG_ENDIAN +#ifndef __IEEE_LITTLE_ENDIAN +#error Endianess not declared!! +#endif /* not __IEEE_LITTLE_ENDIAN */ +#endif /* not __IEEE_BIG_ENDIAN */ + +#endif /* not __IEEE_LITTLE_ENDIAN */ +#endif /* not __IEEE_BIG_ENDIAN */ + diff --git a/src/math/math.h b/src/math/math.h new file mode 100644 index 00000000..c62f583d --- /dev/null +++ b/src/math/math.h @@ -0,0 +1,35 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _MATH_H_ +#define _MATH_H_ + +float acosf(float x); + +float cosf(float x); + +float sqrtf(float x); + +float fabsf(float x); + +float floorf(float x); + +float scalbnf(float x, int n); + +float copysignf(float x, float y); + +#endif diff --git a/src/math/sf_copysign.c b/src/math/sf_copysign.c new file mode 100644 index 00000000..f547c82e --- /dev/null +++ b/src/math/sf_copysign.c @@ -0,0 +1,50 @@ +/* sf_copysign.c -- float version of s_copysign.c. + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * copysignf(float x, float y) + * copysignf(x,y) returns a value with the magnitude of x and + * with the sign bit of y. + */ + +#include "fdlibm.h" + +#ifdef __STDC__ + float copysignf(float x, float y) +#else + float copysignf(x,y) + float x,y; +#endif +{ + __uint32_t ix,iy; + GET_FLOAT_WORD(ix,x); + GET_FLOAT_WORD(iy,y); + SET_FLOAT_WORD(x,(ix&0x7fffffff)|(iy&0x80000000)); + return x; +} + +#ifdef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + double copysign(double x, double y) +#else + double copysign(x,y) + double x,y; +#endif +{ + return (double) copysignf((float) x, (float) y); +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/src/math/sf_cos.c b/src/math/sf_cos.c new file mode 100644 index 00000000..4c0a9a53 --- /dev/null +++ b/src/math/sf_cos.c @@ -0,0 +1,68 @@ +/* sf_cos.c -- float version of s_cos.c. + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include "fdlibm.h" + +#ifdef __STDC__ +static const float one=1.0; +#else +static float one=1.0; +#endif + +#ifdef __STDC__ + float cosf(float x) +#else + float cosf(x) + float x; +#endif +{ + float y[2],z=0.0; + __int32_t n,ix; + + GET_FLOAT_WORD(ix,x); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffff; + if(ix <= 0x3f490fd8) return __kernel_cosf(x,z); + + /* cos(Inf or NaN) is NaN */ + else if (!FLT_UWORD_IS_FINITE(ix)) return x-x; + + /* argument reduction needed */ + else { + n = __ieee754_rem_pio2f(x,y); + switch(n&3) { + case 0: return __kernel_cosf(y[0],y[1]); + case 1: return -__kernel_sinf(y[0],y[1],1); + case 2: return -__kernel_cosf(y[0],y[1]); + default: + return __kernel_sinf(y[0],y[1],1); + } + } +} + +#ifdef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + double cos(double x) +#else + double cos(x) + double x; +#endif +{ + return (double) cosf((float) x); +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/src/math/sf_fabs.c b/src/math/sf_fabs.c new file mode 100644 index 00000000..2aaed326 --- /dev/null +++ b/src/math/sf_fabs.c @@ -0,0 +1,47 @@ +/* sf_fabs.c -- float version of s_fabs.c. + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * fabsf(x) returns the absolute value of x. + */ + +#include "fdlibm.h" + +#ifdef __STDC__ + float fabsf(float x) +#else + float fabsf(x) + float x; +#endif +{ + __uint32_t ix; + GET_FLOAT_WORD(ix,x); + SET_FLOAT_WORD(x,ix&0x7fffffff); + return x; +} + +#ifdef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + double fabs(double x) +#else + double fabs(x) + double x; +#endif +{ + return (double) fabsf((float) x); +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/src/math/sf_floor.c b/src/math/sf_floor.c new file mode 100644 index 00000000..9264d81e --- /dev/null +++ b/src/math/sf_floor.c @@ -0,0 +1,80 @@ +/* sf_floor.c -- float version of s_floor.c. + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +/* + * floorf(x) + * Return x rounded toward -inf to integral value + * Method: + * Bit twiddling. + * Exception: + * Inexact flag raised if x not equal to floorf(x). + */ + +#include "fdlibm.h" + +#ifdef __STDC__ +static const float huge = 1.0e30; +#else +static float huge = 1.0e30; +#endif + +#ifdef __STDC__ + float floorf(float x) +#else + float floorf(x) + float x; +#endif +{ + __int32_t i0,j0; + __uint32_t i,ix; + GET_FLOAT_WORD(i0,x); + ix = (i0&0x7fffffff); + j0 = (ix>>23)-0x7f; + if(j0<23) { + if(j0<0) { /* raise inexact if x != 0 */ + if(huge+x>(float)0.0) {/* return 0*sign(x) if |x|<1 */ + if(i0>=0) {i0=0;} + else if(!FLT_UWORD_IS_ZERO(ix)) + { i0=0xbf800000;} + } + } else { + i = (0x007fffff)>>j0; + if((i0&i)==0) return x; /* x is integral */ + if(huge+x>(float)0.0) { /* raise inexact flag */ + if(i0<0) i0 += (0x00800000)>>j0; + i0 &= (~i); + } + } + } else { + if(!FLT_UWORD_IS_FINITE(ix)) return x+x; /* inf or NaN */ + else return x; /* x is integral */ + } + SET_FLOAT_WORD(x,i0); + return x; +} + +#ifdef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + double floor(double x) +#else + double floor(x) + double x; +#endif +{ + return (double) floorf((float) x); +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ diff --git a/src/math/sf_scalbn.c b/src/math/sf_scalbn.c new file mode 100644 index 00000000..70006001 --- /dev/null +++ b/src/math/sf_scalbn.c @@ -0,0 +1,86 @@ +/* sf_scalbn.c -- float version of s_scalbn.c. + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include "fdlibm.h" +#include +#include + +#if INT_MAX > 50000 +#define OVERFLOW_INT 50000 +#else +#define OVERFLOW_INT 30000 +#endif + +#ifdef __STDC__ +static const float +#else +static float +#endif +two25 = 3.355443200e+07, /* 0x4c000000 */ +twom25 = 2.9802322388e-08, /* 0x33000000 */ +huge = 1.0e+30, +tiny = 1.0e-30; + +#ifdef __STDC__ + float scalbnf (float x, int n) +#else + float scalbnf (x,n) + float x; int n; +#endif +{ + __int32_t k,ix; + __uint32_t hx; + + GET_FLOAT_WORD(ix,x); + hx = ix&0x7fffffff; + k = hx>>23; /* extract exponent */ + if (FLT_UWORD_IS_ZERO(hx)) + return x; + if (!FLT_UWORD_IS_FINITE(hx)) + return x+x; /* NaN or Inf */ + if (FLT_UWORD_IS_SUBNORMAL(hx)) { + x *= two25; + GET_FLOAT_WORD(ix,x); + k = ((ix&0x7f800000)>>23) - 25; + if (n< -50000) return tiny*x; /*underflow*/ + } + k = k+n; + if (k > FLT_LARGEST_EXP) return huge*copysignf(huge,x); /* overflow */ + if (k > 0) /* normal result */ + {SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23)); return x;} + if (k < FLT_SMALLEST_EXP) { + if (n > OVERFLOW_INT) /* in case integer overflow in n+k */ + return huge*copysignf(huge,x); /*overflow*/ + else return tiny*copysignf(tiny,x); /*underflow*/ + } + k += 25; /* subnormal result */ + SET_FLOAT_WORD(x,(ix&0x807fffff)|(k<<23)); + return x*twom25; +} + +#ifdef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + double scalbn(double x, int n) +#else + double scalbn(x,n) + double x; + int n; +#endif +{ + return (double) scalbnf((float) x, n); +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ -- cgit v1.2.3 From ba99630f33440b993c69830856d2a7741ffdef71 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 25 Oct 2013 04:03:39 -0700 Subject: altos: Fix GPS test frameworks to handle shared ao_gps_new variable Signed-off-by: Keith Packard --- src/drivers/ao_gps_ublox.c | 2 +- src/test/ao_gps_test.c | 3 +++ src/test/ao_gps_test_skytraq.c | 3 +++ src/test/ao_gps_test_ublox.c | 3 +++ 4 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/drivers/ao_gps_ublox.c b/src/drivers/ao_gps_ublox.c index 3582d6e0..4fb90746 100644 --- a/src/drivers/ao_gps_ublox.c +++ b/src/drivers/ao_gps_ublox.c @@ -21,7 +21,7 @@ #include "ao_gps_ublox.h" -#define AO_UBLOX_DEBUG 1 +#define AO_UBLOX_DEBUG 0 #include diff --git a/src/test/ao_gps_test.c b/src/test/ao_gps_test.c index b6cc9ba7..e799ab0f 100644 --- a/src/test/ao_gps_test.c +++ b/src/test/ao_gps_test.c @@ -26,6 +26,9 @@ #define AO_GPS_NUM_SAT_MASK (0xf << 0) #define AO_GPS_NUM_SAT_SHIFT (0) +#define AO_GPS_NEW_DATA 1 +#define AO_GPS_NEW_TRACKING 2 + #define AO_GPS_VALID (1 << 4) #define AO_GPS_RUNNING (1 << 5) #define AO_GPS_DATE_VALID (1 << 6) diff --git a/src/test/ao_gps_test_skytraq.c b/src/test/ao_gps_test_skytraq.c index bf2ab5b8..1b590d5e 100644 --- a/src/test/ao_gps_test_skytraq.c +++ b/src/test/ao_gps_test_skytraq.c @@ -26,6 +26,9 @@ #define AO_GPS_NUM_SAT_MASK (0xf << 0) #define AO_GPS_NUM_SAT_SHIFT (0) +#define AO_GPS_NEW_DATA 1 +#define AO_GPS_NEW_TRACKING 2 + #define AO_GPS_VALID (1 << 4) #define AO_GPS_RUNNING (1 << 5) #define AO_GPS_DATE_VALID (1 << 6) diff --git a/src/test/ao_gps_test_ublox.c b/src/test/ao_gps_test_ublox.c index 31c7af60..4eb4b837 100644 --- a/src/test/ao_gps_test_ublox.c +++ b/src/test/ao_gps_test_ublox.c @@ -26,6 +26,9 @@ #define AO_GPS_NUM_SAT_MASK (0xf << 0) #define AO_GPS_NUM_SAT_SHIFT (0) +#define AO_GPS_NEW_DATA 1 +#define AO_GPS_NEW_TRACKING 2 + #define AO_GPS_VALID (1 << 4) #define AO_GPS_RUNNING (1 << 5) #define AO_GPS_DATE_VALID (1 << 6) -- cgit v1.2.3 From 08143a922fe27bc50a19924f46538f9476ab5fd1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 25 Oct 2013 04:05:09 -0700 Subject: altos: Add gyro-based orientation tracking This tracks the angle-from-vertical as an additional input to the pyro channels. Signed-off-by: Keith Packard --- src/core/ao_data.h | 6 +- src/core/ao_flight.c | 4 + src/core/ao_kalman.c | 3 - src/core/ao_pyro.c | 4 +- src/core/ao_quaternion.h | 116 +++++++++++++++++++ src/core/ao_sample.c | 98 +++++++++++++++- src/core/ao_sample.h | 3 +- src/core/ao_telemetry.c | 1 + src/core/ao_telemetry.h | 2 +- src/drivers/ao_mpu6000.c | 2 + src/drivers/ao_mpu6000.h | 17 ++- src/stm/Makefile.defs | 4 +- src/telemega-v0.3/Makefile | 16 +++ src/test/Makefile | 9 +- src/test/ao_flight_test.c | 259 ++---------------------------------------- src/test/ao_quaternion_test.c | 67 +++++++++++ 16 files changed, 343 insertions(+), 268 deletions(-) create mode 100644 src/core/ao_quaternion.h create mode 100644 src/test/ao_quaternion_test.c (limited to 'src') diff --git a/src/core/ao_data.h b/src/core/ao_data.h index 339afe69..5a232885 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -18,6 +18,8 @@ #ifndef _AO_DATA_H_ #define _AO_DATA_H_ +#define GRAVITY 9.80665 + #if HAS_ADC #define AO_DATA_ADC (1 << 0) #else @@ -300,8 +302,8 @@ typedef int16_t accel_t; #define HAS_GYRO 1 -typedef int16_t gyro_t; -typedef int32_t angle_t; +typedef int16_t gyro_t; /* in raw sample units */ +typedef int16_t angle_t; /* in degrees */ /* Y axis is aligned with the direction of motion (along) */ /* X axis is aligned in the other board axis (across) */ diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index 2495a44b..240b348a 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -20,6 +20,10 @@ #include #endif +#if HAS_MPU6000 +#include +#endif + #ifndef HAS_ACCEL #error Please define HAS_ACCEL #endif diff --git a/src/core/ao_kalman.c b/src/core/ao_kalman.c index 762b2c0a..7fd4f889 100644 --- a/src/core/ao_kalman.c +++ b/src/core/ao_kalman.c @@ -292,7 +292,4 @@ ao_kalman(void) else #endif ao_avg_height = (ao_avg_height_scaled + 63) >> 7; -#ifdef AO_FLIGHT_TEST - ao_sample_prev_tick = ao_sample_tick; -#endif } diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index 531e1f50..24c9fe99 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -113,7 +113,7 @@ ao_pyro_ready(struct ao_pyro *pyro) continue; break; -#if HAS_ORIENT +#if HAS_GYRO case ao_pyro_orient_less: if (ao_orient <= pyro->orient_less) continue; @@ -310,7 +310,7 @@ const struct { { "h<", ao_pyro_height_less, offsetof(struct ao_pyro, height_less), HELP("height less (m)") }, { "h>", ao_pyro_height_greater, offsetof(struct ao_pyro, height_greater), HELP("height greater (m)") }, -#if HAS_ORIENT +#if HAS_GYRO { "o<", ao_pyro_orient_less, offsetof(struct ao_pyro, orient_less), HELP("orient less (deg)") }, { "o>", ao_pyro_orient_greater, offsetof(struct ao_pyro, orient_greater), HELP("orient greater (deg)") }, #endif diff --git a/src/core/ao_quaternion.h b/src/core/ao_quaternion.h new file mode 100644 index 00000000..f4b8aaa4 --- /dev/null +++ b/src/core/ao_quaternion.h @@ -0,0 +1,116 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_QUATERNION_H_ +#define _AO_QUATERNION_H_ + +#include + +struct ao_quaternion { + float r; /* real bit */ + float x, y, z; /* imaginary bits */ +}; + +static inline void ao_quaternion_multiply(struct ao_quaternion *r, + struct ao_quaternion *a, + struct ao_quaternion *b) +{ + struct ao_quaternion t; +#define T(_a,_b) (((a)->_a) * ((b)->_b)) + t.r = T(r,r) - T(x,x) - T(y,y) - T(z,z); + t.x = T(r,x) + T(x,r) + T(y,z) - T(z,y); + t.y = T(r,y) - T(x,z) + T(y,r) + T(z,x); + t.z = T(r,z) + T(x,y) - T(y,x) + T(z,r); +#undef T + *r = t; +} + +static inline void ao_quaternion_conjugate(struct ao_quaternion *r, + struct ao_quaternion *a) +{ + r->r = a->r; + r->x = -a->x; + r->y = -a->y; + r->z = -a->z; +} + +static inline float ao_quaternion_normal(struct ao_quaternion *a) +{ +#define S(_a) (((a)->_a) * ((a)->_a)) + return S(r) + S(x) + S(y) + S(z); +#undef S +} + +static inline void ao_quaternion_scale(struct ao_quaternion *r, + struct ao_quaternion *a, + float b) +{ + r->r = a->r * b; + r->x = a->x * b; + r->y = a->y * b; + r->z = a->z * b; +} + +static inline void ao_quaternion_normalize(struct ao_quaternion *r, + struct ao_quaternion *a) +{ + float n = ao_quaternion_normal(a); + + if (n > 0) + ao_quaternion_scale(r, a, 1/sqrtf(n)); + else + *r = *a; +} + +static inline void ao_quaternion_rotate(struct ao_quaternion *r, + struct ao_quaternion *a, + struct ao_quaternion *b) +{ + struct ao_quaternion c; + struct ao_quaternion t; + + ao_quaternion_conjugate(&c, b); + ao_quaternion_multiply(&t, b, a); + ao_quaternion_multiply(r, &t, &c); +} + +static inline void ao_quaternion_init_vector(struct ao_quaternion *r, + float x, float y, float z) +{ + r->r = 0; + r->x = x; + r->y = y; + r->z = z; +} + +static inline void ao_quaternion_init_rotation(struct ao_quaternion *r, + float x, float y, float z, + float s, float c) +{ + r->r = c; + r->x = s * x; + r->y = s * y; + r->z = s * z; +} + +static inline void ao_quaternion_init_zero_rotation(struct ao_quaternion *r) +{ + r->r = 1; + r->x = r->y = r->z = 0; +} + +#endif /* _AO_QUATERNION_H_ */ diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c index dec44f9f..676e0ffd 100644 --- a/src/core/ao_sample.c +++ b/src/core/ao_sample.c @@ -20,6 +20,10 @@ #include #endif +#if HAS_GYRO +#include +#endif + /* * Current sensor values */ @@ -44,8 +48,7 @@ __pdata accel_t ao_sample_accel_through; __pdata gyro_t ao_sample_roll; __pdata gyro_t ao_sample_pitch; __pdata gyro_t ao_sample_yaw; -__pdata angle_t ao_sample_angle; -__pdata angle_t ao_sample_roll_angle; +__pdata angle_t ao_orient; #endif __data uint8_t ao_sample_data; @@ -86,6 +89,8 @@ __pdata int32_t ao_sample_accel_through_sum; __pdata int32_t ao_sample_pitch_sum; __pdata int32_t ao_sample_yaw_sum; __pdata int32_t ao_sample_roll_sum; +static struct ao_quaternion ao_rotation; +static struct ao_quaternion ao_pad_orientation; #endif static void @@ -129,11 +134,91 @@ ao_sample_preflight_set(void) ao_sample_pitch_sum = 0; ao_sample_yaw_sum = 0; ao_sample_roll_sum = 0; - ao_sample_angle = 0; + ao_orient = 0; + + /* No rotation yet */ + ao_quaternion_init_zero_rotation(&ao_rotation); + + /* XXX Assume we're pointing straight up for now */ + ao_quaternion_init_vector(&ao_pad_orientation, + ao_ground_accel_across, + ao_ground_accel_through, + -ao_ground_accel_along); + ao_quaternion_normalize(&ao_pad_orientation, + &ao_pad_orientation); + + printf ("pad r%8.5f x%8.5f y%8.5f z%8.5f\n", + ao_pad_orientation.r, + ao_pad_orientation.x, + ao_pad_orientation.y, + ao_pad_orientation.z); #endif nsamples = 0; } +#if HAS_GYRO +static void +ao_sample_rotate(void) +{ +#ifdef AO_FLIGHT_TEST + float dt = (ao_sample_tick - ao_sample_prev_tick) / 100.0; +#else + static const float dt = 1/100.0; +#endif + float x = ao_mpu6000_gyro(ao_sample_pitch - ao_ground_pitch) * dt; + float y = ao_mpu6000_gyro(ao_sample_yaw - ao_ground_yaw) * dt; + float z = ao_mpu6000_gyro(ao_sample_roll - ao_ground_roll) * dt; + + float n_2, n; + float s, c; + + struct ao_quaternion rot; + struct ao_quaternion point; + + /* The amount of rotation is just the length of the vector. Now, + * here's the trick -- assume that the rotation amount is small. In this case, + * sin(x) ≃ x, so we can just make this the sin. + */ + + n_2 = x*x + y*y + z*z; + n = sqrtf(n_2); + s = n / 2; + if (s > 1) + s = 1; + c = sqrtf(1 - s*s); + + /* Make unit vector */ + if (n > 0) { + x /= n; + y /= n; + z /= n; + } + + /* Now compute the unified rotation quaternion */ + + ao_quaternion_init_rotation(&rot, + x, y, z, + s, c); + + /* Integrate with the previous rotation amount */ + ao_quaternion_multiply(&ao_rotation, &ao_rotation, &rot); + + /* And normalize to make sure it remains a unit vector */ + ao_quaternion_normalize(&ao_rotation, &ao_rotation); + + /* Compute pitch angle from vertical by taking the pad + * orientation vector and rotating it by the current total + * rotation value. That will be a unit vector pointing along + * the airframe axis. The Z value will be the cosine of the + * change in the angle from vertical since boost + */ + + ao_quaternion_rotate(&point, &ao_pad_orientation, &ao_rotation); + + ao_orient = acosf(point.z) * (float) (180.0/M_PI); +} +#endif + static void ao_sample_preflight(void) { @@ -232,9 +317,12 @@ ao_sample(void) ao_sample_preflight_update(); ao_kalman(); #if HAS_GYRO - /* do quaternion stuff here... */ + ao_sample_rotate(); #endif } +#ifdef AO_FLIGHT_TEST + ao_sample_prev_tick = ao_sample_tick; +#endif ao_sample_data = ao_data_ring_next(ao_sample_data); } return !ao_preflight; @@ -264,7 +352,7 @@ ao_sample_init(void) ao_sample_pitch = 0; ao_sample_yaw = 0; ao_sample_roll = 0; - ao_sample_angle = 0; + ao_orient = 0; #endif ao_sample_data = ao_data_head; ao_preflight = TRUE; diff --git a/src/core/ao_sample.h b/src/core/ao_sample.h index 5bd29536..1d1bcc7c 100644 --- a/src/core/ao_sample.h +++ b/src/core/ao_sample.h @@ -64,8 +64,6 @@ * for all further flight computations */ -#define GRAVITY 9.80665 - /* * Above this height, the baro sensor doesn't work */ @@ -118,6 +116,7 @@ extern __pdata accel_t ao_ground_accel_through; extern __pdata gyro_t ao_ground_pitch; extern __pdata gyro_t ao_ground_yaw; extern __pdata gyro_t ao_ground_roll; +extern __pdata angle_t ao_orient; #endif void ao_sample_init(void); diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 6b47a06a..a2726016 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -115,6 +115,7 @@ ao_send_mega_sensor(void) telemetry.generic.tick = packet->tick; telemetry.generic.type = AO_TELEMETRY_MEGA_SENSOR; + telemetry.mega_sensor.orient = ao_orient; telemetry.mega_sensor.accel = ao_data_accel(packet); telemetry.mega_sensor.pres = ao_data_pres(packet); telemetry.mega_sensor.temp = ao_data_temp(packet); diff --git a/src/core/ao_telemetry.h b/src/core/ao_telemetry.h index fd6b76b3..237a35ab 100644 --- a/src/core/ao_telemetry.h +++ b/src/core/ao_telemetry.h @@ -162,7 +162,7 @@ struct ao_telemetry_mega_sensor { uint16_t tick; /* 2 */ uint8_t type; /* 4 */ - uint8_t pad5; /* 5 */ + uint8_t orient; /* 5 angle from vertical */ int16_t accel; /* 6 Z axis */ int32_t pres; /* 8 Pa * 10 */ diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index 73057820..5e75b78a 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -118,6 +118,7 @@ _ao_mpu6000_sample(struct ao_mpu6000_sample *sample) #define G 981 /* in cm/s² */ +#if 0 static int16_t /* cm/s² */ ao_mpu6000_accel(int16_t v) { @@ -129,6 +130,7 @@ ao_mpu6000_gyro(int16_t v) { return (int16_t) ((v * (int32_t) 20000) / 32767); } +#endif static uint8_t ao_mpu6000_accel_check(int16_t normal, int16_t test, char *which) diff --git a/src/drivers/ao_mpu6000.h b/src/drivers/ao_mpu6000.h index a42f69c4..2241bf80 100644 --- a/src/drivers/ao_mpu6000.h +++ b/src/drivers/ao_mpu6000.h @@ -18,6 +18,10 @@ #ifndef _AO_MPU6000_H_ #define _AO_MPU6000_H_ +#ifndef M_PI +#define M_PI 3.1415926535897832384626433 +#endif + #define MPU6000_ADDR_WRITE 0xd0 #define MPU6000_ADDR_READ 0xd1 @@ -166,9 +170,20 @@ /* Self test gyro is approximately 50°/s */ #define MPU6000_ST_GYRO(full_scale) ((int16_t) (((int32_t) 32767 * (int32_t) 50) / (full_scale))) -#define MPU6000_GYRO_FULLSCALE 2000 +#define MPU6000_GYRO_FULLSCALE ((float) 2000 * M_PI/180.0) + +static inline float +ao_mpu6000_gyro(int16_t sensor) { + return (float) sensor * ((float) (MPU6000_GYRO_FULLSCALE / 32767.0)); +} + #define MPU6000_ACCEL_FULLSCALE 16 +static inline float +ao_mpu6000_accel(int16_t sensor) { + return (float) sensor * ((float) (MPU6000_ACCEL_FULLSCALE * GRAVITY / 32767.0)); +} + struct ao_mpu6000_sample { int16_t accel_x; int16_t accel_y; diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index ee1cb658..0710d747 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -1,4 +1,4 @@ -vpath % ../stm:../product:../drivers:../core:../util:../kalman:../aes:.. +vpath % ../stm:../product:../drivers:../core:../util:../kalman:../aes:../math:.. vpath make-altitude ../util vpath make-kalman ../util vpath kalman.5c ../kalman @@ -24,7 +24,7 @@ include $(TOPDIR)/Makedefs CC=$(ARM_CC) LIBS=-lpdclib-cortex-m3 -lgcc -AO_CFLAGS=-I. -I../stm -I../core -I../drivers -I.. +AO_CFLAGS=-I. -I../stm -I../core -I../drivers -I../math -I.. STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) LDFLAGS=-L../stm -Wl,-Taltos.ld diff --git a/src/telemega-v0.3/Makefile b/src/telemega-v0.3/Makefile index 6e5da721..2f460105 100644 --- a/src/telemega-v0.3/Makefile +++ b/src/telemega-v0.3/Makefile @@ -27,6 +27,7 @@ INC = \ ao_sample_profile.h \ ao_mpu.h \ stm32l.h \ + math.h \ Makefile # @@ -44,6 +45,20 @@ INC = \ #STACK_GUARD=ao_mpu_stm.c #STACK_GUARD_DEF=-DHAS_STACK_GUARD=1 +MATH_SRC=\ + ef_acos.c \ + ef_sqrt.c + +# ef_rem_pio2.c \ +# kf_cos.c \ +# kf_sin.c \ +# kf_rem_pio2.c \ +# sf_copysign.c \ +# sf_cos.c \ +# sf_fabs.c \ +# sf_floor.c \ +# sf_scalbn.c + ALTOS_SRC = \ ao_boot_chain.c \ ao_interrupt.c \ @@ -93,6 +108,7 @@ ALTOS_SRC = \ ao_companion.c \ ao_pyro.c \ ao_aprs.c \ + $(MATH_SRC) \ $(PROFILE) \ $(SAMPLE_PROFILE) \ $(STACK_GUARD) diff --git a/src/test/Makefile b/src/test/Makefile index 5eee6bbb..f64a9531 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,15 +1,15 @@ -vpath % ..:../core:../drivers:../util:../micropeak:../aes +vpath % ..:../core:../drivers:../util:../micropeak:../aes:../product PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_flight_test_mm \ ao_gps_test ao_gps_test_skytraq ao_gps_test_ublox ao_convert_test ao_convert_pa_test ao_fec_test \ ao_aprs_test ao_micropeak_test ao_fat_test ao_aes_test ao_int64_test \ - ao_ms5607_convert_test + ao_ms5607_convert_test ao_quaternion_test INCS=ao_kalman.h ao_ms5607.h ao_log.h ao_data.h altitude-pa.h altitude.h KALMAN=make-kalman -CFLAGS=-I.. -I. -I../core -I../drivers -I../micropeak -O0 -g -Wall +CFLAGS=-I.. -I. -I../core -I../drivers -I../micropeak -I../product -O0 -g -Wall all: $(PROGS) ao_aprs_data.wav @@ -80,3 +80,6 @@ ao_int64_test: ao_int64_test.c ao_int64.c ao_int64.h ao_ms5607_convert_test: ao_ms5607_convert_test.c ao_ms5607_convert_8051.c ao_int64.c ao_int64.h cc $(CFLAGS) -o $@ ao_ms5607_convert_test.c + +ao_quaternion_test: ao_quaternion_test.c ao_quaternion.h + cc $(CFLAGS) -o $@ ao_quaternion_test.c -lm \ No newline at end of file diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index faf31aa7..e2f63e34 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -25,6 +25,8 @@ #include #include +#define GRAVITY 9.80665 + #define AO_HERTZ 100 #define HAS_ADC 1 @@ -36,6 +38,11 @@ #define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) #define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) +#define AO_GPS_NEW_DATA 1 +#define AO_GPS_NEW_TRACKING 2 + +int ao_gps_new; + #if TELEMEGA #define AO_ADC_NUM_SENSE 6 #define HAS_MS5607 1 @@ -240,7 +247,6 @@ struct ao_config ao_config; #define DATA_TO_XDATA(x) (x) -#define GRAVITY 9.80665 extern int16_t ao_ground_accel, ao_flight_accel; extern int16_t ao_accel_2g; @@ -339,20 +345,6 @@ ao_test_exit(void) exit(0); } -#if HAS_MPU6000 -static double -ao_mpu6000_accel(int16_t sensor) -{ - return sensor / 32767.0 * MPU6000_ACCEL_FULLSCALE * GRAVITY; -} - -static double -ao_mpu6000_gyro(int32_t sensor) -{ - return sensor / 32767.0 * MPU6000_GYRO_FULLSCALE; -} -#endif - void ao_insert(void) { @@ -408,23 +400,23 @@ ao_insert(void) if (!ao_summary) { printf("%7.2f height %8.2f accel %8.3f " #if TELEMEGA - "roll %8.3f angle %8.3f qangle %8.3f " - "accel_x %8.3f accel_y %8.3f accel_z %8.3f gyro_x %8.3f gyro_y %8.3f gyro_z %8.3f " + "angle %5d " +/* "accel_x %8.3f accel_y %8.3f accel_z %8.3f gyro_x %8.3f gyro_y %8.3f gyro_z %8.3f " */ #endif "state %-8.8s k_height %8.2f k_speed %8.3f k_accel %8.3f avg_height %5d drogue %4d main %4d error %5d\n", time, height, accel, #if TELEMEGA - ao_mpu6000_gyro(ao_sample_roll_angle) / 100.0, - ao_mpu6000_gyro(ao_sample_angle) / 100.0, - ao_sample_qangle, + ao_orient, +/* ao_mpu6000_accel(ao_data_static.mpu6000.accel_x), ao_mpu6000_accel(ao_data_static.mpu6000.accel_y), ao_mpu6000_accel(ao_data_static.mpu6000.accel_z), ao_mpu6000_gyro(ao_data_static.mpu6000.gyro_x - ao_ground_mpu6000.gyro_x), ao_mpu6000_gyro(ao_data_static.mpu6000.gyro_y - ao_ground_mpu6000.gyro_y), ao_mpu6000_gyro(ao_data_static.mpu6000.gyro_z - ao_ground_mpu6000.gyro_z), +*/ #endif ao_state_names[ao_flight_state], ao_k_height / 65536.0, @@ -589,207 +581,6 @@ int32(uint8_t *bytes, int off) static int log_format; -#if TELEMEGA - -static double -ao_vec_norm(double x, double y, double z) -{ - return x*x + y*y + z*z; -} - -static void -ao_vec_normalize(double *x, double *y, double *z) -{ - double scale = 1/sqrt(ao_vec_norm(*x, *y, *z)); - - *x *= scale; - *y *= scale; - *z *= scale; -} - -struct ao_quat { - double q0, q1, q2, q3; -}; - -static void -ao_quat_mul(struct ao_quat *r, struct ao_quat *a, struct ao_quat *b) -{ - r->q0 = a->q0 * b->q0 - a->q1 * b->q1 - a->q2 * b->q2 - a->q3 * b->q3; - r->q1 = a->q0 * b->q1 + a->q1 * b->q0 + a->q2 * b->q3 - a->q3 * b->q2; - r->q2 = a->q0 * b->q2 - a->q1 * b->q3 + a->q2 * b->q0 + a->q3 * b->q1; - r->q3 = a->q0 * b->q3 + a->q1 * b->q2 - a->q2 * b->q1 + a->q3 * b->q0; -} - -#if 0 -static void -ao_quat_scale(struct ao_quat *r, struct ao_quat *a, double s) -{ - r->q0 = a->q0 * s; - r->q1 = a->q1 * s; - r->q2 = a->q2 * s; - r->q3 = a->q3 * s; -} -#endif - -static void -ao_quat_conj(struct ao_quat *r, struct ao_quat *a) -{ - r->q0 = a->q0; - r->q1 = -a->q1; - r->q2 = -a->q2; - r->q3 = -a->q3; -} - -static void -ao_quat_rot(struct ao_quat *r, struct ao_quat *a, struct ao_quat *q) -{ - struct ao_quat t; - struct ao_quat c; - ao_quat_mul(&t, q, a); - ao_quat_conj(&c, q); - ao_quat_mul(r, &t, &c); -} - -static void -ao_quat_from_angle(struct ao_quat *r, - double x_rad, - double y_rad, - double z_rad) -{ - double angle = sqrt (x_rad * x_rad + y_rad * y_rad + z_rad * z_rad); - double s = sin(angle/2); - double c = cos(angle/2); - - r->q0 = c; - r->q1 = x_rad * s / angle; - r->q2 = y_rad * s / angle; - r->q3 = z_rad * s / angle; -} - -static void -ao_quat_from_vector(struct ao_quat *r, double x, double y, double z) -{ - ao_vec_normalize(&x, &y, &z); - double x_rad = atan2(z, y); - double y_rad = atan2(x, z); - double z_rad = atan2(y, x); - - ao_quat_from_angle(r, x_rad, y_rad, z_rad); -} - -static double -ao_quat_norm(struct ao_quat *a) -{ - return (a->q0 * a->q0 + - a->q1 * a->q1 + - a->q2 * a->q2 + - a->q3 * a->q3); -} - -static void -ao_quat_normalize(struct ao_quat *a) -{ - double norm = ao_quat_norm(a); - - if (norm) { - double m = 1/sqrt(norm); - - a->q0 *= m; - a->q1 *= m; - a->q2 *= m; - a->q3 *= m; - } -} - -static struct ao_quat ao_up, ao_current; -static struct ao_quat ao_orient; -static int ao_orient_tick; - -void -set_orientation(double x, double y, double z, int tick) -{ - struct ao_quat t; - - printf ("set_orientation %g %g %g\n", x, y, z); - ao_quat_from_vector(&ao_orient, x, y, z); - ao_up.q1 = ao_up.q2 = 0; - ao_up.q0 = ao_up.q3 = sqrt(2)/2; - ao_orient_tick = tick; - - ao_orient.q0 = 1; - ao_orient.q1 = 0; - ao_orient.q2 = 0; - ao_orient.q3 = 0; - - printf ("orient (%g) %g %g %g up (%g) %g %g %g\n", - ao_orient.q0, - ao_orient.q1, - ao_orient.q2, - ao_orient.q3, - ao_up.q0, - ao_up.q1, - ao_up.q2, - ao_up.q3); - - ao_quat_rot(&t, &ao_up, &ao_orient); - printf ("pad orient (%g) %g %g %g\n", - t.q0, - t.q1, - t.q2, - t.q3); - -} - -void -update_orientation (double rate_x, double rate_y, double rate_z, int tick) -{ - struct ao_quat q_dot; - double lambda; - double dt = (tick - ao_orient_tick) / 100.0; - - ao_orient_tick = tick; - -// lambda = 1 - ao_quat_norm(&ao_orient); - lambda = 0; - - q_dot.q0 = -0.5 * (ao_orient.q1 * rate_x + ao_orient.q2 * rate_y + ao_orient.q3 * rate_z) + lambda * ao_orient.q0; - q_dot.q1 = 0.5 * (ao_orient.q0 * rate_x + ao_orient.q2 * rate_z - ao_orient.q3 * rate_y) + lambda * ao_orient.q1; - q_dot.q2 = 0.5 * (ao_orient.q0 * rate_y + ao_orient.q3 * rate_x - ao_orient.q1 * rate_z) + lambda * ao_orient.q2; - q_dot.q3 = 0.5 * (ao_orient.q0 * rate_z + ao_orient.q1 * rate_y - ao_orient.q2 * rate_x) + lambda * ao_orient.q3; - -#if 0 - printf ("update_orientation %g %g %g (%g s)\n", rate_x, rate_y, rate_z, dt); - printf ("q_dot (%g) %g %g %g\n", - q_dot.q0, - q_dot.q1, - q_dot.q2, - q_dot.q3); -#endif - - ao_orient.q0 += q_dot.q0 * dt; - ao_orient.q1 += q_dot.q1 * dt; - ao_orient.q2 += q_dot.q2 * dt; - ao_orient.q3 += q_dot.q3 * dt; - - ao_quat_normalize(&ao_orient); - - ao_quat_rot(&ao_current, &ao_up, &ao_orient); - - ao_sample_qangle = 180 / M_PI * acos(ao_current.q3 * sqrt(2)); -#if 0 - printf ("orient (%g) %g %g %g current (%g) %g %g %g\n", - ao_orient.q0, - ao_orient.q1, - ao_orient.q2, - ao_orient.q3, - ao_current.q0, - ao_current.q1, - ao_current.q2, - ao_current.q3); -#endif -} -#endif - void ao_sleep(void *wchan) { @@ -872,32 +663,6 @@ ao_sleep(void *wchan) #if HAS_MMA655X ao_data_static.mma655x = int16(bytes, 26); #endif - if (ao_records_read == 0) - ao_ground_mpu6000 = ao_data_static.mpu6000; - else if (ao_records_read < 10) { -#define f(f) ao_ground_mpu6000.f = ao_ground_mpu6000.f + ((ao_data_static.mpu6000.f - ao_ground_mpu6000.f) >> 2) - f(accel_x); - f(accel_y); - f(accel_z); - f(gyro_x); - f(gyro_y); - f(gyro_z); - - double accel_x = ao_mpu6000_accel(ao_ground_mpu6000.accel_x); - double accel_y = ao_mpu6000_accel(ao_ground_mpu6000.accel_y); - double accel_z = ao_mpu6000_accel(ao_ground_mpu6000.accel_z); - - /* X and Y are in the ground plane, arbitraryily picked as MPU X and Z axes - * Z is normal to the ground, the MPU y axis - */ - set_orientation(accel_x, accel_z, accel_y, tick); - } else { - double rate_x = ao_mpu6000_gyro(ao_data_static.mpu6000.gyro_x - ao_ground_mpu6000.gyro_x); - double rate_y = ao_mpu6000_gyro(ao_data_static.mpu6000.gyro_y - ao_ground_mpu6000.gyro_y); - double rate_z = ao_mpu6000_gyro(ao_data_static.mpu6000.gyro_z - ao_ground_mpu6000.gyro_z); - - update_orientation(rate_x * M_PI / 180, rate_z * M_PI / 180, rate_y * M_PI / 180, tick); - } ao_records_read++; ao_insert(); return; diff --git a/src/test/ao_quaternion_test.c b/src/test/ao_quaternion_test.c new file mode 100644 index 00000000..0e4b5b07 --- /dev/null +++ b/src/test/ao_quaternion_test.c @@ -0,0 +1,67 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include +#include +#include + +#include "ao_quaternion.h" + +static void +print_q(char *name, struct ao_quaternion *q) +{ + printf ("%8.8s: r%8.5f x%8.5f y%8.5f z%8.5f ", name, + q->r, q->x, q->y, q->z); +} + +int main(int argc, char **argv) +{ + struct ao_quaternion position; + struct ao_quaternion rotation; + struct ao_quaternion little_rotation; + int i; + + /* unit x vector */ + ao_quaternion_init_vector(&position, 1, 0, 0); + + /* zero rotation */ + ao_quaternion_init_zero_rotation(&rotation); + + /* π/16 rotation around Z axis */ + ao_quaternion_init_rotation(&little_rotation, 0, 0, 1, + sin((M_PI/16)/2), + cos((M_PI/16)/2)); + for (i = 0; i <= 16; i++) { + struct ao_quaternion rotated; + + ao_quaternion_rotate(&rotated, &position, &rotation); + print_q("position", &position); + print_q("rotated", &rotated); + print_q("rotation", &rotation); + printf ("\n"); + ao_quaternion_multiply(&rotation, &rotation, &little_rotation); + ao_quaternion_normalize(&rotation, &rotation); + } + return 0; +} + -- cgit v1.2.3 From 351d53836e201834a2d89773a08ab7c2dab2b2f4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 25 Oct 2013 04:34:16 -0700 Subject: altos: Calibrate IMU accelerometers too Average the IMU accelerometer values pointing up and down so that we have a zero-g offset for all three axes. This can then be used to compute which direction the rocket is pointing while sitting on the pad. Signed-off-by: Keith Packard --- src/core/ao.h | 7 +++++- src/core/ao_config.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++ src/core/ao_sample.c | 15 +++++------- src/test/ao_flight_test.c | 10 ++++++++ 4 files changed, 83 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index ea37885e..d12f13a0 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -739,7 +739,7 @@ extern __xdata uint8_t ao_force_freq; #endif #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 14 +#define AO_CONFIG_MINOR 15 #define AO_AES_LEN 16 @@ -773,6 +773,11 @@ struct ao_config { #if HAS_RADIO_AMP uint8_t radio_amp; /* minor version 14 */ #endif +#if HAS_GYRO + uint16_t accel_zero_along; /* minor version 15 */ + uint16_t accel_zero_across; /* minor version 15 */ + uint16_t accel_zero_through; /* minor version 15 */ +#endif }; #define AO_IGNITE_MODE_DUAL 0 diff --git a/src/core/ao_config.c b/src/core/ao_config.c index b480e14c..82faf32b 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -155,6 +155,19 @@ _ao_config_get(void) #if HAS_RADIO_AMP if (minor < 14) ao_config.radio_amp = AO_CONFIG_DEFAULT_RADIO_AMP; +#endif +#if HAS_GYRO + if (minor < 15) { + ao_config.accel_zero_along = 0; + ao_config.accel_zero_across = 0; + ao_config.accel_zero_through = 0; + + /* Reset the main accel offsets to force + * re-calibration + */ + ao_config.accel_plus_g = 0; + ao_config.accel_minus_g = 0; + } #endif ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; @@ -275,17 +288,34 @@ ao_config_accel_calibrate_show(void) __reentrant { printf("Accel cal +1g: %d -1g: %d\n", ao_config.accel_plus_g, ao_config.accel_minus_g); +#if HAS_GYRO + printf ("IMU cal along %d across %d through %d\n", + ao_config.accel_zero_along, + ao_config.accel_zero_across, + ao_config.accel_zero_through); +#endif } #define ACCEL_CALIBRATE_SAMPLES 1024 #define ACCEL_CALIBRATE_SHIFT 10 +#if HAS_GYRO +static int16_t accel_cal_along; +static int16_t accel_cal_across; +static int16_t accel_cal_through; +#endif + static int16_t ao_config_accel_calibrate_auto(char *orientation) __reentrant { uint16_t i; int32_t accel_total; uint8_t cal_data_ring; +#if HAS_GYRO + int32_t accel_along_total = 0; + int32_t accel_across_total = 0; + int32_t accel_through_total = 0; +#endif printf("Orient antenna %s and press a key...", orientation); flush(); @@ -299,10 +329,20 @@ ao_config_accel_calibrate_auto(char *orientation) __reentrant ao_sleep(DATA_TO_XDATA(&ao_sample_data)); while (i && cal_data_ring != ao_sample_data) { accel_total += (int32_t) ao_data_accel(&ao_data_ring[cal_data_ring]); +#if HAS_GYRO + accel_along_total += (int32_t) ao_data_along(&ao_data_ring[cal_data_ring]); + accel_across_total += (int32_t) ao_data_across(&ao_data_ring[cal_data_ring]); + accel_through_total += (int32_t) ao_data_through(&ao_data_ring[cal_data_ring]); +#endif cal_data_ring = ao_data_ring_next(cal_data_ring); i--; } } +#if HAS_GYRO + accel_cal_along = accel_along_total >> ACCEL_CALIBRATE_SHIFT; + accel_cal_across = accel_across_total >> ACCEL_CALIBRATE_SHIFT; + accel_cal_through = accel_through_total >> ACCEL_CALIBRATE_SHIFT; +#endif return accel_total >> ACCEL_CALIBRATE_SHIFT; } @@ -310,12 +350,28 @@ void ao_config_accel_calibrate_set(void) __reentrant { int16_t up, down; +#if HAS_GYRO + int16_t accel_along_up, accel_along_down; + int16_t accel_across_up, accel_across_down; + int16_t accel_through_up, accel_through_down; +#endif + ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; if (ao_cmd_lex_i == 0) { up = ao_config_accel_calibrate_auto("up"); +#if HAS_GYRO + accel_along_up = accel_cal_along; + accel_across_up = accel_cal_across; + accel_through_up = accel_cal_through; +#endif down = ao_config_accel_calibrate_auto("down"); +#if HAS_GYRO + accel_along_down = accel_cal_along; + accel_across_down = accel_cal_across; + accel_through_down = accel_cal_through; +#endif } else { up = ao_cmd_lex_i; ao_cmd_decimal(); @@ -331,6 +387,11 @@ ao_config_accel_calibrate_set(void) __reentrant _ao_config_edit_start(); ao_config.accel_plus_g = up; ao_config.accel_minus_g = down; +#if HAS_GYRO + ao_config.accel_zero_along = (accel_along_up + accel_along_down) / 2; + ao_config.accel_zero_across = (accel_across_up + accel_across_down) / 2; + ao_config.accel_zero_through = (accel_through_up + accel_through_down) / 2; +#endif _ao_config_edit_finish(); } #endif /* HAS_ACCEL */ diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c index 676e0ffd..a9d50cb2 100644 --- a/src/core/ao_sample.c +++ b/src/core/ao_sample.c @@ -139,19 +139,16 @@ ao_sample_preflight_set(void) /* No rotation yet */ ao_quaternion_init_zero_rotation(&ao_rotation); - /* XXX Assume we're pointing straight up for now */ + /* Take the pad IMU acceleration values and compute our current direction + */ ao_quaternion_init_vector(&ao_pad_orientation, - ao_ground_accel_across, - ao_ground_accel_through, - -ao_ground_accel_along); + ao_ground_accel_across - ao_config.accel_zero_across, + ao_ground_accel_through - ao_config.accel_zero_through, + -ao_ground_accel_along - ao_config.accel_zero_along); + ao_quaternion_normalize(&ao_pad_orientation, &ao_pad_orientation); - printf ("pad r%8.5f x%8.5f y%8.5f z%8.5f\n", - ao_pad_orientation.r, - ao_pad_orientation.x, - ao_pad_orientation.y, - ao_pad_orientation.z); #endif nsamples = 0; } diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index e2f63e34..7f18c80e 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -234,6 +234,9 @@ struct ao_config { uint16_t apogee_lockout; #if TELEMEGA struct ao_pyro pyro[AO_PYRO_NUM]; /* minor version 12 */ + int16_t accel_zero_along; + int16_t accel_zero_across; + int16_t accel_zero_through; #endif }; @@ -719,6 +722,13 @@ ao_sleep(void *wchan) } else if (nword >= 6 && strcmp(words[0], "Accel") == 0) { ao_config.accel_plus_g = atoi(words[3]); ao_config.accel_minus_g = atoi(words[5]); +#ifdef TELEMEGA + } else if (nword >= 8 && strcmp(words[0], "IMU") == 0) { + ao_config.accel_zero_along = atoi(words[3]); + ao_config.accel_zero_across = atoi(words[5]); + ao_config.accel_zero_through = atoi(words[7]); + printf ("%d %d %d\n", ao_config.accel_zero_along, ao_config.accel_zero_across, ao_config.accel_zero_through); +#endif } else if (nword >= 4 && strcmp(words[0], "Main") == 0) { ao_config.main_deploy = atoi(words[2]); } else if (nword >= 3 && strcmp(words[0], "Apogee") == 0 && -- cgit v1.2.3 From e923e11e185fd42d2a83e18b3d13bd839a72b1aa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 Oct 2013 22:44:49 -0700 Subject: altos: IMU accel calibration values need to be signed The MPU6000 reports signed values. Signed-off-by: Keith Packard --- src/core/ao.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index d12f13a0..0b634a79 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -774,9 +774,9 @@ struct ao_config { uint8_t radio_amp; /* minor version 14 */ #endif #if HAS_GYRO - uint16_t accel_zero_along; /* minor version 15 */ - uint16_t accel_zero_across; /* minor version 15 */ - uint16_t accel_zero_through; /* minor version 15 */ + int16_t accel_zero_along; /* minor version 15 */ + int16_t accel_zero_across; /* minor version 15 */ + int16_t accel_zero_through; /* minor version 15 */ #endif }; -- cgit v1.2.3 From 616977d2955da13383a1869b9ccdb07338172109 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 Oct 2013 23:10:13 -0700 Subject: altos: Mark arguments to quaternion functions as const Lets us pass constants without the compile whinging Signed-off-by: Keith Packard --- src/core/ao_quaternion.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/core/ao_quaternion.h b/src/core/ao_quaternion.h index f4b8aaa4..1c0617c4 100644 --- a/src/core/ao_quaternion.h +++ b/src/core/ao_quaternion.h @@ -26,8 +26,8 @@ struct ao_quaternion { }; static inline void ao_quaternion_multiply(struct ao_quaternion *r, - struct ao_quaternion *a, - struct ao_quaternion *b) + const struct ao_quaternion *a, + const struct ao_quaternion *b) { struct ao_quaternion t; #define T(_a,_b) (((a)->_a) * ((b)->_b)) @@ -40,7 +40,7 @@ static inline void ao_quaternion_multiply(struct ao_quaternion *r, } static inline void ao_quaternion_conjugate(struct ao_quaternion *r, - struct ao_quaternion *a) + const struct ao_quaternion *a) { r->r = a->r; r->x = -a->x; @@ -48,7 +48,7 @@ static inline void ao_quaternion_conjugate(struct ao_quaternion *r, r->z = -a->z; } -static inline float ao_quaternion_normal(struct ao_quaternion *a) +static inline float ao_quaternion_normal(const struct ao_quaternion *a) { #define S(_a) (((a)->_a) * ((a)->_a)) return S(r) + S(x) + S(y) + S(z); @@ -56,7 +56,7 @@ static inline float ao_quaternion_normal(struct ao_quaternion *a) } static inline void ao_quaternion_scale(struct ao_quaternion *r, - struct ao_quaternion *a, + const struct ao_quaternion *a, float b) { r->r = a->r * b; @@ -66,7 +66,7 @@ static inline void ao_quaternion_scale(struct ao_quaternion *r, } static inline void ao_quaternion_normalize(struct ao_quaternion *r, - struct ao_quaternion *a) + const struct ao_quaternion *a) { float n = ao_quaternion_normal(a); -- cgit v1.2.3 From 3b25860b5b3b69642928dd9c30dec4b4b937a88c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 Oct 2013 23:11:09 -0700 Subject: altos: Add some comments describing quaternion multiplication Signed-off-by: Keith Packard --- src/core/ao_quaternion.h | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'src') diff --git a/src/core/ao_quaternion.h b/src/core/ao_quaternion.h index 1c0617c4..6a701a18 100644 --- a/src/core/ao_quaternion.h +++ b/src/core/ao_quaternion.h @@ -31,6 +31,39 @@ static inline void ao_quaternion_multiply(struct ao_quaternion *r, { struct ao_quaternion t; #define T(_a,_b) (((a)->_a) * ((b)->_b)) + +/* + * Quaternions + * + * ii = jj = kk = ijk = -1; + * + * kji = 1; + * + * ij = k; ji = -k; + * kj = -i; jk = i; + * ik = -j; ki = j; + * + * Multiplication p * q: + * + * (pr + ipx + jpy + kpz) (qr + iqx + jqy + kqz) = + * + * ( pr * qr + pr * iqx + pr * jqy + pr * kqz) + + * (ipx * qr + ipx * iqx + ipx * jqy + ipx * kqz) + + * (jpy * qr + jpy * iqx + jpy * jqy + jpy * kqz) + + * (kpz * qr + kpz * iqx + kpz * jqy + kpz * kqz) = + * + * + * (pr * qr) + i(pr * qx) + j(pr * qy) + k(pr * qz) + + * i(px * qr) - (px * qx) + k(px * qy) - j(px * qz) + + * j(py * qr) - k(py * qx) - (py * qy) + i(py * qz) + + * k(pz * qr) + j(pz * qx) - i(pz * qy) - (pz * qz) = + * + * 1 * ( (pr * qr) - (px * qx) - (py * qy) - (pz * qz) ) + + * i * ( (pr * qx) + (px * qr) + (py * qz) - (pz * qy) ) + + * j * ( (pr * qy) - (px * qz) + (py * qr) + (pz * qx) ) + + * k * ( (pr * qz) + (px * qy) - (py * qx) + (pz * qr); + */ + t.r = T(r,r) - T(x,x) - T(y,y) - T(z,z); t.x = T(r,x) + T(x,r) + T(y,z) - T(z,y); t.y = T(r,y) - T(x,z) + T(y,r) + T(z,x); -- cgit v1.2.3 From c10cb9d31765e6ef0ba737bc484c5aed22a332f9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 Oct 2013 23:11:37 -0700 Subject: altos: Add functions to init quaternions from vector pairs and euler angles MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Our low sampling rate means that the "cheap" hack for integrating quaternion rotations by using sin(x) ≃ x doesn't work, so instead we have to compute the partial rotation the hard way. Signed-off-by: Keith Packard --- src/core/ao_quaternion.h | 97 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 94 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/core/ao_quaternion.h b/src/core/ao_quaternion.h index 6a701a18..6c885500 100644 --- a/src/core/ao_quaternion.h +++ b/src/core/ao_quaternion.h @@ -110,17 +110,68 @@ static inline void ao_quaternion_normalize(struct ao_quaternion *r, } static inline void ao_quaternion_rotate(struct ao_quaternion *r, - struct ao_quaternion *a, - struct ao_quaternion *b) + const struct ao_quaternion *a, + const struct ao_quaternion *b) { struct ao_quaternion c; struct ao_quaternion t; - ao_quaternion_conjugate(&c, b); ao_quaternion_multiply(&t, b, a); + ao_quaternion_conjugate(&c, b); ao_quaternion_multiply(r, &t, &c); } +/* + * Compute a rotation quaternion between two vectors + * + * cos(θ) + u * sin(θ) + * + * where θ is the angle between the two vectors and u + * is a unit vector axis of rotation + */ + +static inline void ao_quaternion_vectors_to_rotation(struct ao_quaternion *r, + const struct ao_quaternion *a, + const struct ao_quaternion *b) +{ + /* + * The cross product will point orthogonally to the two + * vectors, forming our rotation axis. The length will be + * sin(θ), so these values are already multiplied by that. + */ + + float x = a->y * b->z - a->z * b->y; + float y = a->z * b->x - a->x * b->z; + float z = a->x * b->y - a->y * b->x; + + float s_2 = x*x + y*y + z*z; + float s = sqrtf(s_2); + + /* cos(θ) = a · b / (|a| |b|). + * + * a and b are both unit vectors, so the divisor is one + */ + float c = a->x*b->x + a->y*b->y + a->z*b->z; + + float c_half = sqrtf ((1 + c) / 2); + float s_half = sqrtf ((1 - c) / 2); + + /* + * Divide out the sine factor from the + * cross product, then multiply in the + * half sine factor needed for the quaternion + */ + float s_scale = s_half / s; + + r->x = x * s_scale; + r->y = y * s_scale; + r->z = z * s_scale; + + r->r = c_half; + + ao_quaternion_normalize(r, r); +} + static inline void ao_quaternion_init_vector(struct ao_quaternion *r, float x, float y, float z) { @@ -146,4 +197,44 @@ static inline void ao_quaternion_init_zero_rotation(struct ao_quaternion *r) r->x = r->y = r->z = 0; } +/* + * The sincosf from newlib just calls sinf and cosf. This is a bit + * faster, if slightly less precise + */ + +static inline void +ao_sincosf(float a, float *s, float *c) { + float _s = sinf(a); + *s = _s; + *c = sqrtf(1 - _s*_s); +} + +/* + * Initialize a quaternion from 1/2 euler rotation angles (in radians). + * + * Yes, it would be nicer if there were a faster way, but because we + * sample the gyros at only 100Hz, we end up getting angles too large + * to take advantage of sin(x) ≃ x. + * + * We might be able to use just a couple of elements of the sin taylor + * series though, instead of the whole sin function? + */ + +static inline void ao_quaternion_init_half_euler(struct ao_quaternion *r, + float x, float y, float z) +{ + float s_x, c_x; + float s_y, c_y; + float s_z, c_z; + + ao_sincosf(x, &s_x, &c_x); + ao_sincosf(y, &s_y, &c_y); + ao_sincosf(z, &s_z, &c_z); + + r->r = c_x * c_y * c_z + s_x * s_y * s_z; + r->x = s_x * c_y * c_z - c_x * s_y * s_z; + r->y = c_x * s_y * c_z + s_x * c_y * s_z; + r->z = c_x * c_y * s_z - s_x * s_y * c_z; +} + #endif /* _AO_QUATERNION_H_ */ -- cgit v1.2.3 From 58f08c4b3cb9049d0c9cb02cde0d8dbdc3d33920 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 Oct 2013 23:23:59 -0700 Subject: altos: Rename ao_orient to ao_sample_orient Keeps it clear where this name comes from. Signed-off-by: Keith Packard --- src/core/ao_pyro.c | 4 ++-- src/core/ao_sample.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index 24c9fe99..a260aa99 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -115,11 +115,11 @@ ao_pyro_ready(struct ao_pyro *pyro) #if HAS_GYRO case ao_pyro_orient_less: - if (ao_orient <= pyro->orient_less) + if (ao_sample_orient <= pyro->orient_less) continue; break; case ao_pyro_orient_greater: - if (ao_orient >= pyro->orient_greater) + if (ao_sample_orient >= pyro->orient_greater) continue; break; #endif diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c index a9d50cb2..47c5ea2e 100644 --- a/src/core/ao_sample.c +++ b/src/core/ao_sample.c @@ -48,7 +48,7 @@ __pdata accel_t ao_sample_accel_through; __pdata gyro_t ao_sample_roll; __pdata gyro_t ao_sample_pitch; __pdata gyro_t ao_sample_yaw; -__pdata angle_t ao_orient; +__pdata angle_t ao_sample_orient; #endif __data uint8_t ao_sample_data; @@ -134,7 +134,7 @@ ao_sample_preflight_set(void) ao_sample_pitch_sum = 0; ao_sample_yaw_sum = 0; ao_sample_roll_sum = 0; - ao_orient = 0; + ao_sample_orient = 0; /* No rotation yet */ ao_quaternion_init_zero_rotation(&ao_rotation); @@ -212,7 +212,7 @@ ao_sample_rotate(void) ao_quaternion_rotate(&point, &ao_pad_orientation, &ao_rotation); - ao_orient = acosf(point.z) * (float) (180.0/M_PI); + ao_sample_orient = acosf(rotz) * (float) (180.0/M_PI); } #endif @@ -349,7 +349,7 @@ ao_sample_init(void) ao_sample_pitch = 0; ao_sample_yaw = 0; ao_sample_roll = 0; - ao_orient = 0; + ao_sample_orient = 0; #endif ao_sample_data = ao_data_head; ao_preflight = TRUE; -- cgit v1.2.3 From fa7d0ba0efdde3ac9fb4df0589f9ead07b7ffff5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 Oct 2013 23:26:28 -0700 Subject: altos: Keep 9 more bits of average pad IMU gyro data This reduces the offset error by a bit, minimizing gyro drift. Signed-off-by: Keith Packard --- src/core/ao_sample.c | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c index 47c5ea2e..b425aee7 100644 --- a/src/core/ao_sample.c +++ b/src/core/ao_sample.c @@ -70,9 +70,9 @@ __pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ __pdata accel_t ao_ground_accel_along; __pdata accel_t ao_ground_accel_across; __pdata accel_t ao_ground_accel_through; -__pdata gyro_t ao_ground_pitch; -__pdata gyro_t ao_ground_yaw; -__pdata gyro_t ao_ground_roll; +__pdata int32_t ao_ground_pitch; +__pdata int32_t ao_ground_yaw; +__pdata int32_t ao_ground_roll; #endif static __pdata uint8_t ao_preflight; /* in preflight mode */ @@ -125,9 +125,9 @@ ao_sample_preflight_set(void) ao_ground_accel_along = ao_sample_accel_along_sum >> 9; ao_ground_accel_across = ao_sample_accel_across_sum >> 9; ao_ground_accel_through = ao_sample_accel_through_sum >> 9; - ao_ground_pitch = ao_sample_pitch_sum >> 9; - ao_ground_yaw = ao_sample_yaw_sum >> 9; - ao_ground_roll = ao_sample_roll_sum >> 9; + ao_ground_pitch = ao_sample_pitch_sum; + ao_ground_yaw = ao_sample_yaw_sum; + ao_ground_roll = ao_sample_roll_sum; ao_sample_accel_along_sum = 0; ao_sample_accel_across_sum = 0; ao_sample_accel_through_sum = 0; @@ -162,13 +162,9 @@ ao_sample_rotate(void) #else static const float dt = 1/100.0; #endif - float x = ao_mpu6000_gyro(ao_sample_pitch - ao_ground_pitch) * dt; - float y = ao_mpu6000_gyro(ao_sample_yaw - ao_ground_yaw) * dt; - float z = ao_mpu6000_gyro(ao_sample_roll - ao_ground_roll) * dt; - - float n_2, n; - float s, c; - + float x = ao_mpu6000_gyro((float) ((ao_sample_pitch << 9) - ao_ground_pitch) / 512.0f) * dt; + float y = ao_mpu6000_gyro((float) ((ao_sample_yaw << 9) - ao_ground_yaw) / 512.0f) * dt; + float z = ao_mpu6000_gyro((float) ((ao_sample_roll << 9) - ao_ground_roll) / 512.0f) * dt; struct ao_quaternion rot; struct ao_quaternion point; -- cgit v1.2.3 From d96fd33aa8a220d547512eb43c88fc8f5651e39e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 Oct 2013 23:28:50 -0700 Subject: altos: Add sinf to math code Needed for the quaternion gyro tracking code Signed-off-by: Keith Packard --- src/math/math.h | 2 ++ src/math/sf_sin.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 src/math/sf_sin.c (limited to 'src') diff --git a/src/math/math.h b/src/math/math.h index c62f583d..fd543bc2 100644 --- a/src/math/math.h +++ b/src/math/math.h @@ -22,6 +22,8 @@ float acosf(float x); float cosf(float x); +float sinf(float x); + float sqrtf(float x); float fabsf(float x); diff --git a/src/math/sf_sin.c b/src/math/sf_sin.c new file mode 100644 index 00000000..da81845d --- /dev/null +++ b/src/math/sf_sin.c @@ -0,0 +1,62 @@ +/* sf_sin.c -- float version of s_sin.c. + * Conversion to float by Ian Lance Taylor, Cygnus Support, ian@cygnus.com. + */ + +/* + * ==================================================== + * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved. + * + * Developed at SunPro, a Sun Microsystems, Inc. business. + * Permission to use, copy, modify, and distribute this + * software is freely granted, provided that this notice + * is preserved. + * ==================================================== + */ + +#include "fdlibm.h" + +#ifdef __STDC__ + float sinf(float x) +#else + float sinf(x) + float x; +#endif +{ + float y[2],z=0.0; + __int32_t n,ix; + + GET_FLOAT_WORD(ix,x); + + /* |x| ~< pi/4 */ + ix &= 0x7fffffff; + if(ix <= 0x3f490fd8) return __kernel_sinf(x,z,0); + + /* sin(Inf or NaN) is NaN */ + else if (!FLT_UWORD_IS_FINITE(ix)) return x-x; + + /* argument reduction needed */ + else { + n = __ieee754_rem_pio2f(x,y); + switch(n&3) { + case 0: return __kernel_sinf(y[0],y[1],1); + case 1: return __kernel_cosf(y[0],y[1]); + case 2: return -__kernel_sinf(y[0],y[1],1); + default: + return -__kernel_cosf(y[0],y[1]); + } + } +} + +#ifdef _DOUBLE_IS_32BITS + +#ifdef __STDC__ + double sin(double x) +#else + double sin(x) + double x; +#endif +{ + return (double) sinf((float) x); +} + +#endif /* defined(_DOUBLE_IS_32BITS) */ -- cgit v1.2.3 From cdbe8ce33e4a75e85caf07538ed7e997f462b758 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 Oct 2013 23:33:11 -0700 Subject: altos: Fixup for ao_sample_orient rename Signed-off-by: Keith Packard --- src/core/ao_telemetry.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index a2726016..c118d007 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -115,7 +115,7 @@ ao_send_mega_sensor(void) telemetry.generic.tick = packet->tick; telemetry.generic.type = AO_TELEMETRY_MEGA_SENSOR; - telemetry.mega_sensor.orient = ao_orient; + telemetry.mega_sensor.orient = ao_sample_orient; telemetry.mega_sensor.accel = ao_data_accel(packet); telemetry.mega_sensor.pres = ao_data_pres(packet); telemetry.mega_sensor.temp = ao_data_temp(packet); -- cgit v1.2.3 From 06b0c1b768a7d3eae57e66bc9aea25db49f9ea8a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 Oct 2013 23:35:54 -0700 Subject: altos: Compute initial rotation from vertical This initializes the rotation with the angle from vertical, rather than simply recording the off-angle vector. Doing this allows us to accurately track the true orientation of the rocket, instead of just the offset from the initial non-vertical orientation. Signed-off-by: Keith Packard --- src/core/ao_sample.c | 50 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 37 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c index b425aee7..fc8f8680 100644 --- a/src/core/ao_sample.c +++ b/src/core/ao_sample.c @@ -90,7 +90,6 @@ __pdata int32_t ao_sample_pitch_sum; __pdata int32_t ao_sample_yaw_sum; __pdata int32_t ao_sample_roll_sum; static struct ao_quaternion ao_rotation; -static struct ao_quaternion ao_pad_orientation; #endif static void @@ -136,19 +135,30 @@ ao_sample_preflight_set(void) ao_sample_roll_sum = 0; ao_sample_orient = 0; - /* No rotation yet */ - ao_quaternion_init_zero_rotation(&ao_rotation); + struct ao_quaternion orient; /* Take the pad IMU acceleration values and compute our current direction */ - ao_quaternion_init_vector(&ao_pad_orientation, - ao_ground_accel_across - ao_config.accel_zero_across, - ao_ground_accel_through - ao_config.accel_zero_through, - -ao_ground_accel_along - ao_config.accel_zero_along); - - ao_quaternion_normalize(&ao_pad_orientation, - &ao_pad_orientation); - + + ao_quaternion_init_vector(&orient, + (ao_ground_accel_across - ao_config.accel_zero_across), + (ao_ground_accel_through - ao_config.accel_zero_through), + (ao_ground_accel_along - ao_config.accel_zero_along)); + + ao_quaternion_normalize(&orient, + &orient); + + /* Here's up */ + + struct ao_quaternion up = { .r = 0, .x = 0, .y = 0, .z = 1 }; + + if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) + up.z = -1; + + /* Compute rotation to get from up to our current orientation, set + * that as the current rotation vector + */ + ao_quaternion_vectors_to_rotation(&ao_rotation, &up, &orient); #endif nsamples = 0; } @@ -203,10 +213,24 @@ ao_sample_rotate(void) * orientation vector and rotating it by the current total * rotation value. That will be a unit vector pointing along * the airframe axis. The Z value will be the cosine of the - * change in the angle from vertical since boost + * change in the angle from vertical since boost. + * + * rot = ao_rotation * vertical * ao_rotation° + * rot = ao_rotation * (0,0,0,1) * ao_rotation° + * = ((a.z, a.y, -a.x, a.r) * (a.r, -a.x, -a.y, -a.z)) .z + * + * = (-a.z * -a.z) + (a.y * -a.y) - (-a.x * -a.x) + (a.r * a.r) + * = a.z² - a.y² - a.x² + a.r² + * + * rot = ao_rotation * (0, 0, 0, -1) * ao_rotation° + * = ((-a.z, -a.y, a.x, -a.r) * (a.r, -a.x, -a.y, -a.z)) .z + * + * = (a.z * -a.z) + (-a.y * -a.y) - (a.x * -a.x) + (-a.r * a.r) + * = -a.z² + a.y² + a.x² - a.r² */ - ao_quaternion_rotate(&point, &ao_pad_orientation, &ao_rotation); + float rotz; + rotz = ao_rotation.z * ao_rotation.z - ao_rotation.y * ao_rotation.y - ao_rotation.x * ao_rotation.x + ao_rotation.r * ao_rotation.r; ao_sample_orient = acosf(rotz) * (float) (180.0/M_PI); } -- cgit v1.2.3 From 4bebade9e9004bad81df1a423687f3e3f356f1c2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 Oct 2013 23:37:55 -0700 Subject: altos: Correct incremental rotation computation Trying to compute the combined rotation by taking the x/y/z rotations as a vector is a good approximation, but not accurate enough for our application given the large angles we sometimes see. Instead, use a correct-but-expensive function with a pile of transcendental function calls. The STM32L seems to be fast enough at least... Signed-off-by: Keith Packard --- src/core/ao_sample.c | 37 +++++++------------------------------ 1 file changed, 7 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c index fc8f8680..adf8399d 100644 --- a/src/core/ao_sample.c +++ b/src/core/ao_sample.c @@ -164,47 +164,24 @@ ao_sample_preflight_set(void) } #if HAS_GYRO + +#define TIME_DIV 200.0f + static void ao_sample_rotate(void) { #ifdef AO_FLIGHT_TEST - float dt = (ao_sample_tick - ao_sample_prev_tick) / 100.0; + float dt = (ao_sample_tick - ao_sample_prev_tick) / TIME_DIV; #else - static const float dt = 1/100.0; + static const float dt = 1/TIME_DIV; #endif float x = ao_mpu6000_gyro((float) ((ao_sample_pitch << 9) - ao_ground_pitch) / 512.0f) * dt; float y = ao_mpu6000_gyro((float) ((ao_sample_yaw << 9) - ao_ground_yaw) / 512.0f) * dt; float z = ao_mpu6000_gyro((float) ((ao_sample_roll << 9) - ao_ground_roll) / 512.0f) * dt; struct ao_quaternion rot; - struct ao_quaternion point; - - /* The amount of rotation is just the length of the vector. Now, - * here's the trick -- assume that the rotation amount is small. In this case, - * sin(x) ≃ x, so we can just make this the sin. - */ - - n_2 = x*x + y*y + z*z; - n = sqrtf(n_2); - s = n / 2; - if (s > 1) - s = 1; - c = sqrtf(1 - s*s); - - /* Make unit vector */ - if (n > 0) { - x /= n; - y /= n; - z /= n; - } - - /* Now compute the unified rotation quaternion */ - - ao_quaternion_init_rotation(&rot, - x, y, z, - s, c); - /* Integrate with the previous rotation amount */ - ao_quaternion_multiply(&ao_rotation, &ao_rotation, &rot); + ao_quaternion_init_half_euler(&rot, x, y, z); + ao_quaternion_multiply(&ao_rotation, &rot, &ao_rotation); /* And normalize to make sure it remains a unit vector */ ao_quaternion_normalize(&ao_rotation, &ao_rotation); -- cgit v1.2.3 From 3d3fe7e9b6502432868f4430befac871dfea4869 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 Oct 2013 23:42:26 -0700 Subject: altos: Fixup for 32-bit gyro averages Signed-off-by: Keith Packard --- src/core/ao_sample.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/core/ao_sample.h b/src/core/ao_sample.h index 1d1bcc7c..16d4c507 100644 --- a/src/core/ao_sample.h +++ b/src/core/ao_sample.h @@ -113,10 +113,16 @@ extern __pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ extern __pdata accel_t ao_ground_accel_along; extern __pdata accel_t ao_ground_accel_across; extern __pdata accel_t ao_ground_accel_through; -extern __pdata gyro_t ao_ground_pitch; -extern __pdata gyro_t ao_ground_yaw; -extern __pdata gyro_t ao_ground_roll; -extern __pdata angle_t ao_orient; +extern __pdata int32_t ao_ground_pitch; /* * 512 */ +extern __pdata int32_t ao_ground_yaw; /* * 512 */ +extern __pdata int32_t ao_ground_roll; /* * 512 */ +extern __pdata accel_t ao_sample_accel_along; +extern __pdata accel_t ao_sample_accel_across; +extern __pdata accel_t ao_sample_accel_through; +extern __pdata gyro_t ao_sample_roll; +extern __pdata gyro_t ao_sample_pitch; +extern __pdata gyro_t ao_sample_yaw; +extern __pdata angle_t ao_sample_orient; #endif void ao_sample_init(void); -- cgit v1.2.3 From 195fd70cdc7f519cd8d4ac323088ed0b6c188280 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 Oct 2013 23:42:58 -0700 Subject: altos: Change ao_mpu6000_gyro arg to float This lets callers pass more precision than just the original sensor value Signed-off-by: Keith Packard --- src/drivers/ao_mpu6000.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_mpu6000.h b/src/drivers/ao_mpu6000.h index 2241bf80..dc3a9fbf 100644 --- a/src/drivers/ao_mpu6000.h +++ b/src/drivers/ao_mpu6000.h @@ -173,8 +173,8 @@ #define MPU6000_GYRO_FULLSCALE ((float) 2000 * M_PI/180.0) static inline float -ao_mpu6000_gyro(int16_t sensor) { - return (float) sensor * ((float) (MPU6000_GYRO_FULLSCALE / 32767.0)); +ao_mpu6000_gyro(float sensor) { + return sensor * ((float) (MPU6000_GYRO_FULLSCALE / 32767.0)); } #define MPU6000_ACCEL_FULLSCALE 16 -- cgit v1.2.3 From 5d9e715d570b24ac124c30772b11923bd26ed670 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 Oct 2013 23:44:47 -0700 Subject: altos: Update quaternion tests to check vectors_to_rotation Signed-off-by: Keith Packard --- src/test/Makefile | 2 +- src/test/ao_flight_test.c | 3 +- src/test/ao_quaternion_test.c | 121 ++++++++++++++++++++++++++++++++++++------ src/test/plotmm | 22 ++++++-- src/test/run-mm | 59 ++++++++++---------- 5 files changed, 158 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/test/Makefile b/src/test/Makefile index f64a9531..686fde0c 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -5,7 +5,7 @@ PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noi ao_aprs_test ao_micropeak_test ao_fat_test ao_aes_test ao_int64_test \ ao_ms5607_convert_test ao_quaternion_test -INCS=ao_kalman.h ao_ms5607.h ao_log.h ao_data.h altitude-pa.h altitude.h +INCS=ao_kalman.h ao_ms5607.h ao_log.h ao_data.h altitude-pa.h altitude.h ao_quaternion.h KALMAN=make-kalman diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 7f18c80e..952a811a 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -128,6 +128,7 @@ int ao_summary = 0; #define ao_rdf_set(rdf) #define ao_packet_slave_start() #define ao_packet_slave_stop() +#define flush() enum ao_igniter { ao_igniter_drogue = 0, @@ -411,7 +412,7 @@ ao_insert(void) height, accel, #if TELEMEGA - ao_orient, + ao_sample_orient, /* ao_mpu6000_accel(ao_data_static.mpu6000.accel_x), ao_mpu6000_accel(ao_data_static.mpu6000.accel_y), diff --git a/src/test/ao_quaternion_test.c b/src/test/ao_quaternion_test.c index 0e4b5b07..b630f1d3 100644 --- a/src/test/ao_quaternion_test.c +++ b/src/test/ao_quaternion_test.c @@ -27,41 +27,128 @@ #include "ao_quaternion.h" +#if 0 static void print_q(char *name, struct ao_quaternion *q) { printf ("%8.8s: r%8.5f x%8.5f y%8.5f z%8.5f ", name, q->r, q->x, q->y, q->z); } +#endif + +#define STEPS 16 + +#define DEG (1.0f * 3.1415926535f / 180.0f) + +struct ao_rotation { + int steps; + float x, y, z; +}; + +static struct ao_rotation ao_path[] = { + { .steps = 45, .x = 2*DEG, .y = 0, .z = 0 }, + + { .steps = 45, .x = 0, .y = 2*DEG, .z = 0 }, + + { .steps = 45, .x = -2*DEG, .y = 0, .z = 0 }, + + { .steps = 45, .x = 0, .y = -2*DEG, .z = 0 }, +}; + +#define NUM_PATH (sizeof ao_path / sizeof ao_path[0]) + +static int close(float a, float b) { + return fabsf (a - b) < 1e-5; +} + +static int check_quaternion(char *where, struct ao_quaternion *got, struct ao_quaternion *expect) { + if (!close (got->r, expect->r) || + !close (got->x, expect->x) || + !close (got->y, expect->y) || + !close (got->z, expect->z)) + { + printf ("%s: got r%8.5f x%8.5f y%8.5f z%8.5f expect r%8.5f x%8.5f y%8.5f z%8.5f\n", + where, + got->r, got->x, got->y, got->z, + expect->r, expect->x, expect->y, expect->z); + return 1; + } + return 0; +} int main(int argc, char **argv) { struct ao_quaternion position; + struct ao_quaternion position_expect; struct ao_quaternion rotation; + struct ao_quaternion rotated; struct ao_quaternion little_rotation; int i; + int p; + int ret = 0; - /* unit x vector */ - ao_quaternion_init_vector(&position, 1, 0, 0); + /* vector */ + ao_quaternion_init_vector(&position, 1, 1, 1); + ao_quaternion_init_vector(&position_expect, -1, -1, 1); /* zero rotation */ ao_quaternion_init_zero_rotation(&rotation); - /* π/16 rotation around Z axis */ - ao_quaternion_init_rotation(&little_rotation, 0, 0, 1, - sin((M_PI/16)/2), - cos((M_PI/16)/2)); - for (i = 0; i <= 16; i++) { - struct ao_quaternion rotated; - - ao_quaternion_rotate(&rotated, &position, &rotation); - print_q("position", &position); - print_q("rotated", &rotated); - print_q("rotation", &rotation); - printf ("\n"); - ao_quaternion_multiply(&rotation, &rotation, &little_rotation); - ao_quaternion_normalize(&rotation, &rotation); +#define dump() do { \ + \ + ao_quaternion_rotate(&rotated, &position, &rotation); \ + print_q("rotated", &rotated); \ + print_q("rotation", &rotation); \ + printf ("\n"); \ + } while (0) + +// dump(); + + for (p = 0; p < NUM_PATH; p++) { + ao_quaternion_init_half_euler(&little_rotation, + ao_path[p].x / 2.0f, + ao_path[p].y / 2.0f, + ao_path[p].z / 2.0f); +// printf ("\t\tx: %8.4f, y: %8.4f, z: %8.4f ", ao_path[p].x, ao_path[p].y, ao_path[p].z); +// print_q("step", &little_rotation); +// printf("\n"); + for (i = 0; i < ao_path[p].steps; i++) { + ao_quaternion_multiply(&rotation, &little_rotation, &rotation); + + ao_quaternion_normalize(&rotation, &rotation); + +// dump(); + } } - return 0; + + ao_quaternion_rotate(&rotated, &position, &rotation); + + ret += check_quaternion("rotation", &rotated, &position_expect); + + struct ao_quaternion vertical; + struct ao_quaternion angle; + struct ao_quaternion rot; + + ao_quaternion_init_vector(&vertical, 0, 0, 1); + ao_quaternion_init_vector(&angle, 0, 0, 1); + + ao_quaternion_init_half_euler(&rot, + M_PI * 3.0 / 8.0 , 0, 0); + + ao_quaternion_rotate(&angle, &angle, &rot); + + struct ao_quaternion rot_compute; + + ao_quaternion_vectors_to_rotation(&rot_compute, &vertical, &angle); + + ret += check_quaternion("vector rotation", &rot_compute, &rot); + + struct ao_quaternion rotd; + + ao_quaternion_rotate(&rotd, &vertical, &rot_compute); + + ret += check_quaternion("vector rotated", &rotd, &angle); + + return ret; } diff --git a/src/test/plotmm b/src/test/plotmm index 5f5bd2ca..bfe15f4c 100755 --- a/src/test/plotmm +++ b/src/test/plotmm @@ -1,3 +1,19 @@ +#!/bin/sh + +case $# in +1) + file="$1" + title="$1" + ;; +2) + file="$1" + title="$2" + ;; +*) + echo "Usage: $0 " + exit 1 +esac + gnuplot -persist << EOF set ylabel "altitude (m)" set y2label "angle (d)" @@ -5,7 +21,7 @@ set xlabel "time (s)" set xtics border out nomirror set ytics border out nomirror set y2tics border out nomirror -plot "$1" using 1:3 with lines axes x1y1 title "raw height",\ -"$1" using 1:9 with lines axes x1y2 title "angle",\ -"$1" using 1:11 with lines axes x1y2 title "qangle" +set title "$title" +plot "$file" using 1:3 with lines axes x1y1 title "raw height",\ +"$file" using 1:7 with lines axes x1y2 title "angle" EOF diff --git a/src/test/run-mm b/src/test/run-mm index 6f3d97a2..ae5e5f42 100755 --- a/src/test/run-mm +++ b/src/test/run-mm @@ -3,15 +3,20 @@ DIR=~/misc/rockets/flights for i in "$@"; do -case "$i" in - */*) - file="$i" - ;; - *) - file="$DIR/$i" - ;; -esac -./ao_flight_test_mm "$file" > run-out.mm + case "$i" in + */*) + file="$i" + ;; + *) + file="$DIR/$i" + ;; + esac + base=`basename "$i" .eeprom` + + ./ao_flight_test_mm "$file" > $base.plot + + sh ./plotmm $base.plot `basename "$file"` +done #./ao_flight_test_accel "$file" > run-out.accel #"run-out.accel" using 1:9 with lines lt 4 axes x1y1 title "accel height",\ @@ -21,21 +26,21 @@ esac #"run-out.accel" using 1:17 with lines lt 4 axes x1y1 title "accel main",\ # -gnuplot << EOF -set ylabel "altitude (m)" -set y2label "velocity (m/s), acceleration(m/s²)" -set xlabel "time (s)" -set xtics border out nomirror -set ytics border out nomirror -set y2tics border out nomirror -set title "$i" -plot "run-out.mm" using 1:3 with lines lw 2 lt 1 axes x1y1 title "raw height",\ -"run-out.mm" using 1:5 with lines lw 2 lt 1 axes x1y2 title "raw accel",\ -"run-out.mm" using 1:21 with lines lt 2 axes x1y1 title "mm height",\ -"run-out.mm" using 1:23 with lines lt 2 axes x1y2 title "mm speed",\ -"run-out.mm" using 1:25 with lines lt 2 axes x1y2 title "mm accel",\ -"run-out.mm" using 1:29 with lines lt 2 axes x1y1 title "mm drogue",\ -"run-out.mm" using 1:31 with lines lt 2 axes x1y1 title "mm main" -pause mouse close -EOF -done \ No newline at end of file +#gnuplot << EOF +#set ylabel "altitude (m)" +#set y2label "velocity (m/s), acceleration(m/s²)" +#set xlabel "time (s)" +#set xtics border out nomirror +#set ytics border out nomirror +#set y2tics border out nomirror +#set title "$i" +#plot "run-out.mm" using 1:3 with lines lw 2 lt 1 axes x1y1 title "raw height",\ +#"run-out.mm" using 1:5 with lines lw 2 lt 1 axes x1y2 title "raw accel",\ +#"run-out.mm" using 1:21 with lines lt 2 axes x1y1 title "mm height",\ +#"run-out.mm" using 1:23 with lines lt 2 axes x1y2 title "mm speed",\ +#"run-out.mm" using 1:25 with lines lt 2 axes x1y2 title "mm accel",\ +#"run-out.mm" using 1:29 with lines lt 2 axes x1y1 title "mm drogue",\ +#"run-out.mm" using 1:31 with lines lt 2 axes x1y1 title "mm main" +#pause mouse close +#EOF +#done \ No newline at end of file -- cgit v1.2.3 From 9b0ce8ca65d76b9cf55dfff002e13ce2fbb5f7fc Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Sun, 27 Oct 2013 23:45:48 -0700 Subject: altos: Add orientation test when HAS_FLIGHT_DEBUG is set This just dumps the current orientation to stdout so you can monitor it in real time Signed-off-by: Keith Packard <keithp@keithp.com> --- src/core/ao_flight.c | 21 +++++++++++++++++++++ src/core/ao_flight.h | 3 ++- 2 files changed, 23 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index 240b348a..4a53bdc6 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -364,6 +364,18 @@ ao_flight(void) ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; } break; +#if HAS_FLIGHT_DEBUG + case ao_flight_test: +#if HAS_GYRO + printf ("angle %4d pitch %7d yaw %7d roll %7d\n", + ao_sample_orient, + ((ao_sample_pitch << 9) - ao_ground_pitch) >> 9, + ((ao_sample_yaw << 9) - ao_ground_yaw) >> 9, + ((ao_sample_roll << 9) - ao_ground_roll) >> 9); +#endif + flush(); + break; +#endif /* HAS_FLIGHT_DEBUG */ default: break; } @@ -414,8 +426,17 @@ ao_flight_dump(void) printf (" error_avg %d\n", ao_error_h_sq_avg); } +static void +ao_gyro_test(void) +{ + ao_flight_state = ao_flight_test; + ao_getchar(); + ao_flight_state = ao_flight_idle; +} + __code struct ao_cmds ao_flight_cmds[] = { { ao_flight_dump, "F\0Dump flight status" }, + { ao_gyro_test, "G\0Test gyro code" }, { 0, NULL }, }; #endif diff --git a/src/core/ao_flight.h b/src/core/ao_flight.h index b80202f0..ac3e9cfb 100644 --- a/src/core/ao_flight.h +++ b/src/core/ao_flight.h @@ -33,7 +33,8 @@ enum ao_flight_state { ao_flight_drogue = 6, ao_flight_main = 7, ao_flight_landed = 8, - ao_flight_invalid = 9 + ao_flight_invalid = 9, + ao_flight_test = 10 }; extern __pdata enum ao_flight_state ao_flight_state; -- cgit v1.2.3 From e838bd2847e5684ce93b6f7cbe736ebed681c3c6 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Sun, 27 Oct 2013 23:46:54 -0700 Subject: altos: Make telemega v0.1 compile with new quaternion code Adds the necessary math code Signed-off-by: Keith Packard <keithp@keithp.com> --- src/telemega-v0.1/Makefile | 17 +++++++++++++++++ src/telemega-v0.1/ao_pins.h | 2 -- 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/telemega-v0.1/Makefile b/src/telemega-v0.1/Makefile index bbf46f3c..7acaedd2 100644 --- a/src/telemega-v0.1/Makefile +++ b/src/telemega-v0.1/Makefile @@ -25,6 +25,8 @@ INC = \ ao_task.h \ ao_whiten.h \ ao_sample_profile.h \ + ao_quaternion.h \ + math.h \ ao_mpu.h \ stm32l.h \ Makefile @@ -44,6 +46,20 @@ INC = \ #STACK_GUARD=ao_mpu_stm.c #STACK_GUARD_DEF=-DHAS_STACK_GUARD=1 +MATH_SRC=\ + ef_acos.c \ + ef_sqrt.c \ + ef_rem_pio2.c \ + kf_cos.c \ + kf_sin.c \ + kf_rem_pio2.c \ + sf_copysign.c \ + sf_cos.c \ + sf_sin.c \ + sf_fabs.c \ + sf_floor.c \ + sf_scalbn.c + ALTOS_SRC = \ ao_boot_chain.c \ ao_interrupt.c \ @@ -95,6 +111,7 @@ ALTOS_SRC = \ ao_aprs.c \ $(PROFILE) \ $(SAMPLE_PROFILE) \ + $(MATH_SRC) \ $(STACK_GUARD) PRODUCT=TeleMega-v0.1 diff --git a/src/telemega-v0.1/ao_pins.h b/src/telemega-v0.1/ao_pins.h index 78e887c3..11934bd2 100644 --- a/src/telemega-v0.1/ao_pins.h +++ b/src/telemega-v0.1/ao_pins.h @@ -319,8 +319,6 @@ struct ao_adc { #define AO_MPU6000_INT_PIN 13 #define AO_MPU6000_I2C_INDEX STM_I2C_INDEX(1) -#define HAS_HIGHG_ACCEL 0 - /* * mma655x */ -- cgit v1.2.3 From 7c1c6728bce4237ca3a8f6fde01356697a465dfd Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Sun, 27 Oct 2013 23:47:27 -0700 Subject: altos: Make telemega v0.3 compile with new quaternion code Adds lots more math code Signed-off-by: Keith Packard <keithp@keithp.com> --- src/telemega-v0.3/Makefile | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/telemega-v0.3/Makefile b/src/telemega-v0.3/Makefile index 2f460105..01209f7d 100644 --- a/src/telemega-v0.3/Makefile +++ b/src/telemega-v0.3/Makefile @@ -25,6 +25,8 @@ INC = \ ao_task.h \ ao_whiten.h \ ao_sample_profile.h \ + ao_quaternion.h \ + math.h \ ao_mpu.h \ stm32l.h \ math.h \ @@ -47,17 +49,17 @@ INC = \ MATH_SRC=\ ef_acos.c \ - ef_sqrt.c - -# ef_rem_pio2.c \ -# kf_cos.c \ -# kf_sin.c \ -# kf_rem_pio2.c \ -# sf_copysign.c \ -# sf_cos.c \ -# sf_fabs.c \ -# sf_floor.c \ -# sf_scalbn.c + ef_sqrt.c \ + ef_rem_pio2.c \ + kf_cos.c \ + kf_sin.c \ + kf_rem_pio2.c \ + sf_copysign.c \ + sf_cos.c \ + sf_fabs.c \ + sf_floor.c \ + sf_scalbn.c \ + sf_sin.c ALTOS_SRC = \ ao_boot_chain.c \ -- cgit v1.2.3 From d3628bd2dd3612065792aef6c7ae5bc967b4f081 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Mon, 28 Oct 2013 00:24:59 -0700 Subject: altos: sample profile address range was too narrow The range was cranked down at some point to diagnose issues within the task scheduler. Unfortunately, that change got merged, which meant that general profiling lost information outside of the lower 4kB of code. Signed-off-by: Keith Packard <keithp@keithp.com> --- src/core/ao_sample_profile.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/ao_sample_profile.c b/src/core/ao_sample_profile.c index e682bd98..d3743d12 100644 --- a/src/core/ao_sample_profile.c +++ b/src/core/ao_sample_profile.c @@ -24,11 +24,11 @@ #endif #ifndef AO_SAMPLE_PROFILE_HIGH_PC -#define AO_SAMPLE_PROFILE_HIGH_PC 0x08003000 +#define AO_SAMPLE_PROFILE_HIGH_PC 0x0800f000 #endif #ifndef AO_SAMPLE_PROFILE_SHIFT -#define AO_SAMPLE_PROFILE_SHIFT 3 +#define AO_SAMPLE_PROFILE_SHIFT 6 #endif #define AO_SAMPLE_PROFILE_RANGE (AO_SAMPLE_PROFILE_HIGH_PC - AO_SAMPLE_PROFILE_LOW_PC) -- cgit v1.2.3 From 29b48b63305881471d9b97ef3fb236af03cb79f5 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Mon, 28 Oct 2013 00:36:13 -0700 Subject: altos: Don't hold GPS mutex while waiting for GPS data in report code Oops. This kinda breaks anyone else waiting for GPS data Signed-off-by: Keith Packard <keithp@keithp.com> --- src/core/ao_gps_report_mega.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_gps_report_mega.c b/src/core/ao_gps_report_mega.c index e2adbfbc..a66068ab 100644 --- a/src/core/ao_gps_report_mega.c +++ b/src/core/ao_gps_report_mega.c @@ -29,9 +29,9 @@ ao_gps_report_mega(void) uint8_t c, n, i; for (;;) { - ao_mutex_get(&ao_gps_mutex); while (!(new = ao_gps_new)) ao_sleep(&ao_gps_new); + ao_mutex_get(&ao_gps_mutex); if (new & AO_GPS_NEW_DATA) ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); if (new & AO_GPS_NEW_TRACKING) -- cgit v1.2.3 From bdd6244d8b4a55c9aa4fb79b0cb1a0727afbc2ac Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Tue, 12 Nov 2013 14:01:55 +0900 Subject: altos: Add orientation tracking to ao_flight_test Shows calculated offset from vertical in ao_flight_test output Signed-off-by: Keith Packard <keithp@keithp.com> --- src/core/ao_data.h | 12 +++++ src/core/ao_quaternion.h | 9 ++++ src/test/ao_flight_test.c | 111 +++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 127 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/core/ao_data.h b/src/core/ao_data.h index 5a232885..e1d8a139 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -319,4 +319,16 @@ typedef int16_t angle_t; /* in degrees */ #endif +#if !HAS_MAG && HAS_HMC5883 + +#define HAS_MAG 1 + +typedef int16_t ao_mag_t; /* in raw sample units */ + +#define ao_data_mag_along(packet) ((packet)->hmc5883.x) +#define ao_data_mag_across(packet) ((packet)->hmc5883.y) +#define ao_data_mag_through(packet) ((packet)->hmc5883.z) + +#endif + #endif /* _AO_DATA_H_ */ diff --git a/src/core/ao_quaternion.h b/src/core/ao_quaternion.h index 6c885500..044f1607 100644 --- a/src/core/ao_quaternion.h +++ b/src/core/ao_quaternion.h @@ -109,6 +109,15 @@ static inline void ao_quaternion_normalize(struct ao_quaternion *r, *r = *a; } +static inline float ao_quaternion_dot(const struct ao_quaternion *a, + const struct ao_quaternion *b) +{ +#define T(_a) (((a)->_a) * ((b)->_a)) + return T(r) + T(x) + T(y) + T(z); +#undef T +} + + static inline void ao_quaternion_rotate(struct ao_quaternion *r, const struct ao_quaternion *a, const struct ao_quaternion *b) diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 952a811a..452f5b75 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -48,6 +48,7 @@ int ao_gps_new; #define HAS_MS5607 1 #define HAS_MPU6000 1 #define HAS_MMA655X 1 +#define HAS_HMC5883 1 struct ao_adc { int16_t sense[AO_ADC_NUM_SENSE]; @@ -349,6 +350,23 @@ ao_test_exit(void) exit(0); } +#ifdef TELEMEGA +struct ao_azel { + int az; + int el; +}; + +static void +azel (struct ao_azel *r, struct ao_quaternion *q) +{ + double v; + + r->az = floor (atan2(q->y, q->x) * 180/M_PI + 0.5); + v = sqrt (q->x*q->x + q->y*q->y); + r->el = floor (atan2(q->z, v) * 180/M_PI + 0.5); +} +#endif + void ao_insert(void) { @@ -402,10 +420,86 @@ ao_insert(void) } if (!ao_summary) { +#if TELEMEGA + static struct ao_quaternion ao_ground_mag; + static int ao_ground_mag_set; + + if (!ao_ground_mag_set) { + ao_quaternion_init_vector (&ao_ground_mag, + ao_data_mag_across(&ao_data_static), + ao_data_mag_through(&ao_data_static), + ao_data_mag_along(&ao_data_static)); + ao_quaternion_normalize(&ao_ground_mag, &ao_ground_mag); + ao_quaternion_rotate(&ao_ground_mag, &ao_ground_mag, &ao_rotation); + ao_ground_mag_set = 1; + } + + struct ao_quaternion ao_mag, ao_mag_rot; + + ao_quaternion_init_vector(&ao_mag, + ao_data_mag_across(&ao_data_static), + ao_data_mag_through(&ao_data_static), + ao_data_mag_along(&ao_data_static)); + + ao_quaternion_normalize(&ao_mag, &ao_mag); + ao_quaternion_rotate(&ao_mag_rot, &ao_mag, &ao_rotation); + + float ao_dot; + int ao_mag_angle; + + ao_dot = ao_quaternion_dot(&ao_mag_rot, &ao_ground_mag); + + struct ao_azel ground_azel, mag_azel, rot_azel; + + azel(&ground_azel, &ao_ground_mag); + azel(&mag_azel, &ao_mag); + azel(&rot_azel, &ao_mag_rot); + + ao_mag_angle = floor (acos(ao_dot) * 180 / M_PI + 0.5); + + static struct ao_quaternion ao_x = { .r = 0, .x = 1, .y = 0, .z = 0 }; + struct ao_quaternion ao_out; + + ao_quaternion_rotate(&ao_out, &ao_x, &ao_rotation); + + int out = floor (atan2(ao_out.y, ao_out.x) * 180 / M_PI); + + printf ("%7.2f state %-8.8s height %8.4f tilt %4d rot %4d mag_tilt %4d mag_rot %4d\n", + time, + ao_state_names[ao_flight_state], + ao_k_height / 65536.0, + ao_sample_orient, out, + mag_azel.el, + mag_azel.az); + + +#if 0 + printf ("\t\tstate %-8.8s ground az: %4d el %4d mag az %4d el %4d rot az %4d el %4d el_diff %4d az_diff %4d angle %4d tilt %4d ground %8.5f %8.5f %8.5f cur %8.5f %8.5f %8.5f rot %8.5f %8.5f %8.5f\n", + ao_state_names[ao_flight_state], + ground_azel.az, ground_azel.el, + mag_azel.az, mag_azel.el, + rot_azel.az, rot_azel.el, + ground_azel.el - rot_azel.el, + ground_azel.az - rot_azel.az, + ao_mag_angle, + ao_sample_orient, + ao_ground_mag.x, + ao_ground_mag.y, + ao_ground_mag.z, + ao_mag.x, + ao_mag.y, + ao_mag.z, + ao_mag_rot.x, + ao_mag_rot.y, + ao_mag_rot.z); +#endif +#endif + +#if 0 printf("%7.2f height %8.2f accel %8.3f " #if TELEMEGA "angle %5d " -/* "accel_x %8.3f accel_y %8.3f accel_z %8.3f gyro_x %8.3f gyro_y %8.3f gyro_z %8.3f " */ + "accel_x %8.3f accel_y %8.3f accel_z %8.3f gyro_x %8.3f gyro_y %8.3f gyro_z %8.3f mag_x %8d mag_y %8d, mag_z %8d mag_angle %4d " #endif "state %-8.8s k_height %8.2f k_speed %8.3f k_accel %8.3f avg_height %5d drogue %4d main %4d error %5d\n", time, @@ -413,14 +507,17 @@ ao_insert(void) accel, #if TELEMEGA ao_sample_orient, -/* + ao_mpu6000_accel(ao_data_static.mpu6000.accel_x), ao_mpu6000_accel(ao_data_static.mpu6000.accel_y), ao_mpu6000_accel(ao_data_static.mpu6000.accel_z), ao_mpu6000_gyro(ao_data_static.mpu6000.gyro_x - ao_ground_mpu6000.gyro_x), ao_mpu6000_gyro(ao_data_static.mpu6000.gyro_y - ao_ground_mpu6000.gyro_y), ao_mpu6000_gyro(ao_data_static.mpu6000.gyro_z - ao_ground_mpu6000.gyro_z), -*/ + ao_data_static.hmc5883.x, + ao_data_static.hmc5883.y, + ao_data_static.hmc5883.z, + ao_mag_angle, #endif ao_state_names[ao_flight_state], ao_k_height / 65536.0, @@ -430,6 +527,7 @@ ao_insert(void) drogue_height, main_height, ao_error_h_sq_avg); +#endif // if (ao_flight_state == ao_flight_landed) // ao_test_exit(); @@ -659,11 +757,14 @@ ao_sleep(void *wchan) ao_data_static.ms5607_raw.temp = int32(bytes, 4); ao_ms5607_convert(&ao_data_static.ms5607_raw, &value); ao_data_static.mpu6000.accel_x = int16(bytes, 8); - ao_data_static.mpu6000.accel_y = -int16(bytes, 10); + ao_data_static.mpu6000.accel_y = int16(bytes, 10); ao_data_static.mpu6000.accel_z = int16(bytes, 12); ao_data_static.mpu6000.gyro_x = int16(bytes, 14); - ao_data_static.mpu6000.gyro_y = -int16(bytes, 16); + ao_data_static.mpu6000.gyro_y = int16(bytes, 16); ao_data_static.mpu6000.gyro_z = int16(bytes, 18); + ao_data_static.hmc5883.x = int16(bytes, 20); + ao_data_static.hmc5883.y = int16(bytes, 22); + ao_data_static.hmc5883.z = int16(bytes, 24); #if HAS_MMA655X ao_data_static.mma655x = int16(bytes, 26); #endif -- cgit v1.2.3 From 9d2eb0b00a5a0faefce95bce949be7206b0aad37 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Tue, 12 Nov 2013 14:48:21 +0900 Subject: Add ublox checksum generating program --- src/drivers/ublox-csum.5c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/drivers/ublox-csum.5c (limited to 'src') diff --git a/src/drivers/ublox-csum.5c b/src/drivers/ublox-csum.5c new file mode 100644 index 00000000..4e0c7c5a --- /dev/null +++ b/src/drivers/ublox-csum.5c @@ -0,0 +1,23 @@ +#!/usr/bin/nickle +string[] speeds = { "57600", "19200", "9600" }; + +string make_set_nmea(string speed) { + return sprintf ("PUBX,41,1,3,1,%s,0", speed); +} + +int csum(string x) { + int csum = 0; + for (int i = 0; i < String::length(x); i++) + csum ^= x[i]; + return csum; +} + +for (int i = 0; i < dim(speeds); i++) { + string s = make_set_nmea(speeds[i]); + int c = csum(s); + printf ("/* $%s* */\n", s); + printf ("#define SERIAL_SPEED_STRING \"%s\"\n", speeds[i]); + printf ("#define SERIAL_SPEED_CHECKSUM \"%02x\"\n", c); +} + + -- cgit v1.2.3 From 40d3575a9365d77ca507ebee226d51d081e1ecc6 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Tue, 12 Nov 2013 14:54:57 +0900 Subject: altos: Clean up .gitignore and add a few random files Signed-off-by: Keith Packard <keithp@keithp.com> --- src/.gitignore | 1 + src/lpcxpresso/.gitignore | 3 +++ src/telefire-v0.2/.gitignore | 2 ++ src/telefire-v0.2/.sdcdbrc | 2 ++ src/telegps-v0.3/.gitignore | 3 +++ src/telemini-v2.0/.gitignore | 2 ++ src/telemini-v2.0/.sdcdbrc | 2 ++ src/telescience-pwm/.gitignore | 2 +- src/test/.gitignore | 4 ++++ src/test/mega.flights | 12 ++++++++++++ src/test/plot-rot | 30 ++++++++++++++++++++++++++++++ src/test/run-all-mm | 2 ++ 12 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 src/lpcxpresso/.gitignore create mode 100644 src/telefire-v0.2/.gitignore create mode 100644 src/telefire-v0.2/.sdcdbrc create mode 100644 src/telegps-v0.3/.gitignore create mode 100644 src/telemini-v2.0/.gitignore create mode 100644 src/telemini-v2.0/.sdcdbrc create mode 100644 src/test/mega.flights create mode 100755 src/test/plot-rot create mode 100755 src/test/run-all-mm (limited to 'src') diff --git a/src/.gitignore b/src/.gitignore index cae36ae6..a8628fae 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,3 +1,4 @@ +Makedefs altitude.h altitude-pa.h ao_whiten.h diff --git a/src/lpcxpresso/.gitignore b/src/lpcxpresso/.gitignore new file mode 100644 index 00000000..892c3acc --- /dev/null +++ b/src/lpcxpresso/.gitignore @@ -0,0 +1,3 @@ +ao_product.h +ao_serial_lpc.h +*.elf diff --git a/src/telefire-v0.2/.gitignore b/src/telefire-v0.2/.gitignore new file mode 100644 index 00000000..4d4f4200 --- /dev/null +++ b/src/telefire-v0.2/.gitignore @@ -0,0 +1,2 @@ +telefire-* +ao_product.h diff --git a/src/telefire-v0.2/.sdcdbrc b/src/telefire-v0.2/.sdcdbrc new file mode 100644 index 00000000..b9f6129c --- /dev/null +++ b/src/telefire-v0.2/.sdcdbrc @@ -0,0 +1,2 @@ +--directory=../cc1111:../product:../core:../drivers:. + diff --git a/src/telegps-v0.3/.gitignore b/src/telegps-v0.3/.gitignore new file mode 100644 index 00000000..892c3acc --- /dev/null +++ b/src/telegps-v0.3/.gitignore @@ -0,0 +1,3 @@ +ao_product.h +ao_serial_lpc.h +*.elf diff --git a/src/telemini-v2.0/.gitignore b/src/telemini-v2.0/.gitignore new file mode 100644 index 00000000..568925a2 --- /dev/null +++ b/src/telemini-v2.0/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +telemini-v2.0* diff --git a/src/telemini-v2.0/.sdcdbrc b/src/telemini-v2.0/.sdcdbrc new file mode 100644 index 00000000..b9f6129c --- /dev/null +++ b/src/telemini-v2.0/.sdcdbrc @@ -0,0 +1,2 @@ +--directory=../cc1111:../product:../core:../drivers:. + diff --git a/src/telescience-pwm/.gitignore b/src/telescience-pwm/.gitignore index dfccadf8..5d9c0970 100644 --- a/src/telescience-pwm/.gitignore +++ b/src/telescience-pwm/.gitignore @@ -1,2 +1,2 @@ -telescience-v0.1* +telescience-pwm* ao_product.h diff --git a/src/test/.gitignore b/src/test/.gitignore index 90af6517..b8b2513e 100644 --- a/src/test/.gitignore +++ b/src/test/.gitignore @@ -5,6 +5,10 @@ ao_flight_test_baro ao_flight_test_accel ao_gps_test ao_gps_test_skytraq +ao_gps_test_ublox +ao_int64_test +ao_ms5607_convert_test +ao_quaternion_test ao_convert_test ao_convert_pa_test ao_fat_test diff --git a/src/test/mega.flights b/src/test/mega.flights new file mode 100644 index 00000000..71c44e65 --- /dev/null +++ b/src/test/mega.flights @@ -0,0 +1,12 @@ +2013-10-12-serial-0094-flight-0001.eeprom +2013-09-02-serial-094-flight-002.eeprom +2013-03-02-serial-069-flight-002.eeprom +2013-03-02-serial-069-flight-001.eeprom +2013-05-27-serial-084-flight-001.mega +2013-05-26-serial-085-flight-002.mega +2013-05-19-serial-084-flight-003.mega +2013-04-21-serial-069-flight-002.mega +2012-10-20-serial-068-flight-004.mega +2012-07-03-serial-058-flight-007.mega +2012-06-30-serial-058-flight-006.mega +2012-06-30-serial-058-flight-005.mega diff --git a/src/test/plot-rot b/src/test/plot-rot new file mode 100755 index 00000000..b6b77c93 --- /dev/null +++ b/src/test/plot-rot @@ -0,0 +1,30 @@ +#!/bin/sh + +case $# in +1) + file="$1" + title="$1" + ;; +2) + file="$1" + title="$2" + ;; +*) + echo "Usage: $0 <data-file> <title>" + exit 1 +esac + +gnuplot -persist << EOF +set ylabel "altitude (m)" +set y2label "angle (d)" +set xlabel "time (s)" +set xtics border out nomirror +set ytics border out nomirror +set y2tics border out nomirror +set title "$title" +plot "$file" using 1:5 with lines axes x1y1 title "height",\ +"$file" using 1:9 with lines axes x1y2 title "gyro rot", \ +"$file" using 1:7 with lines axes x1y2 title "gyro tilt", \ +"$file" using 1:13 with lines axes x1y2 title "mag rot", \ +"$file" using 1:11 with lines axes x1y2 title "mag tilt" +EOF diff --git a/src/test/run-all-mm b/src/test/run-all-mm new file mode 100755 index 00000000..d9c2043d --- /dev/null +++ b/src/test/run-all-mm @@ -0,0 +1,2 @@ +#!/bin/sh +./run-mm `cat mega.flights` -- cgit v1.2.3 From 0951b1ef83d8d741d65811fa23bde43ee843a939 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Tue, 12 Nov 2013 15:18:53 +0900 Subject: altos: Build TM v2.0 firmware by default Signed-off-by: Keith Packard <keithp@keithp.com> --- src/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index a0a271c6..e7fa728b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -27,6 +27,7 @@ SDCCDIRS=\ ARMM3DIRS=\ telemega-v0.1 telemega-v0.1/flash-loader \ telemega-v0.3 telemega-v0.3/flash-loader \ + telemetrum-v2.0 telemetrum-v2.0/flash-loader \ megadongle-v0.1 megadongle-v0.1/flash-loader \ telegps-v0.3 telegps-v0.3/flash-loader \ stm-bringup stm-demo \ -- cgit v1.2.3 From b57f1cabfe5052306cb4c28793bea477f4aeb2d2 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Tue, 12 Nov 2013 15:18:58 +0900 Subject: altos: Don't hold GPS mutex while waiting in TM v2.0 report Holding the GPS mutex while waiting for the GPS code to dump data into the GPS variables is rather counter-productive. Signed-off-by: Keith Packard <keithp@keithp.com> --- src/core/ao_gps_report_metrum.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_gps_report_metrum.c b/src/core/ao_gps_report_metrum.c index b82936dd..fa038976 100644 --- a/src/core/ao_gps_report_metrum.c +++ b/src/core/ao_gps_report_metrum.c @@ -27,11 +27,12 @@ ao_gps_report_metrum(void) uint8_t c, n, i, p, valid, packets; uint8_t svid; uint8_t date_reported = 0; + uint8_t new; for (;;) { - ao_mutex_get(&ao_gps_mutex); while (!(new = ao_gps_new)) ao_sleep(&ao_gps_new); + ao_mutex_get(&ao_gps_mutex); if (new & AO_GPS_NEW_DATA) ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); if (new & AO_GPS_NEW_TRACKING) -- cgit v1.2.3 From 83437b2fe304599e22d0a98b5410808bcb67dc97 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Tue, 12 Nov 2013 15:45:32 +0900 Subject: altos: Allow use of internal EEPROM for config storage This stops exposing eeprom as 'storage' and instead exposes it with a separate eeprom API so that it can be used for config storage without also using it for flight log storage. The config code has been changed to allow it to either use storage for configuration data or eeprom. Signed-off-by: Keith Packard <keithp@keithp.com> --- src/core/ao_config.c | 21 ++++++++-------- src/core/ao_config.h | 57 +++++++++++++++++++++++++++++++++++++++++++ src/core/ao_eeprom.h | 43 ++++++++++++++++++++++++++++++++ src/core/ao_storage.c | 2 +- src/core/ao_storage.h | 10 ++++++++ src/stm/ao_eeprom_stm.c | 57 ++++++++++--------------------------------- src/telegps-v0.1/Makefile | 1 - src/telegps-v0.1/ao_pins.h | 5 +++- src/telegps-v0.1/ao_telegps.c | 3 ++- src/telelco-v0.2/Makefile | 1 - src/telelco-v0.2/ao_pins.h | 2 ++ src/telelco-v0.2/ao_telelco.c | 3 ++- 12 files changed, 145 insertions(+), 60 deletions(-) create mode 100644 src/core/ao_config.h create mode 100644 src/core/ao_eeprom.h (limited to 'src') diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 82faf32b..5567587b 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -17,7 +17,7 @@ #include "ao.h" #include "ao_log.h" -#include <ao_storage.h> +#include <ao_config.h> #if HAS_FLIGHT #include <ao_sample.h> #include <ao_data.h> @@ -59,13 +59,12 @@ __xdata uint8_t ao_config_mutex; static void _ao_config_put(void) { - ao_storage_setup(); - ao_storage_erase(ao_storage_config); - ao_storage_write(ao_storage_config, &ao_config, sizeof (ao_config)); + ao_config_setup(); + ao_config_write(&ao_config, sizeof (ao_config)); #if HAS_FLIGHT ao_log_write_erase(0); #endif - ao_storage_flush(); + ao_config_flush(); } void @@ -97,8 +96,8 @@ _ao_config_get(void) * but ao_storage_setup *also* sets ao_storage_config, which we * need before calling ao_storage_read here */ - ao_storage_setup(); - ao_storage_read(ao_storage_config, &ao_config, sizeof (ao_config)); + ao_config_setup(); + ao_config_read(&ao_config, sizeof (ao_config)); #endif if (ao_config.major != AO_CONFIG_MAJOR) { ao_config.major = AO_CONFIG_MAJOR; @@ -127,8 +126,10 @@ _ao_config_get(void) ao_config.radio_cal = ao_radio_cal; #endif /* Fixups for minor version 4 */ +#if HAS_FLIGHT if (minor < 4) ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; +#endif /* Fixupes for minor version 5 */ if (minor < 5) ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; @@ -655,7 +656,7 @@ static void ao_config_show(void) __reentrant; static void -ao_config_write(void) __reentrant; +ao_config_save(void) __reentrant; __code struct ao_config_var ao_config_vars[] = { #if HAS_FLIGHT @@ -714,7 +715,7 @@ __code struct ao_config_var ao_config_vars[] = { ao_config_show, 0 }, #if HAS_EEPROM { "w\0Write to eeprom", - ao_config_write, 0 }, + ao_config_save, 0 }, #endif { "?\0Help", ao_config_help, 0 }, @@ -766,7 +767,7 @@ ao_config_show(void) __reentrant #if HAS_EEPROM static void -ao_config_write(void) __reentrant +ao_config_save(void) __reentrant { uint8_t saved = 0; ao_mutex_get(&ao_config_mutex); diff --git a/src/core/ao_config.h b/src/core/ao_config.h new file mode 100644 index 00000000..5e38430e --- /dev/null +++ b/src/core/ao_config.h @@ -0,0 +1,57 @@ +/* + * Copyright © 2013 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_CONFIG_H_ +#define _AO_CONFIG_H_ + +#ifndef USE_STORAGE_CONFIG +#define USE_STORAGE_CONFIG 1 +#endif + +#ifndef USE_EEPROM_CONFIG +#define USE_EEPROM_CONFIG 0 +#endif + +#if USE_STORAGE_CONFIG + +#include <ao_storage.h> + +#define ao_config_setup() ao_storage_setup() + +#define ao_config_write(bytes, len) do { \ + ao_storage_erase(ao_storage_config); \ + ao_storage_write(ao_storage_config, bytes, len); \ + } while (0) + +#define ao_config_read(bytes, len) ao_storage_read(ao_storage_config, bytes, len) + +#define ao_config_flush() ao_storage_flush() + +#endif + +#if USE_EEPROM_CONFIG + +#include <ao_eeprom.h> + +#define ao_config_setup() +#define ao_config_write(bytes, len) ao_eeprom_write(0, bytes, len) +#define ao_config_read(bytes, len) ao_eeprom_read(0, bytes, len) +#define ao_config_flush() + +#endif + +#endif /* _AO_CONFIG_H_ */ diff --git a/src/core/ao_eeprom.h b/src/core/ao_eeprom.h new file mode 100644 index 00000000..915522bf --- /dev/null +++ b/src/core/ao_eeprom.h @@ -0,0 +1,43 @@ +/* + * Copyright © 2013 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_EEPROM_H_ +#define _AO_EEPROM_H_ + +extern const ao_pos_t ao_eeprom_total; + +/* + * Write to eeprom + */ + +uint8_t +ao_eeprom_write(ao_pos_t pos32, __xdata void *v, uint16_t len); + +/* + * Read from eeprom + */ +uint8_t +ao_eeprom_read(ao_pos_t pos, __xdata void *v, uint16_t len); + +/* + * Initialize eeprom + */ + +void +ao_eeprom_init(void); + +#endif /* _AO_EEPROM_H_ */ diff --git a/src/core/ao_storage.c b/src/core/ao_storage.c index adf7e4d4..6eddae7f 100644 --- a/src/core/ao_storage.c +++ b/src/core/ao_storage.c @@ -154,7 +154,7 @@ ao_storage_zapall(void) __reentrant ao_cmd_white(); if (!ao_match_word("DoIt")) return; - for (pos = 0; pos < ao_storage_config; pos += ao_storage_block) + for (pos = 0; pos < ao_storage_log_max; pos += ao_storage_block) ao_storage_erase(pos); } diff --git a/src/core/ao_storage.h b/src/core/ao_storage.h index ea946399..d6e95605 100644 --- a/src/core/ao_storage.h +++ b/src/core/ao_storage.h @@ -35,9 +35,19 @@ extern __pdata ao_pos_t ao_storage_total; /* Block size - device is erased in these units. At least 256 bytes */ extern __pdata ao_pos_t ao_storage_block; +#ifndef USE_STORAGE_CONFIG +#define USE_STORAGE_CONFIG 1 +#endif + +#if USE_STORAGE_CONFIG /* Byte offset of config block. Will be ao_storage_block bytes long */ extern __pdata ao_pos_t ao_storage_config; +#define ao_storage_log_max ao_storage_config +#else +#define ao_storage_log_max ao_storage_total +#endif + /* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ extern __pdata uint16_t ao_storage_unit; diff --git a/src/stm/ao_eeprom_stm.c b/src/stm/ao_eeprom_stm.c index 58783f1a..4207a860 100644 --- a/src/stm/ao_eeprom_stm.c +++ b/src/stm/ao_eeprom_stm.c @@ -16,19 +16,10 @@ */ #include <ao.h> -#include <ao_storage.h> +#include <ao_eeprom.h> /* Total bytes of available storage */ -ao_pos_t ao_storage_total = 4096; - -/* Block size - device is erased in these units. */ -ao_pos_t ao_storage_block = 1024; - -/* Byte offset of config block. Will be ao_storage_block bytes long */ -ao_pos_t ao_storage_config = 0; - -/* Storage unit size - device reads and writes must be within blocks of this size. */ -uint16_t ao_storage_unit = 1024; +const ao_pos_t ao_eeprom_total = 4096; /* Location of eeprom in address space */ #define stm_eeprom ((uint8_t *) 0x08080000) @@ -42,16 +33,6 @@ uint16_t ao_storage_unit = 1024; * the same contents, or append to an existing page easily enough */ -/* - * Erase the specified sector - */ -uint8_t -ao_storage_erase(ao_pos_t pos) __reentrant -{ - /* Not necessary */ - return 1; -} - static void ao_intflash_unlock(void) { @@ -131,16 +112,16 @@ ao_intflash_read(uint16_t pos) } /* - * Write to flash + * Write to eeprom */ uint8_t -ao_storage_device_write(ao_pos_t pos32, __xdata void *v, uint16_t len) __reentrant +ao_eeprom_write(ao_pos_t pos32, __xdata void *v, uint16_t len) { uint16_t pos = pos32; __xdata uint8_t *d = v; - if (pos >= ao_storage_total || pos + len > ao_storage_total) + if (pos >= ao_eeprom_total || pos + len > ao_eeprom_total) return 0; ao_intflash_unlock(); @@ -166,38 +147,26 @@ ao_storage_device_write(ao_pos_t pos32, __xdata void *v, uint16_t len) __reentra } /* - * Read from flash + * Read from eeprom */ uint8_t -ao_storage_device_read(ao_pos_t pos, __xdata void *v, uint16_t len) __reentrant +ao_eeprom_read(ao_pos_t pos, __xdata void *v, uint16_t len) { uint8_t *d = v; - if (pos >= ao_storage_total || pos + len > ao_storage_total) + if (pos >= ao_eeprom_total || pos + len > ao_eeprom_total) return 0; while (len--) *d++ = ao_intflash_read(pos++); return 1; } -void -ao_storage_flush(void) __reentrant -{ -} - -void -ao_storage_setup(void) -{ -} - -void -ao_storage_device_info(void) __reentrant -{ - uint8_t i; - printf ("Using internal flash\n"); -} +/* + * Initialize eeprom + */ void -ao_storage_device_init(void) +ao_eeprom_init(void) { + /* Nothing to do here */ } diff --git a/src/telegps-v0.1/Makefile b/src/telegps-v0.1/Makefile index 170294e6..f5533d51 100644 --- a/src/telegps-v0.1/Makefile +++ b/src/telegps-v0.1/Makefile @@ -57,7 +57,6 @@ ALTOS_SRC = \ ao_fec_tx.c \ ao_rfpa0133.c \ ao_aprs.c \ - ao_storage.c \ ao_eeprom_stm.c \ ao_sdcard.c \ ao_bufio.c \ diff --git a/src/telegps-v0.1/ao_pins.h b/src/telegps-v0.1/ao_pins.h index 5bea2681..7ff59956 100644 --- a/src/telegps-v0.1/ao_pins.h +++ b/src/telegps-v0.1/ao_pins.h @@ -65,7 +65,10 @@ #define ao_gps_fifo (ao_stm_usart2.rx_fifo) #define HAS_EEPROM 1 -#define USE_INTERNAL_FLASH 1 +#define USE_INTERNAL_FLASH 0 +#define USE_EEPROM_CONFIG 1 +#define USE_STORAGE_CONFIG 0 + #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_RADIO 1 diff --git a/src/telegps-v0.1/ao_telegps.c b/src/telegps-v0.1/ao_telegps.c index 68116bfb..bc37b504 100644 --- a/src/telegps-v0.1/ao_telegps.c +++ b/src/telegps-v0.1/ao_telegps.c @@ -18,6 +18,7 @@ #include <ao.h> #include <ao_exti.h> #include <ao_fat.h> +#include <ao_eeprom.h> uint16_t ao_flight_number = 1; @@ -40,7 +41,7 @@ main(void) ao_dma_init(); ao_exti_init(); - ao_storage_init(); + ao_eeprom_init(); ao_serial_init(); diff --git a/src/telelco-v0.2/Makefile b/src/telelco-v0.2/Makefile index bc5f8571..2fb4db5e 100644 --- a/src/telelco-v0.2/Makefile +++ b/src/telelco-v0.2/Makefile @@ -48,7 +48,6 @@ ALTOS_SRC = \ ao_dma_stm.c \ ao_spi_stm.c \ ao_beep_stm.c \ - ao_storage.c \ ao_eeprom_stm.c \ ao_fast_timer.c \ ao_lcd_stm.c \ diff --git a/src/telelco-v0.2/ao_pins.h b/src/telelco-v0.2/ao_pins.h index d86782f3..62f221a1 100644 --- a/src/telelco-v0.2/ao_pins.h +++ b/src/telelco-v0.2/ao_pins.h @@ -43,6 +43,8 @@ #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 1 +#define USE_EEPROM_CONFIG 1 +#define USE_STORAGE_CONFIG 0 #define HAS_USB 1 #define HAS_BEEP 1 #define HAS_RADIO 1 diff --git a/src/telelco-v0.2/ao_telelco.c b/src/telelco-v0.2/ao_telelco.c index 66bf0ba1..d9f7c693 100644 --- a/src/telelco-v0.2/ao_telelco.c +++ b/src/telelco-v0.2/ao_telelco.c @@ -28,6 +28,7 @@ #include <ao_lco.h> #include <ao_lco_cmd.h> #include <ao_radio_cmac_cmd.h> +#include <ao_eeprom.h> int main(void) @@ -52,7 +53,7 @@ main(void) ao_quadrature_init(); ao_button_init(); - ao_storage_init(); + ao_eeprom_init(); ao_radio_init(); -- cgit v1.2.3 From 9c53ad6f8222878a26efecebd3bb1d1fe054a4b6 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Tue, 12 Nov 2013 16:06:59 +0900 Subject: altos: Move TeleMetrum v2.0 to using internal eeprom for config This leaves the whole 8MB of flash for flight storage Signed-off-by: Keith Packard <keithp@keithp.com> --- src/core/ao_config.c | 11 ++++++----- src/core/ao_config.h | 16 ++++++---------- src/core/ao_log.c | 11 ++++++----- src/telemetrum-v2.0/Makefile | 1 + src/telemetrum-v2.0/ao_pins.h | 3 +++ src/telemetrum-v2.0/ao_telemetrum.c | 2 ++ 6 files changed, 24 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 5567587b..a30ec64a 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -60,7 +60,8 @@ static void _ao_config_put(void) { ao_config_setup(); - ao_config_write(&ao_config, sizeof (ao_config)); + ao_config_erase(); + ao_config_write(0, &ao_config, sizeof (ao_config)); #if HAS_FLIGHT ao_log_write_erase(0); #endif @@ -97,7 +98,7 @@ _ao_config_get(void) * need before calling ao_storage_read here */ ao_config_setup(); - ao_config_read(&ao_config, sizeof (ao_config)); + ao_config_read(0, &ao_config, sizeof (ao_config)); #endif if (ao_config.major != AO_CONFIG_MAJOR) { ao_config.major = AO_CONFIG_MAJOR; @@ -466,7 +467,7 @@ void ao_config_log_set(void) __reentrant { uint16_t block = (uint16_t) (ao_storage_block >> 10); - uint16_t config = (uint16_t) (ao_storage_config >> 10); + uint16_t log_max = (uint16_t) (ao_storage_log_max >> 10); ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) @@ -475,8 +476,8 @@ ao_config_log_set(void) __reentrant printf("Storage must be empty before changing log size\n"); else if (block > 1024 && (ao_cmd_lex_i & (block - 1))) printf("Flight log size must be multiple of %d kB\n", block); - else if (ao_cmd_lex_i > config) - printf("Flight log max %d kB\n", config); + else if (ao_cmd_lex_i > log_max) + printf("Flight log max %d kB\n", log_max); else { _ao_config_edit_start(); ao_config.flight_log_max = (uint32_t) ao_cmd_lex_i << 10; diff --git a/src/core/ao_config.h b/src/core/ao_config.h index 5e38430e..e101af8e 100644 --- a/src/core/ao_config.h +++ b/src/core/ao_config.h @@ -31,14 +31,9 @@ #include <ao_storage.h> #define ao_config_setup() ao_storage_setup() - -#define ao_config_write(bytes, len) do { \ - ao_storage_erase(ao_storage_config); \ - ao_storage_write(ao_storage_config, bytes, len); \ - } while (0) - -#define ao_config_read(bytes, len) ao_storage_read(ao_storage_config, bytes, len) - +#define ao_config_erase() ao_storage_erase(ao_storage_config) +#define ao_config_write(pos,bytes, len) ao_storage_write(ao_storage_config+(pos), bytes, len) +#define ao_config_read(pos,bytes, len) ao_storage_read(ao_storage_config+(pos), bytes, len) #define ao_config_flush() ao_storage_flush() #endif @@ -48,8 +43,9 @@ #include <ao_eeprom.h> #define ao_config_setup() -#define ao_config_write(bytes, len) ao_eeprom_write(0, bytes, len) -#define ao_config_read(bytes, len) ao_eeprom_read(0, bytes, len) +#define ao_config_erase() +#define ao_config_write(pos,bytes, len) ao_eeprom_write(pos, bytes, len) +#define ao_config_read(pos,bytes, len) ao_eeprom_read(pos, bytes, len) #define ao_config_flush() #endif diff --git a/src/core/ao_log.c b/src/core/ao_log.c index 8bcb7707..1a1f5ff6 100644 --- a/src/core/ao_log.c +++ b/src/core/ao_log.c @@ -17,6 +17,7 @@ #include "ao.h" #include <ao_log.h> +#include <ao_config.h> __pdata uint32_t ao_log_current_pos; __pdata uint32_t ao_log_end_pos; @@ -48,7 +49,7 @@ static __xdata struct ao_log_erase erase; static uint32_t ao_log_erase_pos(uint8_t i) { - return i * sizeof (struct ao_log_erase) + AO_STORAGE_ERASE_LOG; + return i * sizeof (struct ao_log_erase); } void @@ -56,14 +57,14 @@ ao_log_write_erase(uint8_t pos) { erase.unused = 0x00; erase.flight = ao_flight_number; - ao_storage_write(ao_log_erase_pos(pos), &erase, sizeof (erase)); - ao_storage_flush(); + ao_config_write(ao_log_erase_pos(pos), &erase, sizeof (erase)); + ao_config_flush(); } static void ao_log_read_erase(uint8_t pos) { - ao_storage_read(ao_log_erase_pos(pos), &erase, sizeof (erase)); + ao_config_read(ao_log_erase_pos(pos), &erase, sizeof (erase)); } @@ -87,7 +88,7 @@ ao_log_erase_mark(void) static uint8_t ao_log_slots() { - return (uint8_t) (ao_storage_config / ao_config.flight_log_max); + return (uint8_t) (ao_storage_log_max / ao_config.flight_log_max); } uint32_t diff --git a/src/telemetrum-v2.0/Makefile b/src/telemetrum-v2.0/Makefile index be72d493..a5370224 100644 --- a/src/telemetrum-v2.0/Makefile +++ b/src/telemetrum-v2.0/Makefile @@ -70,6 +70,7 @@ ALTOS_SRC = \ ao_m25.c \ ao_usb_stm.c \ ao_exti_stm.c \ + ao_eeprom_stm.c \ ao_report.c \ ao_convert_pa.c \ ao_log.c \ diff --git a/src/telemetrum-v2.0/ao_pins.h b/src/telemetrum-v2.0/ao_pins.h index a7236b80..02f0f5e3 100644 --- a/src/telemetrum-v2.0/ao_pins.h +++ b/src/telemetrum-v2.0/ao_pins.h @@ -59,8 +59,11 @@ #define SERIAL_3_PC10_PC11 0 #define SERIAL_3_PD8_PD9 0 +#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX (512 * 1024) #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 0 +#define USE_EEPROM_CONFIG 1 +#define USE_STORAGE_CONFIG 0 #define HAS_USB 1 #define HAS_BEEP 1 #define BEEPER_CHANNEL 4 diff --git a/src/telemetrum-v2.0/ao_telemetrum.c b/src/telemetrum-v2.0/ao_telemetrum.c index d79aba54..23556c6c 100644 --- a/src/telemetrum-v2.0/ao_telemetrum.c +++ b/src/telemetrum-v2.0/ao_telemetrum.c @@ -62,6 +62,8 @@ main(void) ao_mma655x_init(); #endif + ao_eeprom_init(); + ao_storage_init(); ao_flight_init(); -- cgit v1.2.3 From 92eafd01f2809f39c5bc4058977c790d94a99df1 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Tue, 12 Nov 2013 16:08:50 +0900 Subject: altos: Move telemega to using internal eeprom for config And crank up the default per-flight storage to 1MB Signed-off-by: Keith Packard <keithp@keithp.com> --- src/telemega-v0.3/Makefile | 1 + src/telemega-v0.3/ao_pins.h | 3 +++ src/telemega-v0.3/ao_telemega.c | 1 + 3 files changed, 5 insertions(+) (limited to 'src') diff --git a/src/telemega-v0.3/Makefile b/src/telemega-v0.3/Makefile index 01209f7d..a25b8b68 100644 --- a/src/telemega-v0.3/Makefile +++ b/src/telemega-v0.3/Makefile @@ -91,6 +91,7 @@ ALTOS_SRC = \ ao_hmc5883.c \ ao_adc_stm.c \ ao_beep_stm.c \ + ao_eeprom_stm.c \ ao_storage.c \ ao_m25.c \ ao_usb_stm.c \ diff --git a/src/telemega-v0.3/ao_pins.h b/src/telemega-v0.3/ao_pins.h index a5a9eaf4..7ff676ea 100644 --- a/src/telemega-v0.3/ao_pins.h +++ b/src/telemega-v0.3/ao_pins.h @@ -64,8 +64,11 @@ #define ao_gps_set_speed ao_serial3_set_speed #define ao_gps_fifo (ao_stm_usart3.rx_fifo) +#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX (1024 * 1024) #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 0 +#define USE_EEPROM_CONFIG 1 +#define USE_STORAGE_CONFIG 0 #define HAS_USB 1 #define HAS_BEEP 1 #define HAS_RADIO 1 diff --git a/src/telemega-v0.3/ao_telemega.c b/src/telemega-v0.3/ao_telemega.c index fbdab64a..273c0426 100644 --- a/src/telemega-v0.3/ao_telemega.c +++ b/src/telemega-v0.3/ao_telemega.c @@ -71,6 +71,7 @@ main(void) ao_mma655x_init(); #endif + ao_eeprom_init(); ao_storage_init(); ao_flight_init(); -- cgit v1.2.3 From bf893a4149b05b97f18f9f487af805adef859d74 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Tue, 12 Nov 2013 16:22:49 +0900 Subject: altos: Make sure flight erase log comes after config blog Oops. When converting from ao_storage to ao_config, I accidentally had the flight erase log overwriting the config block. Signed-off-by: Keith Packard <keithp@keithp.com> --- src/core/ao_log.c | 2 +- src/core/ao_storage.h | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/core/ao_log.c b/src/core/ao_log.c index 1a1f5ff6..701c81ab 100644 --- a/src/core/ao_log.c +++ b/src/core/ao_log.c @@ -49,7 +49,7 @@ static __xdata struct ao_log_erase erase; static uint32_t ao_log_erase_pos(uint8_t i) { - return i * sizeof (struct ao_log_erase); + return i * sizeof (struct ao_log_erase) + AO_CONFIG_MAX_SIZE; } void diff --git a/src/core/ao_storage.h b/src/core/ao_storage.h index d6e95605..6cc6fcb7 100644 --- a/src/core/ao_storage.h +++ b/src/core/ao_storage.h @@ -51,8 +51,6 @@ extern __pdata ao_pos_t ao_storage_config; /* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ extern __pdata uint16_t ao_storage_unit; -#define AO_STORAGE_ERASE_LOG (ao_storage_config + AO_CONFIG_MAX_SIZE) - /* Initialize above values. Can only be called once the OS is running */ void ao_storage_setup(void) __reentrant; -- cgit v1.2.3 From 12481415c2e5fb03b003343c9499df711eb14f91 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Tue, 12 Nov 2013 16:26:02 +0900 Subject: altos: include ao_eeprom.h in ao_telemetrum.c to define ao_eeprom_init Signed-off-by: Keith Packard <keithp@keithp.com> --- src/telemetrum-v2.0/ao_telemetrum.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/telemetrum-v2.0/ao_telemetrum.c b/src/telemetrum-v2.0/ao_telemetrum.c index 23556c6c..46599cb2 100644 --- a/src/telemetrum-v2.0/ao_telemetrum.c +++ b/src/telemetrum-v2.0/ao_telemetrum.c @@ -22,6 +22,7 @@ #include <ao_exti.h> #include <ao_packet.h> #include <ao_companion.h> +#include <ao_eeprom.h> #include <ao_profile.h> #if HAS_SAMPLE_PROFILE #include <ao_sample_profile.h> -- cgit v1.2.3 From de2e812b02a99a2f6d85f15a9600265931f6f6b0 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Sat, 7 Dec 2013 09:38:50 -0800 Subject: src/cc1111: Turn off RC osc after xtal is running There's no reason to keep running the RC oscillator after we switch to the crystal, so turn it off. Signed-off-by: Keith Packard <keithp@keithp.com> --- src/cc1111/ao_timer.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/cc1111/ao_timer.c b/src/cc1111/ao_timer.c index 54af9605..75cc4ce8 100644 --- a/src/cc1111/ao_timer.c +++ b/src/cc1111/ao_timer.c @@ -95,6 +95,13 @@ ao_clock_init(void) while (!(SLEEP & SLEEP_XOSC_STB)) ; + /* Power down the unused HFRC oscillator */ + SLEEP |= SLEEP_OSC_PD; + + /* Wait for HFRC to power down */ + while ((SLEEP & SLEEP_HFRC_STB) != 0) + ; + /* Crank up the timer tick and system clock speed */ CLKCON = ((CLKCON & ~(CLKCON_TICKSPD_MASK | CLKCON_CLKSPD_MASK)) | (CLKCON_TICKSPD_1 | CLKCON_CLKSPD_1)); -- cgit v1.2.3 From 2a9b0cdff5db03dc11b6ef69cf5436c834c3acc4 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Sat, 7 Dec 2013 09:39:41 -0800 Subject: altos: Add lots more GPS data to mega log There's plenty of space in the GPS log packets to hold course, speed, climb and DOP values, so just stick them in. Signed-off-by: Keith Packard <keithp@keithp.com> --- src/core/ao_gps_report_mega.c | 7 +++++++ src/core/ao_log.h | 10 ++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/ao_gps_report_mega.c b/src/core/ao_gps_report_mega.c index a66068ab..d13885dd 100644 --- a/src/core/ao_gps_report_mega.c +++ b/src/core/ao_gps_report_mega.c @@ -53,6 +53,13 @@ ao_gps_report_mega(void) gps_log.u.gps.year = gps_data.year; gps_log.u.gps.month = gps_data.month; gps_log.u.gps.day = gps_data.day; + gps_log.u.gps.course = gps_data.course; + gps_log.u.gps.ground_speed = gps_data.ground_speed; + gps_log.u.gps.climb_rate = gps_data.climb_rate; + gps_log.u.gps.pdop = gps_data.pdop; + gps_log.u.gps.hdop = gps_data.hdop; + gps_log.u.gps.vdop = gps_data.vdop; + gps_log.u.gps.mode = gps_data.mode; ao_log_mega(&gps_log); } if ((new & AO_GPS_NEW_TRACKING) && (n = gps_tracking_data.channels) != 0) { diff --git a/src/core/ao_log.h b/src/core/ao_log.h index 4b09faeb..09f31188 100644 --- a/src/core/ao_log.h +++ b/src/core/ao_log.h @@ -253,8 +253,14 @@ struct ao_log_mega { uint8_t year; /* 18 */ uint8_t month; /* 19 */ uint8_t day; /* 20 */ - uint8_t pad; /* 21 */ - } gps; /* 22 */ + uint8_t course; /* 21 */ + uint16_t ground_speed; /* 22 */ + int16_t climb_rate; /* 24 */ + uint8_t pdop; /* 26 */ + uint8_t hdop; /* 27 */ + uint8_t vdop; /* 28 */ + uint8_t mode; /* 29 */ + } gps; /* 30 */ /* AO_LOG_GPS_SAT */ struct { uint16_t channels; /* 4 */ -- cgit v1.2.3 From 6fbf4829569d5edb476654f4e383b834af527dc6 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Sat, 7 Dec 2013 09:40:53 -0800 Subject: altos: Telemega uses eeprom, include it in main file ao_telemega.c didn't include ao_eeprom.h leaving a function undefined Signed-off-by: Keith Packard <keithp@keithp.com> --- src/telemega-v0.3/ao_telemega.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/telemega-v0.3/ao_telemega.c b/src/telemega-v0.3/ao_telemega.c index 273c0426..7b035269 100644 --- a/src/telemega-v0.3/ao_telemega.c +++ b/src/telemega-v0.3/ao_telemega.c @@ -24,6 +24,7 @@ #include <ao_packet.h> #include <ao_companion.h> #include <ao_profile.h> +#include <ao_eeprom.h> #if HAS_SAMPLE_PROFILE #include <ao_sample_profile.h> #endif -- cgit v1.2.3 From cdb32b1717db4e8cb8cf94d810e74ce2b569566b Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Sat, 7 Dec 2013 09:47:45 -0800 Subject: altos/test: Compute and plot tilt based on GPS track This lets us compare the gyro-computed tilt angle against the actual flight path. Signed-off-by: Keith Packard <keithp@keithp.com> --- src/test/ao_flight_test.c | 233 ++++++++++++++++++++++------------------------ src/test/plotmm | 8 +- 2 files changed, 118 insertions(+), 123 deletions(-) (limited to 'src') diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 452f5b75..0abb4090 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -92,6 +92,95 @@ struct ao_adc { #include <ao_data.h> #include <ao_log.h> +#include <ao_telemetry.h> + +#if TELEMEGA +int ao_gps_count; +struct ao_telemetry_location ao_gps_first; +struct ao_telemetry_location ao_gps_prev; +struct ao_telemetry_location ao_gps_static; + +struct ao_telemetry_satellite ao_gps_tracking; + +static inline double sqr(double a) { return a * a; } + +void +cc_great_circle (double start_lat, double start_lon, + double end_lat, double end_lon, + double *dist, double *bearing) +{ + const double rad = M_PI / 180; + const double earth_radius = 6371.2 * 1000; /* in meters */ + double lat1 = rad * start_lat; + double lon1 = rad * -start_lon; + double lat2 = rad * end_lat; + double lon2 = rad * -end_lon; + +// double d_lat = lat2 - lat1; + double d_lon = lon2 - lon1; + + /* From http://en.wikipedia.org/wiki/Great-circle_distance */ + double vdn = sqrt(sqr(cos(lat2) * sin(d_lon)) + + sqr(cos(lat1) * sin(lat2) - + sin(lat1) * cos(lat2) * cos(d_lon))); + double vdd = sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2) * cos(d_lon); + double d = atan2(vdn,vdd); + double course; + + if (cos(lat1) < 1e-20) { + if (lat1 > 0) + course = M_PI; + else + course = -M_PI; + } else { + if (d < 1e-10) + course = 0; + else + course = acos((sin(lat2)-sin(lat1)*cos(d)) / + (sin(d)*cos(lat1))); + if (sin(lon2-lon1) > 0) + course = 2 * M_PI-course; + } + *dist = d * earth_radius; + *bearing = course * 180/M_PI; +} + +double +ao_distance_from_pad(void) +{ + double dist, bearing; + if (!ao_gps_count) + return 0; + + cc_great_circle(ao_gps_first.latitude / 1e7, + ao_gps_first.longitude / 1e7, + ao_gps_static.latitude / 1e7, + ao_gps_static.longitude / 1e7, + &dist, &bearing); + return dist; +} + +double +ao_gps_angle(void) +{ + double dist, bearing; + double height; + double angle; + + if (ao_gps_count < 2) + return 0; + + cc_great_circle(ao_gps_prev.latitude / 1e7, + ao_gps_prev.longitude / 1e7, + ao_gps_static.latitude / 1e7, + ao_gps_static.longitude / 1e7, + &dist, &bearing); + height = ao_gps_static.altitude - ao_gps_prev.altitude; + + angle = atan2(dist, height); + return angle * 180/M_PI; +} +#endif #define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) #define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) @@ -390,6 +479,7 @@ ao_insert(void) double height = ao_pres_to_altitude(ao_data_static.adc.pres_real) - ao_ground_height; #endif + (void) accel; if (!tick_offset) tick_offset = -ao_data_static.tick; if ((prev_tick - ao_data_static.tick) > 0x400) @@ -457,6 +547,8 @@ ao_insert(void) ao_mag_angle = floor (acos(ao_dot) * 180 / M_PI + 0.5); + (void) ao_mag_angle; + static struct ao_quaternion ao_x = { .r = 0, .x = 1, .y = 0, .z = 0 }; struct ao_quaternion ao_out; @@ -464,6 +556,7 @@ ao_insert(void) int out = floor (atan2(ao_out.y, ao_out.x) * 180 / M_PI); +#if 0 printf ("%7.2f state %-8.8s height %8.4f tilt %4d rot %4d mag_tilt %4d mag_rot %4d\n", time, ao_state_names[ao_flight_state], @@ -471,7 +564,15 @@ ao_insert(void) ao_sample_orient, out, mag_azel.el, mag_azel.az); - +#endif + printf ("%7.2f state %-8.8s height %8.4f tilt %4d rot %4d dist %12.2f gps_tilt %4d gps_sats %2d\n", + time, + ao_state_names[ao_flight_state], + ao_k_height / 65536.0, + ao_sample_orient, out, + ao_distance_from_pad(), + (int) floor (ao_gps_angle() + 0.5), + (ao_gps_static.flags & 0xf) * 10); #if 0 printf ("\t\tstate %-8.8s ground az: %4d el %4d mag az %4d el %4d rot az %4d el %4d el_diff %4d az_diff %4d angle %4d tilt %4d ground %8.5f %8.5f %8.5f cur %8.5f %8.5f %8.5f rot %8.5f %8.5f %8.5f\n", @@ -535,125 +636,6 @@ ao_insert(void) } } -#define AO_MAX_CALLSIGN 8 -#define AO_MAX_VERSION 8 -#define AO_MAX_TELEMETRY 128 - -struct ao_telemetry_generic { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t payload[27]; /* 5 */ - /* 32 */ -}; - -#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 -#define AO_TELEMETRY_SENSOR_TELEMINI 0x02 -#define AO_TELEMETRY_SENSOR_TELENANO 0x03 - -struct ao_telemetry_sensor { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t state; /* 5 flight state */ - int16_t accel; /* 6 accelerometer (TM only) */ - int16_t pres; /* 8 pressure sensor */ - int16_t temp; /* 10 temperature sensor */ - int16_t v_batt; /* 12 battery voltage */ - int16_t sense_d; /* 14 drogue continuity sense (TM/Tm) */ - int16_t sense_m; /* 16 main continuity sense (TM/Tm) */ - - int16_t acceleration; /* 18 m/s² * 16 */ - int16_t speed; /* 20 m/s * 16 */ - int16_t height; /* 22 m */ - - int16_t ground_pres; /* 24 average pres on pad */ - int16_t ground_accel; /* 26 average accel on pad */ - int16_t accel_plus_g; /* 28 accel calibration at +1g */ - int16_t accel_minus_g; /* 30 accel calibration at -1g */ - /* 32 */ -}; - -#define AO_TELEMETRY_CONFIGURATION 0x04 - -struct ao_telemetry_configuration { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t device; /* 5 device type */ - uint16_t flight; /* 6 flight number */ - uint8_t config_major; /* 8 Config major version */ - uint8_t config_minor; /* 9 Config minor version */ - uint16_t apogee_delay; /* 10 Apogee deploy delay in seconds */ - uint16_t main_deploy; /* 12 Main deploy alt in meters */ - uint16_t flight_log_max; /* 14 Maximum flight log size in kB */ - char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ - char version[AO_MAX_VERSION]; /* 24 Software version */ - /* 32 */ -}; - -#define AO_TELEMETRY_LOCATION 0x05 - -#define AO_GPS_MODE_NOT_VALID 'N' -#define AO_GPS_MODE_AUTONOMOUS 'A' -#define AO_GPS_MODE_DIFFERENTIAL 'D' -#define AO_GPS_MODE_ESTIMATED 'E' -#define AO_GPS_MODE_MANUAL 'M' -#define AO_GPS_MODE_SIMULATED 'S' - -struct ao_telemetry_location { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t flags; /* 5 Number of sats and other flags */ - int16_t altitude; /* 6 GPS reported altitude (m) */ - int32_t latitude; /* 8 latitude (degrees * 10⁷) */ - int32_t longitude; /* 12 longitude (degrees * 10⁷) */ - uint8_t year; /* 16 (- 2000) */ - uint8_t month; /* 17 (1-12) */ - uint8_t day; /* 18 (1-31) */ - uint8_t hour; /* 19 (0-23) */ - uint8_t minute; /* 20 (0-59) */ - uint8_t second; /* 21 (0-59) */ - uint8_t pdop; /* 22 (m * 5) */ - uint8_t hdop; /* 23 (m * 5) */ - uint8_t vdop; /* 24 (m * 5) */ - uint8_t mode; /* 25 */ - uint16_t ground_speed; /* 26 cm/s */ - int16_t climb_rate; /* 28 cm/s */ - uint8_t course; /* 30 degrees / 2 */ - uint8_t unused[1]; /* 31 */ - /* 32 */ -}; - -#define AO_TELEMETRY_SATELLITE 0x06 - -struct ao_telemetry_satellite_info { - uint8_t svid; - uint8_t c_n_1; -}; - -struct ao_telemetry_satellite { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t channels; /* 5 number of reported sats */ - - struct ao_telemetry_satellite_info sats[12]; /* 6 */ - uint8_t unused[2]; /* 30 */ - /* 32 */ -}; - -union ao_telemetry_all { - struct ao_telemetry_generic generic; - struct ao_telemetry_sensor sensor; - struct ao_telemetry_configuration configuration; - struct ao_telemetry_location location; - struct ao_telemetry_satellite satellite; -}; uint16_t uint16(uint8_t *bytes, int off) @@ -771,6 +753,17 @@ ao_sleep(void *wchan) ao_records_read++; ao_insert(); return; + case 'G': + ao_gps_prev = ao_gps_static; + ao_gps_static.tick = tick; + ao_gps_static.latitude = int32(bytes, 0); + ao_gps_static.longitude = int32(bytes, 4); + ao_gps_static.altitude = int32(bytes, 8); + ao_gps_static.flags = bytes[13]; + if (!ao_gps_count) + ao_gps_first = ao_gps_static; + ao_gps_count++; + break; } continue; } else if (nword == 3 && strcmp(words[0], "ms5607") == 0) { diff --git a/src/test/plotmm b/src/test/plotmm index bfe15f4c..27f8ddcd 100755 --- a/src/test/plotmm +++ b/src/test/plotmm @@ -15,13 +15,15 @@ case $# in esac gnuplot -persist << EOF -set ylabel "altitude (m)" +set ylabel "distance (m)" set y2label "angle (d)" set xlabel "time (s)" set xtics border out nomirror set ytics border out nomirror set y2tics border out nomirror set title "$title" -plot "$file" using 1:3 with lines axes x1y1 title "raw height",\ -"$file" using 1:7 with lines axes x1y2 title "angle" +plot "$file" using 1:5 with lines axes x1y1 title "height",\ +"$file" using 1:7 with lines axes x1y2 title "angle",\ +"$file" using 1:13 with lines axes x1y2 title "gps angle",\ +"$file" using 1:15 with lines axes x1y2 title "sats" EOF -- cgit v1.2.3 From 44249a9262a16ed103aedf30a300003fc2a17579 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Sat, 7 Dec 2013 09:49:00 -0800 Subject: altos: Nothing in altos uses AES decryption, so don't compile it Saves a bit of space where AES is used, and avoids some compiler warnings. Signed-off-by: Keith Packard <keithp@keithp.com> --- src/aes/ao_aes.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/aes/ao_aes.c b/src/aes/ao_aes.c index 71ffadb1..52463f5d 100644 --- a/src/aes/ao_aes.c +++ b/src/aes/ao_aes.c @@ -310,6 +310,10 @@ void xrijndaelEncrypt(word32 block[], roundkey *rkk) xKeyAddition(block, block2, rp, BC); } +#if NOTUSED +/* We don't actually need this in AltOS, so don't bother including it */ + +/* Decryption of one block. */ static void xrijndaelDecrypt(word32 block[], roundkey *rkk) { @@ -352,6 +356,7 @@ void xrijndaelDecrypt(word32 block[], roundkey *rkk) xKeyAddition(block, block, rp, BC); } +#endif uint8_t ao_aes_mutex; static uint8_t key[16]; -- cgit v1.2.3 From a1e4750a7d4af72e8e9086735885f48c9b56c18e Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Sun, 8 Dec 2013 11:11:41 -0800 Subject: altos: Allow products to override default 100mA USB current This will allow products to specify their own current limit. Signed-off-by: Keith Packard <keithp@keithp.com> --- src/core/ao_product.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_product.c b/src/core/ao_product.c index ec91b978..b9327bac 100644 --- a/src/core/ao_product.c +++ b/src/core/ao_product.c @@ -27,6 +27,12 @@ const char ao_product[] = AO_iProduct_STRING; #define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) #if HAS_USB + +/* Maximum power in mA */ +#ifndef AO_USB_MAX_POWER +#define AO_USB_MAX_POWER 100 +#endif + #include "ao_usb.h" /* USB descriptors in one giant block of bytes */ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] = @@ -55,7 +61,7 @@ AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] = 0x01, /* bConfigurationValue */ 0x00, /* iConfiguration */ 0xC0, /* bmAttributes */ - 0x32, /* bMaxPower */ + AO_USB_MAX_POWER >> 1, /* bMaxPower, 2mA units */ /* Control class interface */ 0x09, -- cgit v1.2.3 From 52b19511222980138faddb2047707baceff0a596 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Sun, 8 Dec 2013 11:14:29 -0800 Subject: altos: Build .ihx files for all arm projects The .ihx version can be processed by the java loader Signed-off-by: Keith Packard <keithp@keithp.com> --- src/easymini-v1.0/Makefile | 5 +++-- src/lpc/Makefile-lpc.defs | 3 ++- src/megadongle-v0.1/Makefile | 3 ++- src/stm/Makefile.defs | 3 ++- src/telegps-v0.1/Makefile | 3 ++- src/telelco-v0.1/Makefile | 3 ++- src/telelco-v0.2/Makefile | 3 ++- src/telemega-v0.1/Makefile | 3 ++- src/telemega-v0.3/Makefile | 3 ++- src/telemetrum-v2.0/Makefile | 3 ++- src/telescience-v0.2/Makefile | 3 ++- 11 files changed, 23 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/easymini-v1.0/Makefile b/src/easymini-v1.0/Makefile index 6ab79425..8042874f 100644 --- a/src/easymini-v1.0/Makefile +++ b/src/easymini-v1.0/Makefile @@ -54,11 +54,12 @@ CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -g -Os PROGNAME=easymini-v1.0 PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx SRC=$(ALTOS_SRC) ao_easymini.c OBJ=$(SRC:.c=.o) -all: $(PROG) +all: $(PROG) $(HEX) $(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) @@ -74,7 +75,7 @@ load: $(PROG) distclean: clean clean: - rm -f *.o $(PROG) + rm -f *.o $(PROGNAME)-*.elf rm -f ao_product.h install: diff --git a/src/lpc/Makefile-lpc.defs b/src/lpc/Makefile-lpc.defs index 32a02a4c..fbd413b0 100644 --- a/src/lpc/Makefile-lpc.defs +++ b/src/lpc/Makefile-lpc.defs @@ -16,13 +16,14 @@ vpath ao-make-product.5c $(TOPDIR)/util .SUFFIXES: .elf .ihx .elf.ihx: - objcopy -O ihex $*.elf $@ + $(ELFTOHEX) --output=$@ $*.elf ifndef VERSION include $(TOPDIR)/Version endif +ELFTOHEX=$(TOPDIR)/../ao-tools/ao-elftohex/ao-elftohex CC=$(ARM_CC) AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) diff --git a/src/megadongle-v0.1/Makefile b/src/megadongle-v0.1/Makefile index 268f186f..a8c3a584 100644 --- a/src/megadongle-v0.1/Makefile +++ b/src/megadongle-v0.1/Makefile @@ -62,11 +62,12 @@ CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STA PROGNAME=megadongle-v0.1 PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx SRC=$(ALTOS_SRC) ao_megadongle.c OBJ=$(SRC:.c=.o) -all: $(PROG) +all: $(PROG) $(HEX) $(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index 0710d747..b1998f93 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -10,7 +10,7 @@ vpath ao-make-product.5c ../util .SUFFIXES: .elf .ihx .elf.ihx: - objcopy -O ihex $*.elf $@ + $(ELFTOHEX) --output=$@ $*.elf ifndef TOPDIR TOPDIR=.. @@ -30,6 +30,7 @@ STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -no LDFLAGS=-L../stm -Wl,-Taltos.ld NICKLE=nickle +ELFTOHEX=$(TOPDIR)/../ao-tools/ao-elftohex/ao-elftohex V=0 # The user has explicitly enabled quiet compilation. diff --git a/src/telegps-v0.1/Makefile b/src/telegps-v0.1/Makefile index f5533d51..96366cfc 100644 --- a/src/telegps-v0.1/Makefile +++ b/src/telegps-v0.1/Makefile @@ -74,11 +74,12 @@ CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STA PROGNAME=telegps-v0.1 PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx SRC=$(ALTOS_SRC) ao_telegps.c OBJ=$(SRC:.c=.o) -all: $(PROG) +all: $(PROG) $(HEX) $(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) diff --git a/src/telelco-v0.1/Makefile b/src/telelco-v0.1/Makefile index 0f61788c..e494403c 100644 --- a/src/telelco-v0.1/Makefile +++ b/src/telelco-v0.1/Makefile @@ -69,11 +69,12 @@ CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g PROGNAME=telelco-v0.1 PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx SRC=$(ALTOS_SRC) ao_telelco.c OBJ=$(SRC:.c=.o) -all: $(PROG) +all: $(PROG) $(HEX) $(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) diff --git a/src/telelco-v0.2/Makefile b/src/telelco-v0.2/Makefile index 2fb4db5e..32cf7edd 100644 --- a/src/telelco-v0.2/Makefile +++ b/src/telelco-v0.2/Makefile @@ -77,11 +77,12 @@ CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g PROGNAME=telelco-v0.2 PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx SRC=$(ALTOS_SRC) ao_telelco.c OBJ=$(SRC:.c=.o) -all: $(PROG) +all: $(PROG) $(HEX) $(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) diff --git a/src/telemega-v0.1/Makefile b/src/telemega-v0.1/Makefile index 7acaedd2..0166ebc9 100644 --- a/src/telemega-v0.1/Makefile +++ b/src/telemega-v0.1/Makefile @@ -122,11 +122,12 @@ CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STA PROGNAME=telemega-v0.1 PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx SRC=$(ALTOS_SRC) ao_telemega.c OBJ=$(SRC:.c=.o) -all: $(PROG) +all: $(PROG) $(HEX) $(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) diff --git a/src/telemega-v0.3/Makefile b/src/telemega-v0.3/Makefile index a25b8b68..12e4152c 100644 --- a/src/telemega-v0.3/Makefile +++ b/src/telemega-v0.3/Makefile @@ -124,11 +124,12 @@ CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STA PROGNAME=telemega-v0.3 PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx SRC=$(ALTOS_SRC) ao_telemega.c OBJ=$(SRC:.c=.o) -all: $(PROG) +all: $(PROG) $(HEX) $(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) diff --git a/src/telemetrum-v2.0/Makefile b/src/telemetrum-v2.0/Makefile index a5370224..16408b03 100644 --- a/src/telemetrum-v2.0/Makefile +++ b/src/telemetrum-v2.0/Makefile @@ -95,11 +95,12 @@ CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STA PROGNAME=telemetrum-v2.0 PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx SRC=$(ALTOS_SRC) ao_telemetrum.c OBJ=$(SRC:.c=.o) -all: $(PROG) +all: $(PROG) $(HEX) $(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) diff --git a/src/telescience-v0.2/Makefile b/src/telescience-v0.2/Makefile index c53a6cc3..d76183c5 100644 --- a/src/telescience-v0.2/Makefile +++ b/src/telescience-v0.2/Makefile @@ -61,11 +61,12 @@ CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STA PROGNAME=telescience-v0.2 PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx SRC=$(ALTOS_SRC) ao_telescience.c OBJ=$(SRC:.c=.o) -all: $(PROG) +all: $(PROG) $(HEX) $(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) -- cgit v1.2.3 From bb72b4018dd6a422afe1916d9538bb9ff1e45353 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Sun, 8 Dec 2013 11:15:37 -0800 Subject: altos: Change flash loader name to just AltosFlash Remove the software version string from the product name Signed-off-by: Keith Packard <keithp@keithp.com> --- src/lpc/Makefile-flash.defs | 4 ++-- src/stm/Makefile-flash.defs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/lpc/Makefile-flash.defs b/src/lpc/Makefile-flash.defs index bb90b0d7..4a245d10 100644 --- a/src/lpc/Makefile-flash.defs +++ b/src/lpc/Makefile-flash.defs @@ -29,7 +29,7 @@ SRC = \ OBJ=$(SRC:.c=.o) -PRODUCT=AltosFlash-$(VERSION) +PRODUCT=AltosFlash PRODUCT_DEF=-DALTOS_FLASH IDPRODUCT=0x000a @@ -53,7 +53,7 @@ all: $(PROG) distclean: clean clean: - rm -f *.o $(PROG) + rm -f *.o $(HARDWARE)-$(PROGNAME)-*.elf rm -f ao_product.h install: diff --git a/src/stm/Makefile-flash.defs b/src/stm/Makefile-flash.defs index 159f8b9c..be3ae799 100644 --- a/src/stm/Makefile-flash.defs +++ b/src/stm/Makefile-flash.defs @@ -61,7 +61,7 @@ SRC = \ OBJ=$(SRC:.c=.o) -PRODUCT=AltosFlash-$(VERSION) +PRODUCT=AltosFlash PRODUCT_DEF=-DALTOS_FLASH IDPRODUCT=0x000a @@ -83,7 +83,7 @@ all: $(PROG) distclean: clean clean: - rm -f *.o $(PROG) + rm -f *.o $(HARDWARE)-$(PROGNAME)-*.elf rm -f ao_product.h install: -- cgit v1.2.3 From eded084c6caa1f9423d690c8b45c8042f8355987 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Sun, 8 Dec 2013 11:17:28 -0800 Subject: altos: remove all versions of stm-demo executable Signed-off-by: Keith Packard <keithp@keithp.com> --- src/stm-demo/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 990968c2..2c7e9df5 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -66,7 +66,7 @@ $(OBJ): $(INC) distclean: clean clean: - rm -f *.o $(PROG) + rm -f *.o stm-demo-*.elf rm -f ao_product.h install: -- cgit v1.2.3 From 2cb7a96567e1302a699f78290fab5e29693940ab Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Sun, 8 Dec 2013 19:05:01 -0800 Subject: altos/stm: arm-none-eabi-binutils now puts 'main' into .text.startup Change name of .text.ram to .ramtext, then load .text* into flash and .ramtext into ram. This ensures that 'main' and anything else in a random .text.* segment will get loaded into flash as appropriate. Signed-off-by: Keith Packard <keithp@keithp.com> --- src/stm/altos-loader.ld | 6 +++--- src/stm/ao_flash_stm.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/stm/altos-loader.ld b/src/stm/altos-loader.ld index 2be964f2..0753f5f7 100644 --- a/src/stm/altos-loader.ld +++ b/src/stm/altos-loader.ld @@ -37,11 +37,11 @@ SECTIONS { ao_romconfig.o(.romconfig*) ao_product.o(.romconfig*) - *(.text) /* Executable code */ + *(.text*) /* Executable code */ *(.ARM.exidx* .gnu.linkonce.armexidx.*) *(.rodata*) /* Constants */ - __text_end__ = .; } > rom + __text_end__ = .; /* Boot data which must live at the start of ram so that * the application and bootloader share the same addresses. @@ -66,7 +66,7 @@ SECTIONS { .textram BLOCK(8): { __data_start__ = .; __text_ram_start__ = .; - *(.text.ram) + *(.ramtext) __text_ram_end = .; } >ram AT>rom diff --git a/src/stm/ao_flash_stm.c b/src/stm/ao_flash_stm.c index d7a85582..38b1c2d8 100644 --- a/src/stm/ao_flash_stm.c +++ b/src/stm/ao_flash_stm.c @@ -69,7 +69,7 @@ ao_flash_wait_bsy(void) ; } -static void __attribute__ ((section(".text.ram"),noinline)) +static void __attribute__ ((section(".ramtext"),noinline)) _ao_flash_erase_page(uint32_t *page) { stm_flash.pecr |= (1 << STM_FLASH_PECR_ERASE) | (1 << STM_FLASH_PECR_PROG); @@ -91,7 +91,7 @@ ao_flash_erase_page(uint32_t *page) ao_flash_lock(); } -static void __attribute__ ((section(".text.ram"), noinline)) +static void __attribute__ ((section(".ramtext"), noinline)) _ao_flash_half_page(uint32_t *dst, uint32_t *src) { uint8_t i; -- cgit v1.2.3 From dd91a5d5069ff940e07b8817a934ee65d4e8e235 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Sun, 8 Dec 2013 21:08:36 -0800 Subject: altos: Oops. Was only filling out part of the TeleMetrum ADC record Because it's missing a return, we'd end up filling out one element of the ADC record per interrupt, and rotating through which one was set, hitting all of the even offsets within the struct. Yikes! Signed-off-by: Keith Packard <keithp@keithp.com> --- src/cc1111/ao_adc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index 15429677..1689ebef 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -85,6 +85,7 @@ ao_adc_isr(void) __interrupt 1 else #endif ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | sequence; + return; } #endif -- cgit v1.2.3 From ecb0465be76e9299511aeec663d267967834f6c3 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Mon, 9 Dec 2013 16:06:22 -0800 Subject: altos: Rename telemega-v0.3 to telemega-v1.0 Signed-off-by: Keith Packard <keithp@keithp.com> --- src/Makefile | 2 +- src/telemega-v0.3/.gitignore | 2 - src/telemega-v0.3/Makefile | 153 ------------- src/telemega-v0.3/ao_pins.h | 361 ------------------------------- src/telemega-v0.3/ao_telemega.c | 102 --------- src/telemega-v0.3/flash-loader/Makefile | 8 - src/telemega-v0.3/flash-loader/ao_pins.h | 34 --- src/telemega-v1.0/.gitignore | 2 + src/telemega-v1.0/Makefile | 153 +++++++++++++ src/telemega-v1.0/ao_pins.h | 361 +++++++++++++++++++++++++++++++ src/telemega-v1.0/ao_telemega.c | 102 +++++++++ src/telemega-v1.0/flash-loader/Makefile | 8 + src/telemega-v1.0/flash-loader/ao_pins.h | 34 +++ 13 files changed, 661 insertions(+), 661 deletions(-) delete mode 100644 src/telemega-v0.3/.gitignore delete mode 100644 src/telemega-v0.3/Makefile delete mode 100644 src/telemega-v0.3/ao_pins.h delete mode 100644 src/telemega-v0.3/ao_telemega.c delete mode 100644 src/telemega-v0.3/flash-loader/Makefile delete mode 100644 src/telemega-v0.3/flash-loader/ao_pins.h create mode 100644 src/telemega-v1.0/.gitignore create mode 100644 src/telemega-v1.0/Makefile create mode 100644 src/telemega-v1.0/ao_pins.h create mode 100644 src/telemega-v1.0/ao_telemega.c create mode 100644 src/telemega-v1.0/flash-loader/Makefile create mode 100644 src/telemega-v1.0/flash-loader/ao_pins.h (limited to 'src') diff --git a/src/Makefile b/src/Makefile index e7fa728b..bdd3307a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -26,7 +26,7 @@ SDCCDIRS=\ ARMM3DIRS=\ telemega-v0.1 telemega-v0.1/flash-loader \ - telemega-v0.3 telemega-v0.3/flash-loader \ + telemega-v1.0 telemega-v1.0/flash-loader \ telemetrum-v2.0 telemetrum-v2.0/flash-loader \ megadongle-v0.1 megadongle-v0.1/flash-loader \ telegps-v0.3 telegps-v0.3/flash-loader \ diff --git a/src/telemega-v0.3/.gitignore b/src/telemega-v0.3/.gitignore deleted file mode 100644 index e67759a2..00000000 --- a/src/telemega-v0.3/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -ao_product.h -telemega-*.elf diff --git a/src/telemega-v0.3/Makefile b/src/telemega-v0.3/Makefile deleted file mode 100644 index 12e4152c..00000000 --- a/src/telemega-v0.3/Makefile +++ /dev/null @@ -1,153 +0,0 @@ -# -# AltOS build -# -# - -include ../stm/Makefile.defs - -INC = \ - ao.h \ - ao_arch.h \ - ao_arch_funcs.h \ - ao_companion.h \ - ao_data.h \ - ao_sample.h \ - ao_pins.h \ - altitude-pa.h \ - ao_kalman.h \ - ao_product.h \ - ao_ms5607.h \ - ao_hmc5883.h \ - ao_mpu6000.h \ - ao_mma655x.h \ - ao_cc1120_CC1120.h \ - ao_profile.h \ - ao_task.h \ - ao_whiten.h \ - ao_sample_profile.h \ - ao_quaternion.h \ - math.h \ - ao_mpu.h \ - stm32l.h \ - math.h \ - Makefile - -# -# Common AltOS sources -# -# ao_hmc5883.c - -#PROFILE=ao_profile.c -#PROFILE_DEF=-DAO_PROFILE=1 - -#SAMPLE_PROFILE=ao_sample_profile.c \ -# ao_sample_profile_timer.c -#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1 - -#STACK_GUARD=ao_mpu_stm.c -#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1 - -MATH_SRC=\ - ef_acos.c \ - ef_sqrt.c \ - ef_rem_pio2.c \ - kf_cos.c \ - kf_sin.c \ - kf_rem_pio2.c \ - sf_copysign.c \ - sf_cos.c \ - sf_fabs.c \ - sf_floor.c \ - sf_scalbn.c \ - sf_sin.c - -ALTOS_SRC = \ - ao_boot_chain.c \ - ao_interrupt.c \ - ao_product.c \ - ao_romconfig.c \ - ao_cmd.c \ - ao_config.c \ - ao_task.c \ - ao_led.c \ - ao_stdio.c \ - ao_panic.c \ - ao_timer.c \ - ao_mutex.c \ - ao_serial_stm.c \ - ao_gps_ublox.c \ - ao_gps_show.c \ - ao_gps_report_mega.c \ - ao_ignite.c \ - ao_freq.c \ - ao_dma_stm.c \ - ao_spi_stm.c \ - ao_cc1120.c \ - ao_fec_tx.c \ - ao_fec_rx.c \ - ao_data.c \ - ao_ms5607.c \ - ao_mma655x.c \ - ao_hmc5883.c \ - ao_adc_stm.c \ - ao_beep_stm.c \ - ao_eeprom_stm.c \ - ao_storage.c \ - ao_m25.c \ - ao_usb_stm.c \ - ao_exti_stm.c \ - ao_report.c \ - ao_i2c_stm.c \ - ao_mpu6000.c \ - ao_convert_pa.c \ - ao_log.c \ - ao_log_mega.c \ - ao_sample.c \ - ao_kalman.c \ - ao_flight.c \ - ao_telemetry.c \ - ao_packet_slave.c \ - ao_packet.c \ - ao_companion.c \ - ao_pyro.c \ - ao_aprs.c \ - $(MATH_SRC) \ - $(PROFILE) \ - $(SAMPLE_PROFILE) \ - $(STACK_GUARD) - -PRODUCT=TeleMega-v0.3 -PRODUCT_DEF=-DTELEMEGA -IDPRODUCT=0x0023 - -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g - -PROGNAME=telemega-v0.3 -PROG=$(PROGNAME)-$(VERSION).elf -HEX=$(PROGNAME)-$(VERSION).ihx - -SRC=$(ALTOS_SRC) ao_telemega.c -OBJ=$(SRC:.c=.o) - -all: $(PROG) $(HEX) - -$(PROG): Makefile $(OBJ) altos.ld - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) - -../altitude-pa.h: make-altitude-pa - nickle $< > $@ - -$(OBJ): $(INC) - -ao_product.h: ao-make-product.5c ../Version - $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ - -distclean: clean - -clean: - rm -f *.o $(PROGNAME)-*.elf - rm -f ao_product.h - -install: - -uninstall: diff --git a/src/telemega-v0.3/ao_pins.h b/src/telemega-v0.3/ao_pins.h deleted file mode 100644 index 7ff676ea..00000000 --- a/src/telemega-v0.3/ao_pins.h +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright © 2012 Keith Packard <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_PINS_H_ -#define _AO_PINS_H_ - -#define HAS_TASK_QUEUE 1 - -/* 8MHz High speed external crystal */ -#define AO_HSE 8000000 - -/* PLLVCO = 96MHz (so that USB will work) */ -#define AO_PLLMUL 12 -#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12) - -/* SYSCLK = 32MHz (no need to go faster than CPU) */ -#define AO_PLLDIV 3 -#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3) - -/* HCLK = 32MHz (CPU clock) */ -#define AO_AHB_PRESCALER 1 -#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 - -/* Run APB1 at 16MHz (HCLK/2) */ -#define AO_APB1_PRESCALER 2 -#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2 - -/* Run APB2 at 16MHz (HCLK/2) */ -#define AO_APB2_PRESCALER 2 -#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2 - -#define HAS_SERIAL_1 1 -#define USE_SERIAL_1_STDIN 0 -#define SERIAL_1_PB6_PB7 0 -#define SERIAL_1_PA9_PA10 1 - -#define HAS_SERIAL_2 0 -#define USE_SERIAL_2_STDIN 0 -#define SERIAL_2_PA2_PA3 0 -#define SERIAL_2_PD5_PD6 0 - -#define HAS_SERIAL_3 1 -#define USE_SERIAL_3_STDIN 0 -#define SERIAL_3_PB10_PB11 0 -#define SERIAL_3_PC10_PC11 1 -#define SERIAL_3_PD8_PD9 0 - -#define ao_gps_getchar ao_serial3_getchar -#define ao_gps_putchar ao_serial3_putchar -#define ao_gps_set_speed ao_serial3_set_speed -#define ao_gps_fifo (ao_stm_usart3.rx_fifo) - -#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX (1024 * 1024) -#define HAS_EEPROM 1 -#define USE_INTERNAL_FLASH 0 -#define USE_EEPROM_CONFIG 1 -#define USE_STORAGE_CONFIG 0 -#define HAS_USB 1 -#define HAS_BEEP 1 -#define HAS_RADIO 1 -#define HAS_TELEMETRY 1 -#define HAS_APRS 1 - -#define HAS_SPI_1 1 -#define SPI_1_PA5_PA6_PA7 1 /* Barometer */ -#define SPI_1_PB3_PB4_PB5 0 -#define SPI_1_PE13_PE14_PE15 1 /* Accelerometer, Gyro */ -#define SPI_1_OSPEEDR STM_OSPEEDR_10MHz - -#define HAS_SPI_2 1 -#define SPI_2_PB13_PB14_PB15 1 /* Flash, Companion */ -#define SPI_2_PD1_PD3_PD4 0 -#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz - -#define SPI_2_PORT (&stm_gpiob) -#define SPI_2_SCK_PIN 13 -#define SPI_2_MISO_PIN 14 -#define SPI_2_MOSI_PIN 15 - -#define HAS_I2C_1 1 -#define I2C_1_PB8_PB9 1 - -#define HAS_I2C_2 0 -#define I2C_2_PB10_PB11 0 - -#define PACKET_HAS_SLAVE 1 -#define PACKET_HAS_MASTER 0 - -#define LOW_LEVEL_DEBUG 0 - -#define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOCEN -#define LED_PORT (&stm_gpioc) -#define LED_PIN_RED 8 -#define LED_PIN_GREEN 9 -#define AO_LED_RED (1 << LED_PIN_RED) -#define AO_LED_GREEN (1 << LED_PIN_GREEN) - -#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN) - -#define HAS_GPS 1 -#define HAS_FLIGHT 1 -#define HAS_ADC 1 -#define HAS_ADC_TEMP 1 -#define HAS_LOG 1 - -/* - * Igniter - */ - -#define HAS_IGNITE 1 -#define HAS_IGNITE_REPORT 1 - -#define AO_SENSE_PYRO(p,n) ((p)->adc.sense[n]) -#define AO_SENSE_DROGUE(p) ((p)->adc.sense[4]) -#define AO_SENSE_MAIN(p) ((p)->adc.sense[5]) -#define AO_IGNITER_CLOSED 400 -#define AO_IGNITER_OPEN 60 - -/* Pyro A */ -#define AO_PYRO_PORT_0 (&stm_gpiod) -#define AO_PYRO_PIN_0 6 - -/* Pyro B */ -#define AO_PYRO_PORT_1 (&stm_gpiod) -#define AO_PYRO_PIN_1 7 - -/* Pyro C */ -#define AO_PYRO_PORT_2 (&stm_gpiob) -#define AO_PYRO_PIN_2 5 - -/* Pyro D */ -#define AO_PYRO_PORT_3 (&stm_gpioe) -#define AO_PYRO_PIN_3 4 - -/* Drogue */ -#define AO_IGNITER_DROGUE_PORT (&stm_gpioe) -#define AO_IGNITER_DROGUE_PIN 6 - -/* Main */ -#define AO_IGNITER_MAIN_PORT (&stm_gpioe) -#define AO_IGNITER_MAIN_PIN 5 - -/* Number of general purpose pyro channels available */ -#define AO_PYRO_NUM 4 - -#define AO_IGNITER_SET_DROGUE(v) stm_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, v) -#define AO_IGNITER_SET_MAIN(v) stm_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, v) - -/* - * ADC - */ -#define AO_DATA_RING 32 -#define AO_ADC_NUM_SENSE 6 - -struct ao_adc { - int16_t sense[AO_ADC_NUM_SENSE]; - int16_t v_batt; - int16_t v_pbatt; - int16_t temp; -}; - -#define AO_ADC_DUMP(p) \ - printf("tick: %5u A: %5d B: %5d C: %5d D: %5d drogue: %5d main: %5d batt: %5d pbatt: %5d temp: %5d\n", \ - (p)->tick, \ - (p)->adc.sense[0], (p)->adc.sense[1], (p)->adc.sense[2], \ - (p)->adc.sense[3], (p)->adc.sense[4], (p)->adc.sense[5], \ - (p)->adc.v_batt, (p)->adc.v_pbatt, (p)->adc.temp) - -#define AO_ADC_SENSE_A 0 -#define AO_ADC_SENSE_A_PORT (&stm_gpioa) -#define AO_ADC_SENSE_A_PIN 0 - -#define AO_ADC_SENSE_B 1 -#define AO_ADC_SENSE_B_PORT (&stm_gpioa) -#define AO_ADC_SENSE_B_PIN 1 - -#define AO_ADC_SENSE_C 2 -#define AO_ADC_SENSE_C_PORT (&stm_gpioa) -#define AO_ADC_SENSE_C_PIN 2 - -#define AO_ADC_SENSE_D 3 -#define AO_ADC_SENSE_D_PORT (&stm_gpioa) -#define AO_ADC_SENSE_D_PIN 3 - -#define AO_ADC_SENSE_DROGUE 4 -#define AO_ADC_SENSE_DROGUE_PORT (&stm_gpioa) -#define AO_ADC_SENSE_DROGUE_PIN 4 - -#define AO_ADC_SENSE_MAIN 22 -#define AO_ADC_SENSE_MAIN_PORT (&stm_gpioe) -#define AO_ADC_SENSE_MAIN_PIN 7 - -#define AO_ADC_V_BATT 8 -#define AO_ADC_V_BATT_PORT (&stm_gpiob) -#define AO_ADC_V_BATT_PIN 0 - -#define AO_ADC_V_PBATT 9 -#define AO_ADC_V_PBATT_PORT (&stm_gpiob) -#define AO_ADC_V_PBATT_PIN 1 - -#define AO_ADC_TEMP 16 - -#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN) | \ - (1 << STM_RCC_AHBENR_GPIOEEN) | \ - (1 << STM_RCC_AHBENR_GPIOBEN)) - -#define AO_NUM_ADC_PIN (AO_ADC_NUM_SENSE + 2) - -#define AO_ADC_PIN0_PORT AO_ADC_SENSE_A_PORT -#define AO_ADC_PIN0_PIN AO_ADC_SENSE_A_PIN -#define AO_ADC_PIN1_PORT AO_ADC_SENSE_B_PORT -#define AO_ADC_PIN1_PIN AO_ADC_SENSE_B_PIN -#define AO_ADC_PIN2_PORT AO_ADC_SENSE_C_PORT -#define AO_ADC_PIN2_PIN AO_ADC_SENSE_C_PIN -#define AO_ADC_PIN3_PORT AO_ADC_SENSE_D_PORT -#define AO_ADC_PIN3_PIN AO_ADC_SENSE_D_PIN -#define AO_ADC_PIN4_PORT AO_ADC_SENSE_DROGUE_PORT -#define AO_ADC_PIN4_PIN AO_ADC_SENSE_DROGUE_PIN -#define AO_ADC_PIN5_PORT AO_ADC_SENSE_MAIN_PORT -#define AO_ADC_PIN5_PIN AO_ADC_SENSE_MAIN_PIN -#define AO_ADC_PIN6_PORT AO_ADC_V_BATT_PORT -#define AO_ADC_PIN6_PIN AO_ADC_V_BATT_PIN -#define AO_ADC_PIN7_PORT AO_ADC_V_PBATT_PORT -#define AO_ADC_PIN7_PIN AO_ADC_V_PBATT_PIN - -#define AO_NUM_ADC (AO_ADC_NUM_SENSE + 3) - -#define AO_ADC_SQ1 AO_ADC_SENSE_A -#define AO_ADC_SQ2 AO_ADC_SENSE_B -#define AO_ADC_SQ3 AO_ADC_SENSE_C -#define AO_ADC_SQ4 AO_ADC_SENSE_D -#define AO_ADC_SQ5 AO_ADC_SENSE_DROGUE -#define AO_ADC_SQ6 AO_ADC_SENSE_MAIN -#define AO_ADC_SQ7 AO_ADC_V_BATT -#define AO_ADC_SQ8 AO_ADC_V_PBATT -#define AO_ADC_SQ9 AO_ADC_TEMP - -/* - * Pressure sensor settings - */ -#define HAS_MS5607 1 -#define HAS_MS5611 0 -#define AO_MS5607_PRIVATE_PINS 1 -#define AO_MS5607_CS_PORT (&stm_gpioc) -#define AO_MS5607_CS_PIN 4 -#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) -#define AO_MS5607_MISO_PORT (&stm_gpioa) -#define AO_MS5607_MISO_PIN 6 -#define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO) -#define AO_MS5607_SPI_INDEX AO_SPI_1_PA5_PA6_PA7 - -/* - * SPI Flash memory - */ - -#define M25_MAX_CHIPS 1 -#define AO_M25_SPI_CS_PORT (&stm_gpiod) -#define AO_M25_SPI_CS_MASK (1 << 3) -#define AO_M25_SPI_BUS AO_SPI_2_PB13_PB14_PB15 - -/* - * Radio (cc1120) - */ - -/* gets pretty close to 434.550 */ - -#define AO_RADIO_CAL_DEFAULT 0x6ca333 - -#define AO_FEC_DEBUG 0 -#define AO_CC1120_SPI_CS_PORT (&stm_gpioc) -#define AO_CC1120_SPI_CS_PIN 5 -#define AO_CC1120_SPI_BUS AO_SPI_2_PB13_PB14_PB15 -#define AO_CC1120_SPI stm_spi2 - -#define AO_CC1120_INT_PORT (&stm_gpioe) -#define AO_CC1120_INT_PIN 1 -#define AO_CC1120_MCU_WAKEUP_PORT (&stm_gpioc) -#define AO_CC1120_MCU_WAKEUP_PIN (0) - -#define AO_CC1120_INT_GPIO 2 -#define AO_CC1120_INT_GPIO_IOCFG CC1120_IOCFG2 - -#define AO_CC1120_MARC_GPIO 3 -#define AO_CC1120_MARC_GPIO_IOCFG CC1120_IOCFG3 - -#define HAS_BOOT_RADIO 0 - -/* - * Mag sensor (hmc5883) - */ - -#define HAS_HMC5883 1 -#define AO_HMC5883_INT_PORT (&stm_gpioc) -#define AO_HMC5883_INT_PIN 12 -#define AO_HMC5883_I2C_INDEX STM_I2C_INDEX(1) - -/* - * mpu6000 - */ - -#define HAS_MPU6000 1 -#define AO_MPU6000_INT_PORT (&stm_gpioe) -#define AO_MPU6000_INT_PIN 0 -#define AO_MPU6000_SPI_BUS AO_SPI_1_PE13_PE14_PE15 -#define AO_MPU6000_SPI_CS_PORT (&stm_gpiod) -#define AO_MPU6000_SPI_CS_PIN 2 - -#define HAS_HIGHG_ACCEL 1 - -/* - * mma655x - */ - -#define HAS_MMA655X 1 -#define AO_MMA655X_SPI_INDEX AO_SPI_1_PE13_PE14_PE15 -#define AO_MMA655X_CS_PORT (&stm_gpiod) -#define AO_MMA655X_CS_PIN 4 - -#define NUM_CMDS 16 - -/* - * Companion - */ - -#define AO_COMPANION_CS_PORT (&stm_gpiod) -#define AO_COMPANION_CS_PIN (0) -#define AO_COMPANION_SPI_BUS AO_SPI_2_PB13_PB14_PB15 - -/* - * Monitor - */ - -#define HAS_MONITOR 0 -#define LEGACY_MONITOR 0 -#define HAS_MONITOR_PUT 1 -#define AO_MONITOR_LED 0 -#define HAS_RSSI 0 - -/* - * Profiling Viterbi decoding - */ - -#ifndef AO_PROFILE -#define AO_PROFILE 0 -#endif - -#endif /* _AO_PINS_H_ */ diff --git a/src/telemega-v0.3/ao_telemega.c b/src/telemega-v0.3/ao_telemega.c deleted file mode 100644 index 7b035269..00000000 --- a/src/telemega-v0.3/ao_telemega.c +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright © 2011 Keith Packard <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include <ao.h> -#include <ao_hmc5883.h> -#include <ao_mpu6000.h> -#include <ao_mma655x.h> -#include <ao_log.h> -#include <ao_exti.h> -#include <ao_packet.h> -#include <ao_companion.h> -#include <ao_profile.h> -#include <ao_eeprom.h> -#if HAS_SAMPLE_PROFILE -#include <ao_sample_profile.h> -#endif -#include <ao_pyro.h> -#if HAS_STACK_GUARD -#include <ao_mpu.h> -#endif - -int -main(void) -{ - ao_clock_init(); - -#if HAS_STACK_GUARD - ao_mpu_init(); -#endif - - ao_task_init(); - ao_serial_init(); - ao_led_init(LEDS_AVAILABLE); - ao_led_on(AO_LED_GREEN); - ao_timer_init(); - - ao_i2c_init(); - ao_spi_init(); - ao_dma_init(); - ao_exti_init(); - - ao_adc_init(); -#if HAS_BEEP - ao_beep_init(); -#endif - ao_cmd_init(); - -#if HAS_MS5607 - ao_ms5607_init(); -#endif -#if HAS_HMC5883 - ao_hmc5883_init(); -#endif -#if HAS_MPU6000 - ao_mpu6000_init(); -#endif -#if HAS_MMA655X - ao_mma655x_init(); -#endif - - ao_eeprom_init(); - ao_storage_init(); - - ao_flight_init(); - ao_log_init(); - ao_report_init(); - - ao_usb_init(); - ao_gps_init(); - ao_gps_report_mega_init(); - ao_telemetry_init(); - ao_radio_init(); - ao_packet_slave_init(FALSE); - ao_igniter_init(); - ao_companion_init(); - ao_pyro_init(); - - ao_config_init(); -#if AO_PROFILE - ao_profile_init(); -#endif -#if HAS_SAMPLE_PROFILE - ao_sample_profile_init(); -#endif - - ao_start_scheduler(); - return 0; -} diff --git a/src/telemega-v0.3/flash-loader/Makefile b/src/telemega-v0.3/flash-loader/Makefile deleted file mode 100644 index 8fda18cd..00000000 --- a/src/telemega-v0.3/flash-loader/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# -# AltOS flash loader build -# -# - -TOPDIR=../.. -HARDWARE=telemega-v0.3 -include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telemega-v0.3/flash-loader/ao_pins.h b/src/telemega-v0.3/flash-loader/ao_pins.h deleted file mode 100644 index 1af92f13..00000000 --- a/src/telemega-v0.3/flash-loader/ao_pins.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright © 2013 Keith Packard <keithp@keithp.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_PINS_H_ -#define _AO_PINS_H_ - -/* External crystal at 8MHz */ -#define AO_HSE 8000000 - -#include <ao_flash_stm_pins.h> - -/* Companion port cs_companion0 PD0 */ - -#define AO_BOOT_PIN 1 -#define AO_BOOT_APPLICATION_GPIO stm_gpiod -#define AO_BOOT_APPLICATION_PIN 0 -#define AO_BOOT_APPLICATION_VALUE 1 -#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP - -#endif /* _AO_PINS_H_ */ diff --git a/src/telemega-v1.0/.gitignore b/src/telemega-v1.0/.gitignore new file mode 100644 index 00000000..e67759a2 --- /dev/null +++ b/src/telemega-v1.0/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +telemega-*.elf diff --git a/src/telemega-v1.0/Makefile b/src/telemega-v1.0/Makefile new file mode 100644 index 00000000..e3204c11 --- /dev/null +++ b/src/telemega-v1.0/Makefile @@ -0,0 +1,153 @@ +# +# AltOS build +# +# + +include ../stm/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_companion.h \ + ao_data.h \ + ao_sample.h \ + ao_pins.h \ + altitude-pa.h \ + ao_kalman.h \ + ao_product.h \ + ao_ms5607.h \ + ao_hmc5883.h \ + ao_mpu6000.h \ + ao_mma655x.h \ + ao_cc1120_CC1120.h \ + ao_profile.h \ + ao_task.h \ + ao_whiten.h \ + ao_sample_profile.h \ + ao_quaternion.h \ + math.h \ + ao_mpu.h \ + stm32l.h \ + math.h \ + Makefile + +# +# Common AltOS sources +# +# ao_hmc5883.c + +#PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 + +#SAMPLE_PROFILE=ao_sample_profile.c \ +# ao_sample_profile_timer.c +#SAMPLE_PROFILE_DEF=-DHAS_SAMPLE_PROFILE=1 + +#STACK_GUARD=ao_mpu_stm.c +#STACK_GUARD_DEF=-DHAS_STACK_GUARD=1 + +MATH_SRC=\ + ef_acos.c \ + ef_sqrt.c \ + ef_rem_pio2.c \ + kf_cos.c \ + kf_sin.c \ + kf_rem_pio2.c \ + sf_copysign.c \ + sf_cos.c \ + sf_fabs.c \ + sf_floor.c \ + sf_scalbn.c \ + sf_sin.c + +ALTOS_SRC = \ + ao_boot_chain.c \ + ao_interrupt.c \ + ao_product.c \ + ao_romconfig.c \ + ao_cmd.c \ + ao_config.c \ + ao_task.c \ + ao_led.c \ + ao_stdio.c \ + ao_panic.c \ + ao_timer.c \ + ao_mutex.c \ + ao_serial_stm.c \ + ao_gps_ublox.c \ + ao_gps_show.c \ + ao_gps_report_mega.c \ + ao_ignite.c \ + ao_freq.c \ + ao_dma_stm.c \ + ao_spi_stm.c \ + ao_cc1120.c \ + ao_fec_tx.c \ + ao_fec_rx.c \ + ao_data.c \ + ao_ms5607.c \ + ao_mma655x.c \ + ao_hmc5883.c \ + ao_adc_stm.c \ + ao_beep_stm.c \ + ao_eeprom_stm.c \ + ao_storage.c \ + ao_m25.c \ + ao_usb_stm.c \ + ao_exti_stm.c \ + ao_report.c \ + ao_i2c_stm.c \ + ao_mpu6000.c \ + ao_convert_pa.c \ + ao_log.c \ + ao_log_mega.c \ + ao_sample.c \ + ao_kalman.c \ + ao_flight.c \ + ao_telemetry.c \ + ao_packet_slave.c \ + ao_packet.c \ + ao_companion.c \ + ao_pyro.c \ + ao_aprs.c \ + $(MATH_SRC) \ + $(PROFILE) \ + $(SAMPLE_PROFILE) \ + $(STACK_GUARD) + +PRODUCT=TeleMega-v1.0 +PRODUCT_DEF=-DTELEMEGA +IDPRODUCT=0x0023 + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) $(SAMPLE_PROFILE_DEF) $(STACK_GUARD_DEF) -Os -g + +PROGNAME=telemega-v1.0 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_telemega.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +../altitude-pa.h: make-altitude-pa + nickle $< > $@ + +$(OBJ): $(INC) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f *.o $(PROGNAME)-*.elf + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/telemega-v1.0/ao_pins.h b/src/telemega-v1.0/ao_pins.h new file mode 100644 index 00000000..7ff676ea --- /dev/null +++ b/src/telemega-v1.0/ao_pins.h @@ -0,0 +1,361 @@ +/* + * Copyright © 2012 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_TASK_QUEUE 1 + +/* 8MHz High speed external crystal */ +#define AO_HSE 8000000 + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL 12 +#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12) + +/* SYSCLK = 32MHz (no need to go faster than CPU) */ +#define AO_PLLDIV 3 +#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHz (CPU clock) */ +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at 16MHz (HCLK/2) */ +#define AO_APB1_PRESCALER 2 +#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +/* Run APB2 at 16MHz (HCLK/2) */ +#define AO_APB2_PRESCALER 2 +#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +#define HAS_SERIAL_1 1 +#define USE_SERIAL_1_STDIN 0 +#define SERIAL_1_PB6_PB7 0 +#define SERIAL_1_PA9_PA10 1 + +#define HAS_SERIAL_2 0 +#define USE_SERIAL_2_STDIN 0 +#define SERIAL_2_PA2_PA3 0 +#define SERIAL_2_PD5_PD6 0 + +#define HAS_SERIAL_3 1 +#define USE_SERIAL_3_STDIN 0 +#define SERIAL_3_PB10_PB11 0 +#define SERIAL_3_PC10_PC11 1 +#define SERIAL_3_PD8_PD9 0 + +#define ao_gps_getchar ao_serial3_getchar +#define ao_gps_putchar ao_serial3_putchar +#define ao_gps_set_speed ao_serial3_set_speed +#define ao_gps_fifo (ao_stm_usart3.rx_fifo) + +#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX (1024 * 1024) +#define HAS_EEPROM 1 +#define USE_INTERNAL_FLASH 0 +#define USE_EEPROM_CONFIG 1 +#define USE_STORAGE_CONFIG 0 +#define HAS_USB 1 +#define HAS_BEEP 1 +#define HAS_RADIO 1 +#define HAS_TELEMETRY 1 +#define HAS_APRS 1 + +#define HAS_SPI_1 1 +#define SPI_1_PA5_PA6_PA7 1 /* Barometer */ +#define SPI_1_PB3_PB4_PB5 0 +#define SPI_1_PE13_PE14_PE15 1 /* Accelerometer, Gyro */ +#define SPI_1_OSPEEDR STM_OSPEEDR_10MHz + +#define HAS_SPI_2 1 +#define SPI_2_PB13_PB14_PB15 1 /* Flash, Companion */ +#define SPI_2_PD1_PD3_PD4 0 +#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz + +#define SPI_2_PORT (&stm_gpiob) +#define SPI_2_SCK_PIN 13 +#define SPI_2_MISO_PIN 14 +#define SPI_2_MOSI_PIN 15 + +#define HAS_I2C_1 1 +#define I2C_1_PB8_PB9 1 + +#define HAS_I2C_2 0 +#define I2C_2_PB10_PB11 0 + +#define PACKET_HAS_SLAVE 1 +#define PACKET_HAS_MASTER 0 + +#define LOW_LEVEL_DEBUG 0 + +#define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOCEN +#define LED_PORT (&stm_gpioc) +#define LED_PIN_RED 8 +#define LED_PIN_GREEN 9 +#define AO_LED_RED (1 << LED_PIN_RED) +#define AO_LED_GREEN (1 << LED_PIN_GREEN) + +#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN) + +#define HAS_GPS 1 +#define HAS_FLIGHT 1 +#define HAS_ADC 1 +#define HAS_ADC_TEMP 1 +#define HAS_LOG 1 + +/* + * Igniter + */ + +#define HAS_IGNITE 1 +#define HAS_IGNITE_REPORT 1 + +#define AO_SENSE_PYRO(p,n) ((p)->adc.sense[n]) +#define AO_SENSE_DROGUE(p) ((p)->adc.sense[4]) +#define AO_SENSE_MAIN(p) ((p)->adc.sense[5]) +#define AO_IGNITER_CLOSED 400 +#define AO_IGNITER_OPEN 60 + +/* Pyro A */ +#define AO_PYRO_PORT_0 (&stm_gpiod) +#define AO_PYRO_PIN_0 6 + +/* Pyro B */ +#define AO_PYRO_PORT_1 (&stm_gpiod) +#define AO_PYRO_PIN_1 7 + +/* Pyro C */ +#define AO_PYRO_PORT_2 (&stm_gpiob) +#define AO_PYRO_PIN_2 5 + +/* Pyro D */ +#define AO_PYRO_PORT_3 (&stm_gpioe) +#define AO_PYRO_PIN_3 4 + +/* Drogue */ +#define AO_IGNITER_DROGUE_PORT (&stm_gpioe) +#define AO_IGNITER_DROGUE_PIN 6 + +/* Main */ +#define AO_IGNITER_MAIN_PORT (&stm_gpioe) +#define AO_IGNITER_MAIN_PIN 5 + +/* Number of general purpose pyro channels available */ +#define AO_PYRO_NUM 4 + +#define AO_IGNITER_SET_DROGUE(v) stm_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, v) +#define AO_IGNITER_SET_MAIN(v) stm_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, v) + +/* + * ADC + */ +#define AO_DATA_RING 32 +#define AO_ADC_NUM_SENSE 6 + +struct ao_adc { + int16_t sense[AO_ADC_NUM_SENSE]; + int16_t v_batt; + int16_t v_pbatt; + int16_t temp; +}; + +#define AO_ADC_DUMP(p) \ + printf("tick: %5u A: %5d B: %5d C: %5d D: %5d drogue: %5d main: %5d batt: %5d pbatt: %5d temp: %5d\n", \ + (p)->tick, \ + (p)->adc.sense[0], (p)->adc.sense[1], (p)->adc.sense[2], \ + (p)->adc.sense[3], (p)->adc.sense[4], (p)->adc.sense[5], \ + (p)->adc.v_batt, (p)->adc.v_pbatt, (p)->adc.temp) + +#define AO_ADC_SENSE_A 0 +#define AO_ADC_SENSE_A_PORT (&stm_gpioa) +#define AO_ADC_SENSE_A_PIN 0 + +#define AO_ADC_SENSE_B 1 +#define AO_ADC_SENSE_B_PORT (&stm_gpioa) +#define AO_ADC_SENSE_B_PIN 1 + +#define AO_ADC_SENSE_C 2 +#define AO_ADC_SENSE_C_PORT (&stm_gpioa) +#define AO_ADC_SENSE_C_PIN 2 + +#define AO_ADC_SENSE_D 3 +#define AO_ADC_SENSE_D_PORT (&stm_gpioa) +#define AO_ADC_SENSE_D_PIN 3 + +#define AO_ADC_SENSE_DROGUE 4 +#define AO_ADC_SENSE_DROGUE_PORT (&stm_gpioa) +#define AO_ADC_SENSE_DROGUE_PIN 4 + +#define AO_ADC_SENSE_MAIN 22 +#define AO_ADC_SENSE_MAIN_PORT (&stm_gpioe) +#define AO_ADC_SENSE_MAIN_PIN 7 + +#define AO_ADC_V_BATT 8 +#define AO_ADC_V_BATT_PORT (&stm_gpiob) +#define AO_ADC_V_BATT_PIN 0 + +#define AO_ADC_V_PBATT 9 +#define AO_ADC_V_PBATT_PORT (&stm_gpiob) +#define AO_ADC_V_PBATT_PIN 1 + +#define AO_ADC_TEMP 16 + +#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN) | \ + (1 << STM_RCC_AHBENR_GPIOEEN) | \ + (1 << STM_RCC_AHBENR_GPIOBEN)) + +#define AO_NUM_ADC_PIN (AO_ADC_NUM_SENSE + 2) + +#define AO_ADC_PIN0_PORT AO_ADC_SENSE_A_PORT +#define AO_ADC_PIN0_PIN AO_ADC_SENSE_A_PIN +#define AO_ADC_PIN1_PORT AO_ADC_SENSE_B_PORT +#define AO_ADC_PIN1_PIN AO_ADC_SENSE_B_PIN +#define AO_ADC_PIN2_PORT AO_ADC_SENSE_C_PORT +#define AO_ADC_PIN2_PIN AO_ADC_SENSE_C_PIN +#define AO_ADC_PIN3_PORT AO_ADC_SENSE_D_PORT +#define AO_ADC_PIN3_PIN AO_ADC_SENSE_D_PIN +#define AO_ADC_PIN4_PORT AO_ADC_SENSE_DROGUE_PORT +#define AO_ADC_PIN4_PIN AO_ADC_SENSE_DROGUE_PIN +#define AO_ADC_PIN5_PORT AO_ADC_SENSE_MAIN_PORT +#define AO_ADC_PIN5_PIN AO_ADC_SENSE_MAIN_PIN +#define AO_ADC_PIN6_PORT AO_ADC_V_BATT_PORT +#define AO_ADC_PIN6_PIN AO_ADC_V_BATT_PIN +#define AO_ADC_PIN7_PORT AO_ADC_V_PBATT_PORT +#define AO_ADC_PIN7_PIN AO_ADC_V_PBATT_PIN + +#define AO_NUM_ADC (AO_ADC_NUM_SENSE + 3) + +#define AO_ADC_SQ1 AO_ADC_SENSE_A +#define AO_ADC_SQ2 AO_ADC_SENSE_B +#define AO_ADC_SQ3 AO_ADC_SENSE_C +#define AO_ADC_SQ4 AO_ADC_SENSE_D +#define AO_ADC_SQ5 AO_ADC_SENSE_DROGUE +#define AO_ADC_SQ6 AO_ADC_SENSE_MAIN +#define AO_ADC_SQ7 AO_ADC_V_BATT +#define AO_ADC_SQ8 AO_ADC_V_PBATT +#define AO_ADC_SQ9 AO_ADC_TEMP + +/* + * Pressure sensor settings + */ +#define HAS_MS5607 1 +#define HAS_MS5611 0 +#define AO_MS5607_PRIVATE_PINS 1 +#define AO_MS5607_CS_PORT (&stm_gpioc) +#define AO_MS5607_CS_PIN 4 +#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) +#define AO_MS5607_MISO_PORT (&stm_gpioa) +#define AO_MS5607_MISO_PIN 6 +#define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO) +#define AO_MS5607_SPI_INDEX AO_SPI_1_PA5_PA6_PA7 + +/* + * SPI Flash memory + */ + +#define M25_MAX_CHIPS 1 +#define AO_M25_SPI_CS_PORT (&stm_gpiod) +#define AO_M25_SPI_CS_MASK (1 << 3) +#define AO_M25_SPI_BUS AO_SPI_2_PB13_PB14_PB15 + +/* + * Radio (cc1120) + */ + +/* gets pretty close to 434.550 */ + +#define AO_RADIO_CAL_DEFAULT 0x6ca333 + +#define AO_FEC_DEBUG 0 +#define AO_CC1120_SPI_CS_PORT (&stm_gpioc) +#define AO_CC1120_SPI_CS_PIN 5 +#define AO_CC1120_SPI_BUS AO_SPI_2_PB13_PB14_PB15 +#define AO_CC1120_SPI stm_spi2 + +#define AO_CC1120_INT_PORT (&stm_gpioe) +#define AO_CC1120_INT_PIN 1 +#define AO_CC1120_MCU_WAKEUP_PORT (&stm_gpioc) +#define AO_CC1120_MCU_WAKEUP_PIN (0) + +#define AO_CC1120_INT_GPIO 2 +#define AO_CC1120_INT_GPIO_IOCFG CC1120_IOCFG2 + +#define AO_CC1120_MARC_GPIO 3 +#define AO_CC1120_MARC_GPIO_IOCFG CC1120_IOCFG3 + +#define HAS_BOOT_RADIO 0 + +/* + * Mag sensor (hmc5883) + */ + +#define HAS_HMC5883 1 +#define AO_HMC5883_INT_PORT (&stm_gpioc) +#define AO_HMC5883_INT_PIN 12 +#define AO_HMC5883_I2C_INDEX STM_I2C_INDEX(1) + +/* + * mpu6000 + */ + +#define HAS_MPU6000 1 +#define AO_MPU6000_INT_PORT (&stm_gpioe) +#define AO_MPU6000_INT_PIN 0 +#define AO_MPU6000_SPI_BUS AO_SPI_1_PE13_PE14_PE15 +#define AO_MPU6000_SPI_CS_PORT (&stm_gpiod) +#define AO_MPU6000_SPI_CS_PIN 2 + +#define HAS_HIGHG_ACCEL 1 + +/* + * mma655x + */ + +#define HAS_MMA655X 1 +#define AO_MMA655X_SPI_INDEX AO_SPI_1_PE13_PE14_PE15 +#define AO_MMA655X_CS_PORT (&stm_gpiod) +#define AO_MMA655X_CS_PIN 4 + +#define NUM_CMDS 16 + +/* + * Companion + */ + +#define AO_COMPANION_CS_PORT (&stm_gpiod) +#define AO_COMPANION_CS_PIN (0) +#define AO_COMPANION_SPI_BUS AO_SPI_2_PB13_PB14_PB15 + +/* + * Monitor + */ + +#define HAS_MONITOR 0 +#define LEGACY_MONITOR 0 +#define HAS_MONITOR_PUT 1 +#define AO_MONITOR_LED 0 +#define HAS_RSSI 0 + +/* + * Profiling Viterbi decoding + */ + +#ifndef AO_PROFILE +#define AO_PROFILE 0 +#endif + +#endif /* _AO_PINS_H_ */ diff --git a/src/telemega-v1.0/ao_telemega.c b/src/telemega-v1.0/ao_telemega.c new file mode 100644 index 00000000..7b035269 --- /dev/null +++ b/src/telemega-v1.0/ao_telemega.c @@ -0,0 +1,102 @@ +/* + * Copyright © 2011 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include <ao.h> +#include <ao_hmc5883.h> +#include <ao_mpu6000.h> +#include <ao_mma655x.h> +#include <ao_log.h> +#include <ao_exti.h> +#include <ao_packet.h> +#include <ao_companion.h> +#include <ao_profile.h> +#include <ao_eeprom.h> +#if HAS_SAMPLE_PROFILE +#include <ao_sample_profile.h> +#endif +#include <ao_pyro.h> +#if HAS_STACK_GUARD +#include <ao_mpu.h> +#endif + +int +main(void) +{ + ao_clock_init(); + +#if HAS_STACK_GUARD + ao_mpu_init(); +#endif + + ao_task_init(); + ao_serial_init(); + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_GREEN); + ao_timer_init(); + + ao_i2c_init(); + ao_spi_init(); + ao_dma_init(); + ao_exti_init(); + + ao_adc_init(); +#if HAS_BEEP + ao_beep_init(); +#endif + ao_cmd_init(); + +#if HAS_MS5607 + ao_ms5607_init(); +#endif +#if HAS_HMC5883 + ao_hmc5883_init(); +#endif +#if HAS_MPU6000 + ao_mpu6000_init(); +#endif +#if HAS_MMA655X + ao_mma655x_init(); +#endif + + ao_eeprom_init(); + ao_storage_init(); + + ao_flight_init(); + ao_log_init(); + ao_report_init(); + + ao_usb_init(); + ao_gps_init(); + ao_gps_report_mega_init(); + ao_telemetry_init(); + ao_radio_init(); + ao_packet_slave_init(FALSE); + ao_igniter_init(); + ao_companion_init(); + ao_pyro_init(); + + ao_config_init(); +#if AO_PROFILE + ao_profile_init(); +#endif +#if HAS_SAMPLE_PROFILE + ao_sample_profile_init(); +#endif + + ao_start_scheduler(); + return 0; +} diff --git a/src/telemega-v1.0/flash-loader/Makefile b/src/telemega-v1.0/flash-loader/Makefile new file mode 100644 index 00000000..a11f800b --- /dev/null +++ b/src/telemega-v1.0/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telemega-v1.0 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telemega-v1.0/flash-loader/ao_pins.h b/src/telemega-v1.0/flash-loader/ao_pins.h new file mode 100644 index 00000000..1af92f13 --- /dev/null +++ b/src/telemega-v1.0/flash-loader/ao_pins.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2013 Keith Packard <keithp@keithp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +/* External crystal at 8MHz */ +#define AO_HSE 8000000 + +#include <ao_flash_stm_pins.h> + +/* Companion port cs_companion0 PD0 */ + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO stm_gpiod +#define AO_BOOT_APPLICATION_PIN 0 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +#endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From a4596c134aa5e7867f1ca1d86d36afb2af9b8999 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Tue, 10 Dec 2013 00:39:52 -0800 Subject: altos: Remove ARM .ihx files on 'make clean' Signed-off-by: Keith Packard <keithp@keithp.com> --- src/easymini-v1.0/Makefile | 2 +- src/megadongle-v0.1/Makefile | 2 +- src/stm-demo/Makefile | 2 +- src/telegps-v0.1/Makefile | 2 +- src/telegps-v0.3/Makefile | 2 +- src/telelco-v0.1/Makefile | 2 +- src/telelco-v0.2/Makefile | 2 +- src/telemega-v0.1/Makefile | 2 +- src/telemega-v1.0/Makefile | 2 +- src/telemetrum-v2.0/Makefile | 2 +- src/telescience-v0.2/Makefile | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/easymini-v1.0/Makefile b/src/easymini-v1.0/Makefile index 8042874f..7dae2692 100644 --- a/src/easymini-v1.0/Makefile +++ b/src/easymini-v1.0/Makefile @@ -75,7 +75,7 @@ load: $(PROG) distclean: clean clean: - rm -f *.o $(PROGNAME)-*.elf + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx rm -f ao_product.h install: diff --git a/src/megadongle-v0.1/Makefile b/src/megadongle-v0.1/Makefile index a8c3a584..6035c348 100644 --- a/src/megadongle-v0.1/Makefile +++ b/src/megadongle-v0.1/Makefile @@ -80,7 +80,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean clean: - rm -f *.o $(PROGNAME)-*.elf + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx rm -f ao_product.h install: diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 2c7e9df5..98fcd9e5 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -66,7 +66,7 @@ $(OBJ): $(INC) distclean: clean clean: - rm -f *.o stm-demo-*.elf + rm -f *.o *.elf *.ihx rm -f ao_product.h install: diff --git a/src/telegps-v0.1/Makefile b/src/telegps-v0.1/Makefile index 96366cfc..49e325ac 100644 --- a/src/telegps-v0.1/Makefile +++ b/src/telegps-v0.1/Makefile @@ -92,7 +92,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean clean: - rm -f *.o $(PROGNAME)-*.elf + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx rm -f ao_product.h install: diff --git a/src/telegps-v0.3/Makefile b/src/telegps-v0.3/Makefile index d129d295..bb9c8c64 100644 --- a/src/telegps-v0.3/Makefile +++ b/src/telegps-v0.3/Makefile @@ -76,7 +76,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean clean: - rm -f *.o ao_serial_lpc.h $(PROGNAME)-*.elf + rm -f *.o ao_serial_lpc.h $(PROGNAME)-*.elf $(PROGNAME)-*.ihx rm -f ao_product.h install: diff --git a/src/telelco-v0.1/Makefile b/src/telelco-v0.1/Makefile index e494403c..44d9237f 100644 --- a/src/telelco-v0.1/Makefile +++ b/src/telelco-v0.1/Makefile @@ -90,7 +90,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean clean: - rm -f *.o $(PROGNAME)-*.elf + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx rm -f ao_product.h install: diff --git a/src/telelco-v0.2/Makefile b/src/telelco-v0.2/Makefile index 32cf7edd..f28bdd32 100644 --- a/src/telelco-v0.2/Makefile +++ b/src/telelco-v0.2/Makefile @@ -98,7 +98,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean clean: - rm -f *.o $(PROGNAME)-*.elf + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx rm -f ao_product.h install: diff --git a/src/telemega-v0.1/Makefile b/src/telemega-v0.1/Makefile index 0166ebc9..26afa38d 100644 --- a/src/telemega-v0.1/Makefile +++ b/src/telemega-v0.1/Makefile @@ -143,7 +143,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean clean: - rm -f *.o $(PROGNAME)-*.elf + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx rm -f ao_product.h install: diff --git a/src/telemega-v1.0/Makefile b/src/telemega-v1.0/Makefile index e3204c11..543f7e74 100644 --- a/src/telemega-v1.0/Makefile +++ b/src/telemega-v1.0/Makefile @@ -145,7 +145,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean clean: - rm -f *.o $(PROGNAME)-*.elf + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx rm -f ao_product.h install: diff --git a/src/telemetrum-v2.0/Makefile b/src/telemetrum-v2.0/Makefile index 16408b03..cebc9cab 100644 --- a/src/telemetrum-v2.0/Makefile +++ b/src/telemetrum-v2.0/Makefile @@ -116,7 +116,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean clean: - rm -f *.o $(PROGNAME)-*.elf + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx rm -f ao_product.h install: diff --git a/src/telescience-v0.2/Makefile b/src/telescience-v0.2/Makefile index d76183c5..6b7ea8c7 100644 --- a/src/telescience-v0.2/Makefile +++ b/src/telescience-v0.2/Makefile @@ -79,7 +79,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean clean: - rm -f *.o $(PROGNAME)-*.elf + rm -f *.o $(PROGNAME)-*.elf $(PROGNAME)-*.ihx rm -f ao_product.h install: -- cgit v1.2.3 From 2ecb6a8276b2ce40d2a4da586dbc17581cfda26d Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Tue, 17 Dec 2013 20:23:00 -0800 Subject: altos: Broke TeleMetrum GPS reporting by holding the GPS mutex too much We can't hold the GPS mutex while waiting for the GPS receiver to load data as it protects the GPS data with the GPS mutex. Signed-off-by: Keith Packard <keithp@keithp.com> --- src/core/ao_gps_report.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_gps_report.c b/src/core/ao_gps_report.c index 8d15c083..07201ac2 100644 --- a/src/core/ao_gps_report.c +++ b/src/core/ao_gps_report.c @@ -27,9 +27,9 @@ ao_gps_report(void) uint8_t new; for (;;) { - ao_mutex_get(&ao_gps_mutex); while ((new = ao_gps_new) == 0) ao_sleep(&ao_gps_new); + ao_mutex_get(&ao_gps_mutex); if (new & AO_GPS_NEW_DATA) ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); if (new & AO_GPS_NEW_TRACKING) -- cgit v1.2.3 From 1f035ac2df1cfa6964ae904aba0aedde279ca921 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Tue, 17 Dec 2013 23:50:54 -0800 Subject: altos: Use all 16 bits of setup packet len when limiting reply len We were only using the low 8 bits of the setup packet reply max len, which meant that if the other side sent a weird max len (as Windows 7 does), then we'd truncate our setup reply to whatever was in the low 8 bits of that value. Signed-off-by: Keith Packard <keithp@keithp.com> --- src/lpc/ao_usb_lpc.c | 2 +- src/stm/ao_usb_stm.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index 144d1075..108822ce 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -450,7 +450,7 @@ ao_usb_ep0_out_set(uint8_t *data, uint8_t len) } static void -ao_usb_ep0_in_start(uint8_t max) +ao_usb_ep0_in_start(uint16_t max) { /* Don't send more than asked for */ if (ao_usb_ep0_in_len > max) diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index 11dde92e..b00390ec 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -572,7 +572,7 @@ ao_usb_ep0_out_set(uint8_t *data, uint8_t len) } static void -ao_usb_ep0_in_start(uint8_t max) +ao_usb_ep0_in_start(uint16_t max) { /* Don't send more than asked for */ if (ao_usb_ep0_in_len > max) -- cgit v1.2.3 From 18852efa108ba6e6e69dfd5076d4f4c01f62b4ef Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Wed, 18 Dec 2013 01:12:11 -0800 Subject: altos: Make TeleMega v0.1 work more like TeleMega v1.0 I've still got one working v0.1 board which is useful for testing stuff, so make it work more like the released TeleMega: * Use E for drogue, F for main * Use on-chip eeprom for config * Fix ADC report printf to match Signed-off-by: Keith Packard <keithp@keithp.com> --- src/telemega-v0.1/Makefile | 3 +- src/telemega-v0.1/ao_pins.h | 98 ++++++++++++++++++++--------------------- src/telemega-v0.1/ao_telemega.c | 2 + 3 files changed, 52 insertions(+), 51 deletions(-) (limited to 'src') diff --git a/src/telemega-v0.1/Makefile b/src/telemega-v0.1/Makefile index 26afa38d..0145f49c 100644 --- a/src/telemega-v0.1/Makefile +++ b/src/telemega-v0.1/Makefile @@ -90,6 +90,7 @@ ALTOS_SRC = \ ao_hmc5883.c \ ao_adc_stm.c \ ao_beep_stm.c \ + ao_eeprom_stm.c \ ao_storage.c \ ao_m25.c \ ao_usb_stm.c \ @@ -109,9 +110,9 @@ ALTOS_SRC = \ ao_companion.c \ ao_pyro.c \ ao_aprs.c \ + $(MATH_SRC) \ $(PROFILE) \ $(SAMPLE_PROFILE) \ - $(MATH_SRC) \ $(STACK_GUARD) PRODUCT=TeleMega-v0.1 diff --git a/src/telemega-v0.1/ao_pins.h b/src/telemega-v0.1/ao_pins.h index 11934bd2..7ba3a1a7 100644 --- a/src/telemega-v0.1/ao_pins.h +++ b/src/telemega-v0.1/ao_pins.h @@ -64,8 +64,11 @@ #define ao_gps_set_speed ao_serial3_set_speed #define ao_gps_fifo (ao_stm_usart3.rx_fifo) +#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX (1024 * 1024) #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 0 +#define USE_EEPROM_CONFIG 1 +#define USE_STORAGE_CONFIG 0 #define HAS_USB 1 #define HAS_BEEP 1 #define HAS_RADIO 1 @@ -111,6 +114,7 @@ #define HAS_GPS 1 #define HAS_FLIGHT 1 #define HAS_ADC 1 +#define HAS_ADC_TEMP 1 #define HAS_LOG 1 /* @@ -120,34 +124,39 @@ #define HAS_IGNITE 1 #define HAS_IGNITE_REPORT 1 -#define AO_SENSE_DROGUE(p) ((p)->adc.sense[0]) -#define AO_SENSE_MAIN(p) ((p)->adc.sense[1]) +#define AO_SENSE_PYRO(p,n) ((p)->adc.sense[n]) +#define AO_SENSE_DROGUE(p) ((p)->adc.sense[4]) +#define AO_SENSE_MAIN(p) ((p)->adc.sense[5]) #define AO_IGNITER_CLOSED 400 #define AO_IGNITER_OPEN 60 -#define AO_IGNITER_DROGUE_PORT (&stm_gpiod) -#define AO_IGNITER_DROGUE_PIN 6 +/* Pyro A */ +#define AO_PYRO_PORT_0 (&stm_gpiod) +#define AO_PYRO_PIN_0 6 -#define AO_IGNITER_MAIN_PORT (&stm_gpiod) -#define AO_IGNITER_MAIN_PIN 7 +/* Pyro B */ +#define AO_PYRO_PORT_1 (&stm_gpiod) +#define AO_PYRO_PIN_1 7 -#define AO_PYRO_PORT_0 (&stm_gpiob) -#define AO_PYRO_PIN_0 5 +/* Pyro C */ +#define AO_PYRO_PORT_2 (&stm_gpiob) +#define AO_PYRO_PIN_2 5 -#define AO_PYRO_PORT_1 (&stm_gpioe) -#define AO_PYRO_PIN_1 4 +/* Pyro D */ +#define AO_PYRO_PORT_3 (&stm_gpioe) +#define AO_PYRO_PIN_3 4 -#define AO_PYRO_PORT_2 (&stm_gpioe) -#define AO_PYRO_PIN_2 6 +/* Drogue */ +#define AO_IGNITER_DROGUE_PORT (&stm_gpioe) +#define AO_IGNITER_DROGUE_PIN 6 -#define AO_PYRO_PORT_3 (&stm_gpioe) -#define AO_PYRO_PIN_3 5 +/* Main */ +#define AO_IGNITER_MAIN_PORT (&stm_gpioe) +#define AO_IGNITER_MAIN_PIN 5 /* Number of general purpose pyro channels available */ #define AO_PYRO_NUM 4 -#define AO_SENSE_PYRO(a,p) ((a)->adc.sense[(p) + 2]) - #define AO_IGNITER_SET_DROGUE(v) stm_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, v) #define AO_IGNITER_SET_MAIN(v) stm_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, v) @@ -161,11 +170,16 @@ struct ao_adc { int16_t sense[AO_ADC_NUM_SENSE]; int16_t v_batt; int16_t v_pbatt; - int16_t accel_ref; - int16_t accel; int16_t temp; }; +#define AO_ADC_DUMP(p) \ + printf("tick: %5u A: %5d B: %5d C: %5d D: %5d drogue: %5d main: %5d batt: %5d pbatt: %5d temp: %5d\n", \ + (p)->tick, \ + (p)->adc.sense[0], (p)->adc.sense[1], (p)->adc.sense[2], \ + (p)->adc.sense[3], (p)->adc.sense[4], (p)->adc.sense[5], \ + (p)->adc.v_batt, (p)->adc.v_pbatt, (p)->adc.temp) + #define AO_ADC_SENSE_A 0 #define AO_ADC_SENSE_A_PORT (&stm_gpioa) #define AO_ADC_SENSE_A_PIN 0 @@ -182,13 +196,13 @@ struct ao_adc { #define AO_ADC_SENSE_D_PORT (&stm_gpioa) #define AO_ADC_SENSE_D_PIN 3 -#define AO_ADC_SENSE_E 4 -#define AO_ADC_SENSE_E_PORT (&stm_gpioa) -#define AO_ADC_SENSE_E_PIN 4 +#define AO_ADC_SENSE_DROGUE 4 +#define AO_ADC_SENSE_DROGUE_PORT (&stm_gpioa) +#define AO_ADC_SENSE_DROGUE_PIN 4 -#define AO_ADC_SENSE_F 22 -#define AO_ADC_SENSE_F_PORT (&stm_gpioe) -#define AO_ADC_SENSE_F_PIN 7 +#define AO_ADC_SENSE_MAIN 22 +#define AO_ADC_SENSE_MAIN_PORT (&stm_gpioe) +#define AO_ADC_SENSE_MAIN_PIN 7 #define AO_ADC_V_BATT 8 #define AO_ADC_V_BATT_PORT (&stm_gpiob) @@ -198,22 +212,13 @@ struct ao_adc { #define AO_ADC_V_PBATT_PORT (&stm_gpiob) #define AO_ADC_V_PBATT_PIN 1 -#define AO_ADC_ACCEL_REF 10 -#define AO_ADC_ACCEL_REF_PORT (&stm_gpioc) -#define AO_ADC_ACCEL_REF_PIN 0 - -#define AO_ADC_ACCEL 11 -#define AO_ADC_ACCEL_PORT (&stm_gpioc) -#define AO_ADC_ACCEL_PIN 1 - #define AO_ADC_TEMP 16 #define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN) | \ (1 << STM_RCC_AHBENR_GPIOEEN) | \ - (1 << STM_RCC_AHBENR_GPIOBEN) | \ - (1 << STM_RCC_AHBENR_GPIOCEN)) + (1 << STM_RCC_AHBENR_GPIOBEN)) -#define AO_NUM_ADC_PIN (AO_ADC_NUM_SENSE + 4) +#define AO_NUM_ADC_PIN (AO_ADC_NUM_SENSE + 2) #define AO_ADC_PIN0_PORT AO_ADC_SENSE_A_PORT #define AO_ADC_PIN0_PIN AO_ADC_SENSE_A_PIN @@ -223,32 +228,26 @@ struct ao_adc { #define AO_ADC_PIN2_PIN AO_ADC_SENSE_C_PIN #define AO_ADC_PIN3_PORT AO_ADC_SENSE_D_PORT #define AO_ADC_PIN3_PIN AO_ADC_SENSE_D_PIN -#define AO_ADC_PIN4_PORT AO_ADC_SENSE_E_PORT -#define AO_ADC_PIN4_PIN AO_ADC_SENSE_E_PIN -#define AO_ADC_PIN5_PORT AO_ADC_SENSE_F_PORT -#define AO_ADC_PIN5_PIN AO_ADC_SENSE_F_PIN +#define AO_ADC_PIN4_PORT AO_ADC_SENSE_DROGUE_PORT +#define AO_ADC_PIN4_PIN AO_ADC_SENSE_DROGUE_PIN +#define AO_ADC_PIN5_PORT AO_ADC_SENSE_MAIN_PORT +#define AO_ADC_PIN5_PIN AO_ADC_SENSE_MAIN_PIN #define AO_ADC_PIN6_PORT AO_ADC_V_BATT_PORT #define AO_ADC_PIN6_PIN AO_ADC_V_BATT_PIN #define AO_ADC_PIN7_PORT AO_ADC_V_PBATT_PORT #define AO_ADC_PIN7_PIN AO_ADC_V_PBATT_PIN -#define AO_ADC_PIN8_PORT AO_ADC_ACCEL_REF_PORT -#define AO_ADC_PIN8_PIN AO_ADC_ACCEL_REF_PIN -#define AO_ADC_PIN9_PORT AO_ADC_ACCEL_PORT -#define AO_ADC_PIN9_PIN AO_ADC_ACCEL_PIN -#define AO_NUM_ADC (AO_ADC_NUM_SENSE + 5) +#define AO_NUM_ADC (AO_ADC_NUM_SENSE + 3) #define AO_ADC_SQ1 AO_ADC_SENSE_A #define AO_ADC_SQ2 AO_ADC_SENSE_B #define AO_ADC_SQ3 AO_ADC_SENSE_C #define AO_ADC_SQ4 AO_ADC_SENSE_D -#define AO_ADC_SQ5 AO_ADC_SENSE_E -#define AO_ADC_SQ6 AO_ADC_SENSE_F +#define AO_ADC_SQ5 AO_ADC_SENSE_DROGUE +#define AO_ADC_SQ6 AO_ADC_SENSE_MAIN #define AO_ADC_SQ7 AO_ADC_V_BATT #define AO_ADC_SQ8 AO_ADC_V_PBATT -#define AO_ADC_SQ9 AO_ADC_ACCEL_REF -#define AO_ADC_SQ10 AO_ADC_ACCEL -#define AO_ADC_SQ11 AO_ADC_TEMP +#define AO_ADC_SQ9 AO_ADC_TEMP /* * Pressure sensor settings @@ -298,7 +297,6 @@ struct ao_adc { #define AO_CC1120_MARC_GPIO 3 #define AO_CC1120_MARC_GPIO_IOCFG CC1120_IOCFG3 - #define HAS_BOOT_RADIO 0 /* diff --git a/src/telemega-v0.1/ao_telemega.c b/src/telemega-v0.1/ao_telemega.c index fbdab64a..7b035269 100644 --- a/src/telemega-v0.1/ao_telemega.c +++ b/src/telemega-v0.1/ao_telemega.c @@ -24,6 +24,7 @@ #include <ao_packet.h> #include <ao_companion.h> #include <ao_profile.h> +#include <ao_eeprom.h> #if HAS_SAMPLE_PROFILE #include <ao_sample_profile.h> #endif @@ -71,6 +72,7 @@ main(void) ao_mma655x_init(); #endif + ao_eeprom_init(); ao_storage_init(); ao_flight_init(); -- cgit v1.2.3 From 012abeda6ae846d74729e96e7ed7c8af2edca572 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Wed, 18 Dec 2013 02:02:12 -0800 Subject: altos/lpc: Be a bit more resistant to toolchain section name changes Just add some wild cards on the ends of each section name in case the toolchain changes names in the future. Signed-off-by: Keith Packard <keithp@keithp.com> --- src/lpc/altos-loader.ld | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/lpc/altos-loader.ld b/src/lpc/altos-loader.ld index 4f78f552..9df6e456 100644 --- a/src/lpc/altos-loader.ld +++ b/src/lpc/altos-loader.ld @@ -53,7 +53,7 @@ SECTIONS { */ .boot ORIGIN(ram) + SIZEOF(.interrupt) (NOLOAD) : { __boot_start__ = .; - *(.boot) + *(.boot*) __boot_end__ = .; } >ram @@ -61,15 +61,15 @@ SECTIONS { */ .data : { __data_start__ = .; - *(.data) /* initialized data */ + *(.data*) /* initialized data */ __data_end__ = .; } >ram AT>rom .bss : { __bss_start__ = .; - *(.bss) - *(COMMON) + *(.bss*) + *(COMMON*) __bss_end__ = .; } >ram -- cgit v1.2.3 From 9c200c3bc742b4dd1a7e28bfce9d5b27e833aae5 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Wed, 18 Dec 2013 10:01:29 -0800 Subject: altos: Build pdclib locally if necessary Signed-off-by: Keith Packard <keithp@keithp.com> --- configure.ac | 36 +++++++++++++++++++++++++++++------- src/Makedefs.in | 4 ++++ src/Makefile | 9 ++++++++- src/lpc/Makefile-lpc.defs | 4 ++-- src/stm/Makefile.defs | 4 ++-- 5 files changed, 45 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/configure.ac b/configure.ac index 1d80376c..b6e17355 100644 --- a/configure.ac +++ b/configure.ac @@ -238,6 +238,25 @@ fi AC_SUBST(HAVE_ARM_CC) AC_SUBST(ARM_CC) +if test -d pdclib -a x"$HAVE_ARM_CC" = xyes; then + PDCLIB_INCLUDES='-I$(TOPDIR)/../pdclib/opt/include' + PDCLIB_LIBS_M0='-L$(TOPDIR)/../pdclib/opt/lib -lpdclib-cortex-m0' + PDCLIB_LIBS_M3='-L$(TOPDIR)/../pdclib/opt/lib -lpdclib-cortex-m3' + HAVE_PDCLIB=yes +else + PDCLIB_INCLUDES='' + PDCLIB_LIBS_M0='-lpdclib-cortex-m0' + PDCLIB_LIBS_M3='-lpdclib-cortex-m3' + HAVE_PDCLIB=no +fi + +AM_CONDITIONAL(PDCLIB, [test x$HAVE_PDCLIB = xyes]) + +AC_SUBST(PDCLIB_INCLUDES) +AC_SUBST(PDCLIB_LIBS_M0) +AC_SUBST(PDCLIB_LIBS_M3) +AC_SUBST(HAVE_PDCLIB) + if test "x$HAVE_ARM_CC" = "xyes"; then save_CC="$CC" save_CFLAGS="$CFLAGS" @@ -253,10 +272,6 @@ if test "x$HAVE_ARM_CC" = "xyes"; then [HAVE_ARM_M0_CC=no]) AC_MSG_RESULT([$HAVE_ARM_M0_CC]) - AC_CHECK_LIB(pdclib-cortex-m0,memcpy, - [], - [HAVE_ARM_M0_CC=no]) - CFLAGS="-mthumb -mcpu=cortex-m3" AC_MSG_CHECKING([if ]$ARM_CC[ supports cortex-m3]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int i;])], @@ -264,9 +279,15 @@ if test "x$HAVE_ARM_CC" = "xyes"; then [HAVE_ARM_M3_CC=no]) AC_MSG_RESULT([$HAVE_ARM_M3_CC]) - AC_CHECK_LIB(pdclib-cortex-m3,memcpy, - [], - [HAVE_ARM_M3_CC=no]) + if test x$HAVE_PDCLIB != xyes; then + AC_CHECK_LIB(pdclib-cortex-m0,memcpy, + [], + [HAVE_ARM_M0_CC=no]) + + AC_CHECK_LIB(pdclib-cortex-m3,memcpy, + [], + [HAVE_ARM_M3_CC=no]) + fi AC_LANG_POP([C]) LIBS="$save_LIBS" @@ -459,6 +480,7 @@ echo " AVR compiler................: ${AVR_CC} ${AVR_OBJCOPY}" echo " AVR support.................: ${HAVE_AVR_CC}" echo " Android support.............: ${HAVE_ANDROID_SDK}" echo " STlink support..............: ${HAVE_STLINK}" +echo " Local pdclib................: ${HAVE_PDCLIB}" echo "" echo " Java paths" echo " freetts.....................: ${FREETTS}" diff --git a/src/Makedefs.in b/src/Makedefs.in index 6dc9ab0f..d4ef28be 100644 --- a/src/Makedefs.in +++ b/src/Makedefs.in @@ -1,6 +1,10 @@ ARM_CC=@ARM_CC@ HAVE_ARM_M3_CC=@HAVE_ARM_M3_CC@ HAVE_ARM_M0_CC=@HAVE_ARM_M0_CC@ +PDCLIB_INCLUDES=@PDCLIB_INCLUDES@ +PDCLIB_LIBS_M0=@PDCLIB_LIBS_M0@ +PDCLIB_LIBS_M3=@PDCLIB_LIBS_M3@ +HAVE_PDCLIB=@HAVE_PDCLIB@ SDCC=@SDCC@ HAVE_SDCC=@HAVE_SDCC@ diff --git a/src/Makefile b/src/Makefile index bdd3307a..2ba59d94 100644 --- a/src/Makefile +++ b/src/Makefile @@ -42,6 +42,10 @@ AVRDIRS=\ SUBDIRS= +ifeq ($(strip $(HAVE_PDCLIB)),yes) +PDCLIB=pdclib +endif + ifeq ($(strip $(HAVE_SDCC)),yes) SUBDIRS+=$(SDCCDIRS) endif @@ -92,7 +96,7 @@ uninstall: all-recursive: all-local -all-local: altitude.h altitude-pa.h ao_kalman.h ao_whiten.h +all-local: altitude.h altitude-pa.h ao_kalman.h ao_whiten.h $(PDCLIB) altitude.h: make-altitude nickle $< > $@ @@ -108,3 +112,6 @@ ao_whiten.h: make-whiten clean-local: rm -f altitude.h ao_kalman.h + +pdclib: + cd ../pdclib && make && make prefix=`pwd`/opt install diff --git a/src/lpc/Makefile-lpc.defs b/src/lpc/Makefile-lpc.defs index fbd413b0..3d55cf67 100644 --- a/src/lpc/Makefile-lpc.defs +++ b/src/lpc/Makefile-lpc.defs @@ -26,12 +26,12 @@ endif ELFTOHEX=$(TOPDIR)/../ao-tools/ao-elftohex/ao-elftohex CC=$(ARM_CC) -AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) +AO_CFLAGS=-I. -I$(TOPDIR)/lpc -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) $(PDCLIB_INCLUDES) LPC_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m0 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) NICKLE=nickle -LIBS=-lpdclib-cortex-m0 -lgcc +LIBS=$(PDCLIB_LIBS_M0) -lgcc V=0 # The user has explicitly enabled quiet compilation. diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index b1998f93..9adcfeb3 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -22,9 +22,9 @@ endif include $(TOPDIR)/Makedefs CC=$(ARM_CC) -LIBS=-lpdclib-cortex-m3 -lgcc +LIBS=$(PDCLIB_LIBS_M3) -lgcc -AO_CFLAGS=-I. -I../stm -I../core -I../drivers -I../math -I.. +AO_CFLAGS=-I. -I../stm -I../core -I../drivers -I../math -I.. $(PDCLIB_INCLUDES) STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) LDFLAGS=-L../stm -Wl,-Taltos.ld -- cgit v1.2.3 From eb659fb0ee80c25312be36b3d8adb686813db125 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Wed, 18 Dec 2013 10:43:16 -0800 Subject: altos: create target pdclib directories before building --- src/Makefile | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 2ba59d94..2488cbab 100644 --- a/src/Makefile +++ b/src/Makefile @@ -44,6 +44,7 @@ SUBDIRS= ifeq ($(strip $(HAVE_PDCLIB)),yes) PDCLIB=pdclib +CLEAN_PDCLIB=clean-pdclib endif ifeq ($(strip $(HAVE_SDCC)),yes) @@ -110,8 +111,11 @@ ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c ao_whiten.h: make-whiten nickle $< > $@ -clean-local: +clean-local: $(CLEAN_PDCLIB) rm -f altitude.h ao_kalman.h pdclib: - cd ../pdclib && make && make prefix=`pwd`/opt install + cd ../pdclib && mkdir -p opt/include opt/lib && make && make prefix=`pwd`/opt install + +clean-pdclib: + cd ../pdclib && make clean && rm -rf opt \ No newline at end of file -- cgit v1.2.3 From 90386115204bd3bfa55deb5ebe1972bacdba725a Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Wed, 18 Dec 2013 10:50:45 -0800 Subject: altos/stm: Update pdclib paths for flash-loader builds Signed-off-by: Keith Packard <keithp@keithp.com> --- src/stm/Makefile-flash.defs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/stm/Makefile-flash.defs b/src/stm/Makefile-flash.defs index be3ae799..3890eff1 100644 --- a/src/stm/Makefile-flash.defs +++ b/src/stm/Makefile-flash.defs @@ -12,9 +12,9 @@ endif include $(TOPDIR)/Makedefs CC=$(ARM_CC) -LIBS=-lpdclib-cortex-m3 -lgcc +LIBS=$(PDCLIB_LIBS_M3) -lgcc -AO_CFLAGS=-I. -I$(TOPDIR)/stm -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) +AO_CFLAGS=-I. -I$(TOPDIR)/stm -I$(TOPDIR)/core -I$(TOPDIR)/drivers -I$(TOPDIR)/product -I$(TOPDIR) $(PDCLIB_INCLUDES) STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) LDFLAGS=-L$(TOPDIR)/stm -Wl,-Taltos-loader.ld -- cgit v1.2.3 From 262ee65885d55902df96f4aec6a114f5ac6f2c61 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Wed, 18 Dec 2013 10:53:09 -0800 Subject: Remove stale stm test apps from regular build --- src/Makefile | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 2488cbab..0ca101c0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -30,7 +30,6 @@ ARMM3DIRS=\ telemetrum-v2.0 telemetrum-v2.0/flash-loader \ megadongle-v0.1 megadongle-v0.1/flash-loader \ telegps-v0.3 telegps-v0.3/flash-loader \ - stm-bringup stm-demo \ telelco-v0.2 telelco-v0.2/flash-loader \ telescience-v0.2 telescience-v0.2/flash-loader -- cgit v1.2.3 From 8f529633cd4be8a0edb1b067bbf5d7cc055dcc1b Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Wed, 18 Dec 2013 10:55:06 -0800 Subject: altos: get stm-bringup building again Signed-off-by: Keith Packard <keithp@keithp.com> --- src/stm-bringup/Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/stm-bringup/Makefile b/src/stm-bringup/Makefile index 33ecd710..797df2d6 100644 --- a/src/stm-bringup/Makefile +++ b/src/stm-bringup/Makefile @@ -4,13 +4,15 @@ vpath ao-make-product.5c ../util ifndef VERSION include ../Version endif +TOPDIR=.. +include $(TOPDIR)/Makedefs CC=arm-none-eabi-gcc OBJCOPY=arm-none-eabi-objcopy -C_LIB=-lpdclib-cortex-m3 +C_LIB=$(PDCLIB_LIBS_M3) -DEF_CFLAGS=-g -std=gnu99 -Os -mlittle-endian -mthumb -ffreestanding -nostdlib -I. -I../stm +DEF_CFLAGS=-g -std=gnu99 -Os -mlittle-endian -mthumb -ffreestanding -nostdlib -I. -I../stm $(PDCLIB_INCLUDES) # to run from SRAM LD_FLAGS_RAM=-L../stm -Wl,-Taltos-ram.ld -- cgit v1.2.3 From eea036650e62bc0f8652155974b512686754fd13 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Wed, 18 Dec 2013 14:08:41 -0800 Subject: Move pdclib build results to pdclib-root This makes pdclib easier to manage as a submodule Signed-off-by: Keith Packard <keithp@keithp.com> --- .gitignore | 1 + configure.ac | 8 +++++--- pdclib | 2 +- src/Makedefs.in | 1 + src/Makefile | 7 +++++-- 5 files changed, 13 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/.gitignore b/.gitignore index 54834f66..61f48048 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,4 @@ doc/telemetrum.fo doc/telemetrum.html doc/telemetrum.pdf altosui/altos-windows.log +pdclib-root diff --git a/configure.ac b/configure.ac index b6e17355..b92e06a9 100644 --- a/configure.ac +++ b/configure.ac @@ -239,9 +239,10 @@ AC_SUBST(HAVE_ARM_CC) AC_SUBST(ARM_CC) if test -d pdclib -a x"$HAVE_ARM_CC" = xyes; then - PDCLIB_INCLUDES='-I$(TOPDIR)/../pdclib/opt/include' - PDCLIB_LIBS_M0='-L$(TOPDIR)/../pdclib/opt/lib -lpdclib-cortex-m0' - PDCLIB_LIBS_M3='-L$(TOPDIR)/../pdclib/opt/lib -lpdclib-cortex-m3' + PDCLIB_ROOT='$(TOPDIR)/../pdclib-root' + PDCLIB_INCLUDES='-I$(TOPDIR)/../pdclib-root/include' + PDCLIB_LIBS_M0='-L$(TOPDIR)/../pdclib-root/lib -lpdclib-cortex-m0' + PDCLIB_LIBS_M3='-L$(TOPDIR)/../pdclib-root/lib -lpdclib-cortex-m3' HAVE_PDCLIB=yes else PDCLIB_INCLUDES='' @@ -255,6 +256,7 @@ AM_CONDITIONAL(PDCLIB, [test x$HAVE_PDCLIB = xyes]) AC_SUBST(PDCLIB_INCLUDES) AC_SUBST(PDCLIB_LIBS_M0) AC_SUBST(PDCLIB_LIBS_M3) +AC_SUBST(PDCLIB_ROOT) AC_SUBST(HAVE_PDCLIB) if test "x$HAVE_ARM_CC" = "xyes"; then diff --git a/pdclib b/pdclib index f3165dbd..8b1c9061 160000 --- a/pdclib +++ b/pdclib @@ -1 +1 @@ -Subproject commit f3165dbd639299d08033ed5eef62a21b69540a8d +Subproject commit 8b1c9061fa3a8f1b30ee13b373afe5cc1ad9d382 diff --git a/src/Makedefs.in b/src/Makedefs.in index d4ef28be..a52f96fa 100644 --- a/src/Makedefs.in +++ b/src/Makedefs.in @@ -4,6 +4,7 @@ HAVE_ARM_M0_CC=@HAVE_ARM_M0_CC@ PDCLIB_INCLUDES=@PDCLIB_INCLUDES@ PDCLIB_LIBS_M0=@PDCLIB_LIBS_M0@ PDCLIB_LIBS_M3=@PDCLIB_LIBS_M3@ +PDCLIB_ROOT=@PDCLIB_ROOT@ HAVE_PDCLIB=@HAVE_PDCLIB@ SDCC=@SDCC@ diff --git a/src/Makefile b/src/Makefile index 0ca101c0..392262d4 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,6 +13,7 @@ vpath load_csv.5c kalman vpath matrix.5c kalman include Version +TOPDIR=. include Makedefs SDCCDIRS=\ @@ -114,7 +115,9 @@ clean-local: $(CLEAN_PDCLIB) rm -f altitude.h ao_kalman.h pdclib: - cd ../pdclib && mkdir -p opt/include opt/lib && make && make prefix=`pwd`/opt install + mkdir -p $(PDCLIB_ROOT)/include $(PDCLIB_ROOT)/lib + cd ../pdclib && make && make prefix=`pwd`/../pdclib-root install clean-pdclib: - cd ../pdclib && make clean && rm -rf opt \ No newline at end of file + rm -rf $(PDCLIB_ROOT) + cd ../pdclib && make clean -- cgit v1.2.3 From 0673344289772ed89483948184d6608c272c7c26 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Wed, 18 Dec 2013 18:20:55 -0800 Subject: altos/stm: Semantic error in STM usb disable caused it to not work The USB enable register wasn't actually getting rewritten with the enable bit turned off, so the USB device was still powered on in flight. Signed-off-by: Keith Packard <keithp@keithp.com> --- src/stm/ao_usb_stm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index b00390ec..28a9f9f3 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -965,7 +965,7 @@ ao_usb_disable(void) stm_usb.cntr = (1 << STM_USB_CNTR_PDWN) | (1 << STM_USB_CNTR_FRES); /* Disable the interface */ - stm_rcc.apb1enr &+ ~(1 << STM_RCC_APB1ENR_USBEN); + stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_USBEN); ao_arch_release_interrupts(); } -- cgit v1.2.3 From ee4279613b4757453d0d8f8afc06037c61eeb520 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Wed, 18 Dec 2013 20:32:05 -0800 Subject: altos: Try IMU self-test 10 times before giving up This should keep the device from failing to boot unless the IMU is actually broken. Oh, and if self test does fail, this places the flight computer in 'Invalid' state rather than panic. Signed-off-by: Keith Packard <keithp@keithp.com> --- src/core/ao_flight.c | 8 ++++ src/core/ao_flight.h | 4 ++ src/drivers/ao_mpu6000.c | 104 ++++++++++++++++++++++++-------------------- src/telemega-v0.1/ao_pins.h | 1 + src/telemega-v1.0/ao_pins.h | 3 +- 5 files changed, 70 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index 4a53bdc6..463ff4a2 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -46,6 +46,11 @@ __pdata enum ao_flight_state ao_flight_state; /* current flight state */ __pdata uint16_t ao_boost_tick; /* time of launch detect */ __pdata uint16_t ao_motor_number; /* number of motors burned so far */ +#if HAS_IMU +/* Any sensor can set this to mark the flight computer as 'broken' */ +__xdata uint8_t ao_sensor_errors; +#endif + /* * track min/max data over a long interval to detect * resting @@ -99,6 +104,9 @@ ao_flight(void) ao_config.accel_minus_g == 0 || ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP || +#if HAS_IMU + ao_sensor_errors || +#endif ao_ground_height < -1000 || ao_ground_height > 7000) { diff --git a/src/core/ao_flight.h b/src/core/ao_flight.h index ac3e9cfb..c7c02ccf 100644 --- a/src/core/ao_flight.h +++ b/src/core/ao_flight.h @@ -41,6 +41,10 @@ extern __pdata enum ao_flight_state ao_flight_state; extern __pdata uint16_t ao_boost_tick; extern __pdata uint16_t ao_motor_number; +#if HAS_IMU +extern __xdata uint8_t ao_sensor_errors; +#endif + extern __pdata uint16_t ao_launch_time; extern __pdata uint8_t ao_flight_force_idle; diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index 5e75b78a..f8ce7346 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -137,10 +137,10 @@ ao_mpu6000_accel_check(int16_t normal, int16_t test, char *which) { int16_t diff = test - normal; - if (diff < MPU6000_ST_ACCEL(16) / 2) { + if (diff < MPU6000_ST_ACCEL(16) / 4) { return 1; } - if (diff > MPU6000_ST_ACCEL(16) * 2) { + if (diff > MPU6000_ST_ACCEL(16) * 4) { return 1; } return 0; @@ -153,10 +153,10 @@ ao_mpu6000_gyro_check(int16_t normal, int16_t test, char *which) if (diff < 0) diff = -diff; - if (diff < MPU6000_ST_GYRO(2000) / 2) { + if (diff < MPU6000_ST_GYRO(2000) / 4) { return 1; } - if (diff > MPU6000_ST_GYRO(2000) * 2) { + if (diff > MPU6000_ST_GYRO(2000) * 4) { return 1; } return 0; @@ -177,11 +177,14 @@ _ao_mpu6000_wait_alive(void) ao_panic(AO_PANIC_SELF_TEST_MPU6000); } +#define ST_TRIES 10 + static void _ao_mpu6000_setup(void) { struct ao_mpu6000_sample normal_mode, test_mode; - int errors =0; + int errors; + int st_tries; if (ao_mpu6000_configured) return; @@ -236,23 +239,6 @@ _ao_mpu6000_setup(void) (MPU6000_CONFIG_EXT_SYNC_SET_DISABLED << MPU6000_CONFIG_EXT_SYNC_SET) | (MPU6000_CONFIG_DLPF_CFG_260_256 << MPU6000_CONFIG_DLPF_CFG)); - /* Configure accelerometer to +/-16G in self-test mode */ - _ao_mpu6000_reg_write(MPU6000_ACCEL_CONFIG, - (1 << MPU600_ACCEL_CONFIG_XA_ST) | - (1 << MPU600_ACCEL_CONFIG_YA_ST) | - (1 << MPU600_ACCEL_CONFIG_ZA_ST) | - (MPU600_ACCEL_CONFIG_AFS_SEL_16G << MPU600_ACCEL_CONFIG_AFS_SEL)); - - /* Configure gyro to +/- 2000°/s in self-test mode */ - _ao_mpu6000_reg_write(MPU6000_GYRO_CONFIG, - (1 << MPU600_GYRO_CONFIG_XG_ST) | - (1 << MPU600_GYRO_CONFIG_YG_ST) | - (1 << MPU600_GYRO_CONFIG_ZG_ST) | - (MPU600_GYRO_CONFIG_FS_SEL_2000 << MPU600_GYRO_CONFIG_FS_SEL)); - - ao_delay(AO_MS_TO_TICKS(200)); - _ao_mpu6000_sample(&test_mode); - #if TRIDGE // read the product ID rev c has 1/2 the sensitivity of rev d _mpu6000_product_id = _register_read(MPUREG_PRODUCT_ID); @@ -268,36 +254,58 @@ _ao_mpu6000_setup(void) register_write(MPUREG_ACCEL_CONFIG,2<<3); } hal.scheduler->delay(1); - #endif - /* Configure accelerometer to +/-16G */ - _ao_mpu6000_reg_write(MPU6000_ACCEL_CONFIG, - (0 << MPU600_ACCEL_CONFIG_XA_ST) | - (0 << MPU600_ACCEL_CONFIG_YA_ST) | - (0 << MPU600_ACCEL_CONFIG_ZA_ST) | - (MPU600_ACCEL_CONFIG_AFS_SEL_16G << MPU600_ACCEL_CONFIG_AFS_SEL)); - - /* Configure gyro to +/- 2000°/s */ - _ao_mpu6000_reg_write(MPU6000_GYRO_CONFIG, - (0 << MPU600_GYRO_CONFIG_XG_ST) | - (0 << MPU600_GYRO_CONFIG_YG_ST) | - (0 << MPU600_GYRO_CONFIG_ZG_ST) | - (MPU600_GYRO_CONFIG_FS_SEL_2000 << MPU600_GYRO_CONFIG_FS_SEL)); - - ao_delay(AO_MS_TO_TICKS(10)); - _ao_mpu6000_sample(&normal_mode); + for (st_tries = 0; st_tries < ST_TRIES; st_tries++) { + errors = 0; + + /* Configure accelerometer to +/-16G in self-test mode */ + _ao_mpu6000_reg_write(MPU6000_ACCEL_CONFIG, + (1 << MPU600_ACCEL_CONFIG_XA_ST) | + (1 << MPU600_ACCEL_CONFIG_YA_ST) | + (1 << MPU600_ACCEL_CONFIG_ZA_ST) | + (MPU600_ACCEL_CONFIG_AFS_SEL_16G << MPU600_ACCEL_CONFIG_AFS_SEL)); + + /* Configure gyro to +/- 2000°/s in self-test mode */ + _ao_mpu6000_reg_write(MPU6000_GYRO_CONFIG, + (1 << MPU600_GYRO_CONFIG_XG_ST) | + (1 << MPU600_GYRO_CONFIG_YG_ST) | + (1 << MPU600_GYRO_CONFIG_ZG_ST) | + (MPU600_GYRO_CONFIG_FS_SEL_2000 << MPU600_GYRO_CONFIG_FS_SEL)); + + ao_delay(AO_MS_TO_TICKS(200)); + _ao_mpu6000_sample(&test_mode); + + /* Configure accelerometer to +/-16G */ + _ao_mpu6000_reg_write(MPU6000_ACCEL_CONFIG, + (0 << MPU600_ACCEL_CONFIG_XA_ST) | + (0 << MPU600_ACCEL_CONFIG_YA_ST) | + (0 << MPU600_ACCEL_CONFIG_ZA_ST) | + (MPU600_ACCEL_CONFIG_AFS_SEL_16G << MPU600_ACCEL_CONFIG_AFS_SEL)); + + /* Configure gyro to +/- 2000°/s */ + _ao_mpu6000_reg_write(MPU6000_GYRO_CONFIG, + (0 << MPU600_GYRO_CONFIG_XG_ST) | + (0 << MPU600_GYRO_CONFIG_YG_ST) | + (0 << MPU600_GYRO_CONFIG_ZG_ST) | + (MPU600_GYRO_CONFIG_FS_SEL_2000 << MPU600_GYRO_CONFIG_FS_SEL)); + + ao_delay(AO_MS_TO_TICKS(200)); + _ao_mpu6000_sample(&normal_mode); - errors += ao_mpu6000_accel_check(normal_mode.accel_x, test_mode.accel_x, "x"); - errors += ao_mpu6000_accel_check(normal_mode.accel_y, test_mode.accel_y, "y"); - errors += ao_mpu6000_accel_check(normal_mode.accel_z, test_mode.accel_z, "z"); - - errors += ao_mpu6000_gyro_check(normal_mode.gyro_x, test_mode.gyro_x, "x"); - errors += ao_mpu6000_gyro_check(normal_mode.gyro_y, test_mode.gyro_y, "y"); - errors += ao_mpu6000_gyro_check(normal_mode.gyro_z, test_mode.gyro_z, "z"); + errors += ao_mpu6000_accel_check(normal_mode.accel_x, test_mode.accel_x, "x"); + errors += ao_mpu6000_accel_check(normal_mode.accel_y, test_mode.accel_y, "y"); + errors += ao_mpu6000_accel_check(normal_mode.accel_z, test_mode.accel_z, "z"); + + errors += ao_mpu6000_gyro_check(normal_mode.gyro_x, test_mode.gyro_x, "x"); + errors += ao_mpu6000_gyro_check(normal_mode.gyro_y, test_mode.gyro_y, "y"); + errors += ao_mpu6000_gyro_check(normal_mode.gyro_z, test_mode.gyro_z, "z"); + if (!errors) + break; + } - if (errors) - ao_panic(AO_PANIC_SELF_TEST_MPU6000); + if (st_tries == ST_TRIES) + ao_sensor_errors = 1; /* Filter to about 100Hz, which also sets the gyro rate to 1000Hz */ _ao_mpu6000_reg_write(MPU6000_CONFIG, diff --git a/src/telemega-v0.1/ao_pins.h b/src/telemega-v0.1/ao_pins.h index 7ba3a1a7..daeb9f17 100644 --- a/src/telemega-v0.1/ao_pins.h +++ b/src/telemega-v0.1/ao_pins.h @@ -316,6 +316,7 @@ struct ao_adc { #define AO_MPU6000_INT_PORT (&stm_gpioc) #define AO_MPU6000_INT_PIN 13 #define AO_MPU6000_I2C_INDEX STM_I2C_INDEX(1) +#define HAS_IMU 1 /* * mma655x diff --git a/src/telemega-v1.0/ao_pins.h b/src/telemega-v1.0/ao_pins.h index 7ff676ea..95644dae 100644 --- a/src/telemega-v1.0/ao_pins.h +++ b/src/telemega-v1.0/ao_pins.h @@ -318,8 +318,7 @@ struct ao_adc { #define AO_MPU6000_SPI_BUS AO_SPI_1_PE13_PE14_PE15 #define AO_MPU6000_SPI_CS_PORT (&stm_gpiod) #define AO_MPU6000_SPI_CS_PIN 2 - -#define HAS_HIGHG_ACCEL 1 +#define HAS_IMU 1 /* * mma655x -- cgit v1.2.3 From 1ab12861c3e70d7c22b27d988546a925616a0adc Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Wed, 18 Dec 2013 23:27:34 -0800 Subject: altos/lpc: Reset less of the device on USB reset. This leaves most of the device configured across USB reset, which appears to help when sending a IN reply to the first SETUP packet; without this change, the IN reply would always get a length of 0, which is fine for SET_ADDRESS, but not for GET_DESCRIPTOR_DEVICE, which OS X appears to send before setting the address (go figure). Signed-off-by: Keith Packard <keithp@keithp.com> --- src/lpc/ao_usb_lpc.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index 108822ce..713fbc53 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -316,6 +316,13 @@ ao_usb_disable_epn(uint8_t n) ao_usb_disable_ep(&lpc_usb_endpoint.epn[n-1].in[1]); } +static void +ao_usb_reset(void) +{ + ao_usb_set_address(0); + ao_usb_configuration = 0; +} + static void ao_usb_set_ep0(void) { @@ -326,11 +333,8 @@ ao_usb_set_ep0(void) lpc_usb.epinuse = 0; lpc_usb.epskip = 0xffffffff; - ao_usb_set_address(0); lpc_usb.intstat = 0xc00003ff; - ao_usb_configuration = 0; - ao_usb_sram = lpc_usb_sram; lpc_usb.epliststart = (uint32_t) (intptr_t) &lpc_usb_endpoint; @@ -346,7 +350,7 @@ ao_usb_set_ep0(void) /* Clear all of the other endpoints */ for (e = 1; e <= 4; e++) ao_usb_disable_epn(e); - + ao_usb_reset(); } static void @@ -590,7 +594,7 @@ ao_usb_ep0_handle(uint8_t receive) if (receive & AO_USB_EP0_GOT_RESET) { debug ("\treset\n"); - ao_usb_set_ep0(); + ao_usb_reset(); return; } if (receive & AO_USB_EP0_GOT_SETUP) { @@ -936,11 +940,11 @@ ao_usb_enable(void) for (t = 0; t < 1000; t++) ao_arch_nop(); + ao_usb_set_ep0(); + #if HAS_USB_PULLUP ao_gpio_set(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, AO_USB_PULLUP, 1); #endif - - ao_usb_set_ep0(); } #if USB_ECHO -- cgit v1.2.3 From a04c1dd5df76c9127615bc797a9d9f764eec1234 Mon Sep 17 00:00:00 2001 From: Keith Packard <keithp@keithp.com> Date: Thu, 19 Dec 2013 00:08:50 -0800 Subject: altos/lpc: Stop sending SETUP IN when the requested size is reached The host won't keep asking for SETUP IN packets once it has received the amount of data requested, so check to see if we've sent that much and flip back to IDLE state if so. Signed-off-by: Keith Packard <keithp@keithp.com> --- src/lpc/ao_usb_lpc.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/lpc/ao_usb_lpc.c b/src/lpc/ao_usb_lpc.c index 713fbc53..686dc3a4 100644 --- a/src/lpc/ao_usb_lpc.c +++ b/src/lpc/ao_usb_lpc.c @@ -58,6 +58,7 @@ static uint8_t ao_usb_ep0_state; /* Pending EP0 IN data */ static const uint8_t *ao_usb_ep0_in_data; /* Remaining data */ static uint8_t ao_usb_ep0_in_len; /* Remaining amount */ +static uint16_t ao_usb_ep0_in_max; /* Requested amount from host */ /* Temp buffer for smaller EP0 in data */ static uint8_t ao_usb_ep0_in_buf[2]; @@ -380,10 +381,11 @@ ao_usb_ep0_flush(void) if (this_len > AO_USB_CONTROL_SIZE) this_len = AO_USB_CONTROL_SIZE; - if (this_len < AO_USB_CONTROL_SIZE) - ao_usb_ep0_state = AO_USB_EP0_IDLE; - ao_usb_ep0_in_len -= this_len; + ao_usb_ep0_in_max -= this_len; + + if (this_len < AO_USB_CONTROL_SIZE || ao_usb_ep0_in_max == 0) + ao_usb_ep0_state = AO_USB_EP0_IDLE; debug_data ("Flush EP0 len %d:", this_len); memcpy(ao_usb_ep0_tx_buffer, ao_usb_ep0_in_data, this_len); @@ -456,6 +458,7 @@ ao_usb_ep0_out_set(uint8_t *data, uint8_t len) static void ao_usb_ep0_in_start(uint16_t max) { + ao_usb_ep0_in_max = max; /* Don't send more than asked for */ if (ao_usb_ep0_in_len > max) ao_usb_ep0_in_len = max; -- cgit v1.2.3