Add radio support. Build separate executables for TeleMetrum and the TI dongle
authorKeith Packard <keithp@keithp.com>
Tue, 21 Apr 2009 06:33:41 +0000 (23:33 -0700)
committerKeith Packard <keithp@keithp.com>
Tue, 21 Apr 2009 06:33:41 +0000 (23:33 -0700)
Ok, way too big a patch, but things were in rough shape.
This patch adds support for the radio, both transmit and receive.
Then, because I could no longer run the TeleMetrum code on the TI
dongle, I ended up building a separate image for the TI board, which
involved creating a mechanism for having multiple command sets and splitting
code for different functions into different files.

27 files changed:
Makefile
ao.h
ao_adc.c
ao_cmd.c
ao_convert.c
ao_dbg.c
ao_dma.c
ao_ee.c
ao_flight.c
ao_gps.c
ao_gps_print.c [new file with mode: 0644]
ao_log.c
ao_main.c
ao_monitor.c [new file with mode: 0644]
ao_panic.c
ao_radio.c [new file with mode: 0644]
ao_report.c
ao_serial.c
ao_stdio.c [new file with mode: 0644]
ao_task.c
ao_telemetrum.c [new file with mode: 0644]
ao_telemetry.c [new file with mode: 0644]
ao_tidongle.c [new file with mode: 0644]
ao_timer.c
ao_usb.c
cc1111.h
check-stack

index b35b144..550e737 100644 (file)
--- a/Makefile
+++ b/Makefile
-PROG=altos
-CC=sdcc
-NO_OPT=--nogcse --noinvariant --noinduction --nojtbound --noloopreverse \
-       --nolabelopt --nooverlay --peep-asm
-DEBUG=--debug
+#
+# AltOS build
+#
+# 
+CC=/usr/bin/sdcc
 
-CFLAGS=--model-small $(DEBUG) --less-pedantic --opt-code-speed
+CFLAGS=--model-small --debug --opt-code-speed 
 
-LDFLAGS=--out-fmt-ihx
-LDFLAGS_FLASH=$(LDFLAGS) --code-loc 0x0000 --code-size 0x8000 \
+LDFLAGS=--out-fmt-ihx --code-loc 0x0000 --code-size 0x8000 \
        --xram-loc 0xf000 --xram-size 0xf00 --iram-size 0xff
 
 INC = \
        ao.h \
        cc1111.h \
-       altitude.h
+       altitude.h \
+       25lc1024.h
 
-SRC = \
-       ao_adc.c \
-       ao_beep.c \
+#
+# Common AltOS sources
+#
+ALTOS_SRC = \
        ao_cmd.c \
-       ao_convert.c \
        ao_dbg.c \
        ao_dma.c \
-       ao_ee.c \
-       ao_flight.c \
-       ao_gps.c \
-       ao_led.c \
-       ao_log.c \
        ao_mutex.c \
        ao_panic.c \
-       ao_report.c \
-       ao_serial.c \
        ao_task.c \
        ao_timer.c \
-       ao_usb.c \
-       ao_main.c \
        _bp.c
+
+#
+# Shared AltOS drivers
+#
+ALTOS_DRIVER_SRC = \
+       ao_beep.c \
+       ao_led.c \
+       ao_radio.c \
+       ao_stdio.c \
+       ao_usb.c
+
+TELE_COMMON_SRC = \
+       ao_gps_print.c
+
+#
+# Receiver code
+#
+TELE_RECEIVER_SRC =\
+       ao_monitor.c
+
+#
+# Shared Tele drivers (on TeleMetrum, TeleTerra, TeleDongle)
+#
+
+TELE_DRIVER_SRC = \
+       ao_convert.c \
+       ao_gps.c \
+       ao_serial.c
+
+# 
+# Drivers only on TeleMetrum
+#
+TM_DRIVER_SRC = \
+       ao_adc.c \
+       ao_ee.c
+
+#
+# Tasks run on TeleMetrum
+#
+TM_TASK_SRC = \
+       ao_flight.c \
+       ao_log.c \
+       ao_report.c \
+       ao_telemetry.c \
+       ao_telemetrum.c
+
+#
+# All sources for TeleMetrum
+#
+TM_SRC = \
+       $(ALTOS_SRC) \
+       $(ALTOS_DRIVER_SRC) \
+       $(TELE_DRIVER_SRC) \
+       $(TELE_COMMON_SRC) \
+       $(TM_DRIVER_SRC) \
+       $(TM_TASK_SRC)
+
+TI_TASK_SRC = \
+       ao_tidongle.c
+
+#
+# All sources for the TI debug dongle
+#
+TI_SRC = \
+       $(ALTOS_SRC) \
+       $(ALTOS_DRIVER_SRC) \
+       $(TELE_RECEIVER_SRC) \
+       $(TELE_COMMON_SRC) \
+       $(TI_TASK_SRC)
        
+SRC = \
+       $(ALTOS_SRC) \
+       $(ALTOS_DRIVER_SRC) \
+       $(TELE_DRIVER_SRC) \
+       $(TELE_RECEIVER_SRC) \
+       $(TELE_COMMON_SRC) \
+       $(TM_DRIVER_SRC) \
+       $(TM_TASK_SRC) \
+       $(TI_TASK_SRC)
+
+TM_REL=$(TM_SRC:.c=.rel)
+TI_REL=$(TI_SRC:.c=.rel)
+
 ADB=$(SRC:.c=.adb)
 ASM=$(SRC:.c=.asm)
 LNK=$(SRC:.c=.lnk)
@@ -45,7 +118,7 @@ REL=$(SRC:.c=.rel)
 RST=$(SRC:.c=.rst)
 SYM=$(SRC:.c=.sym)
 
-PROGS=$(PROG).ihx
+PROGS=telemetrum.ihx tidongle.ihx
 PCDB=$(PROGS:.ihx=.cdb)
 PLNK=$(PROGS:.ihx=.lnk)
 PMAP=$(PROGS:.ihx=.map)
@@ -57,9 +130,15 @@ PAOM=$(PROGS:.ihx=)
 
 all: $(PROGS)
 
-$(PROG).ihx: $(REL) Makefile
-       $(CC) $(LDFLAGS_FLASH) $(CFLAGS) -o $(PROG).ihx $(REL)
-       sh check-stack ao.h $(PROG).mem
+telemetrum.ihx: $(TM_REL) Makefile
+       $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TM_REL)
+       sh check-stack ao.h telemetrum.mem
+
+tidongle.ihx: $(TI_REL) Makefile
+       $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TI_REL)
+       sh check-stack ao.h tidongle.mem
+
+tidongle.ihx: telemetrum.ihx
 
 altitude.h: make-altitude
        nickle make-altitude > altitude.h
diff --git a/ao.h b/ao.h
index bbf358e..acce918 100644 (file)
--- a/ao.h
+++ b/ao.h
@@ -29,7 +29,7 @@
 /* Stack runs from above the allocated __data space to 0xfe, which avoids
  * writing to 0xff as that triggers the stack overflow indicator
  */
-#define AO_STACK_START 0x62
+#define AO_STACK_START 0x68
 #define AO_STACK_END   0xfe
 #define AO_STACK_SIZE  (AO_STACK_END - AO_STACK_START + 1)
 
@@ -52,11 +52,11 @@ extern __xdata struct ao_task *__data ao_cur_task;
  */
 
 /* Suspend the current task until wchan is awoken */
-int
+void
 ao_sleep(__xdata void *wchan);
 
 /* Wake all tasks sleeping on wchan */
-int
+void
 ao_wakeup(__xdata void *wchan);
 
 /* Yield the processor to another task */
@@ -84,6 +84,7 @@ ao_start_scheduler(void);
 #define AO_PANIC_MUTEX         3       /* Mis-using mutex API */
 #define AO_PANIC_EE            4       /* Mis-using eeprom API */
 #define AO_PANIC_LOG           5       /* Failing to read/write log data */
+#define AO_PANIC_CMD           6       /* Too many command sets registered */
 
 /* Stop the operating system, beeping and blinking the reason */
 void
@@ -105,6 +106,10 @@ ao_time(void);
 void
 ao_delay(uint16_t ticks);
 
+/* Set the ADC interval */
+void
+ao_timer_set_adc_interval(uint8_t interval) __critical;
+
 /* Timer interrupt */
 void
 ao_timer_isr(void) interrupt 9;
@@ -152,8 +157,10 @@ void
 ao_adc_get(__xdata struct ao_adc *packet);
 
 /* The A/D interrupt handler */
+#if !AO_NO_ADC_ISR
 void
 ao_adc_isr(void) interrupt 1;
+#endif
 
 /* Initialize the A/D converter */
 void
@@ -267,6 +274,41 @@ ao_usb_init(void);
 /*
  * ao_cmd.c
  */
+
+enum ao_cmd_status {
+       ao_cmd_success = 0,
+       ao_cmd_lex_error = 1,
+       ao_cmd_syntax_error = 2,
+};
+
+extern __xdata uint16_t ao_cmd_lex_i;
+extern __xdata uint8_t ao_cmd_lex_c;
+extern __xdata enum ao_cmd_status ao_cmd_status;
+
+void
+ao_cmd_lex(void);
+
+void
+ao_cmd_put8(uint8_t v);
+
+void
+ao_cmd_put16(uint16_t v);
+
+void
+ao_cmd_white(void);
+
+void
+ao_cmd_hex(void);
+
+struct ao_cmds {
+       uint8_t         cmd;
+       void            (*func)(void);
+       const char      *help;
+};
+
+void
+ao_cmd_register(__code struct ao_cmds *cmds);
+
 void
 ao_cmd_init(void);
 
@@ -357,6 +399,14 @@ ao_ee_init(void);
  * ao_log.c
  */
 
+/* Structure containing GPS position, either lat or lon */
+
+struct ao_gps_pos {
+       uint8_t degrees;
+       uint8_t minutes;
+       uint16_t minutes_fraction;      /* in units of 1/10000 minutes */
+};
+
 /*
  * The data log is recorded in the eeprom as a sequence
  * of data packets.
@@ -387,6 +437,10 @@ ao_ee_init(void);
 #define AO_LOG_TEMP_VOLT       'T'
 #define AO_LOG_DEPLOY          'D'
 #define AO_LOG_STATE           'S'
+#define AO_LOG_GPS_TIME                'G'
+#define AO_LOG_GPS_LAT         'N'
+#define AO_LOG_GPS_LON         'W'
+#define AO_LOG_GPS_ALT         'H'
 
 #define AO_LOG_POS_NONE                (~0UL)
 
@@ -415,6 +469,18 @@ struct ao_log_record {
                        uint16_t        state;
                        uint16_t        reason;
                } state;
+               struct {
+                       uint8_t         hour;
+                       uint8_t         minute;
+                       uint8_t         second;
+                       uint8_t         flags;
+               } gps_time;
+               struct ao_gps_pos gps_latitude;
+               struct ao_gps_pos gps_longitude;
+               struct {
+                       int16_t         altitude;
+                       uint16_t        unused;
+               } gps_altitude;
                struct {
                        uint16_t        d0;
                        uint16_t        d1;
@@ -465,16 +531,16 @@ ao_log_init(void);
  */
 
 enum ao_flight_state {
-       ao_flight_startup,
-       ao_flight_idle,
-       ao_flight_launchpad,
-       ao_flight_boost,
-       ao_flight_coast,
-       ao_flight_apogee,
-       ao_flight_drogue,
-       ao_flight_main,
-       ao_flight_landed,
-       ao_flight_invalid
+       ao_flight_startup = 0,
+       ao_flight_idle = 1,
+       ao_flight_launchpad = 2,
+       ao_flight_boost = 3,
+       ao_flight_coast = 4,
+       ao_flight_apogee = 5,
+       ao_flight_drogue = 6,
+       ao_flight_main = 7,
+       ao_flight_landed = 8,
+       ao_flight_invalid = 9
 };
 
 extern __xdata struct ao_adc           ao_flight_data;
@@ -499,9 +565,6 @@ ao_flight_init(void);
  * ao_report.c
  */
 
-void
-ao_report_notify(void);
-
 void
 ao_report_init(void);
 
@@ -519,10 +582,7 @@ int16_t
 ao_temp_to_dC(int16_t temp) __reentrant;
 
 int16_t
-ao_accel_to_dm_per_s2(int16_t accel)
-{
-       return (998 - (accel >> 4)) * 3300 / 2047;
-}
+ao_accel_to_cm_per_s2(int16_t accel) __reentrant;
 
 /*
  * ao_dbg.c
@@ -566,11 +626,13 @@ ao_dbg_reset(void);
  * ao_serial.c
  */
 
+#if !AO_NO_SERIAL_ISR
 void
 ao_serial_rx1_isr(void) interrupt 3;
 
 void
 ao_serial_tx1_isr(void) interrupt 14;
+#endif
 
 uint8_t
 ao_serial_getchar(void) __critical;
@@ -585,12 +647,6 @@ ao_serial_init(void);
  * ao_gps.c
  */
 
-struct ao_gps_pos {
-       uint8_t degrees;
-       uint8_t minutes;
-       uint16_t minutes_fraction;      /* in units of 1/10000 minutes */
-};
-
 #define AO_GPS_NUM_SAT_MASK    (0xf << 0)
 #define AO_GPS_NUM_SAT_SHIFT   (0)
 
@@ -619,9 +675,70 @@ extern __xdata struct ao_gps_data ao_gps_data;
 void
 ao_gps(void);
 
+void
+ao_gps_print(__xdata struct ao_gps_data *gps_data);
+
 void
 ao_gps_init(void);
 
+/*
+ * ao_telemetry.c
+ */
+
+#define AO_TELEMETRY_SENSOR    1
+#define AO_TELEMETRY_GPS       2
+
+struct ao_telemetry {
+       uint8_t         addr;
+       uint8_t         type;
+       uint8_t         flight_state;
+       union {
+               struct ao_adc           adc;
+               struct ao_gps_data      gps;
+       } u;
+};
+
+void
+ao_telemetry_send(__xdata struct ao_telemetry *telemetry) __reentrant;
+
+void
+ao_telemetry_init(void);
+
+/*
+ * ao_radio.c
+ */
+
+void
+ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant;
+
+struct ao_radio_recv {
+       struct ao_telemetry     telemetry;
+       uint8_t                 rssi;
+       uint8_t                 status;
+};
+
+void
+ao_radio_recv(__xdata struct ao_radio_recv *recv) __reentrant;
+
+void
+ao_radio_init(void);
+
+/*
+ * ao_monitor.c
+ */
+
+void
+ao_monitor(void);
+
+void
+ao_monitor_init(void);
+
+/*
+ * ao_stdio.c
+ */
+
+void
+flush(void);
 
 #endif /* _AO_H_ */
 
index 9cd3d46..39875bb 100644 (file)
--- a/ao_adc.c
+++ b/ao_adc.c
@@ -65,6 +65,21 @@ ao_adc_isr(void) interrupt 1
        }
 }
 
+static void
+ao_adc_dump(void)
+{
+       __xdata struct ao_adc   packet;
+       ao_adc_get(&packet);
+       printf("tick: %5u accel: %4d pres: %4d temp: %4d batt: %4d drogue: %4d main: %4d\n",
+              packet.tick, packet.accel >> 4, packet.pres >> 4, packet.temp >> 4,
+              packet.sense_d >> 4, packet.sense_m >> 4);
+}
+
+__code struct ao_cmds ao_adc_cmds[] = {
+       { 'a',  ao_adc_dump,    "a                                  Display current ADC values\n" },
+       { 0,    ao_adc_dump, NULL },
+};
+
 void
 ao_adc_init(void)
 {
@@ -78,5 +93,6 @@ ao_adc_init(void)
        /* enable interrupts */
        ADCIF = 0;
        IEN0 |= IEN0_ADCIE;
+       ao_cmd_register(&ao_adc_cmds[0]);
 }
 
index 6e91a72..13def7c 100644 (file)
--- a/ao_cmd.c
+++ b/ao_cmd.c
 
 #include "ao.h"
 
-#define LEX_ERROR      1
-#define SYNTAX_ERROR   2
-#define SUCCESS                0
-
-static __xdata uint16_t lex_i;
-static __xdata uint8_t lex_c;
-static __xdata uint8_t lex_status;
+__xdata uint16_t ao_cmd_lex_i;
+__xdata uint8_t        ao_cmd_lex_c;
+__xdata enum ao_cmd_status ao_cmd_status;
 static __xdata uint8_t lex_echo;
 
 #define CMD_LEN        32
@@ -32,26 +28,6 @@ static __xdata uint8_t       cmd_line[CMD_LEN];
 static __xdata uint8_t cmd_len;
 static __xdata uint8_t cmd_i;
 
-void
-putchar(char c)
-{
-       if (c == '\n')
-               ao_usb_putchar('\r');
-       ao_usb_putchar((uint8_t) c);
-}
-
-void
-flush(void)
-{
-       ao_usb_flush();
-}
-
-char
-getchar(void)
-{
-       return (char) ao_usb_getchar();
-}
-
 static void
 put_string(char *s)
 {
@@ -96,7 +72,7 @@ readline(void)
                
                if (c == '\n') {
                        if (lex_echo)
-                               put_string ("\n");
+                               putchar('\n');
                        break;
                }
 
@@ -114,12 +90,12 @@ readline(void)
        cmd_i = 0;
 }
 
-static void
-lex(void)
+void
+ao_cmd_lex(void)
 {
-       lex_c = '\n';
+       ao_cmd_lex_c = '\n';
        if (cmd_i < cmd_len)
-               lex_c = cmd_line[cmd_i++];
+               ao_cmd_lex_c = cmd_line[cmd_i++];
 }
 
 static void
@@ -132,7 +108,7 @@ putnibble(uint8_t v)
 }
 
 void
-put16(uint16_t v)
+ao_cmd_put16(uint16_t v)
 {
        int8_t i;
        for (i = 3; i >= 0; i--)
@@ -140,144 +116,68 @@ put16(uint16_t v)
 }
 
 void
-put8(uint8_t v)
+ao_cmd_put8(uint8_t v)
 {
        putnibble((v >> 4) & 0xf);
        putnibble(v & 0xf);
 }
 
-#define NUM_LEN 7
-
 void
-puti(int i)
+ao_cmd_white(void)
 {
-       static uint8_t __xdata  num_buffer[NUM_LEN];
-       uint8_t __xdata * __xdata num_ptr = num_buffer + NUM_LEN;
-       uint8_t __xdata neg = 0;
-       
-       *--num_ptr = '\0';
-       if (i < 0) {
-               i = -i;
-               neg = 1;
-       }
-       do {
-               *--num_ptr = '0' + i % 10;
-               i /= 10;
-       } while (i);
-       if (neg)
-               *--num_ptr = '-';
-       while (num_ptr != num_buffer)
-               *--num_ptr = ' ';
-       put_string(num_buffer);
+       while (ao_cmd_lex_c == ' ' || ao_cmd_lex_c == '\t')
+               ao_cmd_lex();
 }
 
-
-static void
-white(void)
-{
-       while (lex_c == ' ' || lex_c == '\t')
-               lex();
-}
-
-static void
-hex(void)
+void
+ao_cmd_hex(void)
 {
-       __xdata uint8_t r = LEX_ERROR;
+       __xdata uint8_t r = ao_cmd_lex_error;
        
-       lex_i = 0;
-       white();
+       ao_cmd_lex_i = 0;
+       ao_cmd_white();
        for(;;) {
-               if ('0' <= lex_c && lex_c <= '9')
-                       lex_i = (lex_i << 4) | (lex_c - '0');
-               else if ('a' <= lex_c && lex_c <= 'f')
-                       lex_i = (lex_i << 4) | (lex_c - 'a' + 10);
-               else if ('A' <= lex_c && lex_c <= 'F')
-                       lex_i = (lex_i << 4) | (lex_c - 'A' + 10);
+               if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9')
+                       ao_cmd_lex_i = (ao_cmd_lex_i << 4) | (ao_cmd_lex_c - '0');
+               else if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f')
+                       ao_cmd_lex_i = (ao_cmd_lex_i << 4) | (ao_cmd_lex_c - 'a' + 10);
+               else if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F')
+                       ao_cmd_lex_i = (ao_cmd_lex_i << 4) | (ao_cmd_lex_c - 'A' + 10);
                else
                        break;
-               r = SUCCESS;
-               lex();
+               r = ao_cmd_success;
+               ao_cmd_lex();
        }
-       if (r != SUCCESS)
-               lex_status = r;
+       if (r != ao_cmd_success)
+               ao_cmd_status = r;
 }
 
 #if 0
 static void
 decimal(void)
 {
-       __xdata uint8_t r = LEX_ERROR;
+       __xdata uint8_t r = ao_cmd_lex_error;
        
-       lex_i = 0;
-       white();
+       ao_cmd_lex_i = 0;
+       ao_cmd_white();
        for(;;) {
-               if ('0' <= lex_c && lex_c <= '9')
-                       lex_i = (lex_i * 10 ) | (lex_c - '0');
+               if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9')
+                       ao_cmd_lex_i = (ao_cmd_lex_i * 10 ) | (ao_cmd_lex_c - '0');
                else
                        break;
-               r = SUCCESS;
-               lex();
+               r = ao_cmd_success;
+               ao_cmd_lex();
        }
-       if (r != SUCCESS)
-               lex_status = r;
+       if (r != ao_cmd_success)
+               ao_cmd_status = r;
 }
 #endif
 
 static void
 eol(void)
 {
-       while (lex_c != '\n')
-               lex();
-}
-
-static void
-adc_dump(void)
-{
-       __xdata struct ao_adc   packet;
-       ao_adc_get(&packet);
-       put_string("tick: ");
-       puti(packet.tick);
-       put_string(" accel: ");
-       puti(packet.accel >> 4);
-       put_string(" pres: ");
-       puti(packet.pres >> 4);
-       put_string(" temp: ");
-       puti(packet.temp >> 4);
-       put_string(" batt: ");
-       puti(packet.v_batt >> 4);
-       put_string(" drogue: ");
-       puti(packet.sense_d >> 4);
-       put_string(" main: ");
-       puti(packet.sense_m >> 4);
-       put_string("\n");
-}
-
-static void
-gps_dump(void) __reentrant
-{
-       ao_mutex_get(&ao_gps_mutex);
-       if (ao_gps_data.flags & AO_GPS_VALID) {
-               printf("GPS %2d:%02d:%02d %2d°%2d.%04d'%c %2d°%2d.%04d'%c %5dm %2d sat\n",
-                      ao_gps_data.hour,
-                      ao_gps_data.minute,
-                      ao_gps_data.second,
-                      ao_gps_data.latitude.degrees,
-                      ao_gps_data.latitude.minutes,
-                      ao_gps_data.latitude.minutes_fraction,
-                      (ao_gps_data.flags & AO_GPS_LATITUDE_MASK) == AO_GPS_LATITUDE_NORTH ?
-                      'N' : 'S',
-                      ao_gps_data.longitude.degrees,
-                      ao_gps_data.longitude.minutes,
-                      ao_gps_data.longitude.minutes_fraction,
-                      (ao_gps_data.flags & AO_GPS_LONGITUDE_MASK) == AO_GPS_LONGITUDE_WEST ?
-                      'W' : 'E',
-                      ao_gps_data.altitude,
-                      (ao_gps_data.flags & AO_GPS_NUM_SAT_MASK) >> AO_GPS_NUM_SAT_SHIFT);
-       } else {
-               printf("GPS %2d sat\n",
-                      (ao_gps_data.flags & AO_GPS_NUM_SAT_MASK) >> AO_GPS_NUM_SAT_SHIFT);;
-       }
-       ao_mutex_put(&ao_gps_mutex);
+       while (ao_cmd_lex_c != '\n')
+               ao_cmd_lex();
 }
 
 static void
@@ -286,350 +186,117 @@ dump(void)
        __xdata uint16_t c;
        __xdata uint8_t * __xdata start, * __xdata end;
 
-       hex();
-       start = (uint8_t __xdata *) lex_i;
-       hex();
-       end = (uint8_t __xdata *) lex_i;
-       if (lex_status != SUCCESS)
+       ao_cmd_hex();
+       start = (uint8_t __xdata *) ao_cmd_lex_i;
+       ao_cmd_hex();
+       end = (uint8_t __xdata *) ao_cmd_lex_i;
+       if (ao_cmd_status != ao_cmd_success)
                return;
        c = 0;
        while (start <= end) {
                if ((c & 7) == 0) {
                        if (c)
-                               put_string("\n");
-                       put16((uint16_t) start);
+                               putchar('\n');
+                       ao_cmd_put16((uint16_t) start);
                }
                putchar(' ');
-               put8(*start);
+               ao_cmd_put8(*start);
                ++c;
                start++;
        }
-       put_string("\n");
-}
-
-static void
-ee_dump(void)
-{
-       __xdata uint8_t b;
-       __xdata uint16_t block;
-       __xdata uint8_t i;
-       
-       hex();
-       block = lex_i;
-       if (lex_status != SUCCESS)
-               return;
-       i = 0;
-       do {
-               if ((i & 7) == 0) {
-                       if (i)
-                               put_string("\n");
-                       put16((uint16_t) i);
-               }
-               putchar(' ');
-               ao_ee_read(((uint32_t) block << 8) | i, &b, 1);
-               put8(b);
-               ++i;
-       } while (i != 0);
-       put_string("\n");
-}
-
-static void
-ee_store(void)
-{
-       __xdata uint16_t block;
-       __xdata uint8_t i;
-       __xdata uint16_t len;
-       __xdata uint8_t b;
-       __xdata uint32_t addr;
-
-       hex();
-       block = lex_i;
-       hex();
-       i = lex_i;
-       addr = ((uint32_t) block << 8) | i;
-       hex();
-       len = lex_i;
-       if (lex_status != SUCCESS)
-               return;
-       while (len--) {
-               hex();
-               if (lex_status != SUCCESS)
-                       return;
-               b = lex_i;
-               ao_ee_write(addr, &b, 1);
-               addr++;
-       }
-       ao_ee_flush();  
+       putchar('\n');
 }
 
 static void
 echo(void)
 {
-       hex();
-       lex_echo = lex_i != 0;
-}
-
-static void
-debug_enable(void)
-{
-       ao_dbg_debug_mode();
-}
-
-static void
-debug_reset(void)
-{
-       ao_dbg_reset();
-}
-
-static void
-debug_put(void)
-{
-       for (;;) {
-               white ();
-               if (lex_c == '\n')
-                       break;
-               hex();
-               if (lex_status != SUCCESS)
-                       break;
-               ao_dbg_send_byte(lex_i);
-       }
-}
-
-static void
-debug_get(void)
-{
-       __xdata uint16_t count;
-       __xdata uint16_t i;
-       __xdata uint8_t byte;
-       hex();
-       if (lex_status != SUCCESS)
-               return;
-       count = lex_i;
-       if (count > 256) {
-               lex_status = SYNTAX_ERROR;
-               return;
-       }
-       for (i = 0; i < count; i++) {
-               if (i && (i & 7) == 0)
-                       put_string("\n");
-               byte = ao_dbg_recv_byte();
-               put8(byte);
-               putchar(' ');
-       }
-       put_string("\n");
+       ao_cmd_hex();
+       lex_echo = ao_cmd_lex_i != 0;
 }
 
-static uint8_t
-getnibble(void)
-{
-       __xdata uint8_t c;
-
-       c = getchar();
-       if ('0' <= c && c <= '9')
-               return c - '0';
-       if ('a' <= c && c <= 'f')
-               return c - ('a' - 10);
-       if ('A' <= c && c <= 'F')
-               return c - ('A' - 10);
-       lex_status = LEX_ERROR;
-       return 0;
-}
+static const uint8_t help_txt[] = "All numbers are in hex";
 
-static void
-debug_input(void)
-{
-       __xdata uint16_t count;
-       __xdata uint16_t addr;
-       __xdata uint8_t b;
-       __xdata uint8_t i;
+#define NUM_CMDS       8
 
-       hex();
-       count = lex_i;
-       hex();
-       addr = lex_i;
-       if (lex_status != SUCCESS)
-               return;
-       ao_dbg_start_transfer(addr);
-       i = 0;
-       while (count--) {
-               if (!(i++ & 7))
-                       put_string("\n");
-               b = ao_dbg_read_byte();
-               put8(b);
-       }
-       ao_dbg_end_transfer();
-       put_string("\n");
-}
-
-static void
-debug_output(void)
-{
-       __xdata uint16_t count;
-       __xdata uint16_t addr;
-       __xdata uint8_t b;
-
-       hex();
-       count = lex_i;
-       hex();
-       addr = lex_i;
-       if (lex_status != SUCCESS)
-               return;
-       ao_dbg_start_transfer(addr);
-       while (count--) {
-               b = getnibble() << 4;
-               b |= getnibble();
-               if (lex_status != SUCCESS)
-                       return;
-               ao_dbg_write_byte(b);
-       }
-       ao_dbg_end_transfer();
-}
-
-static void
-dump_log(void)
-{
-       __xdata uint8_t more;
-
-       for (more = ao_log_dump_first(); more; more = ao_log_dump_next()) {
-               putchar(ao_log_dump.type);
-               putchar(' ');
-               put16(ao_log_dump.tick);
-               putchar(' ');
-               put16(ao_log_dump.u.anon.d0);
-               putchar(' ');
-               put16(ao_log_dump.u.anon.d1);
-               putchar('\n');
-       }
-}
-
-static void
-send_serial(void)
-{
-       white();
-       while (lex_c != '\n') {
-               ao_serial_putchar(lex_c);
-               lex();
-       }
-}
-
-static const uint8_t help_txt[] = 
-       "All numbers are in hex\n"
-       "?                                  Print this message\n"
-       "a                                  Display current ADC values\n"
-       "g                                  Display current GPS values\n"
-       "d <start> <end>                    Dump memory\n"
-       "e <block>                          Dump a block of EEPROM data\n"
-       "w <block> <start> <len> <data> ... Write data to EEPROM\n"
-       "l                                  Dump last flight log\n"
-       "E <0 off, 1 on>                    Set command echo mode\n"
-       "S<data>                            Send data to serial line\n"
-       "T                                  Show task states\n"
-        "\n"
-        "Target debug commands:\n"
-       "D                                  Enable debug mode\n"
-       "R                                  Reset target\n"
-        "P <byte> ...                       Put data to debug port\n"
-       "G <count>                          Get data from debug port\n"
-       "O <count> <addr>                   Output <count> bytes to target at <addr>\n"
-       "I <count> <addr>                   Input <count> bytes to target at <addr>\n"
-;
+static __code struct ao_cmds   *__xdata (ao_cmds[NUM_CMDS]);
+static __xdata uint8_t         ao_ncmds;
 
 static void
 help(void)
 {
-       put_string(help_txt);
+       __xdata uint8_t cmds;
+       __xdata uint8_t cmd;
+       puts(help_txt);
+       for (cmds = 0; cmds < ao_ncmds; cmds++)
+               for (cmd = 0; ao_cmds[cmds][cmd].cmd; cmd++)
+                       puts(ao_cmds[cmds][cmd].help);
 }
 
 static void
 report(void)
 {
-       switch(lex_status) {
-       case LEX_ERROR:
-       case SYNTAX_ERROR:
-               put_string("Syntax error\n");
-               lex_status = 0;
+       switch(ao_cmd_status) {
+       case ao_cmd_lex_error:
+       case ao_cmd_syntax_error:
+               puts("Syntax error");
+               ao_cmd_status = 0;
                break;
        }
 }
 
+void
+ao_cmd_register(__code struct ao_cmds *cmds)
+{
+       if (ao_ncmds >= NUM_CMDS)
+               ao_panic(AO_PANIC_CMD);
+       ao_cmds[ao_ncmds++] = cmds;
+}
+
 void
 ao_cmd(void *parameters)
 {
        __xdata uint8_t c;
+       __xdata uint8_t cmd, cmds;
        (void) parameters;
 
        lex_echo = 1;
        for (;;) {
                readline();
-               lex();
-               white();
-               c = lex_c;
-               lex();
-               switch (c) {
-               case '?':
-                       help();
-                       break;
-               case 'd':
-                       dump();
-                       break;
-               case 'a':
-                       adc_dump();
-                       break;
-               case 'g':
-                       gps_dump();
-                       break;
-               case 'e':
-                       ee_dump();
-                       break;
-               case 'w':
-                       ee_store();
-                       break;
-               case 'l':
-                       dump_log();
-                       break;
-               case 'T':
-                       ao_task_info();
-                       break;
-               case 'S':
-                       send_serial();
-                       break;
-               case 'E':
-                       echo();
-                       break;
-               case 'D':
-                       debug_enable();
-                       break;
-               case 'R':
-                       debug_reset();
-                       break;
-               case 'P':
-                       debug_put();
-                       break;
-               case 'G':
-                       debug_get();
-                       break;
-               case 'I':
-                       debug_input();
-                       break;
-               case 'O':
-                       debug_output();
-                       break;
-               case '\r':
-               case '\n':
-                       break;
-               default:
-                       lex_status = SYNTAX_ERROR;
-                       break;
+               ao_cmd_lex();
+               ao_cmd_white();
+               c = ao_cmd_lex_c;
+               ao_cmd_lex();
+               if (c == '\r' || c == '\n')
+                       continue;
+               cmd = 0;
+               for (cmds = 0; cmds < ao_ncmds; cmds++) {
+                       for (cmd = 0; ao_cmds[cmds][cmd].cmd != '\0'; cmd++)
+                               if (ao_cmds[cmds][cmd].cmd == c)
+                                       break;
+                       if (ao_cmds[cmds][cmd].cmd)
+                               break;
                }
+               if (ao_cmds[cmds][cmd].cmd)
+                       (*ao_cmds[cmds][cmd].func);
+               else
+                       ao_cmd_status = ao_cmd_syntax_error;
                report();
        }
-               
 }
 
 __xdata struct ao_task ao_cmd_task;
 
+__code struct ao_cmds  ao_base_cmds[] = {
+       { '?', help,            "?                                  Print this message" },
+       { 'T', ao_task_info,    "T                                  Show task states\n" },
+       { 'E', echo,            "E <0 off, 1 on>                    Set command echo mode\n" },
+       { 'd', dump,            "d <start> <end>                    Dump memory\n" },
+       { 0,    help,   NULL },
+};
+
 void
 ao_cmd_init(void)
 {
+       ao_cmd_register(&ao_base_cmds[0]);
        ao_add_task(&ao_cmd_task, ao_cmd, "cmd");
 }
index 08f628b..2585db5 100644 (file)
@@ -44,4 +44,8 @@ ao_temp_to_dC(int16_t temp) __reentrant
 }
 
 int16_t
-ao_accel_to_cm_per_s2(int16_t accel) __reentrant;
+ao_accel_to_cm_per_s2(int16_t accel) __reentrant
+{
+       /* this is wrong */
+       return (998 - (accel >> 4)) * 3300 / 2047;
+}
index f493acc..11d8d50 100644 (file)
--- a/ao_dbg.c
+++ b/ao_dbg.c
@@ -213,3 +213,134 @@ ao_dbg_reset(void)
        ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N);
 }
 
+static void
+debug_enable(void)
+{
+       ao_dbg_debug_mode();
+}
+
+static void
+debug_reset(void)
+{
+       ao_dbg_reset();
+}
+
+static void
+debug_put(void)
+{
+       for (;;) {
+               ao_cmd_white ();
+               if (ao_cmd_lex_c == '\n')
+                       break;
+               ao_cmd_hex();
+               if (ao_cmd_status != ao_cmd_success)
+                       break;
+               ao_dbg_send_byte(ao_cmd_lex_i);
+       }
+}
+
+static void
+debug_get(void)
+{
+       __xdata uint16_t count;
+       __xdata uint16_t i;
+       __xdata uint8_t byte;
+       ao_cmd_hex();
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       count = ao_cmd_lex_i;
+       if (count > 256) {
+               ao_cmd_status = ao_cmd_syntax_error;
+               return;
+       }
+       for (i = 0; i < count; i++) {
+               if (i && (i & 7) == 0)
+                       putchar('\n');
+               byte = ao_dbg_recv_byte();
+               ao_cmd_put8(byte);
+               putchar(' ');
+       }
+       putchar('\n');
+}
+
+static uint8_t
+getnibble(void)
+{
+       __xdata uint8_t c;
+
+       c = getchar();
+       if ('0' <= c && c <= '9')
+               return c - '0';
+       if ('a' <= c && c <= 'f')
+               return c - ('a' - 10);
+       if ('A' <= c && c <= 'F')
+               return c - ('A' - 10);
+       ao_cmd_status = ao_cmd_lex_error;
+       return 0;
+}
+
+static void
+debug_input(void)
+{
+       __xdata uint16_t count;
+       __xdata uint16_t addr;
+       __xdata uint8_t b;
+       __xdata uint8_t i;
+
+       ao_cmd_hex();
+       count = ao_cmd_lex_i;
+       ao_cmd_hex();
+       addr = ao_cmd_lex_i;
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       ao_dbg_start_transfer(addr);
+       i = 0;
+       while (count--) {
+               if (!(i++ & 7))
+                       putchar('\n');
+               b = ao_dbg_read_byte();
+               ao_cmd_put8(b);
+       }
+       ao_dbg_end_transfer();
+       putchar('\n');
+}
+
+static void
+debug_output(void)
+{
+       __xdata uint16_t count;
+       __xdata uint16_t addr;
+       __xdata uint8_t b;
+
+       ao_cmd_hex();
+       count = ao_cmd_lex_i;
+       ao_cmd_hex();
+       addr = ao_cmd_lex_i;
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       ao_dbg_start_transfer(addr);
+       while (count--) {
+               b = getnibble() << 4;
+               b |= getnibble();
+               if (ao_cmd_status != ao_cmd_success)
+                       return;
+               ao_dbg_write_byte(b);
+       }
+       ao_dbg_end_transfer();
+}
+
+__code struct ao_cmds ao_dbg_cmds[7] = {
+       { 'D',  debug_enable,   "D                                  Enable debug mode\n" },
+       { 'G',  debug_get,      "G <count>                          Get data from debug port\n" },
+       { 'I',  debug_input,    "I <count> <addr>                   Input <count> bytes to target at <addr>\n" },
+       { 'O',  debug_output,   "O <count> <addr>                   Output <count> bytes to target at <addr>\n" },
+       { 'P',  debug_put,      "P <byte> ...                       Put data to debug port\n" },
+       { 'R',  debug_reset,    "R                                  Reset target\n" },
+       { 0, debug_reset,       0 },
+};
+
+void
+ao_dbg_init(void)
+{
+       ao_cmd_register(&ao_dbg_cmds[0]);
+}
index a109242..8d96cc4 100644 (file)
--- a/ao_dma.c
+++ b/ao_dma.c
@@ -88,11 +88,11 @@ ao_dma_start(uint8_t id)
        DMAARM = 0x80 | mask;
        nop(); nop(); nop(); nop();
        nop(); nop(); nop(); nop();
+       *(ao_dma_done[id]) = 0;
        DMAARM = mask;
        nop(); nop(); nop(); nop();
        nop(); nop(); nop(); nop();
        nop();
-       *(ao_dma_done[id]) = 0;
 }
 
 void
diff --git a/ao_ee.c b/ao_ee.c
index ea127c1..642de19 100644 (file)
--- a/ao_ee.c
+++ b/ao_ee.c
@@ -347,6 +347,67 @@ ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant
        return 1;
 }
 
+static void
+ee_dump(void)
+{
+       __xdata uint8_t b;
+       __xdata uint16_t block;
+       __xdata uint8_t i;
+       
+       ao_cmd_hex();
+       block = ao_cmd_lex_i;
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       i = 0;
+       do {
+               if ((i & 7) == 0) {
+                       if (i)
+                               putchar('\n');
+                       ao_cmd_put16((uint16_t) i);
+               }
+               putchar(' ');
+               ao_ee_read(((uint32_t) block << 8) | i, &b, 1);
+               ao_cmd_put8(b);
+               ++i;
+       } while (i != 0);
+       putchar('\n');
+}
+
+static void
+ee_store(void)
+{
+       __xdata uint16_t block;
+       __xdata uint8_t i;
+       __xdata uint16_t len;
+       __xdata uint8_t b;
+       __xdata uint32_t addr;
+
+       ao_cmd_hex();
+       block = ao_cmd_lex_i;
+       ao_cmd_hex();
+       i = ao_cmd_lex_i;
+       addr = ((uint32_t) block << 8) | i;
+       ao_cmd_hex();
+       len = ao_cmd_lex_i;
+       if (ao_cmd_status != ao_cmd_success)
+               return;
+       while (len--) {
+               ao_cmd_hex();
+               if (ao_cmd_status != ao_cmd_success)
+                       return;
+               b = ao_cmd_lex_i;
+               ao_ee_write(addr, &b, 1);
+               addr++;
+       }
+       ao_ee_flush();  
+}
+
+__code struct ao_cmds ao_ee_cmds[] = {
+       { 'e', ee_dump,         "e <block>                          Dump a block of EEPROM data\n" },
+       { 'w', ee_store,        "w <block> <start> <len> <data> ... Write data to EEPROM\n" },
+       { 0,   ee_store, NULL },
+};
+
 /*
  * To initialize the chip, set up the CS line and
  * the SPI interface
@@ -393,4 +454,5 @@ ao_ee_init(void)
                 UxGCR_CPHA_FIRST_EDGE |
                 UxGCR_ORDER_MSB |
                 (17 << UxGCR_BAUD_E_SHIFT));
+       ao_cmd_register(&ao_ee_cmds[0]);
 }
index dac110a..3aff866 100644 (file)
@@ -134,12 +134,19 @@ ao_flight(void)
                        
                        ao_interval_end = ao_flight_tick;
                        
-                       if (ao_flight_accel < ACCEL_NOSE_UP) {
+                       /* Go to launchpad state if the nose is pointing up and the battery is charged */
+                       if (ao_flight_accel < ACCEL_NOSE_UP && ao_flight_data.v_batt > 23000) {
                                ao_flight_state = ao_flight_launchpad;
-                               ao_report_notify();
+                               ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
                        } else {
                                ao_flight_state = ao_flight_idle;
-                               ao_report_notify();
+                               
+                               /* Turn on the Green LED in idle mode
+                                * This also happens to bring the USB up for the TI board
+                                */
+                               ao_led_on(AO_LED_GREEN);
+                               ao_timer_set_adc_interval(100);
+                               ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
                        }
                        /* signal successful initialization by turning off the LED */
                        ao_led_off(AO_LED_RED);
@@ -150,7 +157,7 @@ ao_flight(void)
                        {
                                ao_flight_state = ao_flight_boost;
                                ao_log_start();
-                               ao_report_notify();
+                               ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
                                break;
                        }
                        break;
@@ -159,7 +166,7 @@ ao_flight(void)
                            (int16_t) (ao_flight_data.tick - ao_launch_time) > BOOST_TICKS_MAX)
                        {
                                ao_flight_state = ao_flight_coast;
-                               ao_report_notify();
+                               ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
                                break;
                        }
                        break;
@@ -168,29 +175,29 @@ ao_flight(void)
                                ao_min_pres = ao_flight_pres;
                        if (ao_flight_pres - BARO_APOGEE > ao_min_pres) {
                                ao_flight_state = ao_flight_apogee;
-                               ao_report_notify();
+                               ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
                        }
                        break;
                case ao_flight_apogee:
 //                     ao_ignite(AO_IGNITE_DROGUE);
                        ao_flight_state = ao_flight_drogue;
-                       ao_report_notify();
+                       ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
                        break; 
                case ao_flight_drogue:
                        if (ao_flight_pres >= ao_main_pres) {
 //                             ao_ignite(AO_IGNITE_MAIN);
                                ao_flight_state = ao_flight_main;
-                               ao_report_notify();
+                               ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
                        }
                        if ((ao_interval_max_pres - ao_interval_min_pres) < BARO_LAND) {
                                ao_flight_state = ao_flight_landed;
-                               ao_report_notify();
+                               ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
                        }
                        break;
                case ao_flight_main:
                        if ((ao_interval_max_pres - ao_interval_min_pres) < BARO_LAND) {
                                ao_flight_state = ao_flight_landed;
-                               ao_report_notify();
+                               ao_wakeup(DATA_TO_XDATA(&ao_flight_state));
                        }
                        break;
                case ao_flight_landed:
index 83f44d5..80b96aa 100644 (file)
--- a/ao_gps.c
+++ b/ao_gps.c
@@ -17,8 +17,6 @@
 
 #include "ao.h"
 
-__xdata struct ao_task ao_gps_task;
-
 #define AO_GPS_LEADER          6
 
 static const uint8_t ao_gps_header[] = "GPGGA,";
@@ -248,15 +246,74 @@ ao_gps(void) __reentrant
                        ao_gps_error = 1;
                if (!ao_gps_error) {
                        ao_mutex_get(&ao_gps_mutex);
-                       memcpy(&ao_gps_data, &ao_gps_next, sizeof (ao_gps_data));
+                       memcpy(&ao_gps_data, &ao_gps_next, sizeof (struct ao_gps_data));
                        ao_mutex_put(&ao_gps_mutex);
                        ao_wakeup(&ao_gps_data);
                }
        }
 }
 
+void
+ao_gps_report(void)
+{
+       static __xdata struct ao_log_record     gps_log;
+       static __xdata struct ao_telemetry      gps_telemetry;
+       static __xdata struct ao_gps_data       gps_data;
+
+       for (;;) {
+               ao_sleep(&ao_gps_data);
+               ao_mutex_get(&ao_gps_mutex);
+               memcpy(&gps_data, &ao_gps_data, sizeof (struct ao_gps_data));
+               ao_mutex_put(&ao_gps_mutex);
+
+               gps_log.tick = ao_time();
+               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.degrees = gps_data.latitude.degrees;
+               gps_log.u.gps_latitude.minutes = gps_data.latitude.minutes;
+               gps_log.u.gps_latitude.minutes_fraction = gps_data.latitude.minutes_fraction;
+               ao_log_data(&gps_log);
+               gps_log.type = AO_LOG_GPS_LON;
+               gps_log.u.gps_longitude.degrees = gps_data.longitude.degrees;
+               gps_log.u.gps_longitude.minutes = gps_data.longitude.minutes;
+               gps_log.u.gps_longitude.minutes_fraction = gps_data.longitude.minutes_fraction;
+               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);
+               gps_telemetry.type = AO_TELEMETRY_GPS;
+               memcpy(&gps_telemetry.u.gps, &gps_data, sizeof (struct ao_gps_data));
+               ao_telemetry_send(&gps_telemetry);
+       }
+               
+}
+
+__xdata struct ao_task ao_gps_task;
+__xdata struct ao_task ao_gps_report_task;
+
+static void
+gps_dump(void) __reentrant
+{
+       ao_mutex_get(&ao_gps_mutex);
+       ao_gps_print(&ao_gps_data);
+       ao_mutex_put(&ao_gps_mutex);
+}
+
+__code struct ao_cmds ao_gps_cmds[] = {
+       { 'g', gps_dump,        "g                                  Display current GPS values\n" },
+       { 0, gps_dump, NULL },
+};
+
 void
 ao_gps_init(void)
 {
        ao_add_task(&ao_gps_task, ao_gps, "gps");
+       ao_add_task(&ao_gps_report_task, ao_gps_report, "gps_report");
+       ao_cmd_register(&ao_gps_cmds[0]);
 }
diff --git a/ao_gps_print.c b/ao_gps_print.c
new file mode 100644 (file)
index 0000000..de4a79c
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2009 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"
+
+void
+ao_gps_print(__xdata struct ao_gps_data *gps_data) __reentrant
+{
+       if (gps_data->flags & AO_GPS_VALID) {
+               printf("GPS %2d:%02d:%02d %2d°%2d.%04d'%c %2d°%2d.%04d'%c %5dm %2d sat\n",
+                      gps_data->hour,
+                      gps_data->minute,
+                      gps_data->second,
+                      gps_data->latitude.degrees,
+                      gps_data->latitude.minutes,
+                      gps_data->latitude.minutes_fraction,
+                      (gps_data->flags & AO_GPS_LATITUDE_MASK) == AO_GPS_LATITUDE_NORTH ?
+                      'N' : 'S',
+                      gps_data->longitude.degrees,
+                      gps_data->longitude.minutes,
+                      gps_data->longitude.minutes_fraction,
+                      (gps_data->flags & AO_GPS_LONGITUDE_MASK) == AO_GPS_LONGITUDE_WEST ?
+                      'W' : 'E',
+                      gps_data->altitude,
+                      (gps_data->flags & AO_GPS_NUM_SAT_MASK) >> AO_GPS_NUM_SAT_SHIFT);
+       } else {
+               printf("GPS %2d sat\n",
+                      (gps_data->flags & AO_GPS_NUM_SAT_MASK) >> AO_GPS_NUM_SAT_SHIFT);;
+       }
+}
+
index 3bb2f84..d7ff5c8 100644 (file)
--- a/ao_log.c
+++ b/ao_log.c
@@ -178,6 +178,25 @@ ao_log_stop(void)
        ao_log_flush();
 }
 
+static void
+dump_log(void)
+{
+       __xdata uint8_t more;
+
+       for (more = ao_log_dump_first(); more; more = ao_log_dump_next()) {
+               printf("%c %4x %4x %4x\n",
+                      ao_log_dump.type,
+                      ao_log_dump.tick,
+                      ao_log_dump.u.anon.d0,
+                      ao_log_dump.u.anon.d1);
+       }
+}
+
+__code struct ao_cmds ao_log_cmds[] = {
+       { 'l',  dump_log,               "l                                  Dump last flight log\n" },
+       { 0, dump_log, NULL },
+};
+
 static __xdata struct ao_task ao_log_task;
 
 void
@@ -192,4 +211,5 @@ ao_log_init(void)
 
        /* Create a task to log events to eeprom */
        ao_add_task(&ao_log_task, ao_log, "log");
+       ao_cmd_register(&ao_log_cmds[0]);
 }
index e4ccdf5..1f7a829 100644 (file)
--- a/ao_main.c
+++ b/ao_main.c
@@ -39,5 +39,7 @@ main(void)
        ao_usb_init();
        ao_serial_init();
        ao_gps_init();
+       ao_telemetry_init();
+       ao_radio_init();
        ao_start_scheduler();
 }
diff --git a/ao_monitor.c b/ao_monitor.c
new file mode 100644 (file)
index 0000000..1c2d127
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * $Id: $
+ *
+ * Copyright © 2009 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "ao.h"
+
+const char const * const ao_state_names[] = {
+       "startup", "idle", "pad", "boost", "coast",
+       "apogee", "drogue", "main", "landed", "invalid"
+};
+
+void
+ao_monitor(void)
+{
+       __xdata struct ao_radio_recv recv;
+       uint8_t state;
+
+       for (;;) {
+               ao_radio_recv(&recv);
+               state = recv.telemetry.flight_state;
+               if (state > ao_flight_invalid)
+                       state = ao_flight_invalid;
+               printf ("SERIAL %3d RSSI %3d STATUS %02x STATE %s ",
+                       recv.telemetry.addr, recv.rssi, recv.status,
+                       ao_state_names[state]);
+               if (!(recv.status & PKT_APPEND_STATUS_1_CRC_OK))
+                       printf("CRC INVALID ");
+               switch (recv.telemetry.type) {
+               case AO_TELEMETRY_SENSOR:
+                       printf("%5u a: %d p: %d t: %d v: %d d: %d m: %d\n",
+                              recv.telemetry.u.adc.tick,
+                              recv.telemetry.u.adc.accel,
+                              recv.telemetry.u.adc.pres,
+                              recv.telemetry.u.adc.temp,
+                              recv.telemetry.u.adc.v_batt,
+                              recv.telemetry.u.adc.sense_d,
+                              recv.telemetry.u.adc.sense_m);
+                       break;
+               case AO_TELEMETRY_GPS:
+                       ao_gps_print(&recv.telemetry.u.gps);
+                       break;
+               }
+               ao_usb_flush();
+       }
+}
+
+__xdata struct ao_task ao_monitor_task;
+
+void
+ao_monitor_init(void)
+{
+       ao_add_task(&ao_monitor_task, ao_monitor, "monitor");
+}
index ec960f0..f6ecc38 100644 (file)
@@ -34,6 +34,7 @@ ao_panic(uint8_t reason)
        uint8_t n;
        
        __critical for (;;) {
+               ao_panic_delay(20);
                for (n = 0; n < 5; n++) {
                        ao_led_on(AO_LED_RED);
                        ao_beep(AO_BEEP_HIGH);
@@ -44,6 +45,7 @@ ao_panic(uint8_t reason)
                }
                ao_beep(AO_BEEP_OFF);
                ao_panic_delay(2);
+#pragma disable_warning 126
                for (n = 0; n < reason; n++) {
                        ao_led_on(AO_LED_RED);
                        ao_beep(AO_BEEP_MID);
@@ -52,6 +54,5 @@ ao_panic(uint8_t reason)
                        ao_beep(AO_BEEP_OFF);
                        ao_panic_delay(10);
                }
-               ao_panic_delay(20);
        }
 }
diff --git a/ao_radio.c b/ao_radio.c
new file mode 100644 (file)
index 0000000..5ff6f9b
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * Copyright © 2009 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"
+
+/* Values from SmartRF® Studio for:
+ *
+ * Deviation:  20.507812 kHz
+ * Datarate:   38.360596 kBaud
+ * Modulation: GFSK
+ * RF Freq:    434.549927 MHz
+ * Channel:    99.975586 kHz
+ * Channel:    0
+ * RX filter:  93.75 kHz
+ */
+
+/*
+ * For 434.550MHz, the frequency value is:
+ *
+ * 434.550e6 / (24e6 / 2**16) = 1186611.2
+ */
+
+#define FREQ_CONTROL   1186611
+
+/*
+ * For IF freq of 140.62kHz, the IF value is:
+ *
+ * 140.62e3 / (24e6 / 2**10) = 6
+ */
+
+#define IF_FREQ_CONTROL        6
+
+/*
+ * For channel bandwidth of 93.75 kHz, the CHANBW_E and CHANBW_M values are
+ *
+ * BW = 24e6 / (8 * (4 + M) * 2 ** E)
+ *
+ * So, M = 0 and E = 3
+ */
+
+#define CHANBW_M       0
+#define CHANBW_E       3
+
+/*
+ * For a symbol rate of 38360kBaud, the DRATE_E and DRATE_M values are:
+ *
+ * R = (256 + M) * 2** E * 24e6 / 2**28
+ *
+ * So M is 163 and E is 10
+ */
+
+#define DRATE_E                10
+#define DRATE_M                163
+
+/*
+ * For a channel deviation of 20.5kHz, the DEVIATION_E and DEVIATION_M values are:
+ *
+ * F = 24e6/2**17 * (8 + DEVIATION_M) * 2**DEVIATION_E
+ *
+ * So M is 6 and E is 3
+ */
+
+#define DEVIATION_M    6
+#define DEVIATION_E    3
+
+/* This are from the table for 433MHz */
+
+#define RF_POWER_M30_DBM       0x12
+#define RF_POWER_M20_DBM       0x0e
+#define RF_POWER_M15_DBM       0x1d
+#define RF_POWER_M10_DBM       0x34
+#define RF_POWER_M5_DBM                0x2c
+#define RF_POWER_0_DBM         0x60
+#define RF_POWER_5_DBM         0x84
+#define RF_POWER_7_DBM         0xc8
+#define RF_POWER_10_DBM                0xc0
+
+#define RF_POWER               RF_POWER_0_DBM
+
+static __code uint8_t radio_setup[] = {
+       RF_PA_TABLE7_OFF,       RF_POWER,
+       RF_PA_TABLE6_OFF,       RF_POWER,
+       RF_PA_TABLE5_OFF,       RF_POWER,
+       RF_PA_TABLE4_OFF,       RF_POWER,
+       RF_PA_TABLE3_OFF,       RF_POWER,
+       RF_PA_TABLE2_OFF,       RF_POWER,
+       RF_PA_TABLE1_OFF,       RF_POWER,
+       RF_PA_TABLE0_OFF,       RF_POWER,
+
+       RF_FREQ2_OFF,           (FREQ_CONTROL >> 16) & 0xff,
+       RF_FREQ1_OFF,           (FREQ_CONTROL >> 8) & 0xff,
+       RF_FREQ0_OFF,           (FREQ_CONTROL >> 0) & 0xff,
+       
+       RF_FSCTRL1_OFF,         (IF_FREQ_CONTROL << RF_FSCTRL1_FREQ_IF_SHIFT),
+       RF_FSCTRL0_OFF,         (0 << RF_FSCTRL0_FREQOFF_SHIFT),
+
+       RF_MDMCFG4_OFF,         ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) |
+                                (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) |
+                                (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)),
+       RF_MDMCFG3_OFF,         (DRATE_M << RF_MDMCFG3_DRATE_M_SHIFT),
+       RF_MDMCFG2_OFF,         (RF_MDMCFG2_DEM_DCFILT_OFF |
+                                RF_MDMCFG2_MOD_FORMAT_GFSK |
+                                RF_MDMCFG2_SYNC_MODE_15_16_THRES),
+       RF_MDMCFG1_OFF,         (RF_MDMCFG1_FEC_EN |
+                                RF_MDMCFG1_NUM_PREAMBLE_4 |
+                                (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)),
+       RF_MDMCFG0_OFF,         (17 << RF_MDMCFG0_CHANSPC_M_SHIFT),
+
+       RF_CHANNR_OFF,          0,
+
+       RF_DEVIATN_OFF,         ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) |
+                                (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)),
+
+       /* SmartRF says set LODIV_BUF_CURRENT_TX to 0
+        * And, we're not using power ramping, so use PA_POWER 0
+        */
+       RF_FREND0_OFF,          ((1 << RF_FREND0_LODIV_BUF_CURRENT_TX_SHIFT) |
+                                (0 << RF_FREND0_PA_POWER_SHIFT)),
+
+       RF_FREND1_OFF,          ((1 << RF_FREND1_LNA_CURRENT_SHIFT) |
+                                (1 << RF_FREND1_LNA2MIX_CURRENT_SHIFT) |
+                                (1 << RF_FREND1_LODIV_BUF_CURRENT_RX_SHIFT) |
+                                (2 << RF_FREND1_MIX_CURRENT_SHIFT)),
+
+       RF_FSCAL3_OFF,          0xE9,
+       RF_FSCAL2_OFF,          0x0A,
+       RF_FSCAL1_OFF,          0x00,
+       RF_FSCAL0_OFF,          0x1F,
+
+       RF_TEST2_OFF,           0x88,
+       RF_TEST1_OFF,           0x31,
+       RF_TEST0_OFF,           0x09,
+
+       /* default sync values */
+       RF_SYNC1_OFF,           0xD3,
+       RF_SYNC0_OFF,           0x91,
+       
+       /* max packet length */
+       RF_PKTLEN_OFF,          sizeof (struct ao_telemetry),
+
+       RF_PKTCTRL1_OFF,        ((1 << PKTCTRL1_PQT_SHIFT)|
+                                PKTCTRL1_APPEND_STATUS|
+                                PKTCTRL1_ADR_CHK_NONE),
+       RF_PKTCTRL0_OFF,        (RF_PKTCTRL0_WHITE_DATA|
+                                RF_PKTCTRL0_PKT_FORMAT_NORMAL|
+                                RF_PKTCTRL0_CRC_EN|
+                                RF_PKTCTRL0_LENGTH_CONFIG_FIXED),
+       RF_ADDR_OFF,            0x00,
+       RF_MCSM2_OFF,           (RF_MCSM2_RX_TIME_END_OF_PACKET),
+       RF_MCSM1_OFF,           (RF_MCSM1_CCA_MODE_RSSI_BELOW_UNLESS_RECEIVING|
+                                RF_MCSM1_RXOFF_MODE_IDLE|
+                                RF_MCSM1_TXOFF_MODE_IDLE),
+       RF_MCSM0_OFF,           (RF_MCSM0_FS_AUTOCAL_FROM_IDLE|
+                                RF_MCSM0_MAGIC_3|
+                                RF_MCSM0_CLOSE_IN_RX_0DB),
+       RF_FOCCFG_OFF,          (RF_FOCCFG_FOC_PRE_K_3K,
+                                RF_FOCCFG_FOC_POST_K_PRE_K,
+                                RF_FOCCFG_FOC_LIMIT_BW_OVER_4),
+       RF_BSCFG_OFF,           (RF_BSCFG_BS_PRE_K_2K|
+                                RF_BSCFG_BS_PRE_KP_3KP|
+                                RF_BSCFG_BS_POST_KI_PRE_KI|
+                                RF_BSCFG_BS_POST_KP_PRE_KP|
+                                RF_BSCFG_BS_LIMIT_0),
+       RF_AGCCTRL2_OFF,        0x43,
+       RF_AGCCTRL1_OFF,        0x40,
+       RF_AGCCTRL0_OFF,        0x91,
+
+       RF_IOCFG2_OFF,          0x00,
+       RF_IOCFG1_OFF,          0x00,
+       RF_IOCFG0_OFF,          0x00,
+};
+
+__xdata uint8_t        ao_radio_dma;
+__xdata uint8_t ao_radio_dma_done;
+__xdata uint8_t ao_radio_mutex;
+
+static void
+ao_radio_idle(void)
+{
+       if (RF_MARCSTATE != RF_MARCSTATE_IDLE)
+       {
+               RFST = RFST_SIDLE;
+               do {
+                       ao_yield();
+               } while (RF_MARCSTATE != RF_MARCSTATE_IDLE);
+       }
+}
+
+void
+ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant
+{
+       ao_mutex_get(&ao_radio_mutex);
+       ao_radio_idle();
+       ao_dma_set_transfer(ao_radio_dma,
+                           telemetry,
+                           &RFDXADDR,
+                           sizeof (struct ao_telemetry),
+                           DMA_CFG0_WORDSIZE_8 |
+                           DMA_CFG0_TMODE_SINGLE |
+                           DMA_CFG0_TRIGGER_RADIO,
+                           DMA_CFG1_SRCINC_1 |
+                           DMA_CFG1_DESTINC_0 |
+                           DMA_CFG1_PRIORITY_HIGH);
+       ao_dma_start(ao_radio_dma);
+       RFST = RFST_STX;
+       while (!ao_radio_dma_done)
+               ao_sleep(&ao_radio_dma_done);
+       ao_mutex_put(&ao_radio_mutex);
+}
+
+void
+ao_radio_recv(__xdata struct ao_radio_recv *radio) __reentrant
+{
+       ao_mutex_get(&ao_radio_mutex);
+       ao_radio_idle();
+       ao_dma_set_transfer(ao_radio_dma,
+                           &RFDXADDR,
+                           radio,
+                           sizeof (struct ao_radio_recv),
+                           DMA_CFG0_WORDSIZE_8 |
+                           DMA_CFG0_TMODE_SINGLE |
+                           DMA_CFG0_TRIGGER_RADIO,
+                           DMA_CFG1_SRCINC_0 |
+                           DMA_CFG1_DESTINC_1 |
+                           DMA_CFG1_PRIORITY_HIGH);
+       ao_dma_start(ao_radio_dma);
+       RFST = RFST_SRX;
+       while (!ao_radio_dma_done)
+               ao_sleep(&ao_radio_dma_done);
+       ao_mutex_put(&ao_radio_mutex);
+}
+
+void
+ao_radio_init(void)
+{
+       uint8_t i;
+       for (i = 0; i < sizeof (radio_setup); i += 2)
+               RF[radio_setup[i]] = radio_setup[i+1];
+       ao_radio_dma_done = 1;
+       ao_radio_dma = ao_dma_alloc(&ao_radio_dma_done);
+}
+
index cee2bf3..b26f671 100644 (file)
@@ -57,12 +57,6 @@ ao_report_beep(void)
        pause(AO_MS_TO_TICKS(400));
 }
 
-void
-ao_report_notify(void)
-{
-       ao_wakeup(&ao_report_state);
-}
-
 void
 ao_report(void)
 {
@@ -71,7 +65,7 @@ ao_report(void)
                ao_report_beep();
                __critical {
                        while (ao_report_state == ao_flight_state)
-                               ao_sleep(&ao_report_state);
+                               ao_sleep(DATA_TO_XDATA(&ao_flight_state));
                        ao_report_state = ao_flight_state;
                }
        }
index 215a301..a229298 100644 (file)
@@ -90,6 +90,21 @@ ao_serial_putchar(uint8_t c) __critical
        ao_serial_tx1_start();
 }
 
+static void
+send_serial(void)
+{
+       ao_cmd_white();
+       while (ao_cmd_lex_c != '\n') {
+               ao_serial_putchar(ao_cmd_lex_c);
+               ao_cmd_lex();
+       }
+}
+
+__code struct ao_cmds ao_serial_cmds[] = {
+       { 'S', send_serial,             "S<data>                            Send data to serial line\n" },
+       { 0, send_serial, NULL },
+};
+
 void
 ao_serial_init(void)
 {
@@ -120,4 +135,6 @@ ao_serial_init(void)
 
        IEN0 |= IEN0_URX1IE;
        IEN2 |= IEN2_UTX1IE;
+
+       ao_cmd_register(&ao_serial_cmds[0]);
 }
diff --git a/ao_stdio.c b/ao_stdio.c
new file mode 100644 (file)
index 0000000..da57f40
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Copyright © 2009 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"
+
+/*
+ * Basic I/O functions to support SDCC stdio package
+ */
+
+void
+putchar(char c)
+{
+       if (c == '\n')
+               ao_usb_putchar('\r');
+       ao_usb_putchar((uint8_t) c);
+}
+
+void
+flush(void)
+{
+       ao_usb_flush();
+}
+
+char
+getchar(void)
+{
+       return (char) ao_usb_getchar();
+}
index 043b3df..878724c 100644 (file)
--- a/ao_task.c
+++ b/ao_task.c
@@ -169,16 +169,16 @@ ao_yield(void) _naked
        _endasm;
 }
 
-int
+void
 ao_sleep(__xdata void *wchan)
 {
        __critical {
-       ao_cur_task->wchan = wchan;
+               ao_cur_task->wchan = wchan;
        }
        ao_yield();
 }
 
-int
+void
 ao_wakeup(__xdata void *wchan)
 {
        uint8_t i;
diff --git a/ao_telemetrum.c b/ao_telemetrum.c
new file mode 100644 (file)
index 0000000..1f7a829
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2009 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"
+
+void
+main(void)
+{
+       CLKCON = 0;
+       while (!(SLEEP & SLEEP_XOSC_STB))
+               ;
+
+       /* Turn on the red LED until the system is stable */
+       ao_led_init();
+       ao_led_on(AO_LED_RED);
+
+       ao_timer_init();
+       ao_adc_init();
+       ao_beep_init();
+       ao_cmd_init();
+       ao_ee_init();
+       ao_flight_init();
+       ao_log_init();
+       ao_report_init();
+       ao_usb_init();
+       ao_serial_init();
+       ao_gps_init();
+       ao_telemetry_init();
+       ao_radio_init();
+       ao_start_scheduler();
+}
diff --git a/ao_telemetry.c b/ao_telemetry.c
new file mode 100644 (file)
index 0000000..092918d
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2009 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"
+
+/* XXX make serial numbers real */
+
+uint8_t        ao_serial_number = 2;
+
+void
+ao_telemetry_send(__xdata struct ao_telemetry *telemetry) __reentrant
+{
+       if (ao_flight_state != ao_flight_idle && ao_flight_state != ao_flight_startup) {
+               telemetry->addr = ao_serial_number;
+               telemetry->flight_state = ao_flight_state;
+               ao_radio_send(telemetry);
+       }
+}
+
+void
+ao_telemetry(void)
+{
+       static __xdata struct ao_radio_recv recv;
+       static uint8_t state;
+
+       while (ao_flight_state == ao_flight_startup || ao_flight_state == ao_flight_idle)
+               ao_sleep(DATA_TO_XDATA(&ao_flight_state));
+
+       recv.telemetry.type = AO_TELEMETRY_SENSOR;
+       for (;;) {
+               ao_adc_get(&recv.telemetry.u.adc);
+               ao_telemetry_send(&recv.telemetry);
+               ao_delay(AO_MS_TO_TICKS(1000));
+       }
+}
+
+__xdata struct ao_task ao_telemetry_task;
+
+void
+ao_telemetry_init()
+{
+       ao_add_task(&ao_telemetry_task, ao_telemetry, "telemetry");
+}
diff --git a/ao_tidongle.c b/ao_tidongle.c
new file mode 100644 (file)
index 0000000..385e0cf
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2009 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.
+ */
+
+#define AO_NO_SERIAL_ISR 1
+#define AO_NO_ADC_ISR 1
+#include "ao.h"
+
+void
+main(void)
+{
+       CLKCON = 0;
+       while (!(SLEEP & SLEEP_XOSC_STB))
+               ;
+       
+       /* Turn on the LED until the system is stable */
+       ao_led_init();
+       ao_led_on(AO_LED_RED);
+       ao_timer_init();
+       ao_cmd_init();
+       ao_usb_init();
+       ao_monitor_init();
+       ao_radio_init();
+       ao_start_scheduler();
+}
+
+/* Stub for systems which have no ADC */
+void
+ao_adc_poll(void)
+{
+}
index 8b485cc..716befe 100644 (file)
@@ -40,8 +40,8 @@ ao_delay(uint16_t ticks)
 #define T1_CLOCK_DIVISOR       8       /* 24e6/8 = 3e6 */
 #define T1_SAMPLE_TIME         30000   /* 3e6/30000 = 100 */
 
-__data uint8_t ao_adc_interval = 1;
-__data uint8_t ao_adc_count;
+volatile __data uint8_t        ao_adc_interval = 1;
+volatile __data uint8_t        ao_adc_count;
 
 void ao_timer_isr(void) interrupt 9
 {
@@ -53,6 +53,12 @@ void ao_timer_isr(void) interrupt 9
        ao_wakeup(DATA_TO_XDATA(&ao_tick_count));
 }
 
+void
+ao_timer_set_adc_interval(uint8_t interval) __critical
+{
+       ao_adc_interval = interval;
+}
+
 void
 ao_timer_init(void)
 {
@@ -63,7 +69,7 @@ ao_timer_init(void)
 
        /* set the sample rate */
        T1CC0H = T1_SAMPLE_TIME >> 8;
-       T1CC0L = T1_SAMPLE_TIME;
+       T1CC0L = (uint8_t) T1_SAMPLE_TIME;
 
        T1CCTL0 = T1CCTL_MODE_COMPARE;
        T1CCTL1 = 0;
index 83fd798..c1520d7 100644 (file)
--- a/ao_usb.c
+++ b/ao_usb.c
@@ -102,7 +102,7 @@ ao_usb_ep0_flush(void)
        USBCS0 = cs0;
 }
 
-#define LE_WORD(x)    ((x)&0xFF),((x)>>8)
+#define LE_WORD(x)    ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8))
 
 /* CDC definitions */
 #define CS_INTERFACE      0x24
@@ -369,6 +369,7 @@ ao_usb_ep0_setup(void)
                        }
                        break;
                case AO_USB_RECIP_INTERFACE:
+                       #pragma disable_warning 110
                        switch(ao_usb_setup.request) {
                        case AO_USB_REQ_GET_STATUS:
                                ao_usb_ep0_queue_byte(0);
index 3cec5e1..10d446c 100644 (file)
--- a/cc1111.h
+++ b/cc1111.h
@@ -830,4 +830,374 @@ __xdata __at (0xDFF9) volatile uint8_t U1DBUFXADDR;
 sfr at 0xc2 U0BAUD;
 sfr at 0xfa U1BAUD;
 
+/* Radio */
+
+sfr at 0xD9 RFD;
+__xdata at (0xDFD9) volatile uint8_t RFDXADDR;
+
+sfr at 0xE9 RFIF;
+#define RFIF_IM_TXUNF  (1 << 7)
+#define RFIF_IM_RXOVF  (1 << 6)
+#define RFIF_IM_TIMEOUT        (1 << 5)
+#define RFIF_IM_DONE   (1 << 4)
+#define RFIF_IM_CS     (1 << 3)
+#define RFIF_IM_PQT    (1 << 2)
+#define RFIF_IM_CCA    (1 << 1)
+#define RFIF_IM_SFD    (1 << 0)
+
+sfr at 0xE1 RFST;
+
+#define RFST_SFSTXON   0x00
+#define RFST_SCAL      0x01
+#define RFST_SRX       0x02
+#define RFST_STX       0x03
+#define RFST_SIDLE     0x04
+
+__xdata __at (0xdf00) uint8_t RF[0x3c];
+
+__xdata __at (0xdf2f) uint8_t RF_IOCFG2;
+#define RF_IOCFG2_OFF  0x2f
+
+__xdata __at (0xdf30) uint8_t RF_IOCFG1;
+#define RF_IOCFG1_OFF  0x30
+
+__xdata __at (0xdf31) uint8_t RF_IOCFG0;
+#define RF_IOCFG0_OFF  0x31
+
+__xdata __at (0xdf00) uint8_t RF_SYNC1;
+#define RF_SYNC1_OFF   0x00
+
+__xdata __at (0xdf01) uint8_t RF_SYNC0;
+#define RF_SYNC0_OFF   0x01
+
+__xdata __at (0xdf02) uint8_t RF_PKTLEN;
+#define RF_PKTLEN_OFF  0x02
+
+__xdata __at (0xdf03) uint8_t RF_PKTCTRL1;
+#define RF_PKTCTRL1_OFF        0x03
+#define PKTCTRL1_PQT_MASK                      (0x7 << 5)
+#define PKTCTRL1_PQT_SHIFT                     5
+#define PKTCTRL1_APPEND_STATUS                 (1 << 2)
+#define PKTCTRL1_ADR_CHK_NONE                  (0 << 0)
+#define PKTCTRL1_ADR_CHK_NO_BROADCAST          (1 << 0)
+#define PKTCTRL1_ADR_CHK_00_BROADCAST          (2 << 0)
+#define PKTCTRL1_ADR_CHK_00_FF_BROADCAST       (3 << 0)
+
+/* If APPEND_STATUS is used, two bytes will be added to the packet data */
+#define PKT_APPEND_STATUS_0_RSSI_MASK          (0xff)
+#define PKT_APPEND_STATUS_0_RSSI_SHIFT         0
+#define PKT_APPEND_STATUS_1_CRC_OK             (1 << 7)
+#define PKT_APPEND_STATUS_1_LQI_MASK           (0x7f)
+#define PKT_APPEND_STATUS_1_LQI_SHIFT          0
+
+__xdata __at (0xdf04) uint8_t RF_PKTCTRL0;
+#define RF_PKTCTRL0_OFF        0x04
+#define RF_PKTCTRL0_WHITE_DATA                 (1 << 6)
+#define RF_PKTCTRL0_PKT_FORMAT_NORMAL          (0 << 4)
+#define RF_PKTCTRL0_PKT_FORMAT_RANDOM          (2 << 4)
+#define RF_PKTCTRL0_CRC_EN                     (1 << 2)
+#define RF_PKTCTRL0_LENGTH_CONFIG_FIXED                (0 << 0)
+#define RF_PKTCTRL0_LENGTH_CONFIG_VARIABLE     (1 << 0)
+
+__xdata __at (0xdf05) uint8_t RF_ADDR;
+#define RF_ADDR_OFF    0x05
+
+__xdata __at (0xdf06) uint8_t RF_CHANNR;
+#define RF_CHANNR_OFF  0x06
+
+__xdata __at (0xdf07) uint8_t RF_FSCTRL1;
+#define RF_FSCTRL1_OFF 0x07
+
+#define RF_FSCTRL1_FREQ_IF_SHIFT       (0)
+
+__xdata __at (0xdf08) uint8_t RF_FSCTRL0;
+#define RF_FSCTRL0_OFF 0x08
+
+#define RF_FSCTRL0_FREQOFF_SHIFT       (0)
+
+__xdata __at (0xdf09) uint8_t RF_FREQ2;
+#define RF_FREQ2_OFF   0x09
+
+__xdata __at (0xdf0a) uint8_t RF_FREQ1;
+#define RF_FREQ1_OFF   0x0a
+
+__xdata __at (0xdf0b) uint8_t RF_FREQ0;
+#define RF_FREQ0_OFF   0x0b
+
+__xdata __at (0xdf0c) uint8_t RF_MDMCFG4;
+#define RF_MDMCFG4_OFF 0x0c
+
+#define RF_MDMCFG4_CHANBW_E_SHIFT      6
+#define RF_MDMCFG4_CHANBW_M_SHIFT      4
+#define RF_MDMCFG4_DRATE_E_SHIFT       0
+
+__xdata __at (0xdf0d) uint8_t RF_MDMCFG3;
+#define RF_MDMCFG3_OFF 0x0d
+
+#define RF_MDMCFG3_DRATE_M_SHIFT       0
+
+__xdata __at (0xdf0e) uint8_t RF_MDMCFG2;
+#define RF_MDMCFG2_OFF 0x0e
+
+#define RF_MDMCFG2_DEM_DCFILT_OFF      (1 << 7)
+#define RF_MDMCFG2_DEM_DCFILT_ON       (0 << 7)
+
+#define RF_MDMCFG2_MOD_FORMAT_MASK     (7 << 4)
+#define RF_MDMCFG2_MOD_FORMAT_2_FSK    (0 << 4)
+#define RF_MDMCFG2_MOD_FORMAT_GFSK     (1 << 4)
+#define RF_MDMCFG2_MOD_FORMAT_ASK_OOK  (3 << 4)
+#define RF_MDMCFG2_MOD_FORMAT_MSK      (7 << 4)
+
+#define RF_MDMCFG2_MANCHESTER_EN       (1 << 3)
+
+#define RF_MDMCFG2_SYNC_MODE_MASK              (0x7 << 0)
+#define RF_MDMCFG2_SYNC_MODE_NONE              (0x0 << 0)
+#define RF_MDMCFG2_SYNC_MODE_15_16             (0x1 << 0)
+#define RF_MDMCFG2_SYNC_MODE_16_16             (0x2 << 0)
+#define RF_MDMCFG2_SYNC_MODE_30_32             (0x3 << 0)
+#define RF_MDMCFG2_SYNC_MODE_NONE_THRES                (0x4 << 0)
+#define RF_MDMCFG2_SYNC_MODE_15_16_THRES       (0x5 << 0)
+#define RF_MDMCFG2_SYNC_MODE_16_16_THRES       (0x6 << 0)
+#define RF_MDMCFG2_SYNC_MODE_30_32_THRES       (0x7 << 0)
+
+__xdata __at (0xdf0f) uint8_t RF_MDMCFG1;
+#define RF_MDMCFG1_OFF 0x0f
+
+#define RF_MDMCFG1_FEC_EN                      (1 << 7)
+#define RF_MDMCFG1_FEC_DIS                     (0 << 7)
+
+#define RF_MDMCFG1_NUM_PREAMBLE_MASK           (7 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_2              (0 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_3              (1 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_4              (2 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_6              (3 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_8              (4 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_12             (5 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_16             (6 << 4)
+#define RF_MDMCFG1_NUM_PREAMBLE_24             (7 << 4)
+
+#define RF_MDMCFG1_CHANSPC_E_MASK              (3 << 0)
+#define RF_MDMCFG1_CHANSPC_E_SHIFT             (0)
+
+__xdata __at (0xdf10) uint8_t RF_MDMCFG0;
+#define RF_MDMCFG0_OFF 0x10
+
+#define RF_MDMCFG0_CHANSPC_M_SHIFT             (0)
+
+__xdata __at (0xdf11) uint8_t RF_DEVIATN;
+#define RF_DEVIATN_OFF 0x11
+
+#define RF_DEVIATN_DEVIATION_E_SHIFT           4
+#define RF_DEVIATN_DEVIATION_M_SHIFT           0
+
+__xdata __at (0xdf12) uint8_t RF_MCSM2;
+#define RF_MCSM2_OFF   0x12
+#define RF_MCSM2_RX_TIME_RSSI                  (1 << 4)
+#define RF_MCSM2_RX_TIME_QUAL                  (1 << 3)
+#define RF_MCSM2_RX_TIME_MASK                  (0x7)
+#define RF_MCSM2_RX_TIME_SHIFT                 0
+#define RF_MCSM2_RX_TIME_END_OF_PACKET         (7)
+
+__xdata __at (0xdf13) uint8_t RF_MCSM1;
+#define RF_MCSM1_OFF   0x13
+#define RF_MCSM1_CCA_MODE_ALWAYS                       (0 << 4)
+#define RF_MCSM1_CCA_MODE_RSSI_BELOW                   (1 << 4)
+#define RF_MCSM1_CCA_MODE_UNLESS_RECEIVING             (2 << 4)
+#define RF_MCSM1_CCA_MODE_RSSI_BELOW_UNLESS_RECEIVING  (3 << 4)
+#define RF_MCSM1_RXOFF_MODE_IDLE                       (0 << 2)
+#define RF_MCSM1_RXOFF_MODE_FSTXON                     (1 << 2)
+#define RF_MCSM1_RXOFF_MODE_TX                         (2 << 2)
+#define RF_MCSM1_RXOFF_MODE_RX                         (3 << 2)
+#define RF_MCSM1_TXOFF_MODE_IDLE                       (0 << 0)
+#define RF_MCSM1_TXOFF_MODE_FSTXON                     (1 << 0)
+#define RF_MCSM1_TXOFF_MODE_TX                         (2 << 0)
+#define RF_MCSM1_TXOFF_MODE_RX                         (3 << 0)
+
+__xdata __at (0xdf14) uint8_t RF_MCSM0;
+#define RF_MCSM0_OFF   0x14
+#define RF_MCSM0_FS_AUTOCAL_NEVER              (0 << 4)
+#define RF_MCSM0_FS_AUTOCAL_FROM_IDLE          (1 << 4)
+#define RF_MCSM0_FS_AUTOCAL_TO_IDLE            (2 << 4)
+#define RF_MCSM0_FS_AUTOCAL_TO_IDLE_EVERY_4    (3 << 4)
+#define RF_MCSM0_MAGIC_3                       (1 << 3)
+#define RF_MCSM0_MAGIC_2                       (1 << 2)
+#define RF_MCSM0_CLOSE_IN_RX_0DB               (0 << 0)
+#define RF_MCSM0_CLOSE_IN_RX_6DB               (1 << 0)
+#define RF_MCSM0_CLOSE_IN_RX_12DB              (2 << 0)
+#define RF_MCSM0_CLOSE_IN_RX_18DB              (3 << 0)
+
+__xdata __at (0xdf15) uint8_t RF_FOCCFG;
+#define RF_FOCCFG_OFF  0x15
+#define RF_FOCCFG_FOC_BS_CS_GATE               (1 << 5)
+#define RF_FOCCFG_FOC_PRE_K_1K                 (0 << 3)
+#define RF_FOCCFG_FOC_PRE_K_2K                 (1 << 3)
+#define RF_FOCCFG_FOC_PRE_K_3K                 (2 << 3)
+#define RF_FOCCFG_FOC_PRE_K_4K                 (3 << 3)
+#define RF_FOCCFG_FOC_POST_K_PRE_K             (0 << 2)
+#define RF_FOCCFG_FOC_POST_K_PRE_K_OVER_2      (1 << 2)
+#define RF_FOCCFG_FOC_LIMIT_0                  (0 << 0)
+#define RF_FOCCFG_FOC_LIMIT_BW_OVER_8          (1 << 0)
+#define RF_FOCCFG_FOC_LIMIT_BW_OVER_4          (2 << 0)
+#define RF_FOCCFG_FOC_LIMIT_BW_OVER_2          (3 << 0)
+
+__xdata __at (0xdf16) uint8_t RF_BSCFG;
+#define RF_BSCFG_OFF   0x16
+#define RF_BSCFG_BS_PRE_K_1K                   (0 << 6)
+#define RF_BSCFG_BS_PRE_K_2K                   (1 << 6)
+#define RF_BSCFG_BS_PRE_K_3K                   (2 << 6)
+#define RF_BSCFG_BS_PRE_K_4K                   (3 << 6)
+#define RF_BSCFG_BS_PRE_KP_1KP                 (0 << 4)
+#define RF_BSCFG_BS_PRE_KP_2KP                 (1 << 4)
+#define RF_BSCFG_BS_PRE_KP_3KP                 (2 << 4)
+#define RF_BSCFG_BS_PRE_KP_4KP                 (3 << 4)
+#define RF_BSCFG_BS_POST_KI_PRE_KI             (0 << 3)
+#define RF_BSCFG_BS_POST_KI_PRE_KI_OVER_2      (1 << 3)
+#define RF_BSCFG_BS_POST_KP_PRE_KP             (0 << 2)
+#define RF_BSCFG_BS_POST_KP_PRE_KP_OVER_2      (1 << 2)
+#define RF_BSCFG_BS_LIMIT_0                    (0 << 0)
+#define RF_BSCFG_BS_LIMIT_3_125                        (1 << 0)
+#define RF_BSCFG_BS_LIMIT_6_25                 (2 << 0)
+#define RF_BSCFG_BS_LIMIT_12_5                 (3 << 0)
+
+__xdata __at (0xdf17) uint8_t RF_AGCCTRL2;
+#define RF_AGCCTRL2_OFF        0x17
+
+__xdata __at (0xdf18) uint8_t RF_AGCCTRL1;
+#define RF_AGCCTRL1_OFF        0x18
+
+__xdata __at (0xdf19) uint8_t RF_AGCCTRL0;
+#define RF_AGCCTRL0_OFF        0x19
+
+__xdata __at (0xdf1a) uint8_t RF_FREND1;
+#define RF_FREND1_OFF  0x1a
+
+#define RF_FREND1_LNA_CURRENT_SHIFT            6
+#define RF_FREND1_LNA2MIX_CURRENT_SHIFT                4
+#define RF_FREND1_LODIV_BUF_CURRENT_RX_SHIFT   2
+#define RF_FREND1_MIX_CURRENT_SHIFT            0
+
+__xdata __at (0xdf1b) uint8_t RF_FREND0;
+#define RF_FREND0_OFF  0x1b
+
+#define RF_FREND0_LODIV_BUF_CURRENT_TX_MASK    (0x3 << 4)
+#define RF_FREND0_LODIV_BUF_CURRENT_TX_SHIFT   4
+#define RF_FREND0_PA_POWER_MASK                        (0x7)
+#define RF_FREND0_PA_POWER_SHIFT               0
+
+__xdata __at (0xdf1c) uint8_t RF_FSCAL3;
+#define RF_FSCAL3_OFF  0x1c
+
+__xdata __at (0xdf1d) uint8_t RF_FSCAL2;
+#define RF_FSCAL2_OFF  0x1d
+
+__xdata __at (0xdf1e) uint8_t RF_FSCAL1;
+#define RF_FSCAL1_OFF  0x1e
+
+__xdata __at (0xdf1f) uint8_t RF_FSCAL0;
+#define RF_FSCAL0_OFF  0x1f
+
+__xdata __at (0xdf23) uint8_t RF_TEST2;
+#define RF_TEST2_OFF   0x23
+
+#define RF_TEST2_NORMAL_MAGIC          0x88
+#define RF_TEST2_RX_LOW_DATA_RATE_MAGIC        0x81
+
+__xdata __at (0xdf24) uint8_t RF_TEST1;
+#define RF_TEST1_OFF   0x24
+
+#define RF_TEST1_TX_MAGIC              0x31
+#define RF_TEST1_RX_LOW_DATA_RATE_MAGIC        0x35
+
+__xdata __at (0xdf25) uint8_t RF_TEST0;
+#define RF_TEST0_OFF   0x25
+
+#define RF_TEST0_7_2_MASK              (0xfc)
+#define RF_TEST0_VCO_SEL_CAL_EN                (1 << 1)
+#define RF_TEST0_0_MASK                        (1)
+
+/* These are undocumented, and must be computed
+ * using the provided tool.
+ */
+__xdata __at (0xdf27) uint8_t RF_PA_TABLE7;
+#define RF_PA_TABLE7_OFF       0x27
+
+__xdata __at (0xdf28) uint8_t RF_PA_TABLE6;
+#define RF_PA_TABLE6_OFF       0x28
+
+__xdata __at (0xdf29) uint8_t RF_PA_TABLE5;
+#define RF_PA_TABLE5_OFF       0x29
+
+__xdata __at (0xdf2a) uint8_t RF_PA_TABLE4;
+#define RF_PA_TABLE4_OFF       0x2a
+
+__xdata __at (0xdf2b) uint8_t RF_PA_TABLE3;
+#define RF_PA_TABLE3_OFF       0x2b
+
+__xdata __at (0xdf2c) uint8_t RF_PA_TABLE2;
+#define RF_PA_TABLE2_OFF       0x2c
+
+__xdata __at (0xdf2d) uint8_t RF_PA_TABLE1;
+#define RF_PA_TABLE1_OFF       0x2d
+
+__xdata __at (0xdf2e) uint8_t RF_PA_TABLE0;
+#define RF_PA_TABLE0_OFF       0x2e
+
+__xdata __at (0xdf36) uint8_t RF_PARTNUM;
+#define RF_PARTNUM_OFF 0x36
+
+__xdata __at (0xdf37) uint8_t RF_VERSION;
+#define RF_VERSION_OFF 0x37
+
+__xdata __at (0xdf38) uint8_t RF_FREQEST;
+#define RF_FREQEST_OFF 0x38
+
+__xdata __at (0xdf39) uint8_t RF_LQI;
+#define RF_LQI_OFF     0x39
+
+#define RF_LQI_CRC_OK                  (1 << 7)
+#define RF_LQI_LQI_EST_MASK            (0x7f)
+
+__xdata __at (0xdf3a) uint8_t RF_RSSI;
+#define RF_RSSI_OFF    0x3a
+
+__xdata __at (0xdf3b) uint8_t RF_MARCSTATE;
+#define RF_MARCSTATE_OFF       0x3b
+
+#define RF_MARCSTATE_MASK              0x1f
+#define RF_MARCSTATE_SLEEP             0x00
+#define RF_MARCSTATE_IDLE              0x01
+#define RF_MARCSTATE_VCOON_MC          0x03
+#define RF_MARCSTATE_REGON_MC          0x04
+#define RF_MARCSTATE_MANCAL            0x05
+#define RF_MARCSTATE_VCOON             0x06
+#define RF_MARCSTATE_REGON             0x07
+#define RF_MARCSTATE_STARTCAL          0x08
+#define RF_MARCSTATE_BWBOOST           0x09
+#define RF_MARCSTATE_FS_LOCK           0x0a
+#define RF_MARCSTATE_IFADCON           0x0b
+#define RF_MARCSTATE_ENDCAL            0x0c
+#define RF_MARCSTATE_RX                        0x0d
+#define RF_MARCSTATE_RX_END            0x0e
+#define RF_MARCSTATE_RX_RST            0x0f
+#define RF_MARCSTATE_TXRX_SWITCH       0x10
+#define RF_MARCSTATE_RX_OVERFLOW       0x11
+#define RF_MARCSTATE_FSTXON            0x12
+#define RF_MARCSTATE_TX                        0x13
+#define RF_MARCSTATE_TX_END            0x14
+#define RF_MARCSTATE_RXTX_SWITCH       0x15
+#define RF_MARCSTATE_TX_UNDERFLOW      0x16
+
+
+__xdata __at (0xdf3c) uint8_t RF_PKTSTATUS;
+#define RF_PKTSTATUS_OFF       0x3c
+
+#define RF_PKTSTATUS_CRC_OK            (1 << 7)
+#define RF_PKTSTATUS_CS                        (1 << 6)
+#define RF_PKTSTATUS_PQT_REACHED       (1 << 5)
+#define RF_PKTSTATUS_CCA               (1 << 4)
+#define RF_PKTSTATUS_SFD               (1 << 3)
+
+__xdata __at (0xdf3d) uint8_t RF_VCO_VC_DAC;
+#define RF_VCO_VC_DAC_OFF      0x3d
+
 #endif
index d93e8e4..6d3106a 100755 (executable)
@@ -2,11 +2,11 @@
 HEADER=$1
 MEM=$2
 
-HEADER_STACK=`awk '/#define AO_STACK_START/ {print $3}' $HEADER`
-MEM_STACK=`awk '/Stack starts at/ {print $4}' $MEM`
+HEADER_STACK=`awk '/#define AO_STACK_START/ {print $3}' $HEADER | nickle`
+MEM_STACK=`awk '/Stack starts at/ {print $4}' $MEM | nickle`
 
-if [ "$HEADER_STACK" != "$MEM_STACK" ]; then
-       echo "Set AO_STACK_START to $MEM_STACK"
+if [ "$HEADER_STACK" -lt "$MEM_STACK" ]; then
+       echo "Set AO_STACK_START to at least $MEM_STACK"
        exit 1
 else
        exit 0