From: Keith Packard Date: Tue, 21 Apr 2009 06:33:41 +0000 (-0700) Subject: Add radio support. Build separate executables for TeleMetrum and the TI dongle X-Git-Tag: 0.1~45 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=43c8f7012102cdb591ace899420c10e4a78385ad;ds=sidebyside Add radio support. Build separate executables for TeleMetrum and the TI dongle 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. --- diff --git a/Makefile b/Makefile index b35b1446..550e7376 100644 --- a/Makefile +++ b/Makefile @@ -1,42 +1,115 @@ -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 bbf358e9..acce9180 100644 --- 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_ */ diff --git a/ao_adc.c b/ao_adc.c index 9cd3d46c..39875bbd 100644 --- 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]); } diff --git a/ao_cmd.c b/ao_cmd.c index 6e91a72d..13def7c2 100644 --- a/ao_cmd.c +++ b/ao_cmd.c @@ -17,13 +17,9 @@ #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 Dump memory\n" - "e Dump a block of EEPROM data\n" - "w ... Write data to EEPROM\n" - "l Dump last flight log\n" - "E <0 off, 1 on> Set command echo mode\n" - "S 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 ... Put data to debug port\n" - "G Get data from debug port\n" - "O Output bytes to target at \n" - "I Input bytes to target at \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 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"); } diff --git a/ao_convert.c b/ao_convert.c index 08f628b4..2585db54 100644 --- a/ao_convert.c +++ b/ao_convert.c @@ -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; +} diff --git a/ao_dbg.c b/ao_dbg.c index f493acc5..11d8d50a 100644 --- 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 Get data from debug port\n" }, + { 'I', debug_input, "I Input bytes to target at \n" }, + { 'O', debug_output, "O Output bytes to target at \n" }, + { 'P', debug_put, "P ... 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]); +} diff --git a/ao_dma.c b/ao_dma.c index a1092425..8d96cc4b 100644 --- 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 ea127c12..642de19d 100644 --- 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 Dump a block of EEPROM data\n" }, + { 'w', ee_store, "w ... 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]); } diff --git a/ao_flight.c b/ao_flight.c index dac110aa..3aff866a 100644 --- a/ao_flight.c +++ b/ao_flight.c @@ -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: diff --git a/ao_gps.c b/ao_gps.c index 83f44d55..80b96aa7 100644 --- 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 index 00000000..de4a79c1 --- /dev/null +++ b/ao_gps_print.c @@ -0,0 +1,45 @@ +/* + * 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" + +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);; + } +} + diff --git a/ao_log.c b/ao_log.c index 3bb2f845..d7ff5c82 100644 --- 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]); } diff --git a/ao_main.c b/ao_main.c index e4ccdf59..1f7a829f 100644 --- 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 index 00000000..1c2d1274 --- /dev/null +++ b/ao_monitor.c @@ -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"); +} diff --git a/ao_panic.c b/ao_panic.c index ec960f01..f6ecc380 100644 --- a/ao_panic.c +++ b/ao_panic.c @@ -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 index 00000000..5ff6f9bf --- /dev/null +++ b/ao_radio.c @@ -0,0 +1,256 @@ +/* + * 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" + +/* 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); +} + diff --git a/ao_report.c b/ao_report.c index cee2bf3a..b26f6713 100644 --- a/ao_report.c +++ b/ao_report.c @@ -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; } } diff --git a/ao_serial.c b/ao_serial.c index 215a301d..a2292980 100644 --- a/ao_serial.c +++ b/ao_serial.c @@ -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 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 index 00000000..da57f409 --- /dev/null +++ b/ao_stdio.c @@ -0,0 +1,42 @@ +/* + * 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" + +/* + * 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(); +} diff --git a/ao_task.c b/ao_task.c index 043b3df2..878724c5 100644 --- 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 index 00000000..1f7a829f --- /dev/null +++ b/ao_telemetrum.c @@ -0,0 +1,45 @@ +/* + * 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" + +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 index 00000000..092918d4 --- /dev/null +++ b/ao_telemetry.c @@ -0,0 +1,57 @@ +/* + * 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" + +/* 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 index 00000000..385e0cfd --- /dev/null +++ b/ao_tidongle.c @@ -0,0 +1,44 @@ +/* + * 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. + */ + +#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) +{ +} diff --git a/ao_timer.c b/ao_timer.c index 8b485cc2..716befe6 100644 --- a/ao_timer.c +++ b/ao_timer.c @@ -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; diff --git a/ao_usb.c b/ao_usb.c index 83fd798f..c1520d75 100644 --- 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); diff --git a/cc1111.h b/cc1111.h index 3cec5e11..10d446c0 100644 --- 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 diff --git a/check-stack b/check-stack index d93e8e44..6d3106a8 100755 --- a/check-stack +++ b/check-stack @@ -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