From cd5ce661e2a8f9694933358ccb5b916fbed089c2 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Tue, 18 Aug 2009 21:49:39 -0600 Subject: add support for building Debian package --- src/Makefile | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 297f676b..5a8afe0b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,7 +4,9 @@ # CC=sdcc +ifndef VERSION VERSION=$(shell git describe) +endif CFLAGS=--model-small --debug --opt-code-speed -- cgit v1.2.3 From 29687cbd462a332d9a36ed87500c5b737dcae3f4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 18 Aug 2009 22:35:15 -0700 Subject: Handle GPS satellite tracking data SiRF message #4 includes signal strength and GPS engine state for each of the satellites being tracked. This data is now parsed and sent to eeprom and the radio. Signed-off-by: Keith Packard --- src/Makefile | 4 +- src/ao.h | 32 ++++++++++ src/ao_dbg.c | 2 +- src/ao_gps.c | 126 ++++++++++++++++++++++++++++-------- src/ao_gps_print.c | 37 ++++++++++- src/ao_gps_report.c | 31 +++++++++ src/ao_gps_test.c | 181 +++++++++++++++++++++++++++++++++++++++++++--------- src/ao_host.h | 4 +- src/ao_monitor.c | 3 + src/ao_telemetry.c | 1 + 10 files changed, 358 insertions(+), 63 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 297f676b..9cc322a2 100644 --- a/src/Makefile +++ b/src/Makefile @@ -260,8 +260,8 @@ clean: install: -ao_flight_test: ao_flight.c ao_flight_test.c +ao_flight_test: ao_flight.c ao_flight_test.c ao_host.h cc -g -o $@ ao_flight_test.c -ao_gps_test: ao_gps.c ao_gps_test.c ao_host.h +ao_gps_test: ao_gps.c ao_gps_test.c ao_gps_print.c ao_host.h cc -g -o $@ ao_gps_test.c diff --git a/src/ao.h b/src/ao.h index 85b7825f..27ec010f 100644 --- a/src/ao.h +++ b/src/ao.h @@ -458,6 +458,7 @@ ao_ee_init(void); #define AO_LOG_GPS_LAT 'N' #define AO_LOG_GPS_LON 'W' #define AO_LOG_GPS_ALT 'H' +#define AO_LOG_GPS_SAT 'V' #define AO_LOG_POS_NONE (~0UL) @@ -498,6 +499,12 @@ struct ao_log_record { int16_t altitude; uint16_t unused; } gps_altitude; + struct { + uint16_t svid; + uint8_t state; + uint8_t c_n; + uint8_t unused; + } gps_sat; struct { uint16_t d0; uint16_t d1; @@ -696,8 +703,29 @@ struct ao_gps_data { uint16_t v_error; /* m */ }; +#define SIRF_SAT_STATE_ACQUIRED (1 << 0) +#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) +#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) +#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) +#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) +#define SIRF_SAT_CODE_LOCKED (1 << 5) +#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) +#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) + +struct ao_gps_sat_data { + uint8_t svid; + uint8_t state; + uint8_t c_n_1; +}; + +struct ao_gps_tracking_data { + uint8_t channels; + struct ao_gps_sat_data sats[12]; +}; + extern __xdata uint8_t ao_gps_mutex; extern __xdata struct ao_gps_data ao_gps_data; +extern __xdata struct ao_gps_tracking_data ao_gps_tracking_data; void ao_gps(void); @@ -705,6 +733,9 @@ ao_gps(void); void ao_gps_print(__xdata struct ao_gps_data *gps_data); +void +ao_gps_tracking_print(__xdata struct ao_gps_tracking_data *gps_tracking_data); + void ao_gps_init(void); @@ -735,6 +766,7 @@ struct ao_telemetry { struct ao_adc adc; struct ao_gps_data gps; char callsign[AO_MAX_CALLSIGN]; + struct ao_gps_tracking_data gps_tracking; }; /* Set delay between telemetry reports (0 to disable) */ diff --git a/src/ao_dbg.c b/src/ao_dbg.c index c8dc6ddc..b218897c 100644 --- a/src/ao_dbg.c +++ b/src/ao_dbg.c @@ -26,7 +26,7 @@ #define DBG_RESET_N_PIN (P0_5) static void -ao_dbg_send_bits(uint8_t msk, uint8_t val) +ao_dbg_send_bits(uint8_t msk, uint8_t val) __reentrant { P0 = (P0 & ~msk) | (val & msk); _asm diff --git a/src/ao_gps.c b/src/ao_gps.c index c4c434fd..7d68b325 100644 --- a/src/ao_gps.c +++ b/src/ao_gps.c @@ -21,6 +21,7 @@ __xdata uint8_t ao_gps_mutex; __xdata struct ao_gps_data ao_gps_data; +__xdata struct ao_gps_tracking_data ao_gps_tracking_data; static const char ao_gps_set_nmea[] = "\r\n$PSRF100,0,57600,8,1,0*37\r\n"; @@ -105,6 +106,21 @@ struct sirf_geodetic_nav_data { static __xdata struct sirf_geodetic_nav_data ao_sirf_data; +struct sirf_measured_sat_data { + uint8_t svid; + uint16_t state; + uint8_t c_n_1; +}; + +struct sirf_measured_tracker_data { + int16_t gps_week; + uint32_t gps_tow; + uint8_t channels; + struct sirf_measured_sat_data sats[12]; +}; + +static __xdata struct sirf_measured_tracker_data ao_sirf_tracker_data; + static __pdata uint16_t ao_sirf_cksum; static __pdata uint16_t ao_sirf_len; @@ -118,9 +134,11 @@ static uint8_t data_byte(void) return c; } +static char __xdata *sirf_target; + static void sirf_u16(uint8_t offset) { - uint16_t __xdata *ptr = (uint16_t __xdata *) (((char __xdata *) &ao_sirf_data) + offset); + uint16_t __xdata *ptr = (uint16_t __xdata *) (sirf_target + offset); uint16_t val; val = data_byte() << 8; @@ -130,16 +148,16 @@ static void sirf_u16(uint8_t offset) static void sirf_u8(uint8_t offset) { - uint8_t __xdata *ptr = (uint8_t __xdata *) (((char __xdata *) &ao_sirf_data) + offset); + uint8_t __xdata *ptr = (uint8_t __xdata *) (sirf_target + offset); uint8_t val; val = data_byte (); *ptr = val; } -static void sirf_u32(uint8_t offset) +static void sirf_u32(uint8_t offset) __reentrant { - uint32_t __xdata *ptr = (uint32_t __xdata *) (((char __xdata *) &ao_sirf_data) + offset); + uint32_t __xdata *ptr = (uint32_t __xdata *) (sirf_target + offset); uint32_t val; val = ((uint32_t) data_byte ()) << 24; @@ -160,12 +178,44 @@ static void sirf_discard(uint8_t len) #define SIRF_U8 2 #define SIRF_U16 3 #define SIRF_U32 4 +#define SIRF_U8X10 5 struct sirf_packet_parse { uint8_t type; uint8_t offset; }; +static void +ao_sirf_parse(void __xdata *target, const struct sirf_packet_parse *parse) __reentrant +{ + uint8_t i, offset, j; + + sirf_target = target; + for (i = 0; ; i++) { + offset = parse[i].offset; + switch (parse[i].type) { + case SIRF_END: + return; + case SIRF_DISCARD: + sirf_discard(offset); + break; + case SIRF_U8: + sirf_u8(offset); + break; + case SIRF_U16: + sirf_u16(offset); + break; + case SIRF_U32: + sirf_u32(offset); + break; + case SIRF_U8X10: + for (j = 10; j--;) + sirf_u8(offset++); + break; + } + } +} + static const struct sirf_packet_parse geodetic_nav_data_packet[] = { { SIRF_DISCARD, 2 }, /* 1 nav valid */ { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, nav_type) }, /* 3 */ @@ -200,29 +250,34 @@ static const struct sirf_packet_parse geodetic_nav_data_packet[] = { }; static void -ao_sirf_parse_41(void) +ao_sirf_parse_41(void) __reentrant { - uint8_t i, offset; + ao_sirf_parse(&ao_sirf_data, geodetic_nav_data_packet); +} - for (i = 0; ; i++) { - offset = geodetic_nav_data_packet[i].offset; - switch (geodetic_nav_data_packet[i].type) { - case SIRF_END: - return; - case SIRF_DISCARD: - sirf_discard(offset); - break; - case SIRF_U8: - sirf_u8(offset); - break; - case SIRF_U16: - sirf_u16(offset); - break; - case SIRF_U32: - sirf_u32(offset); - break; - } - } +static const struct sirf_packet_parse measured_tracker_data_packet[] = { + { SIRF_U16, offsetof (struct sirf_measured_tracker_data, gps_week) }, /* 1 week */ + { SIRF_U32, offsetof (struct sirf_measured_tracker_data, gps_tow) }, /* 3 time of week */ + { SIRF_U8, offsetof (struct sirf_measured_tracker_data, channels) }, /* 7 channels */ + { SIRF_END, 0 }, +}; + +static const struct sirf_packet_parse measured_sat_data_packet[] = { + { SIRF_U8, offsetof (struct sirf_measured_sat_data, svid) }, /* 0 SV id */ + { SIRF_DISCARD, 2 }, /* 1 azimuth, 2 elevation */ + { SIRF_U16, offsetof (struct sirf_measured_sat_data, state) }, /* 2 state */ + { SIRF_U8, offsetof (struct sirf_measured_sat_data, c_n_1) }, /* C/N0 1 */ + { SIRF_DISCARD, 9 }, /* C/N0 2-10 */ + { SIRF_END, 0 }, +}; + +static void +ao_sirf_parse_4(void) __reentrant +{ + uint8_t i; + ao_sirf_parse(&ao_sirf_tracker_data, measured_tracker_data_packet); + for (i = 0; i < 12; i++) + ao_sirf_parse(&ao_sirf_tracker_data.sats[i], measured_sat_data_packet); } static void @@ -267,7 +322,6 @@ ao_sirf_set_message_rate(uint8_t msg, uint8_t rate) static const uint8_t sirf_disable[] = { 2, - 4, 9, 10, 27, @@ -289,6 +343,7 @@ ao_gps(void) __reentrant for (i = 0; i < sizeof (sirf_disable); i++) ao_sirf_set_message_rate(sirf_disable[i], 0); ao_sirf_set_message_rate(41, 1); + ao_sirf_set_message_rate(4, 1); } for (;;) { /* Locate the begining of the next record */ @@ -314,6 +369,11 @@ ao_gps(void) __reentrant break; ao_sirf_parse_41(); break; + case 4: + if (ao_sirf_len < 187) + break; + ao_sirf_parse_4(); + break; } if (ao_sirf_len != 0) continue; @@ -356,6 +416,17 @@ ao_gps(void) __reentrant ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_data); break; + case 4: + ao_mutex_get(&ao_gps_mutex); + ao_gps_tracking_data.channels = ao_sirf_tracker_data.channels; + for (i = 0; i < 12; i++) { + ao_gps_tracking_data.sats[i].svid = ao_sirf_tracker_data.sats[i].svid; + ao_gps_tracking_data.sats[i].state = (uint8_t) ao_sirf_tracker_data.sats[i].state; + ao_gps_tracking_data.sats[i].c_n_1 = ao_sirf_tracker_data.sats[i].c_n_1; + } + ao_mutex_put(&ao_gps_mutex); + ao_wakeup(&ao_gps_tracking_data); + break; } } } @@ -367,6 +438,9 @@ gps_dump(void) __reentrant { ao_mutex_get(&ao_gps_mutex); ao_gps_print(&ao_gps_data); + putchar('\n'); + ao_gps_tracking_print(&ao_gps_tracking_data); + putchar('\n'); ao_mutex_put(&ao_gps_mutex); } diff --git a/src/ao_gps_print.c b/src/ao_gps_print.c index 8cc07c85..ba0ff68a 100644 --- a/src/ao_gps_print.c +++ b/src/ao_gps_print.c @@ -82,14 +82,45 @@ ao_gps_print(__xdata struct ao_gps_data *gps_data) __reentrant gps_data->course * 2, climb / 100, climb % 100); - printf(" %d.%d(hdop) %5u(herr) %5u(verr)\n", + printf(" %d.%d(hdop) %5u(herr) %5u(verr)", gps_data->hdop / 5, (gps_data->hdop * 2) % 10, gps_data->h_error, gps_data->v_error); } else if (gps_data->flags & AO_GPS_RUNNING) { - printf(" unlocked\n"); + printf(" unlocked"); } else { - printf (" not-connected\n"); + printf (" not-connected"); } } + +void +ao_gps_tracking_print(__xdata struct ao_gps_tracking_data *gps_tracking_data) __reentrant +{ + uint8_t c, n, v; + __xdata struct ao_gps_sat_data *sat; + printf("SAT "); + n = gps_tracking_data->channels; + if (n == 0) { + printf("not-connected\n"); + return; + } + sat = gps_tracking_data->sats; + v = 0; + for (c = 0; c < n; c++) { + if (sat->svid && sat->state) + v++; + sat++; + } + printf("%d ", v); + sat = gps_tracking_data->sats; + for (c = 0; c < n; c++) { + if (sat->svid && sat->state) + printf (" %3d %02x %3d", + sat->svid, + sat->state, + sat->c_n_1); + sat++; + } + printf ("\n"); +} diff --git a/src/ao_gps_report.c b/src/ao_gps_report.c index dce12adb..acf8bb40 100644 --- a/src/ao_gps_report.c +++ b/src/ao_gps_report.c @@ -52,10 +52,41 @@ ao_gps_report(void) } } +void +ao_gps_tracking_report(void) +{ + static __xdata struct ao_log_record gps_log; + static __xdata struct ao_gps_tracking_data gps_tracking_data; + uint8_t c, n; + + for (;;) { + ao_sleep(&ao_gps_tracking_data); + ao_mutex_get(&ao_gps_mutex); + memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data)); + ao_mutex_put(&ao_gps_mutex); + + if (!(n = gps_tracking_data.channels)) + continue; + + gps_log.tick = ao_time(); + gps_log.type = AO_LOG_GPS_SAT; + for (c = 0; c < n; c++) + if ((gps_log.u.gps_sat.svid = gps_tracking_data.sats[c].svid) && + (gps_log.u.gps_sat.state = gps_tracking_data.sats[c].state)) + { + gps_log.u.gps_sat.c_n = gps_tracking_data.sats[c].c_n_1; + gps_log.u.gps_sat.unused = 0; + ao_log_data(&gps_log); + } + } +} + __xdata struct ao_task ao_gps_report_task; +__xdata struct ao_task ao_gps_tracking_report_task; void ao_gps_report_init(void) { ao_add_task(&ao_gps_report_task, ao_gps_report, "gps_report"); + ao_add_task(&ao_gps_tracking_report_task, ao_gps_tracking_report, "gps_tracking_report"); } diff --git a/src/ao_gps_test.c b/src/ao_gps_test.c index fb9b0d10..c94128d9 100644 --- a/src/ao_gps_test.c +++ b/src/ao_gps_test.c @@ -44,6 +44,26 @@ struct ao_gps_data { uint16_t v_error; /* m */ }; +#define SIRF_SAT_STATE_ACQUIRED (1 << 0) +#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) +#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) +#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) +#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) +#define SIRF_SAT_CODE_LOCKED (1 << 5) +#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) +#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) + +struct ao_gps_sat_data { + uint8_t svid; + uint8_t state; + uint8_t c_n_1; +}; + +struct ao_gps_tracking_data { + uint8_t channels; + struct ao_gps_sat_data sats[12]; +}; + void ao_mutex_get(uint8_t *mutex) { @@ -78,6 +98,15 @@ ao_dbg_char(char c) static char input_queue[QUEUE_LEN]; int input_head, input_tail; +#include + +int +get_millis(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +} static void check_sirf_message(char *from, uint8_t *msg, int len) @@ -101,9 +130,11 @@ check_sirf_message(char *from, uint8_t *msg, int len) } encoded_len = (msg[2] << 8) | msg[3]; id = msg[4]; +/* printf ("%9d: %3d\n", get_millis(), id); */ if (encoded_len != len - 8) { - printf ("length mismatch (got %d, wanted %d)\n", - len - 8, encoded_len); + if (id != 52) + printf ("length mismatch (got %d, wanted %d)\n", + len - 8, encoded_len); return; } encoded_cksum = (msg[len - 4] << 8) | msg[len-3]; @@ -116,7 +147,8 @@ check_sirf_message(char *from, uint8_t *msg, int len) return; } id = msg[4]; - if (id == 41) { + switch (id) { + case 41:{ int off = 4; uint8_t id; @@ -181,29 +213,83 @@ check_sirf_message(char *from, uint8_t *msg, int len) printf ("Geodetic Navigation Data (41):\n"); printf ("\tNav valid %04x\n", nav_valid); printf ("\tNav type %04x\n", nav_type); - printf ("\tWeek %d\n", week); - printf ("\tTOW %d\n", tow); - printf ("\tyear %d\n", year); - printf ("\tmonth %d\n", month); - printf ("\tday %d\n", day); - printf ("\thour %d\n", hour); - printf ("\tminute %d\n", minute); - printf ("\tsecond %g\n", second / 1000.0); + printf ("\tWeek %5d", week); + printf (" TOW %9d", tow); + printf (" %4d-%2d-%2d %02d:%02d:%07.4f\n", + year, month, day, + hour, minute, second / 1000.0); printf ("\tsats: %08x\n", sat_list); - printf ("\tlat: %g\n", lat / 1.0e7); - printf ("\tlon: %g\n", lon / 1.0e7); - printf ("\talt_ell: %g\n", alt_ell / 100.0); - printf ("\talt_msll: %g\n", alt_msl / 100.0); - printf ("\tdatum: %d\n", datum); - printf ("\tground speed: %g\n", sog / 100.0); - printf ("\tcourse: %g\n", cog / 100.0); - printf ("\tclimb: %g\n", climb_rate / 100.0); - printf ("\theading rate: %g\n", heading_rate / 100.0); - printf ("\th error: %g\n", h_error / 100.0); - printf ("\tv error: %g\n", v_error / 100.0); - printf ("\tt error: %g\n", t_error / 100.0); - printf ("\th vel error: %g\n", h_v_error / 100.0); - } else { + printf ("\tlat: %g", lat / 1.0e7); + printf (" lon: %g", lon / 1.0e7); + printf (" alt_ell: %g", alt_ell / 100.0); + printf (" alt_msll: %g", alt_msl / 100.0); + printf (" datum: %d\n", datum); + printf ("\tground speed: %g", sog / 100.0); + printf (" course: %g", cog / 100.0); + printf (" climb: %g", climb_rate / 100.0); + printf (" heading rate: %g\n", heading_rate / 100.0); + printf ("\th error: %g", h_error / 100.0); + printf (" v error: %g", v_error / 100.0); + printf (" t error: %g", t_error / 100.0); + printf (" h vel error: %g\n", h_v_error / 100.0); + break; + } + case 4: { + int off = 4; + uint8_t id; + int16_t gps_week; + uint32_t gps_tow; + uint8_t channels; + int j, k; + + get_u8(id); + get_u16(gps_week); + get_u32(gps_tow); + get_u8(channels); + + printf ("Measured Tracker Data (4):\n"); + printf ("GPS week: %d\n", gps_week); + printf ("GPS time of week: %d\n", gps_tow); + printf ("channels: %d\n", channels); + for (j = 0; j < 12; j++) { + uint8_t svid, azimuth, elevation; + uint16_t state; + uint8_t c_n[10]; + get_u8(svid); + get_u8(azimuth); + get_u8(elevation); + get_u16(state); + for (k = 0; k < 10; k++) { + get_u8(c_n[k]); + } + printf ("Sat %3d:", svid); + printf (" aziumuth: %6.1f", azimuth * 1.5); + printf (" elevation: %6.1f", elevation * 0.5); + printf (" state: 0x%02x", state); + printf (" c_n:"); + for (k = 0; k < 10; k++) + printf(" %3d", c_n[k]); + if (state & SIRF_SAT_STATE_ACQUIRED) + printf(" acq,"); + if (state & SIRF_SAT_STATE_CARRIER_PHASE_VALID) + printf(" car,"); + if (state & SIRF_SAT_BIT_SYNC_COMPLETE) + printf(" bit,"); + if (state & SIRF_SAT_SUBFRAME_SYNC_COMPLETE) + printf(" sub,"); + if (state & SIRF_SAT_CARRIER_PULLIN_COMPLETE) + printf(" pullin,"); + if (state & SIRF_SAT_CODE_LOCKED) + printf(" code,"); + if (state & SIRF_SAT_ACQUISITION_FAILED) + printf(" fail,"); + if (state & SIRF_SAT_EPHEMERIS_AVAILABLE) + printf(" ephem,"); + printf ("\n"); + } + break; + } + default: return; printf ("%s %4d:", from, encoded_len); for (i = 4; i < len - 4; i++) { @@ -315,9 +401,16 @@ ao_serial_set_speed(uint8_t speed) #include "ao_gps.c" void -ao_dump_state(void) +ao_dump_state(void *wchan) { double lat, lon; + int i; + if (wchan == &ao_gps_data) + ao_gps_print(&ao_gps_data); + else + ao_gps_tracking_print(&ao_gps_tracking_data); + putchar('\n'); + return; printf ("%02d:%02d:%02d", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second); @@ -336,6 +429,12 @@ ao_dump_state(void) ao_gps_data.hdop / 5.0, ao_gps_data.h_error, ao_gps_data.v_error); printf("\n"); + printf ("\t"); + for (i = 0; i < 12; i++) + printf (" %2d(%02x)", + ao_gps_tracking_data.sats[i].svid, + ao_gps_tracking_data.sats[i].state); + printf ("\n"); } int @@ -358,14 +457,38 @@ ao_gps_open(const char *tty) return fd; } +#include + +static const struct option options[] = { + { .name = "tty", .has_arg = 1, .val = 'T' }, + { 0, 0, 0, 0}, +}; + +static void usage(char *program) +{ + fprintf(stderr, "usage: %s [--tty ]\n", program); + exit(1); +} + int main (int argc, char **argv) { - char *gps_file = "/dev/ttyUSB0"; + char *tty = "/dev/ttyUSB0"; + int c; - ao_gps_fd = ao_gps_open(gps_file); + while ((c = getopt_long(argc, argv, "T:", options, NULL)) != -1) { + switch (c) { + case 'T': + tty = optarg; + break; + default: + usage(argv[0]); + break; + } + } + ao_gps_fd = ao_gps_open(tty); if (ao_gps_fd < 0) { - perror (gps_file); + perror (tty); exit (1); } ao_gps_setup(); diff --git a/src/ao_host.h b/src/ao_host.h index 38ff84ac..6b42f9f9 100644 --- a/src/ao_host.h +++ b/src/ao_host.h @@ -65,7 +65,7 @@ uint8_t ao_adc_head; #define ao_led_on(l) #define ao_led_off(l) #define ao_timer_set_adc_interval(i) -#define ao_wakeup(wchan) ao_dump_state() +#define ao_wakeup(wchan) ao_dump_state(wchan) #define ao_cmd_register(c) #define ao_usb_disable() #define ao_telemetry_set_interval(x) @@ -100,7 +100,7 @@ struct ao_adc ao_adc_static; FILE *emulator_in; void -ao_dump_state(void); +ao_dump_state(void *wchan); void ao_sleep(void *wchan); diff --git a/src/ao_monitor.c b/src/ao_monitor.c index 5997d427..e57ea145 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -55,6 +55,9 @@ ao_monitor(void) recv.telemetry.flight_pres, recv.telemetry.ground_pres); ao_gps_print(&recv.telemetry.gps); + putchar(' '); + ao_gps_tracking_print(&recv.telemetry.gps_tracking); + putchar('\n'); ao_rssi_set((int) recv.rssi - 74); } else { printf("CRC INVALID RSSI %3d\n", (int) recv.rssi - 74); diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 463bcd91..9f57f3a9 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -39,6 +39,7 @@ ao_telemetry(void) ao_adc_get(&telemetry.adc); ao_mutex_get(&ao_gps_mutex); memcpy(&telemetry.gps, &ao_gps_data, sizeof (struct ao_gps_data)); + memcpy(&telemetry.gps_tracking, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data)); ao_mutex_put(&ao_gps_mutex); ao_radio_send(&telemetry); ao_delay(ao_telemetry_interval); -- cgit v1.2.3 From 33edd62992a32b0ec8ca66d879fa300871db5937 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 18 Aug 2009 23:38:16 -0700 Subject: Update ao-view to add GPS satellite tracking data This adds another column to the display to hold per-satellite GPS tracking data and a count of the visible and locked sats. Signed-off-by: Keith Packard --- ao-view/aoview.glade | 25 ++++++++++++++++++------- ao-view/aoview.h | 22 ++++++++++++++++++++++ ao-view/aoview_monitor.c | 34 ++++++++++++++++++++++++++++++++-- ao-view/aoview_state.c | 24 ++++++++++++++++++++++++ ao-view/aoview_table.c | 2 +- src/ao_gps_print.c | 3 +-- 6 files changed, 98 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/ao-view/aoview.glade b/ao-view/aoview.glade index 3481a779..9a746110 100644 --- a/ao-view/aoview.glade +++ b/ao-view/aoview.glade @@ -3,7 +3,7 @@ - 550 + 900 700 True AltOS View @@ -412,6 +412,17 @@ 1 + + + True + True + False + both + + + 2 + + 2 @@ -453,7 +464,7 @@ end - gtk-cancel + gtk-cancel 1 True True @@ -470,7 +481,7 @@ - gtk-connect + gtk-connect True True True @@ -511,7 +522,7 @@ end - gtk-cancel + gtk-cancel True True True @@ -526,7 +537,7 @@ - gtk-ok + gtk-ok True True True @@ -693,7 +704,7 @@ You should have received a copy of the GNU General Public License along with AoV end - gtk-cancel + gtk-cancel True True True @@ -708,7 +719,7 @@ You should have received a copy of the GNU General Public License along with AoV - gtk-ok + gtk-ok True True True diff --git a/ao-view/aoview.h b/ao-view/aoview.h index e8334e5b..9ca65298 100644 --- a/ao-view/aoview.h +++ b/ao-view/aoview.h @@ -75,6 +75,26 @@ struct aogps { int v_error; /* m */ }; +#define SIRF_SAT_STATE_ACQUIRED (1 << 0) +#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) +#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) +#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) +#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) +#define SIRF_SAT_CODE_LOCKED (1 << 5) +#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) +#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) + +struct aogps_sat { + int svid; + int state; + int c_n0; +}; + +struct aogps_tracking { + int channels; + struct aogps_sat sats[12]; +}; + struct aodata { char callsign[16]; int serial; @@ -93,6 +113,7 @@ struct aodata { int flight_pres; int ground_pres; struct aogps gps; + struct aogps_tracking gps_tracking; }; struct aostate { @@ -121,6 +142,7 @@ struct aostate { double max_speed; struct aogps gps; + struct aogps_tracking gps_tracking; int gps_valid; double pad_lat; diff --git a/ao-view/aoview_monitor.c b/ao-view/aoview_monitor.c index 9265a199..1f4c8f72 100644 --- a/ao-view/aoview_monitor.c +++ b/ao-view/aoview_monitor.c @@ -47,6 +47,12 @@ aoview_parse_int(int *target, char *source) *target = strtol(source, NULL, 0); } +static void +aoview_parse_hex(int *target, char *source) +{ + *target = strtol(source, NULL, 16); +} + static void aoview_parse_pos(double *target, char *source) { @@ -65,20 +71,23 @@ aoview_parse_pos(double *target, char *source) *target = r; } +#define PARSE_MAX_WORDS 256 + gboolean aoview_monitor_parse(const char *input_line) { char *saveptr; - char *words[64]; + char *words[PARSE_MAX_WORDS]; int nword; char line_buf[8192], *line; struct aodata data; + int tracking_pos; /* avoid smashing our input parameter */ strncpy (line_buf, input_line, sizeof (line_buf)-1); line_buf[sizeof(line_buf) - 1] = '\0'; line = line_buf; - for (nword = 0; nword < 64; nword++) { + for (nword = 0; nword < PARSE_MAX_WORDS; nword++) { words[nword] = strtok_r(line, " \t\n", &saveptr); line = NULL; if (words[nword] == NULL) @@ -112,6 +121,7 @@ aoview_monitor_parse(const char *input_line) data.gps.gps_time.hour = data.gps.gps_time.minute = data.gps.gps_time.second = 0; data.gps.lat = data.gps.lon = 0; data.gps.alt = 0; + tracking_pos = 37; } else if (nword >= 40) { data.gps.gps_locked = 1; data.gps.gps_connected = 1; @@ -119,6 +129,7 @@ aoview_monitor_parse(const char *input_line) aoview_parse_pos(&data.gps.lat, words[37]); aoview_parse_pos(&data.gps.lon, words[38]); sscanf(words[39], "%dm", &data.gps.alt); + tracking_pos = 46; } else { data.gps.gps_connected = 0; data.gps.gps_locked = 0; @@ -143,6 +154,25 @@ aoview_monitor_parse(const char *input_line) data.gps.h_error = 0; data.gps.v_error = 0; } + if (nword >= tracking_pos + 2 && strcmp(words[tracking_pos], "SAT") == 0) { + int c, n, pos; + aoview_parse_int(&n, words[tracking_pos + 1]); + pos = tracking_pos + 2; + if (nword >= pos + n * 3) { + data.gps_tracking.channels = n; + for (c = 0; c < n; c++) { + aoview_parse_int(&data.gps_tracking.sats[c].svid, + words[pos + 0]); + aoview_parse_hex(&data.gps_tracking.sats[c].state, + words[pos + 1]); + aoview_parse_int(&data.gps_tracking.sats[c].c_n0, + words[pos + 2]); + pos += 3; + } + } else { + data.gps_tracking.channels = 0; + } + } aoview_state_notify(&data); return TRUE; } diff --git a/ao-view/aoview_state.c b/ao-view/aoview_state.c index 7efd33b0..f75066dd 100644 --- a/ao-view/aoview_state.c +++ b/ao-view/aoview_state.c @@ -168,6 +168,8 @@ aoview_state_derive(struct aodata *data, struct aostate *state) aoview_great_circle(state->pad_lat, state->pad_lon, state->gps.lat, state->gps.lon, &state->distance, &state->bearing); } + if (data->gps_tracking.channels) + state->gps_tracking = data->gps_tracking; if (state->npad) { state->gps_height = state->gps.alt - state->pad_alt; } else { @@ -308,6 +310,7 @@ aoview_state_notify(struct aodata *data) if (state->gps_valid) { aoview_state_add_deg(1, "Latitude", state->gps.lat, 'N', 'S'); aoview_state_add_deg(1, "Longitude", state->gps.lon, 'E', 'W'); + aoview_table_add_row(1, "GPS altitude", "%d", state->gps.alt); aoview_table_add_row(1, "GPS height", "%d", state->gps_height); aoview_table_add_row(1, "GPS time", "%02d:%02d:%02d", state->gps.gps_time.hour, @@ -330,6 +333,27 @@ aoview_state_notify(struct aodata *data) aoview_state_add_deg(1, "Pad longitude", state->pad_lon, 'E', 'W'); aoview_table_add_row(1, "Pad GPS alt", "%gm", state->pad_alt); } + if (state->gps.gps_connected) { + int nsat_vis = 0; + int nsat_locked = 0; + int c; + + for (c = 0; c < state->gps_tracking.channels; c++) { + if ((state->gps_tracking.sats[c].state & 0xff) == 0xbf) + nsat_locked++; + } + aoview_table_add_row(2, "Satellites Visible", "%d", state->gps_tracking.channels); + aoview_table_add_row(2, "Satellites Locked", "%d", nsat_locked); + for (c = 0; c < state->gps_tracking.channels; c++) { + aoview_table_add_row(2, "Satellite id,state,C/N0", + "%3d,%02x,%2d%s", + state->gps_tracking.sats[c].svid, + state->gps_tracking.sats[c].state, + state->gps_tracking.sats[c].c_n0, + (state->gps_tracking.sats[c].state & 0xff) == 0xbf ? + " LOCKED" : ""); + } + } aoview_table_finish(); aoview_label_show(state); aoview_speak_state(state); diff --git a/ao-view/aoview_table.c b/ao-view/aoview_table.c index 93143009..e75ae670 100644 --- a/ao-view/aoview_table.c +++ b/ao-view/aoview_table.c @@ -17,7 +17,7 @@ #include "aoview.h" -#define NCOL 2 +#define NCOL 3 static GtkTreeView *dataview[NCOL]; static GtkListStore *datalist[NCOL]; diff --git a/src/ao_gps_print.c b/src/ao_gps_print.c index ba0ff68a..cc751337 100644 --- a/src/ao_gps_print.c +++ b/src/ao_gps_print.c @@ -102,7 +102,7 @@ ao_gps_tracking_print(__xdata struct ao_gps_tracking_data *gps_tracking_data) __ printf("SAT "); n = gps_tracking_data->channels; if (n == 0) { - printf("not-connected\n"); + printf("not-connected"); return; } sat = gps_tracking_data->sats; @@ -122,5 +122,4 @@ ao_gps_tracking_print(__xdata struct ao_gps_tracking_data *gps_tracking_data) __ sat->c_n_1); sat++; } - printf ("\n"); } -- cgit v1.2.3 From 6358041f846ba9a20fa650c367d907dc4336e54c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 22 Aug 2009 13:38:56 -0700 Subject: Enable GPS degraded mode, set 10 sec degraded timeout. No reason not to let the GPS report solutions whenever it likes, let's see how this works. Signed-off-by: Keith Packard --- src/ao_gps.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ao_gps.c b/src/ao_gps.c index 7d68b325..2b3a5178 100644 --- a/src/ao_gps.c +++ b/src/ao_gps.c @@ -30,14 +30,14 @@ const char ao_gps_config[] = { 0xa0, 0xa2, 0x00, 0x0e, /* length: 14 bytes */ 136, /* mode control */ 0, 0, /* reserved */ - 4, /* degraded mode (disabled) */ + 0, /* degraded mode (allow 1-SV navigation) */ 0, 0, /* reserved */ 0, 0, /* user specified altitude */ 2, /* alt hold mode (disabled, require 3d fixes) */ 0, /* alt hold source (use last computed altitude) */ 0, /* reserved */ - 0, /* Degraded time out (disabled) */ - 0, /* Dead Reckoning time out (disabled) */ + 10, /* Degraded time out (10 sec) */ + 10, /* Dead Reckoning time out (10 sec) */ 0, /* Track smoothing (disabled) */ 0x00, 0x8e, 0xb0, 0xb3, -- cgit v1.2.3 From 7d39f17684feb49ac8a0017902158f298696e37c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Sep 2009 21:57:54 -0700 Subject: Make eeprom reads and writes across block boundary work Reading and writing across the block boundary was not stepping the eeprom position after the partial i/o operation at the end of the first block. This meant that the operation would re-use the end of the previous block, either re-reading or re-writing it. Signed-off-by: Keith Packard --- src/ao_ee.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/ao_ee.c b/src/ao_ee.c index f299b925..9b6db234 100644 --- a/src/ao_ee.c +++ b/src/ao_ee.c @@ -271,6 +271,7 @@ ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant /* See how much is left */ buf += this_len; len -= this_len; + pos += this_len; } return 1; } @@ -306,6 +307,7 @@ ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant /* See how much is left */ buf += this_len; len -= this_len; + pos += this_len; } return 1; } -- cgit v1.2.3 From acea083d80e1ecc4287083519ea666964016b257 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Sep 2009 22:00:37 -0700 Subject: Make the ao_log_record structures 8 bytes again. When the GPS signal strength data was added, the structure was accidentally extended to 9 bytes, making all log records 9 bytes long. While not a serious problem, this left log records spanning across eeprom block boundaries, which seems like a bad plan. Signed-off-by: Keith Packard --- src/ao.h | 1 - src/ao_gps_report.c | 1 - 2 files changed, 2 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 27ec010f..8e342558 100644 --- a/src/ao.h +++ b/src/ao.h @@ -503,7 +503,6 @@ struct ao_log_record { uint16_t svid; uint8_t state; uint8_t c_n; - uint8_t unused; } gps_sat; struct { uint16_t d0; diff --git a/src/ao_gps_report.c b/src/ao_gps_report.c index acf8bb40..75c944f5 100644 --- a/src/ao_gps_report.c +++ b/src/ao_gps_report.c @@ -75,7 +75,6 @@ ao_gps_tracking_report(void) (gps_log.u.gps_sat.state = gps_tracking_data.sats[c].state)) { gps_log.u.gps_sat.c_n = gps_tracking_data.sats[c].c_n_1; - gps_log.u.gps_sat.unused = 0; ao_log_data(&gps_log); } } -- cgit v1.2.3 From e2e449d5c23356e913f312de1fb2611a9dd5a352 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 2 Sep 2009 22:01:52 -0700 Subject: Remove bit-banging debug support from TM board builds Our current TM boards don't have the wires to do bit-banging to another cc1111 board, so it doesn't make sense to fill up their flash with useless code (and the 'help' text with useless commands). Leave this to the TI board until we have boards that can serve as debug dongles. Signed-off-by: Keith Packard --- src/Makefile | 10 ++++++++-- src/ao_log.c | 3 +++ src/ao_teledongle.c | 1 - src/ao_telemetrum.c | 1 - src/ao_teleterra.c | 1 - 5 files changed, 11 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 96049c65..828c48bd 100644 --- a/src/Makefile +++ b/src/Makefile @@ -24,7 +24,6 @@ INC = \ # ALTOS_SRC = \ ao_cmd.c \ - ao_dbg.c \ ao_dma.c \ ao_mutex.c \ ao_panic.c \ @@ -70,6 +69,12 @@ TELE_FAKE_SRC = \ ao_adc_fake.c \ ao_ee_fake.c +# +# Debug dongle driver (only on TI) +# +DBG_DONGLE_SRC = \ + ao_dbg.c + # # Drivers only on TeleMetrum # @@ -115,7 +120,8 @@ TI_SRC = \ $(TELE_RECEIVER_SRC) \ $(TELE_COMMON_SRC) \ $(TELE_FAKE_SRC) \ - $(TI_MAIN_SRC) + $(TI_MAIN_SRC) \ + $(DBG_DONGLE_SRC) TT_MAIN_SRC = \ ao_teleterra.c diff --git a/src/ao_log.c b/src/ao_log.c index 19bfdfb8..7945ace4 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -109,6 +109,9 @@ ao_log_dump_next(void) __xdata uint8_t ao_log_adc_pos; __xdata enum flight_state ao_log_state; +/* a hack to make sure that ao_log_records fill the eeprom block in even units */ +typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; + void ao_log(void) { diff --git a/src/ao_teledongle.c b/src/ao_teledongle.c index 4ebc53a5..d7b4b75a 100644 --- a/src/ao_teledongle.c +++ b/src/ao_teledongle.c @@ -33,7 +33,6 @@ main(void) ao_monitor_init(AO_LED_GREEN, TRUE); ao_rssi_init(AO_LED_RED); ao_radio_init(); - ao_dbg_init(); ao_config_init(); ao_start_scheduler(); } diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 5e951b49..1dbacf89 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -41,7 +41,6 @@ main(void) ao_telemetry_init(); ao_radio_init(); ao_igniter_init(); - ao_dbg_init(); ao_config_init(); ao_start_scheduler(); } diff --git a/src/ao_teleterra.c b/src/ao_teleterra.c index 6464ccc0..deb63597 100644 --- a/src/ao_teleterra.c +++ b/src/ao_teleterra.c @@ -34,7 +34,6 @@ main(void) ao_gps_init(); ao_monitor_init(AO_LED_GREEN, TRUE); ao_radio_init(); - ao_dbg_init(); ao_config_init(); ao_start_scheduler(); } -- cgit v1.2.3 From 54545640b0db7747137655f84bc67fd290ecb904 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 4 Sep 2009 11:45:52 -0700 Subject: Add back the RDF tone generator Tracking the rocket on the ground may be easier using tones than using the digital data stream, so we'll try that and see what we think. This reverts commit 3a3bfd471a868d546d83cdc431b53c8f5208edb9. Signed-off-by: Keith Packard --- src/ao.h | 9 ++++++ src/ao_flight.c | 7 +++++ src/ao_flight_test.c | 1 + src/ao_radio.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/ao_telemetry.c | 20 ++++++++++++ 5 files changed, 126 insertions(+) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 8e342558..37f21508 100644 --- a/src/ao.h +++ b/src/ao.h @@ -777,6 +777,9 @@ struct ao_telemetry { void ao_telemetry_set_interval(uint16_t interval); +void +ao_rdf_set(uint8_t rdf); + void ao_telemetry_init(void); @@ -796,6 +799,12 @@ struct ao_radio_recv { void ao_radio_recv(__xdata struct ao_radio_recv *recv) __reentrant; +void +ao_radio_rdf(void); + +void +ao_radio_rdf_abort(void); + void ao_radio_init(void); diff --git a/src/ao_flight.c b/src/ao_flight.c index be9b3bb6..2b062c13 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -227,6 +227,7 @@ ao_flight(void) /* Turn on telemetry system */ + ao_rdf_set(1); ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); ao_flight_state = ao_flight_pad; @@ -277,6 +278,9 @@ ao_flight(void) /* Increase telemetry rate */ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); + /* disable RDF beacon */ + ao_rdf_set(0); + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); break; } @@ -356,6 +360,9 @@ ao_flight(void) /* slow down the ADC sample rate */ ao_timer_set_adc_interval(10); + /* Enable RDF beacon */ + ao_rdf_set(1); + /* * Start recording min/max accel and pres for a while * to figure out when the rocket has landed diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 1466b886..9fcb00c2 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -68,6 +68,7 @@ uint8_t ao_adc_head; #define ao_cmd_register(c) #define ao_usb_disable() #define ao_telemetry_set_interval(x) +#define ao_rdf_set(rdf) enum ao_igniter { ao_igniter_drogue = 0, diff --git a/src/ao_radio.c b/src/ao_radio.c index ca1ec7e8..e4d42c6c 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -77,6 +77,29 @@ #define DEVIATION_M 6 #define DEVIATION_E 3 +/* + * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone), + * so the DRATE_E and DRATE_M values are: + * + * M is 94 and E is 6 + * + * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes + */ + +#define RDF_DRATE_E 6 +#define RDF_DRATE_M 94 +#define RDF_PACKET_LEN 50 + +/* + * RDF deviation should match the normal NFM value of 5kHz + * + * M is 6 and E is 1 + * + */ + +#define RDF_DEVIATION_M 6 +#define RDF_DEVIATION_E 1 + /* This are from the table for 433MHz */ #define RF_POWER_M30_DBM 0x12 @@ -184,6 +207,28 @@ static __code uint8_t radio_setup[] = { RF_IOCFG0_OFF, 0x00, }; +static __code uint8_t rdf_setup[] = { + RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | + (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | + (RDF_DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)), + RF_MDMCFG3_OFF, (RDF_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_DIS | + RF_MDMCFG1_NUM_PREAMBLE_2 | + (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), + + RF_DEVIATN_OFF, ((RDF_DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | + (RDF_DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), + + /* packet length */ + RF_PKTLEN_OFF, RDF_PACKET_LEN, + RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| + PKTCTRL1_ADR_CHK_NONE), + RF_PKTCTRL0_OFF, (RF_PKTCTRL0_PKT_FORMAT_NORMAL| + RF_PKTCTRL0_LENGTH_CONFIG_FIXED), +}; static __code uint8_t telemetry_setup[] = { RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | @@ -275,6 +320,50 @@ ao_radio_recv(__xdata struct ao_radio_recv *radio) __reentrant ao_mutex_put(&ao_radio_mutex); } +__xdata ao_radio_rdf_running; +__xdata ao_radio_rdf_value = 0x55; + +void +ao_radio_rdf(void) +{ + uint8_t i; + ao_mutex_get(&ao_radio_mutex); + ao_radio_idle(); + ao_radio_rdf_running = 1; + for (i = 0; i < sizeof (rdf_setup); i += 2) + RF[rdf_setup[i]] = rdf_setup[i+1]; + + ao_dma_set_transfer(ao_radio_dma, + &ao_radio_rdf_value, + &RFDXADDR, + RDF_PACKET_LEN, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_RADIO, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_HIGH); + ao_dma_start(ao_radio_dma); + RFST = RFST_STX; + + __critical while (!ao_radio_dma_done) + ao_sleep(&ao_radio_dma_done); + ao_radio_rdf_running = 0; + ao_radio_idle(); + for (i = 0; i < sizeof (rdf_setup); i += 2) + RF[telemetry_setup[i]] = telemetry_setup[i+1]; + ao_mutex_put(&ao_radio_mutex); +} + +void +ao_radio_rdf_abort(void) +{ + if (ao_radio_rdf_running) { + ao_dma_abort(ao_radio_dma); + ao_radio_idle(); + } +} + void ao_radio_init(void) { diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 9f57f3a9..7eefee3c 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -18,6 +18,10 @@ #include "ao.h" __xdata uint16_t ao_telemetry_interval = 0; +__xdata uint8_t ao_rdf = 0; +__xdata uint16_t ao_rdf_time; + +#define AO_RDF_INTERVAL AO_SEC_TO_TICKS(3) void ao_telemetry(void) @@ -27,6 +31,7 @@ ao_telemetry(void) ao_config_get(); memcpy(telemetry.callsign, ao_config.callsign, AO_MAX_CALLSIGN); telemetry.addr = ao_serial_number; + ao_rdf_time = ao_time(); for (;;) { while (ao_telemetry_interval == 0) ao_sleep(&ao_telemetry_interval); @@ -43,6 +48,13 @@ ao_telemetry(void) ao_mutex_put(&ao_gps_mutex); ao_radio_send(&telemetry); ao_delay(ao_telemetry_interval); + if (ao_rdf && + (int16_t) (ao_time() - ao_rdf_time) >= 0) + { + ao_rdf_time = ao_time() + AO_RDF_INTERVAL; + ao_radio_rdf(); + ao_delay(ao_telemetry_interval); + } } } @@ -53,6 +65,14 @@ ao_telemetry_set_interval(uint16_t interval) ao_wakeup(&ao_telemetry_interval); } +void +ao_rdf_set(uint8_t rdf) +{ + ao_rdf = rdf; + if (rdf == 0) + ao_radio_rdf_abort(); +} + __xdata struct ao_task ao_telemetry_task; void -- cgit v1.2.3 From fee46389b70a624ab5b1128a8b4c3083c7747bcb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 4 Sep 2009 11:46:55 -0700 Subject: Make RDF beacon only run on pad and after landing. It's pretty much impossible to RDF the rocket during flight, and it interferes with the telemetry data stream. Leave it enabled on the pad so that radios can be tested, and then re-enable it once the rocket has landed. This patch also turns the rdf 'on' time into a parameter so it can be changed, and then sets that parameter to 500ms, once every 5 seconds. Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_flight.c | 5 ++--- src/ao_radio.c | 18 +++++++++++++++--- src/ao_telemetry.c | 9 ++++++--- 4 files changed, 24 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 37f21508..4116be65 100644 --- a/src/ao.h +++ b/src/ao.h @@ -800,7 +800,7 @@ void ao_radio_recv(__xdata struct ao_radio_recv *recv) __reentrant; void -ao_radio_rdf(void); +ao_radio_rdf(int ms); void ao_radio_rdf_abort(void); diff --git a/src/ao_flight.c b/src/ao_flight.c index 2b062c13..ec89e7c2 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -360,9 +360,6 @@ ao_flight(void) /* slow down the ADC sample rate */ ao_timer_set_adc_interval(10); - /* Enable RDF beacon */ - ao_rdf_set(1); - /* * Start recording min/max accel and pres for a while * to figure out when the rocket has landed @@ -445,6 +442,8 @@ ao_flight(void) /* turn off the ADC capture */ ao_timer_set_adc_interval(0); + /* Enable RDF beacon */ + ao_rdf_set(1); ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } diff --git a/src/ao_radio.c b/src/ao_radio.c index e4d42c6c..76fa3e5d 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -223,7 +223,6 @@ static __code uint8_t rdf_setup[] = { (RDF_DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), /* packet length */ - RF_PKTLEN_OFF, RDF_PACKET_LEN, RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| PKTCTRL1_ADR_CHK_NONE), RF_PKTCTRL0_OFF, (RF_PKTCTRL0_PKT_FORMAT_NORMAL| @@ -324,19 +323,32 @@ __xdata ao_radio_rdf_running; __xdata ao_radio_rdf_value = 0x55; void -ao_radio_rdf(void) +ao_radio_rdf(int ms) { uint8_t i; + uint8_t pkt_len; ao_mutex_get(&ao_radio_mutex); ao_radio_idle(); ao_radio_rdf_running = 1; for (i = 0; i < sizeof (rdf_setup); i += 2) RF[rdf_setup[i]] = rdf_setup[i+1]; + /* + * Compute the packet length as follows: + * + * 2000 bps (for a 1kHz tone) + * so, for 'ms' milliseconds, we need + * 2 * ms bits, or ms / 4 bytes + */ + if (ms > (255 * 4)) + ms = 255 * 4; + pkt_len = ms >> 2; + RF[RF_PKTLEN_OFF] = pkt_len; + ao_dma_set_transfer(ao_radio_dma, &ao_radio_rdf_value, &RFDXADDR, - RDF_PACKET_LEN, + pkt_len, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | DMA_CFG0_TRIGGER_RADIO, diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 7eefee3c..d52e589c 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -21,7 +21,8 @@ __xdata uint16_t ao_telemetry_interval = 0; __xdata uint8_t ao_rdf = 0; __xdata uint16_t ao_rdf_time; -#define AO_RDF_INTERVAL AO_SEC_TO_TICKS(3) +#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) +#define AO_RDF_LENGTH_MS 500 void ao_telemetry(void) @@ -51,8 +52,8 @@ ao_telemetry(void) if (ao_rdf && (int16_t) (ao_time() - ao_rdf_time) >= 0) { - ao_rdf_time = ao_time() + AO_RDF_INTERVAL; - ao_radio_rdf(); + ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; + ao_radio_rdf(AO_RDF_LENGTH_MS); ao_delay(ao_telemetry_interval); } } @@ -71,6 +72,8 @@ ao_rdf_set(uint8_t rdf) ao_rdf = rdf; if (rdf == 0) ao_radio_rdf_abort(); + else + ao_rdf_time = ao_time(); } __xdata struct ao_task ao_telemetry_task; -- cgit v1.2.3 From 15341b6e6dcf52df083d6aa37ef881ea6ad48ee5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 4 Sep 2009 12:25:37 -0700 Subject: Set all of the values to reset the radio for telemetry Was sizeof(rdf_setup) instead of sizeof(telemetry_setup) when resetting the radio back to telemetry data mode from rdf mode. With the length value removed from the rdf config, these two arrays are no longer the same length, and so the last config value was not set leaving the radio sending garbage. Signed-off-by: Keith Packard --- src/ao_radio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao_radio.c b/src/ao_radio.c index 76fa3e5d..a7fa682e 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -222,7 +222,7 @@ static __code uint8_t rdf_setup[] = { RF_DEVIATN_OFF, ((RDF_DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | (RDF_DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), - /* packet length */ + /* packet length is set in-line */ RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| PKTCTRL1_ADR_CHK_NONE), RF_PKTCTRL0_OFF, (RF_PKTCTRL0_PKT_FORMAT_NORMAL| @@ -362,7 +362,7 @@ ao_radio_rdf(int ms) ao_sleep(&ao_radio_dma_done); ao_radio_rdf_running = 0; ao_radio_idle(); - for (i = 0; i < sizeof (rdf_setup); i += 2) + for (i = 0; i < sizeof (telemetry_setup); i += 2) RF[telemetry_setup[i]] = telemetry_setup[i+1]; ao_mutex_put(&ao_radio_mutex); } -- cgit v1.2.3 From 33b0b6f2f2e07de105619a7b463226d2813152ab Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 9 Oct 2009 22:02:40 -0700 Subject: Add support for the SkyTraq GPS unit This is a build-time option selected by hacking the Makefile at present. Signed-off-by: Keith Packard --- src/Makefile | 9 +- src/ao.h | 3 +- src/ao_gps.c | 457 -------------------------------------------- src/ao_gps_sirf.c | 457 ++++++++++++++++++++++++++++++++++++++++++++ src/ao_gps_skytraq.c | 369 +++++++++++++++++++++++++++++++++++ src/ao_gps_test.c | 2 +- src/ao_gps_test_skytraq.c | 478 ++++++++++++++++++++++++++++++++++++++++++++++ src/ao_serial.c | 9 +- 8 files changed, 1321 insertions(+), 463 deletions(-) delete mode 100644 src/ao_gps.c create mode 100644 src/ao_gps_sirf.c create mode 100644 src/ao_gps_skytraq.c create mode 100644 src/ao_gps_test_skytraq.c (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 828c48bd..892635cb 100644 --- a/src/Makefile +++ b/src/Makefile @@ -59,7 +59,7 @@ TELE_RECEIVER_SRC =\ TELE_DRIVER_SRC = \ ao_convert.c \ - ao_gps.c \ + ao_gps_skytraq.c \ ao_serial.c # @@ -189,7 +189,7 @@ SYM=$(REL:.rel=.sym) PROGS= telemetrum.ihx tidongle.ihx \ teleterra.ihx teledongle.ihx -HOST_PROGS=ao_flight_test ao_gps_test +HOST_PROGS=ao_flight_test ao_gps_test ao_gps_test_skytraq PCDB=$(PROGS:.ihx=.cdb) PLNK=$(PROGS:.ihx=.lnk) @@ -271,5 +271,8 @@ install: ao_flight_test: ao_flight.c ao_flight_test.c ao_host.h cc -g -o $@ ao_flight_test.c -ao_gps_test: ao_gps.c ao_gps_test.c ao_gps_print.c ao_host.h +ao_gps_test: ao_gps_sirf.c ao_gps_test.c ao_gps_print.c ao_host.h cc -g -o $@ ao_gps_test.c + +ao_gps_test_skytraq: ao_gps_skytraq.c ao_gps_test_skytraq.c ao_gps_print.c ao_host.h + cc -g -o $@ ao_gps_test_skytraq.c diff --git a/src/ao.h b/src/ao.h index 4116be65..0f3f0ea7 100644 --- a/src/ao.h +++ b/src/ao.h @@ -668,7 +668,8 @@ void ao_serial_putchar(char c) __critical; #define AO_SERIAL_SPEED_4800 0 -#define AO_SERIAL_SPEED_57600 1 +#define AO_SERIAL_SPEED_9600 1 +#define AO_SERIAL_SPEED_57600 2 void ao_serial_set_speed(uint8_t speed); diff --git a/src/ao_gps.c b/src/ao_gps.c deleted file mode 100644 index 2b3a5178..00000000 --- a/src/ao_gps.c +++ /dev/null @@ -1,457 +0,0 @@ -/* - * 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. - */ - -#ifndef AO_GPS_TEST -#include "ao.h" -#endif - -__xdata uint8_t ao_gps_mutex; -__xdata struct ao_gps_data ao_gps_data; -__xdata struct ao_gps_tracking_data ao_gps_tracking_data; - -static const char ao_gps_set_nmea[] = "\r\n$PSRF100,0,57600,8,1,0*37\r\n"; - -const char ao_gps_config[] = { - - 0xa0, 0xa2, 0x00, 0x0e, /* length: 14 bytes */ - 136, /* mode control */ - 0, 0, /* reserved */ - 0, /* degraded mode (allow 1-SV navigation) */ - 0, 0, /* reserved */ - 0, 0, /* user specified altitude */ - 2, /* alt hold mode (disabled, require 3d fixes) */ - 0, /* alt hold source (use last computed altitude) */ - 0, /* reserved */ - 10, /* Degraded time out (10 sec) */ - 10, /* Dead Reckoning time out (10 sec) */ - 0, /* Track smoothing (disabled) */ - 0x00, 0x8e, 0xb0, 0xb3, - - 0xa0, 0xa2, 0x00, 0x08, /* length: 8 bytes */ - 166, /* Set message rate */ - 2, /* enable/disable all messages */ - 0, /* message id (ignored) */ - 0, /* update rate (0 = disable) */ - 0, 0, 0, 0, /* reserved */ - 0x00, 0xa8, 0xb0, 0xb3, - - 0xa0, 0xa2, 0x00, 0x02, /* length: 2 bytes */ - 143, /* static navigation */ - 0, /* disable */ - 0x00, 0x8f, 0xb0, 0xb3, -}; - -#define NAV_TYPE_GPS_FIX_TYPE_MASK (7 << 0) -#define NAV_TYPE_NO_FIX (0 << 0) -#define NAV_TYPE_SV_KF (1 << 0) -#define NAV_TYPE_2_SV_KF (2 << 0) -#define NAV_TYPE_3_SV_KF (3 << 0) -#define NAV_TYPE_4_SV_KF (4 << 0) -#define NAV_TYPE_2D_LEAST_SQUARES (5 << 0) -#define NAV_TYPE_3D_LEAST_SQUARES (6 << 0) -#define NAV_TYPE_DR (7 << 0) -#define NAV_TYPE_TRICKLE_POWER (1 << 3) -#define NAV_TYPE_ALTITUDE_HOLD_MASK (3 << 4) -#define NAV_TYPE_ALTITUDE_HOLD_NONE (0 << 4) -#define NAV_TYPE_ALTITUDE_HOLD_KF (1 << 4) -#define NAV_TYPE_ALTITUDE_HOLD_USER (2 << 4) -#define NAV_TYPE_ALTITUDE_HOLD_ALWAYS (3 << 4) -#define NAV_TYPE_DOP_LIMIT_EXCEEDED (1 << 6) -#define NAV_TYPE_DGPS_APPLIED (1 << 7) -#define NAV_TYPE_SENSOR_DR (1 << 8) -#define NAV_TYPE_OVERDETERMINED (1 << 9) -#define NAV_TYPE_DR_TIMEOUT_EXCEEDED (1 << 10) -#define NAV_TYPE_FIX_MI_EDIT (1 << 11) -#define NAV_TYPE_INVALID_VELOCITY (1 << 12) -#define NAV_TYPE_ALTITUDE_HOLD_DISABLED (1 << 13) -#define NAV_TYPE_DR_ERROR_STATUS_MASK (3 << 14) -#define NAV_TYPE_DR_ERROR_STATUS_GPS_ONLY (0 << 14) -#define NAV_TYPE_DR_ERROR_STATUS_DR_FROM_GPS (1 << 14) -#define NAV_TYPE_DR_ERROR_STATUS_DR_SENSOR_ERROR (2 << 14) -#define NAV_TYPE_DR_ERROR_STATUS_DR_IN_TEST (3 << 14) - -struct sirf_geodetic_nav_data { - uint16_t nav_type; - uint16_t utc_year; - uint8_t utc_month; - uint8_t utc_day; - uint8_t utc_hour; - uint8_t utc_minute; - uint16_t utc_second; - int32_t lat; - int32_t lon; - int32_t alt_msl; - uint16_t ground_speed; - uint16_t course; - int16_t climb_rate; - uint32_t h_error; - uint32_t v_error; - uint8_t num_sv; - uint8_t hdop; -}; - -static __xdata struct sirf_geodetic_nav_data ao_sirf_data; - -struct sirf_measured_sat_data { - uint8_t svid; - uint16_t state; - uint8_t c_n_1; -}; - -struct sirf_measured_tracker_data { - int16_t gps_week; - uint32_t gps_tow; - uint8_t channels; - struct sirf_measured_sat_data sats[12]; -}; - -static __xdata struct sirf_measured_tracker_data ao_sirf_tracker_data; - -static __pdata uint16_t ao_sirf_cksum; -static __pdata uint16_t ao_sirf_len; - -#define ao_sirf_byte() ((uint8_t) ao_serial_getchar()) - -static uint8_t data_byte(void) -{ - uint8_t c = ao_sirf_byte(); - --ao_sirf_len; - ao_sirf_cksum += c; - return c; -} - -static char __xdata *sirf_target; - -static void sirf_u16(uint8_t offset) -{ - uint16_t __xdata *ptr = (uint16_t __xdata *) (sirf_target + offset); - uint16_t val; - - val = data_byte() << 8; - val |= data_byte (); - *ptr = val; -} - -static void sirf_u8(uint8_t offset) -{ - uint8_t __xdata *ptr = (uint8_t __xdata *) (sirf_target + offset); - uint8_t val; - - val = data_byte (); - *ptr = val; -} - -static void sirf_u32(uint8_t offset) __reentrant -{ - uint32_t __xdata *ptr = (uint32_t __xdata *) (sirf_target + offset); - uint32_t val; - - val = ((uint32_t) data_byte ()) << 24; - val |= ((uint32_t) data_byte ()) << 16; - val |= ((uint32_t) data_byte ()) << 8; - val |= ((uint32_t) data_byte ()); - *ptr = val; -} - -static void sirf_discard(uint8_t len) -{ - while (len--) - data_byte(); -} - -#define SIRF_END 0 -#define SIRF_DISCARD 1 -#define SIRF_U8 2 -#define SIRF_U16 3 -#define SIRF_U32 4 -#define SIRF_U8X10 5 - -struct sirf_packet_parse { - uint8_t type; - uint8_t offset; -}; - -static void -ao_sirf_parse(void __xdata *target, const struct sirf_packet_parse *parse) __reentrant -{ - uint8_t i, offset, j; - - sirf_target = target; - for (i = 0; ; i++) { - offset = parse[i].offset; - switch (parse[i].type) { - case SIRF_END: - return; - case SIRF_DISCARD: - sirf_discard(offset); - break; - case SIRF_U8: - sirf_u8(offset); - break; - case SIRF_U16: - sirf_u16(offset); - break; - case SIRF_U32: - sirf_u32(offset); - break; - case SIRF_U8X10: - for (j = 10; j--;) - sirf_u8(offset++); - break; - } - } -} - -static const struct sirf_packet_parse geodetic_nav_data_packet[] = { - { SIRF_DISCARD, 2 }, /* 1 nav valid */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, nav_type) }, /* 3 */ - { SIRF_DISCARD, 6 }, /* 5 week number, time of week */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, utc_year) }, /* 11 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_month) }, /* 13 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_day) }, /* 14 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_hour) }, /* 15 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_minute) }, /* 16 */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, utc_second) }, /* 17 */ - { SIRF_DISCARD, 4 }, /* satellite id list */ /* 19 */ - { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, lat) }, /* 23 */ - { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, lon) }, /* 27 */ - { SIRF_DISCARD, 4 }, /* altitude from ellipsoid */ /* 31 */ - { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, alt_msl) }, /* 35 */ - { SIRF_DISCARD, 1 }, /* map datum */ /* 39 */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, ground_speed) }, /* 40 */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, course) }, /* 42 */ - { SIRF_DISCARD, 2 }, /* magnetic variation */ /* 44 */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, climb_rate) }, /* 46 */ - { SIRF_DISCARD, 2 }, /* turn rate */ /* 48 */ - { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, h_error) }, /* 50 */ - { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, v_error) }, /* 54 */ - { SIRF_DISCARD, 30 }, /* time error, h_vel error, clock_bias, - clock bias error, clock drift, - clock drift error, distance, - distance error, heading error */ /* 58 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, num_sv) }, /* 88 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, hdop) }, /* 89 */ - { SIRF_DISCARD, 1 }, /* additional mode info */ /* 90 */ - { SIRF_END, 0 }, /* 91 */ -}; - -static void -ao_sirf_parse_41(void) __reentrant -{ - ao_sirf_parse(&ao_sirf_data, geodetic_nav_data_packet); -} - -static const struct sirf_packet_parse measured_tracker_data_packet[] = { - { SIRF_U16, offsetof (struct sirf_measured_tracker_data, gps_week) }, /* 1 week */ - { SIRF_U32, offsetof (struct sirf_measured_tracker_data, gps_tow) }, /* 3 time of week */ - { SIRF_U8, offsetof (struct sirf_measured_tracker_data, channels) }, /* 7 channels */ - { SIRF_END, 0 }, -}; - -static const struct sirf_packet_parse measured_sat_data_packet[] = { - { SIRF_U8, offsetof (struct sirf_measured_sat_data, svid) }, /* 0 SV id */ - { SIRF_DISCARD, 2 }, /* 1 azimuth, 2 elevation */ - { SIRF_U16, offsetof (struct sirf_measured_sat_data, state) }, /* 2 state */ - { SIRF_U8, offsetof (struct sirf_measured_sat_data, c_n_1) }, /* C/N0 1 */ - { SIRF_DISCARD, 9 }, /* C/N0 2-10 */ - { SIRF_END, 0 }, -}; - -static void -ao_sirf_parse_4(void) __reentrant -{ - uint8_t i; - ao_sirf_parse(&ao_sirf_tracker_data, measured_tracker_data_packet); - for (i = 0; i < 12; i++) - ao_sirf_parse(&ao_sirf_tracker_data.sats[i], measured_sat_data_packet); -} - -static void -ao_gps_setup(void) __reentrant -{ - uint8_t i, k; - ao_serial_set_speed(AO_SERIAL_SPEED_4800); - for (i = 0; i < 64; i++) - ao_serial_putchar(0x00); - for (k = 0; k < 3; k++) - for (i = 0; i < sizeof (ao_gps_set_nmea); i++) - ao_serial_putchar(ao_gps_set_nmea[i]); - ao_serial_set_speed(AO_SERIAL_SPEED_57600); - for (i = 0; i < 64; i++) - ao_serial_putchar(0x00); -} - -static const char ao_gps_set_message_rate[] = { - 0xa0, 0xa2, 0x00, 0x08, - 166, - 0, -}; - -void -ao_sirf_set_message_rate(uint8_t msg, uint8_t rate) -{ - uint16_t cksum = 0x00a6; - uint8_t i; - - for (i = 0; i < sizeof (ao_gps_set_message_rate); i++) - ao_serial_putchar(ao_gps_set_message_rate[i]); - ao_serial_putchar(msg); - ao_serial_putchar(rate); - cksum = 0xa6 + msg + rate; - for (i = 0; i < 4; i++) - ao_serial_putchar(0); - ao_serial_putchar((cksum >> 8) & 0x7f); - ao_serial_putchar(cksum & 0xff); - ao_serial_putchar(0xb0); - ao_serial_putchar(0xb3); -} - -static const uint8_t sirf_disable[] = { - 2, - 9, - 10, - 27, - 50, - 52, -}; - -void -ao_gps(void) __reentrant -{ - uint8_t i, k; - uint16_t cksum; - - ao_gps_setup(); - for (k = 0; k < 5; k++) - { - for (i = 0; i < sizeof (ao_gps_config); i++) - ao_serial_putchar(ao_gps_config[i]); - for (i = 0; i < sizeof (sirf_disable); i++) - ao_sirf_set_message_rate(sirf_disable[i], 0); - ao_sirf_set_message_rate(41, 1); - ao_sirf_set_message_rate(4, 1); - } - for (;;) { - /* Locate the begining of the next record */ - while (ao_sirf_byte() != (uint8_t) 0xa0) - ; - if (ao_sirf_byte() != (uint8_t) 0xa2) - continue; - - /* Length */ - ao_sirf_len = ao_sirf_byte() << 8; - ao_sirf_len |= ao_sirf_byte(); - if (ao_sirf_len > 1023) - continue; - - ao_sirf_cksum = 0; - - /* message ID */ - i = data_byte (); /* 0 */ - - switch (i) { - case 41: - if (ao_sirf_len < 90) - break; - ao_sirf_parse_41(); - break; - case 4: - if (ao_sirf_len < 187) - break; - ao_sirf_parse_4(); - break; - } - if (ao_sirf_len != 0) - continue; - - /* verify checksum and end sequence */ - ao_sirf_cksum &= 0x7fff; - cksum = ao_sirf_byte() << 8; - cksum |= ao_sirf_byte(); - if (ao_sirf_cksum != cksum) - continue; - if (ao_sirf_byte() != (uint8_t) 0xb0) - continue; - if (ao_sirf_byte() != (uint8_t) 0xb3) - continue; - - switch (i) { - case 41: - ao_mutex_get(&ao_gps_mutex); - ao_gps_data.hour = ao_sirf_data.utc_hour; - ao_gps_data.minute = ao_sirf_data.utc_minute; - ao_gps_data.second = ao_sirf_data.utc_second / 1000; - ao_gps_data.flags = ((ao_sirf_data.num_sv << AO_GPS_NUM_SAT_SHIFT) & AO_GPS_NUM_SAT_MASK) | AO_GPS_RUNNING; - if ((ao_sirf_data.nav_type & NAV_TYPE_GPS_FIX_TYPE_MASK) >= NAV_TYPE_4_SV_KF) - ao_gps_data.flags |= AO_GPS_VALID; - ao_gps_data.latitude = ao_sirf_data.lat; - ao_gps_data.longitude = ao_sirf_data.lon; - ao_gps_data.altitude = ao_sirf_data.alt_msl / 100; - ao_gps_data.ground_speed = ao_sirf_data.ground_speed; - ao_gps_data.course = ao_sirf_data.course / 200; - ao_gps_data.hdop = ao_sirf_data.hdop; - ao_gps_data.climb_rate = ao_sirf_data.climb_rate; - if (ao_sirf_data.h_error > 6553500) - ao_gps_data.h_error = 65535; - else - ao_gps_data.h_error = ao_sirf_data.h_error / 100; - if (ao_sirf_data.v_error > 6553500) - ao_gps_data.v_error = 65535; - else - ao_gps_data.v_error = ao_sirf_data.v_error / 100; - ao_mutex_put(&ao_gps_mutex); - ao_wakeup(&ao_gps_data); - break; - case 4: - ao_mutex_get(&ao_gps_mutex); - ao_gps_tracking_data.channels = ao_sirf_tracker_data.channels; - for (i = 0; i < 12; i++) { - ao_gps_tracking_data.sats[i].svid = ao_sirf_tracker_data.sats[i].svid; - ao_gps_tracking_data.sats[i].state = (uint8_t) ao_sirf_tracker_data.sats[i].state; - ao_gps_tracking_data.sats[i].c_n_1 = ao_sirf_tracker_data.sats[i].c_n_1; - } - ao_mutex_put(&ao_gps_mutex); - ao_wakeup(&ao_gps_tracking_data); - break; - } - } -} - -__xdata struct ao_task ao_gps_task; - -static void -gps_dump(void) __reentrant -{ - ao_mutex_get(&ao_gps_mutex); - ao_gps_print(&ao_gps_data); - putchar('\n'); - ao_gps_tracking_print(&ao_gps_tracking_data); - putchar('\n'); - ao_mutex_put(&ao_gps_mutex); -} - -__code struct ao_cmds ao_gps_cmds[] = { - { 'g', gps_dump, "g Display current GPS values" }, - { 0, gps_dump, NULL }, -}; - -void -ao_gps_init(void) -{ - ao_add_task(&ao_gps_task, ao_gps, "gps"); - ao_cmd_register(&ao_gps_cmds[0]); -} diff --git a/src/ao_gps_sirf.c b/src/ao_gps_sirf.c new file mode 100644 index 00000000..2b3a5178 --- /dev/null +++ b/src/ao_gps_sirf.c @@ -0,0 +1,457 @@ +/* + * 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. + */ + +#ifndef AO_GPS_TEST +#include "ao.h" +#endif + +__xdata uint8_t ao_gps_mutex; +__xdata struct ao_gps_data ao_gps_data; +__xdata struct ao_gps_tracking_data ao_gps_tracking_data; + +static const char ao_gps_set_nmea[] = "\r\n$PSRF100,0,57600,8,1,0*37\r\n"; + +const char ao_gps_config[] = { + + 0xa0, 0xa2, 0x00, 0x0e, /* length: 14 bytes */ + 136, /* mode control */ + 0, 0, /* reserved */ + 0, /* degraded mode (allow 1-SV navigation) */ + 0, 0, /* reserved */ + 0, 0, /* user specified altitude */ + 2, /* alt hold mode (disabled, require 3d fixes) */ + 0, /* alt hold source (use last computed altitude) */ + 0, /* reserved */ + 10, /* Degraded time out (10 sec) */ + 10, /* Dead Reckoning time out (10 sec) */ + 0, /* Track smoothing (disabled) */ + 0x00, 0x8e, 0xb0, 0xb3, + + 0xa0, 0xa2, 0x00, 0x08, /* length: 8 bytes */ + 166, /* Set message rate */ + 2, /* enable/disable all messages */ + 0, /* message id (ignored) */ + 0, /* update rate (0 = disable) */ + 0, 0, 0, 0, /* reserved */ + 0x00, 0xa8, 0xb0, 0xb3, + + 0xa0, 0xa2, 0x00, 0x02, /* length: 2 bytes */ + 143, /* static navigation */ + 0, /* disable */ + 0x00, 0x8f, 0xb0, 0xb3, +}; + +#define NAV_TYPE_GPS_FIX_TYPE_MASK (7 << 0) +#define NAV_TYPE_NO_FIX (0 << 0) +#define NAV_TYPE_SV_KF (1 << 0) +#define NAV_TYPE_2_SV_KF (2 << 0) +#define NAV_TYPE_3_SV_KF (3 << 0) +#define NAV_TYPE_4_SV_KF (4 << 0) +#define NAV_TYPE_2D_LEAST_SQUARES (5 << 0) +#define NAV_TYPE_3D_LEAST_SQUARES (6 << 0) +#define NAV_TYPE_DR (7 << 0) +#define NAV_TYPE_TRICKLE_POWER (1 << 3) +#define NAV_TYPE_ALTITUDE_HOLD_MASK (3 << 4) +#define NAV_TYPE_ALTITUDE_HOLD_NONE (0 << 4) +#define NAV_TYPE_ALTITUDE_HOLD_KF (1 << 4) +#define NAV_TYPE_ALTITUDE_HOLD_USER (2 << 4) +#define NAV_TYPE_ALTITUDE_HOLD_ALWAYS (3 << 4) +#define NAV_TYPE_DOP_LIMIT_EXCEEDED (1 << 6) +#define NAV_TYPE_DGPS_APPLIED (1 << 7) +#define NAV_TYPE_SENSOR_DR (1 << 8) +#define NAV_TYPE_OVERDETERMINED (1 << 9) +#define NAV_TYPE_DR_TIMEOUT_EXCEEDED (1 << 10) +#define NAV_TYPE_FIX_MI_EDIT (1 << 11) +#define NAV_TYPE_INVALID_VELOCITY (1 << 12) +#define NAV_TYPE_ALTITUDE_HOLD_DISABLED (1 << 13) +#define NAV_TYPE_DR_ERROR_STATUS_MASK (3 << 14) +#define NAV_TYPE_DR_ERROR_STATUS_GPS_ONLY (0 << 14) +#define NAV_TYPE_DR_ERROR_STATUS_DR_FROM_GPS (1 << 14) +#define NAV_TYPE_DR_ERROR_STATUS_DR_SENSOR_ERROR (2 << 14) +#define NAV_TYPE_DR_ERROR_STATUS_DR_IN_TEST (3 << 14) + +struct sirf_geodetic_nav_data { + uint16_t nav_type; + uint16_t utc_year; + uint8_t utc_month; + uint8_t utc_day; + uint8_t utc_hour; + uint8_t utc_minute; + uint16_t utc_second; + int32_t lat; + int32_t lon; + int32_t alt_msl; + uint16_t ground_speed; + uint16_t course; + int16_t climb_rate; + uint32_t h_error; + uint32_t v_error; + uint8_t num_sv; + uint8_t hdop; +}; + +static __xdata struct sirf_geodetic_nav_data ao_sirf_data; + +struct sirf_measured_sat_data { + uint8_t svid; + uint16_t state; + uint8_t c_n_1; +}; + +struct sirf_measured_tracker_data { + int16_t gps_week; + uint32_t gps_tow; + uint8_t channels; + struct sirf_measured_sat_data sats[12]; +}; + +static __xdata struct sirf_measured_tracker_data ao_sirf_tracker_data; + +static __pdata uint16_t ao_sirf_cksum; +static __pdata uint16_t ao_sirf_len; + +#define ao_sirf_byte() ((uint8_t) ao_serial_getchar()) + +static uint8_t data_byte(void) +{ + uint8_t c = ao_sirf_byte(); + --ao_sirf_len; + ao_sirf_cksum += c; + return c; +} + +static char __xdata *sirf_target; + +static void sirf_u16(uint8_t offset) +{ + uint16_t __xdata *ptr = (uint16_t __xdata *) (sirf_target + offset); + uint16_t val; + + val = data_byte() << 8; + val |= data_byte (); + *ptr = val; +} + +static void sirf_u8(uint8_t offset) +{ + uint8_t __xdata *ptr = (uint8_t __xdata *) (sirf_target + offset); + uint8_t val; + + val = data_byte (); + *ptr = val; +} + +static void sirf_u32(uint8_t offset) __reentrant +{ + uint32_t __xdata *ptr = (uint32_t __xdata *) (sirf_target + offset); + uint32_t val; + + val = ((uint32_t) data_byte ()) << 24; + val |= ((uint32_t) data_byte ()) << 16; + val |= ((uint32_t) data_byte ()) << 8; + val |= ((uint32_t) data_byte ()); + *ptr = val; +} + +static void sirf_discard(uint8_t len) +{ + while (len--) + data_byte(); +} + +#define SIRF_END 0 +#define SIRF_DISCARD 1 +#define SIRF_U8 2 +#define SIRF_U16 3 +#define SIRF_U32 4 +#define SIRF_U8X10 5 + +struct sirf_packet_parse { + uint8_t type; + uint8_t offset; +}; + +static void +ao_sirf_parse(void __xdata *target, const struct sirf_packet_parse *parse) __reentrant +{ + uint8_t i, offset, j; + + sirf_target = target; + for (i = 0; ; i++) { + offset = parse[i].offset; + switch (parse[i].type) { + case SIRF_END: + return; + case SIRF_DISCARD: + sirf_discard(offset); + break; + case SIRF_U8: + sirf_u8(offset); + break; + case SIRF_U16: + sirf_u16(offset); + break; + case SIRF_U32: + sirf_u32(offset); + break; + case SIRF_U8X10: + for (j = 10; j--;) + sirf_u8(offset++); + break; + } + } +} + +static const struct sirf_packet_parse geodetic_nav_data_packet[] = { + { SIRF_DISCARD, 2 }, /* 1 nav valid */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, nav_type) }, /* 3 */ + { SIRF_DISCARD, 6 }, /* 5 week number, time of week */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, utc_year) }, /* 11 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_month) }, /* 13 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_day) }, /* 14 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_hour) }, /* 15 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_minute) }, /* 16 */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, utc_second) }, /* 17 */ + { SIRF_DISCARD, 4 }, /* satellite id list */ /* 19 */ + { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, lat) }, /* 23 */ + { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, lon) }, /* 27 */ + { SIRF_DISCARD, 4 }, /* altitude from ellipsoid */ /* 31 */ + { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, alt_msl) }, /* 35 */ + { SIRF_DISCARD, 1 }, /* map datum */ /* 39 */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, ground_speed) }, /* 40 */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, course) }, /* 42 */ + { SIRF_DISCARD, 2 }, /* magnetic variation */ /* 44 */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, climb_rate) }, /* 46 */ + { SIRF_DISCARD, 2 }, /* turn rate */ /* 48 */ + { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, h_error) }, /* 50 */ + { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, v_error) }, /* 54 */ + { SIRF_DISCARD, 30 }, /* time error, h_vel error, clock_bias, + clock bias error, clock drift, + clock drift error, distance, + distance error, heading error */ /* 58 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, num_sv) }, /* 88 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, hdop) }, /* 89 */ + { SIRF_DISCARD, 1 }, /* additional mode info */ /* 90 */ + { SIRF_END, 0 }, /* 91 */ +}; + +static void +ao_sirf_parse_41(void) __reentrant +{ + ao_sirf_parse(&ao_sirf_data, geodetic_nav_data_packet); +} + +static const struct sirf_packet_parse measured_tracker_data_packet[] = { + { SIRF_U16, offsetof (struct sirf_measured_tracker_data, gps_week) }, /* 1 week */ + { SIRF_U32, offsetof (struct sirf_measured_tracker_data, gps_tow) }, /* 3 time of week */ + { SIRF_U8, offsetof (struct sirf_measured_tracker_data, channels) }, /* 7 channels */ + { SIRF_END, 0 }, +}; + +static const struct sirf_packet_parse measured_sat_data_packet[] = { + { SIRF_U8, offsetof (struct sirf_measured_sat_data, svid) }, /* 0 SV id */ + { SIRF_DISCARD, 2 }, /* 1 azimuth, 2 elevation */ + { SIRF_U16, offsetof (struct sirf_measured_sat_data, state) }, /* 2 state */ + { SIRF_U8, offsetof (struct sirf_measured_sat_data, c_n_1) }, /* C/N0 1 */ + { SIRF_DISCARD, 9 }, /* C/N0 2-10 */ + { SIRF_END, 0 }, +}; + +static void +ao_sirf_parse_4(void) __reentrant +{ + uint8_t i; + ao_sirf_parse(&ao_sirf_tracker_data, measured_tracker_data_packet); + for (i = 0; i < 12; i++) + ao_sirf_parse(&ao_sirf_tracker_data.sats[i], measured_sat_data_packet); +} + +static void +ao_gps_setup(void) __reentrant +{ + uint8_t i, k; + ao_serial_set_speed(AO_SERIAL_SPEED_4800); + for (i = 0; i < 64; i++) + ao_serial_putchar(0x00); + for (k = 0; k < 3; k++) + for (i = 0; i < sizeof (ao_gps_set_nmea); i++) + ao_serial_putchar(ao_gps_set_nmea[i]); + ao_serial_set_speed(AO_SERIAL_SPEED_57600); + for (i = 0; i < 64; i++) + ao_serial_putchar(0x00); +} + +static const char ao_gps_set_message_rate[] = { + 0xa0, 0xa2, 0x00, 0x08, + 166, + 0, +}; + +void +ao_sirf_set_message_rate(uint8_t msg, uint8_t rate) +{ + uint16_t cksum = 0x00a6; + uint8_t i; + + for (i = 0; i < sizeof (ao_gps_set_message_rate); i++) + ao_serial_putchar(ao_gps_set_message_rate[i]); + ao_serial_putchar(msg); + ao_serial_putchar(rate); + cksum = 0xa6 + msg + rate; + for (i = 0; i < 4; i++) + ao_serial_putchar(0); + ao_serial_putchar((cksum >> 8) & 0x7f); + ao_serial_putchar(cksum & 0xff); + ao_serial_putchar(0xb0); + ao_serial_putchar(0xb3); +} + +static const uint8_t sirf_disable[] = { + 2, + 9, + 10, + 27, + 50, + 52, +}; + +void +ao_gps(void) __reentrant +{ + uint8_t i, k; + uint16_t cksum; + + ao_gps_setup(); + for (k = 0; k < 5; k++) + { + for (i = 0; i < sizeof (ao_gps_config); i++) + ao_serial_putchar(ao_gps_config[i]); + for (i = 0; i < sizeof (sirf_disable); i++) + ao_sirf_set_message_rate(sirf_disable[i], 0); + ao_sirf_set_message_rate(41, 1); + ao_sirf_set_message_rate(4, 1); + } + for (;;) { + /* Locate the begining of the next record */ + while (ao_sirf_byte() != (uint8_t) 0xa0) + ; + if (ao_sirf_byte() != (uint8_t) 0xa2) + continue; + + /* Length */ + ao_sirf_len = ao_sirf_byte() << 8; + ao_sirf_len |= ao_sirf_byte(); + if (ao_sirf_len > 1023) + continue; + + ao_sirf_cksum = 0; + + /* message ID */ + i = data_byte (); /* 0 */ + + switch (i) { + case 41: + if (ao_sirf_len < 90) + break; + ao_sirf_parse_41(); + break; + case 4: + if (ao_sirf_len < 187) + break; + ao_sirf_parse_4(); + break; + } + if (ao_sirf_len != 0) + continue; + + /* verify checksum and end sequence */ + ao_sirf_cksum &= 0x7fff; + cksum = ao_sirf_byte() << 8; + cksum |= ao_sirf_byte(); + if (ao_sirf_cksum != cksum) + continue; + if (ao_sirf_byte() != (uint8_t) 0xb0) + continue; + if (ao_sirf_byte() != (uint8_t) 0xb3) + continue; + + switch (i) { + case 41: + ao_mutex_get(&ao_gps_mutex); + ao_gps_data.hour = ao_sirf_data.utc_hour; + ao_gps_data.minute = ao_sirf_data.utc_minute; + ao_gps_data.second = ao_sirf_data.utc_second / 1000; + ao_gps_data.flags = ((ao_sirf_data.num_sv << AO_GPS_NUM_SAT_SHIFT) & AO_GPS_NUM_SAT_MASK) | AO_GPS_RUNNING; + if ((ao_sirf_data.nav_type & NAV_TYPE_GPS_FIX_TYPE_MASK) >= NAV_TYPE_4_SV_KF) + ao_gps_data.flags |= AO_GPS_VALID; + ao_gps_data.latitude = ao_sirf_data.lat; + ao_gps_data.longitude = ao_sirf_data.lon; + ao_gps_data.altitude = ao_sirf_data.alt_msl / 100; + ao_gps_data.ground_speed = ao_sirf_data.ground_speed; + ao_gps_data.course = ao_sirf_data.course / 200; + ao_gps_data.hdop = ao_sirf_data.hdop; + ao_gps_data.climb_rate = ao_sirf_data.climb_rate; + if (ao_sirf_data.h_error > 6553500) + ao_gps_data.h_error = 65535; + else + ao_gps_data.h_error = ao_sirf_data.h_error / 100; + if (ao_sirf_data.v_error > 6553500) + ao_gps_data.v_error = 65535; + else + ao_gps_data.v_error = ao_sirf_data.v_error / 100; + ao_mutex_put(&ao_gps_mutex); + ao_wakeup(&ao_gps_data); + break; + case 4: + ao_mutex_get(&ao_gps_mutex); + ao_gps_tracking_data.channels = ao_sirf_tracker_data.channels; + for (i = 0; i < 12; i++) { + ao_gps_tracking_data.sats[i].svid = ao_sirf_tracker_data.sats[i].svid; + ao_gps_tracking_data.sats[i].state = (uint8_t) ao_sirf_tracker_data.sats[i].state; + ao_gps_tracking_data.sats[i].c_n_1 = ao_sirf_tracker_data.sats[i].c_n_1; + } + ao_mutex_put(&ao_gps_mutex); + ao_wakeup(&ao_gps_tracking_data); + break; + } + } +} + +__xdata struct ao_task ao_gps_task; + +static void +gps_dump(void) __reentrant +{ + ao_mutex_get(&ao_gps_mutex); + ao_gps_print(&ao_gps_data); + putchar('\n'); + ao_gps_tracking_print(&ao_gps_tracking_data); + putchar('\n'); + ao_mutex_put(&ao_gps_mutex); +} + +__code struct ao_cmds ao_gps_cmds[] = { + { 'g', gps_dump, "g Display current GPS values" }, + { 0, gps_dump, NULL }, +}; + +void +ao_gps_init(void) +{ + ao_add_task(&ao_gps_task, ao_gps, "gps"); + ao_cmd_register(&ao_gps_cmds[0]); +} diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c new file mode 100644 index 00000000..b397d975 --- /dev/null +++ b/src/ao_gps_skytraq.c @@ -0,0 +1,369 @@ +/* + * 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. + */ + +#ifndef AO_GPS_TEST +#include "ao.h" +#endif + +#define AO_GPS_LEADER 3 + +static const char ao_gps_header[] = "GPG"; + +__xdata uint8_t ao_gps_mutex; +static __xdata char ao_gps_char; +static __xdata uint8_t ao_gps_cksum; +static __xdata uint8_t ao_gps_error; + +__xdata struct ao_gps_data ao_gps_data; +__xdata struct ao_gps_tracking_data ao_gps_tracking_data; + +static __xdata struct ao_gps_data ao_gps_next; +static __xdata struct ao_gps_tracking_data ao_gps_tracking_next; + +static const char ao_gps_config[] = { + 0xa0, 0xa1, 0x00, 0x09, /* length 9 bytes */ + 0x08, /* configure nmea */ + 1, /* gga interval */ + 1, /* gsa interval */ + 1, /* gsv interval */ + 1, /* gll interval */ + 1, /* rmc interval */ + 1, /* vtg interval */ + 1, /* zda interval */ + 0, /* attributes (0 = update to sram, 1 = update flash too) */ + 0x09, 0x0d, 0x0a, +}; + +static void +ao_gps_lexchar(void) +{ + if (ao_gps_error) + ao_gps_char = '\n'; + else + ao_gps_char = ao_serial_getchar(); + ao_gps_cksum ^= ao_gps_char; +} + +void +ao_gps_skip(void) +{ + while (ao_gps_char >= '0') + ao_gps_lexchar(); +} + +void +ao_gps_skip_field(void) +{ + while (ao_gps_char != ',' && ao_gps_char != '*' && ao_gps_char != '\n') + ao_gps_lexchar(); +} + +void +ao_gps_skip_sep(void) +{ + if (ao_gps_char == ',' || ao_gps_char == '.' || ao_gps_char == '*') + ao_gps_lexchar(); +} + +__xdata static uint8_t ao_gps_num_width; + +static int16_t +ao_gps_decimal(uint8_t max_width) +{ + int16_t v; + __xdata uint8_t neg = 0; + + ao_gps_skip_sep(); + if (ao_gps_char == '-') { + neg = 1; + ao_gps_lexchar(); + } + v = 0; + ao_gps_num_width = 0; + while (ao_gps_num_width < max_width) { + if (ao_gps_char < '0' || '9' < ao_gps_char) + break; + v = v * (int16_t) 10 + ao_gps_char - '0'; + ao_gps_num_width++; + ao_gps_lexchar(); + } + if (neg) + v = -v; + return v; +} + +static uint8_t +ao_gps_hex(uint8_t max_width) +{ + uint8_t v, d; + + ao_gps_skip_sep(); + v = 0; + ao_gps_num_width = 0; + while (ao_gps_num_width < max_width) { + if ('0' <= ao_gps_char && ao_gps_char <= '9') + d = ao_gps_char - '0'; + else if ('A' <= ao_gps_char && ao_gps_char <= 'F') + d = ao_gps_char - 'A' + 10; + else if ('a' <= ao_gps_char && ao_gps_char <= 'f') + d = ao_gps_char - 'a' + 10; + else + break; + v = (v << 4) | d; + ao_gps_num_width++; + ao_gps_lexchar(); + } + return v; +} + +static int32_t +ao_gps_parse_pos(uint8_t deg_width) __reentrant +{ + int32_t d; + int32_t m; + int32_t f; + + d = ao_gps_decimal(deg_width); + m = ao_gps_decimal(2); + if (ao_gps_char == '.') { + f = ao_gps_decimal(4); + while (ao_gps_num_width < 4) { + f *= 10; + ao_gps_num_width++; + } + } else { + f = 0; + if (ao_gps_char != ',') + ao_gps_error = 1; + } + d = d * 10000000l; + m = m * 10000l + f; + d = d + m * 50 / 3; + return d; +} + +static uint8_t +ao_gps_parse_flag(char no_c, char yes_c) __reentrant +{ + uint8_t ret = 0; + ao_gps_skip_sep(); + if (ao_gps_char == yes_c) + ret = 1; + else if (ao_gps_char == no_c) + ret = 0; + else + ao_gps_error = 1; + ao_gps_lexchar(); + return ret; +} + + +void +ao_gps(void) __reentrant +{ + char c; + uint8_t i; + + ao_serial_set_speed(AO_SERIAL_SPEED_9600); + for (i = 0; i < sizeof (ao_gps_config); i++) + ao_serial_putchar(ao_gps_config[i]); + for (;;) { + /* Locate the begining of the next record */ + for (;;) { + c = ao_serial_getchar(); + if (c == '$') + break; + } + + ao_gps_cksum = 0; + ao_gps_error = 0; + + /* Skip anything other than GPG */ + for (i = 0; i < AO_GPS_LEADER; i++) { + ao_gps_lexchar(); + if (ao_gps_char != ao_gps_header[i]) + break; + } + if (i != AO_GPS_LEADER) + continue; + + /* pull the record identifier characters off the link */ + ao_gps_lexchar(); + c = ao_gps_char; + ao_gps_lexchar(); + i = ao_gps_char; + ao_gps_lexchar(); + if (ao_gps_char != ',') + continue; + + if (c == (uint8_t) 'G' && i == (uint8_t) 'A') { + /* Now read the data into the gps data record + * + * $GPGGA,025149.000,4528.1723,N,12244.2480,W,1,05,2.0,103.5,M,-19.5,M,,0000*66 + * + * Essential fix data + * + * 025149.000 time (02:51:49.000 GMT) + * 4528.1723,N Latitude 45°28.1723' N + * 12244.2480,W Longitude 122°44.2480' W + * 1 Fix quality: + * 0 = invalid + * 1 = GPS fix (SPS) + * 2 = DGPS fix + * 3 = PPS fix + * 4 = Real Time Kinematic + * 5 = Float RTK + * 6 = estimated (dead reckoning) + * 7 = Manual input mode + * 8 = Simulation mode + * 05 Number of satellites (5) + * 2.0 Horizontal dilution + * 103.5,M Altitude, 103.5M above msl + * -19.5,M Height of geoid above WGS84 ellipsoid + * ? time in seconds since last DGPS update + * 0000 DGPS station ID + * *66 checksum + */ + + ao_gps_next.flags = AO_GPS_RUNNING; + ao_gps_next.hour = ao_gps_decimal(2); + ao_gps_next.minute = ao_gps_decimal(2); + ao_gps_next.second = ao_gps_decimal(2); + ao_gps_skip_field(); /* skip seconds fraction */ + + ao_gps_next.latitude = ao_gps_parse_pos(2); + if (ao_gps_parse_flag('N', 'S')) + ao_gps_next.latitude = -ao_gps_next.latitude; + ao_gps_next.longitude = ao_gps_parse_pos(3); + if (ao_gps_parse_flag('E', 'W')) + ao_gps_next.longitude = -ao_gps_next.longitude; + + i = ao_gps_decimal(0xff); + if (i == 1) + ao_gps_next.flags |= AO_GPS_VALID; + + i = ao_gps_decimal(0xff) << AO_GPS_NUM_SAT_SHIFT; + if (i > AO_GPS_NUM_SAT_MASK) + i = AO_GPS_NUM_SAT_MASK; + ao_gps_next.flags |= i; + + ao_gps_lexchar(); + ao_gps_skip_field(); /* Horizontal dilution */ + + ao_gps_next.altitude = ao_gps_decimal(0xff); + ao_gps_skip_field(); /* skip any fractional portion */ + + /* Skip remaining fields */ + while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { + ao_gps_lexchar(); + ao_gps_skip_field(); + } + if (ao_gps_char == '*') { + uint8_t cksum = ao_gps_cksum ^ '*'; + if (cksum != ao_gps_hex(2)) + ao_gps_error = 1; + } else + ao_gps_error = 1; + if (!ao_gps_error) { + ao_mutex_get(&ao_gps_mutex); + memcpy(&ao_gps_data, &ao_gps_next, sizeof (struct ao_gps_data)); + ao_mutex_put(&ao_gps_mutex); + ao_wakeup(&ao_gps_data); + } + } else if (c == (uint8_t) 'S' && i == (uint8_t) 'V') { + uint8_t done; + /* Now read the data into the GPS tracking data record + * + * $GPGSV,3,1,12,05,54,069,45,12,44,061,44,21,07,184,46,22,78,289,47*72 + * + * Satellites in view data + * + * 3 Total number of GSV messages + * 1 Sequence number of current GSV message + * 12 Total sats in view (0-12) + * 05 SVID + * 54 Elevation + * 069 Azimuth + * 45 C/N0 in dB + * ... other SVIDs + * 72 checksum + */ + c = ao_gps_decimal(1); /* total messages */ + i = ao_gps_decimal(1); /* message sequence */ + if (i == 1) { + ao_gps_tracking_next.channels = 0; + } + done = (uint8_t) c == i; + ao_gps_lexchar(); + ao_gps_skip_field(); /* sats in view */ + while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { + i = ao_gps_tracking_next.channels; + ao_gps_tracking_next.sats[i].svid = ao_gps_decimal(2); /* SVID */ + ao_gps_lexchar(); + ao_gps_skip_field(); /* elevation */ + ao_gps_lexchar(); + ao_gps_skip_field(); /* azimuth */ + if (ao_gps_tracking_next.sats[i].c_n_1 = ao_gps_decimal(2)) /* C/N0 */ + ao_gps_tracking_next.sats[i].state = 0xbf; + else + ao_gps_tracking_next.sats[i].state = 0; + ao_gps_tracking_next.channels = i + 1; + } + if (ao_gps_char == '*') { + uint8_t cksum = ao_gps_cksum ^ '*'; + if (cksum != ao_gps_hex(2)) + ao_gps_error = 1; + } + else + ao_gps_error = 1; + if (ao_gps_error) + ao_gps_tracking_next.channels = 0; + else if (done) { + ao_mutex_get(&ao_gps_mutex); + memcpy(&ao_gps_tracking_data, &ao_gps_tracking_next, + sizeof(ao_gps_tracking_data)); + ao_mutex_put(&ao_gps_mutex); + ao_wakeup(&ao_gps_tracking_data); + } + } + } +} + +__xdata struct ao_task ao_gps_task; + +static void +gps_dump(void) __reentrant +{ + ao_mutex_get(&ao_gps_mutex); + ao_gps_print(&ao_gps_data); + putchar('\n'); + ao_gps_tracking_print(&ao_gps_tracking_data); + putchar('\n'); + ao_mutex_put(&ao_gps_mutex); +} + +__code struct ao_cmds ao_gps_cmds[] = { + { 'g', gps_dump, "g Display current GPS values" }, + { 0, gps_dump, NULL }, +}; + +void +ao_gps_init(void) +{ + ao_add_task(&ao_gps_task, ao_gps, "gps"); + ao_cmd_register(&ao_gps_cmds[0]); +} diff --git a/src/ao_gps_test.c b/src/ao_gps_test.c index c94128d9..366bca71 100644 --- a/src/ao_gps_test.c +++ b/src/ao_gps_test.c @@ -398,7 +398,7 @@ ao_serial_set_speed(uint8_t speed) } #include "ao_gps_print.c" -#include "ao_gps.c" +#include "ao_gps_sirf.c" void ao_dump_state(void *wchan) diff --git a/src/ao_gps_test_skytraq.c b/src/ao_gps_test_skytraq.c new file mode 100644 index 00000000..510bc419 --- /dev/null +++ b/src/ao_gps_test_skytraq.c @@ -0,0 +1,478 @@ +/* + * 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_GPS_TEST +#include "ao_host.h" +#include +#include +#include +#include +#include +#define AO_GPS_NUM_SAT_MASK (0xf << 0) +#define AO_GPS_NUM_SAT_SHIFT (0) + +#define AO_GPS_VALID (1 << 4) +#define AO_GPS_RUNNING (1 << 5) + +struct ao_gps_data { + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t flags; + int32_t latitude; /* degrees * 10⁷ */ + int32_t longitude; /* degrees * 10⁷ */ + int16_t altitude; /* m */ + uint16_t ground_speed; /* cm/s */ + uint8_t course; /* degrees / 2 */ + uint8_t hdop; /* * 5 */ + int16_t climb_rate; /* cm/s */ + uint16_t h_error; /* m */ + uint16_t v_error; /* m */ +}; + +#define SIRF_SAT_STATE_ACQUIRED (1 << 0) +#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) +#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) +#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) +#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) +#define SIRF_SAT_CODE_LOCKED (1 << 5) +#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) +#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) + +struct ao_gps_sat_data { + uint8_t svid; + uint8_t state; + uint8_t c_n_1; +}; + +struct ao_gps_tracking_data { + uint8_t channels; + struct ao_gps_sat_data sats[12]; +}; + +void +ao_mutex_get(uint8_t *mutex) +{ +} + +void +ao_mutex_put(uint8_t *mutex) +{ +} + +static int +ao_gps_fd; + +static void +ao_dbg_char(char c) +{ + char line[128]; + line[0] = '\0'; + if (c < ' ') { + if (c == '\n') + sprintf (line, "\n"); + else + sprintf (line, "\\%02x", ((int) c) & 0xff); + } else { + sprintf (line, "%c", c); + } + write(1, line, strlen(line)); +} + +#define QUEUE_LEN 4096 + +static char input_queue[QUEUE_LEN]; +int input_head, input_tail; + +#include + +int +get_millis(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +} + +static void +check_skytraq_message(char *from, uint8_t *msg, int len) +{ + uint16_t encoded_len, encoded_cksum; + uint16_t cksum; + uint8_t id; + int i; + +// fwrite(msg, 1, len, stdout); + return; + if (msg[0] != 0xa0 || msg[1] != 0xa2) { + printf ("bad header\n"); + return; + } + if (len < 7) { + printf("short\n"); + return; + } + if (msg[len-1] != 0xb3 || msg[len-2] != 0xb0) { + printf ("bad trailer\n"); + return; + } + encoded_len = (msg[2] << 8) | msg[3]; + id = msg[4]; +/* printf ("%9d: %3d\n", get_millis(), id); */ + if (encoded_len != len - 8) { + if (id != 52) + printf ("length mismatch (got %d, wanted %d)\n", + len - 8, encoded_len); + return; + } + encoded_cksum = (msg[len - 4] << 8) | msg[len-3]; + cksum = 0; + for (i = 4; i < len - 4; i++) + cksum = (cksum + msg[i]) & 0x7fff; + if (encoded_cksum != cksum) { + printf ("cksum mismatch (got %04x wanted %04x)\n", + cksum, encoded_cksum); + return; + } + id = msg[4]; + switch (id) { + case 41:{ + int off = 4; + + uint8_t id; + uint16_t nav_valid; + uint16_t nav_type; + uint16_t week; + uint32_t tow; + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint16_t second; + uint32_t sat_list; + int32_t lat; + int32_t lon; + int32_t alt_ell; + int32_t alt_msl; + int8_t datum; + uint16_t sog; + uint16_t cog; + int16_t mag_var; + int16_t climb_rate; + int16_t heading_rate; + uint32_t h_error; + uint32_t v_error; + uint32_t t_error; + uint16_t h_v_error; + +#define get_u8(u) u = (msg[off]); off+= 1 +#define get_u16(u) u = (msg[off] << 8) | (msg[off + 1]); off+= 2 +#define get_u32(u) u = (msg[off] << 24) | (msg[off + 1] << 16) | (msg[off+2] << 8) | (msg[off+3]); off+= 4 + + get_u8(id); + get_u16(nav_valid); + get_u16(nav_type); + get_u16(week); + get_u32(tow); + get_u16(year); + get_u8(month); + get_u8(day); + get_u8(hour); + get_u8(minute); + get_u16(second); + get_u32(sat_list); + get_u32(lat); + get_u32(lon); + get_u32(alt_ell); + get_u32(alt_msl); + get_u8(datum); + get_u16(sog); + get_u16(cog); + get_u16(mag_var); + get_u16(climb_rate); + get_u16(heading_rate); + get_u32(h_error); + get_u32(v_error); + get_u32(t_error); + get_u16(h_v_error); + + + printf ("Geodetic Navigation Data (41):\n"); + printf ("\tNav valid %04x\n", nav_valid); + printf ("\tNav type %04x\n", nav_type); + printf ("\tWeek %5d", week); + printf (" TOW %9d", tow); + printf (" %4d-%2d-%2d %02d:%02d:%07.4f\n", + year, month, day, + hour, minute, second / 1000.0); + printf ("\tsats: %08x\n", sat_list); + printf ("\tlat: %g", lat / 1.0e7); + printf (" lon: %g", lon / 1.0e7); + printf (" alt_ell: %g", alt_ell / 100.0); + printf (" alt_msll: %g", alt_msl / 100.0); + printf (" datum: %d\n", datum); + printf ("\tground speed: %g", sog / 100.0); + printf (" course: %g", cog / 100.0); + printf (" climb: %g", climb_rate / 100.0); + printf (" heading rate: %g\n", heading_rate / 100.0); + printf ("\th error: %g", h_error / 100.0); + printf (" v error: %g", v_error / 100.0); + printf (" t error: %g", t_error / 100.0); + printf (" h vel error: %g\n", h_v_error / 100.0); + break; + } + case 4: { + int off = 4; + uint8_t id; + int16_t gps_week; + uint32_t gps_tow; + uint8_t channels; + int j, k; + + get_u8(id); + get_u16(gps_week); + get_u32(gps_tow); + get_u8(channels); + + printf ("Measured Tracker Data (4):\n"); + printf ("GPS week: %d\n", gps_week); + printf ("GPS time of week: %d\n", gps_tow); + printf ("channels: %d\n", channels); + for (j = 0; j < 12; j++) { + uint8_t svid, azimuth, elevation; + uint16_t state; + uint8_t c_n[10]; + get_u8(svid); + get_u8(azimuth); + get_u8(elevation); + get_u16(state); + for (k = 0; k < 10; k++) { + get_u8(c_n[k]); + } + printf ("Sat %3d:", svid); + printf (" aziumuth: %6.1f", azimuth * 1.5); + printf (" elevation: %6.1f", elevation * 0.5); + printf (" state: 0x%02x", state); + printf (" c_n:"); + for (k = 0; k < 10; k++) + printf(" %3d", c_n[k]); + if (state & SIRF_SAT_STATE_ACQUIRED) + printf(" acq,"); + if (state & SIRF_SAT_STATE_CARRIER_PHASE_VALID) + printf(" car,"); + if (state & SIRF_SAT_BIT_SYNC_COMPLETE) + printf(" bit,"); + if (state & SIRF_SAT_SUBFRAME_SYNC_COMPLETE) + printf(" sub,"); + if (state & SIRF_SAT_CARRIER_PULLIN_COMPLETE) + printf(" pullin,"); + if (state & SIRF_SAT_CODE_LOCKED) + printf(" code,"); + if (state & SIRF_SAT_ACQUISITION_FAILED) + printf(" fail,"); + if (state & SIRF_SAT_EPHEMERIS_AVAILABLE) + printf(" ephem,"); + printf ("\n"); + } + break; + } + default: + return; + printf ("%s %4d:", from, encoded_len); + for (i = 4; i < len - 4; i++) { + if (((i - 4) & 0xf) == 0) + printf("\n "); + printf (" %3d", msg[i]); + } + printf ("\n"); + } +} + +static uint8_t skytraq_message[4096]; +static int skytraq_message_len; +static uint8_t skytraq_in_message[4096]; +static int skytraq_in_len; + +char +ao_serial_getchar(void) +{ + char c; + uint8_t uc; + + while (input_head == input_tail) { + for (;;) { + input_tail = read(ao_gps_fd, input_queue, QUEUE_LEN); + if (input_tail < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + perror ("getchar"); + exit (1); + } + input_head = 0; + break; + } + } + c = input_queue[input_head]; + input_head = (input_head + 1) % QUEUE_LEN; + uc = c; +// printf ("c: %02x %c\n", uc, uc); + if (skytraq_in_len || uc == '$') { + if (skytraq_in_len < 4096) + skytraq_in_message[skytraq_in_len++] = uc; + if (uc == 0x0a) { + check_skytraq_message("recv", skytraq_in_message, skytraq_in_len); + skytraq_in_len = 0; + } + } + return c; +} + + +void +ao_serial_putchar(char c) +{ + int i; + uint8_t uc = (uint8_t) c; + + if (skytraq_message_len || uc == 0xa0) { + if (skytraq_message_len < 4096) + skytraq_message[skytraq_message_len++] = uc; + if (uc == 0x0a) { + check_skytraq_message("send", skytraq_message, skytraq_message_len); + skytraq_message_len = 0; + } + } + for (;;) { + i = write(ao_gps_fd, &c, 1); + if (i == 1) { + if ((uint8_t) c == 0xb3 || c == '\r') { + static const struct timespec delay = { + .tv_sec = 0, + .tv_nsec = 100 * 1000 * 1000 + }; + tcdrain(ao_gps_fd); +// nanosleep(&delay, NULL); + } + break; + } + if (i < 0 && (errno == EINTR || errno == EAGAIN)) + continue; + perror("putchar"); + exit(1); + } +} + +#define AO_SERIAL_SPEED_4800 0 +#define AO_SERIAL_SPEED_9600 1 +#define AO_SERIAL_SPEED_57600 2 + +static void +ao_serial_set_speed(uint8_t speed) +{ + int fd = ao_gps_fd; + struct termios termios; + + tcdrain(fd); + tcgetattr(fd, &termios); + switch (speed) { + case AO_SERIAL_SPEED_4800: + cfsetspeed(&termios, B4800); + break; + case AO_SERIAL_SPEED_9600: + cfsetspeed(&termios, B38400); + break; + case AO_SERIAL_SPEED_57600: + cfsetspeed(&termios, B57600); + break; + } + tcsetattr(fd, TCSAFLUSH, &termios); + tcflush(fd, TCIFLUSH); +} + +#include "ao_gps_print.c" +#include "ao_gps_skytraq.c" + +void +ao_dump_state(void *wchan) +{ + double lat, lon; + int i; + if (wchan == &ao_gps_data) + ao_gps_print(&ao_gps_data); + else + ao_gps_tracking_print(&ao_gps_tracking_data); + putchar('\n'); + return; +} + +int +ao_gps_open(const char *tty) +{ + struct termios termios; + int fd; + + fd = open (tty, O_RDWR); + if (fd < 0) + return -1; + + tcgetattr(fd, &termios); + cfmakeraw(&termios); + cfsetspeed(&termios, B4800); + tcsetattr(fd, TCSAFLUSH, &termios); + + tcdrain(fd); + tcflush(fd, TCIFLUSH); + return fd; +} + +#include + +static const struct option options[] = { + { .name = "tty", .has_arg = 1, .val = 'T' }, + { 0, 0, 0, 0}, +}; + +static void usage(char *program) +{ + fprintf(stderr, "usage: %s [--tty ]\n", program); + exit(1); +} + +int +main (int argc, char **argv) +{ + char *tty = "/dev/ttyUSB0"; + int c; + + while ((c = getopt_long(argc, argv, "T:", options, NULL)) != -1) { + switch (c) { + case 'T': + tty = optarg; + break; + default: + usage(argv[0]); + break; + } + } + ao_gps_fd = ao_gps_open(tty); + if (ao_gps_fd < 0) { + perror (tty); + exit (1); + } + ao_gps(); +} diff --git a/src/ao_serial.c b/src/ao_serial.c index 59110354..1e3ea3e3 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -60,7 +60,10 @@ ao_serial_getchar(void) __critical ao_sleep(&ao_usart1_rx_fifo); ao_fifo_remove(ao_usart1_rx_fifo, c); if (serial_echo) { - printf("%02x\n", ((int) c) & 0xff); + printf("%02x ", ((int) c) & 0xff); + if (c >= ' ') + putchar(c); + putchar('\n'); flush(); } return c; @@ -121,6 +124,10 @@ static const struct { /* .baud = */ 163, /* .gcr = */ (7 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB }, + /* [AO_SERIAL_SPEED_9600] = */ { + /* .baud = */ 163, + /* .gcr = */ (8 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB + }, /* [AO_SERIAL_SPEED_57600] = */ { /* .baud = */ 59, /* .gcr = */ (11 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB -- cgit v1.2.3 From 2f7603490a169df8f18b565db4fa967832ffc9bd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 9 Oct 2009 22:48:29 -0700 Subject: Build two versions of TM, one for SiRF, one for SkyTraq This creates two separate images, depending on which GPS unit is connected. Signed-off-by: Keith Packard --- .gitignore | 4 +++- src/Makefile | 41 ++++++++++++++++++++++++++++++++++------- src/ao_teleterra.c | 1 - src/skytraq-cksum | 44 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 9 deletions(-) create mode 100644 src/skytraq-cksum (limited to 'src') diff --git a/.gitignore b/.gitignore index 0ca4bed4..a6f94439 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ TAGS aclocal.m4 src/ao_flight_test src/ao_gps_test +src/ao_gps_test_skytraq ao-teledongle.h ao-telemetrum.h ao-teleterra.h @@ -47,6 +48,7 @@ missing stamp-h1 tags teledongle -telemetrum +telemetrum-sirf +telemetrum-sky teleterra tidongle diff --git a/src/Makefile b/src/Makefile index 892635cb..9891cdad 100644 --- a/src/Makefile +++ b/src/Makefile @@ -59,7 +59,6 @@ TELE_RECEIVER_SRC =\ TELE_DRIVER_SRC = \ ao_convert.c \ - ao_gps_skytraq.c \ ao_serial.c # @@ -84,6 +83,17 @@ TM_DRIVER_SRC = \ ao_gps_report.c \ ao_ignite.c +# +# Drivers only on TeleMetrum +# +TM_SIRF_DRIVER_SRC = \ + ao_gps_sirf.c +# +# Drivers only on TeleMetrum +# +TM_SKY_DRIVER_SRC = \ + ao_gps_skytraq.c + # # Tasks run on TeleMetrum # @@ -108,6 +118,14 @@ TM_SRC = \ $(TM_TASK_SRC) \ $(TM_MAIN_SRC) +TM_SIRF_SRC = \ + $(TM_SRC) \ + $(TM_SIRF_DRIVER_SRC) + +TM_SKY_SRC = \ + $(TM_SRC) \ + $(TM_SKY_DRIVER_SRC) + TI_MAIN_SRC = \ ao_tidongle.c @@ -161,13 +179,16 @@ SRC = \ $(TELE_COMMON_SRC) \ $(TELE_FAKE_SRC) \ $(TM_DRIVER_SRC) \ + $(TM_SIRF_DRIVER_SRC) \ + $(TM_SKY_DRIVER_SRC) \ $(TM_TASK_SRC) \ $(TM_MAIN_SRC) \ $(TI_MAIN_SRC) \ $(TD_MAIN_SRC) \ $(TT_MAIN_SRC) -TM_REL=$(TM_SRC:.c=.rel) ao_product-telemetrum.rel +TM_SIRF_REL=$(TM_SIRF_SRC:.c=.rel) ao_product-telemetrum.rel +TM_SKY_REL=$(TM_SKY_SRC:.c=.rel) ao_product-telemetrum.rel TI_REL=$(TI_SRC:.c=.rel) ao_product-tidongle.rel TT_REL=$(TT_SRC:.c=.rel) ao_product-teleterra.rel TD_REL=$(TD_SRC:.c=.rel) ao_product-teledongle.rel @@ -186,7 +207,7 @@ LST=$(REL:.rel=.lst) RST=$(REL:.rel=.rst) SYM=$(REL:.rel=.sym) -PROGS= telemetrum.ihx tidongle.ihx \ +PROGS= telemetrum-sirf.ihx telemetrum-sky.ihx tidongle.ihx \ teleterra.ihx teledongle.ihx HOST_PROGS=ao_flight_test ao_gps_test ao_gps_test_skytraq @@ -202,15 +223,21 @@ PAOM=$(PROGS:.ihx=) all: $(PROGS) $(HOST_PROGS) -telemetrum.ihx: $(TM_REL) Makefile - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TM_REL) - sh check-stack ao.h telemetrum.mem +telemetrum-sirf.ihx: $(TM_SIRF_REL) Makefile + $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TM_SIRF_REL) + sh check-stack ao.h telemetrum-sirf.mem + +telemetrum-sky.ihx: $(TM_SKY_REL) Makefile + $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TM_SKY_REL) + sh check-stack ao.h telemetrum-sky.mem + +telemetrum-sky.ihx: telemetrum-sirf.ihx tidongle.ihx: $(TI_REL) Makefile $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TI_REL) sh check-stack ao.h tidongle.mem -tidongle.ihx: telemetrum.ihx +tidongle.ihx: telemetrum-sky.ihx teleterra.ihx: $(TT_REL) Makefile $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TT_REL) diff --git a/src/ao_teleterra.c b/src/ao_teleterra.c index deb63597..d696b914 100644 --- a/src/ao_teleterra.c +++ b/src/ao_teleterra.c @@ -31,7 +31,6 @@ main(void) ao_cmd_init(); ao_usb_init(); ao_serial_init(); - ao_gps_init(); ao_monitor_init(AO_LED_GREEN, TRUE); ao_radio_init(); ao_config_init(); diff --git a/src/skytraq-cksum b/src/skytraq-cksum new file mode 100644 index 00000000..e4960bff --- /dev/null +++ b/src/skytraq-cksum @@ -0,0 +1,44 @@ +#!/usr/bin/env nickle + +int checksum(int[] msg) +{ + int sum = 0; + for (int i = 0; i < dim(msg); i++) { + sum ^= msg[i]; + sum &= 0xff; + } + return sum; +} + +void main() +{ + string[...] input; + int[...] msg; + + setdim(input, 0); + while (!File::end(stdin)) { + input[dim(input)] = gets(); + } + + setdim(msg, 0); + for (int i = 0; i < dim(input); i++) { + string[*] words = String::wordsplit(input[i], " ,\t"); + for (int j = 0; j < dim(words); j++) { + if (words[j] == "/" + "*") + break; + if (String::length(words[j]) > 0 && + Ctype::isdigit(words[j][0])) { + msg[dim(msg)] = string_to_integer(words[j]); + } + } + } + printf("\t0xa0, 0xa1, 0x02x, 0x%02x,\t\t/* length: %d bytes */\n", + dim(msg) >> 8, dim(msg) & 0xff, dim(msg)); + for (int i = 0; i < dim(input); i++) + printf("%s\n", input[i]); + int csum = checksum(msg); + printf ("\t0x%02x, 0x0d, 0x0a,\n", + csum); +} + +main(); -- cgit v1.2.3 From b8fc3975bd92037a0cf53b0ff2b0e05ce0ba668f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 10 Oct 2009 13:39:01 -0700 Subject: Send 0-length IN packet to flush USB after full packet USB bulk transfers are a sequence of maximum-sized packets followed by a short packet, which signals the end of the transfer. When the last packet of the transfer would be a full-sized packet, an additional packet of zero length is sent to signal the transfer end. Signed-off-by: Keith Packard --- src/ao_usb.c | 53 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/ao_usb.c b/src/ao_usb.c index 99f0715b..22665725 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -21,6 +21,7 @@ struct ao_task __xdata ao_usb_task; static __xdata uint16_t ao_usb_in_bytes; +static __xdata uint16_t ao_usb_in_bytes_last; static __xdata uint16_t ao_usb_out_bytes; static __xdata uint8_t ao_usb_iif; static __xdata uint8_t ao_usb_running; @@ -321,13 +322,40 @@ ao_usb_ep0(void) } } +/* Wait for a free IN buffer */ +static void +ao_usb_in_wait(void) +{ + for (;;) { + USBINDEX = AO_USB_IN_EP; + if ((USBCSIL & USBCSIL_INPKT_RDY) == 0) + break; + ao_sleep(&ao_usb_in_bytes); + } +} + +/* Send the current IN packet */ +static void +ao_usb_in_send(void) +{ + USBINDEX = AO_USB_IN_EP; + USBCSIL |= USBCSIL_INPKT_RDY; + ao_usb_in_bytes_last = ao_usb_in_bytes; + ao_usb_in_bytes = 0; +} + void ao_usb_flush(void) __critical { - if (ao_usb_in_bytes) { - USBINDEX = AO_USB_IN_EP; - USBCSIL |= USBCSIL_INPKT_RDY; - ao_usb_in_bytes = 0; + if (!ao_usb_running) + return; + + /* If there are pending bytes, or if the last packet was full, + * send another IN packet + */ + if (ao_usb_in_bytes || (ao_usb_in_bytes_last == AO_USB_IN_SIZE)) { + ao_usb_in_wait(); + ao_usb_in_send(); } } @@ -336,18 +364,13 @@ ao_usb_putchar(char c) __critical { if (!ao_usb_running) return; - for (;;) { - USBINDEX = AO_USB_IN_EP; - if ((USBCSIL & USBCSIL_INPKT_RDY) == 0) - break; - ao_sleep(&ao_usb_in_bytes); - } + + ao_usb_in_wait(); + + /* Queue a byte, sending the packet when full */ USBFIFO[AO_USB_IN_EP << 1] = c; - if (++ao_usb_in_bytes == AO_USB_IN_SIZE) { - USBINDEX = AO_USB_IN_EP; - USBCSIL |= USBCSIL_INPKT_RDY; - ao_usb_in_bytes = 0; - } + if (++ao_usb_in_bytes == AO_USB_IN_SIZE) + ao_usb_in_send(); } char -- cgit v1.2.3 From 8f7ea3de7037f40b0ff462b60d503c19431ae62b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 10 Oct 2009 15:08:14 -0700 Subject: Report igniter continuity in pad/idle mode via beeper one short beep = drogue two short beeps = main three short beeps = both one long warble = neither In idle mode, it does this just once. In pad mode, it keeps testing and reporting. Signed-off-by: Keith Packard --- src/ao_report.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'src') diff --git a/src/ao_report.c b/src/ao_report.c index 14eaf428..3b469de6 100644 --- a/src/ao_report.c +++ b/src/ao_report.c @@ -97,6 +97,34 @@ ao_report_altitude(void) } } +static uint8_t +ao_report_igniter_ready(enum ao_igniter igniter) +{ + return ao_igniter_status(igniter) == ao_igniter_ready ? 1 : 0; +} + +static void +ao_report_continuity(void) __reentrant +{ + uint8_t c = (ao_report_igniter_ready(ao_igniter_drogue) | + (ao_report_igniter_ready(ao_igniter_main) << 1)); + if (c) { + while (c--) { + ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(25)); + pause(AO_MS_TO_TICKS(100)); + } + } else { + c = 10; + while (c--) { + ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(20)); + ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(20)); + } + } + c = 50; + while (c-- && ao_flight_state == ao_flight_pad) + pause(AO_MS_TO_TICKS(100)); +} + void ao_report(void) { @@ -105,6 +133,10 @@ ao_report(void) if (ao_flight_state == ao_flight_landed) ao_report_altitude(); ao_report_beep(); + if (ao_flight_state == ao_flight_idle) + ao_report_continuity(); + while (ao_flight_state == ao_flight_pad) + ao_report_continuity(); __critical { while (ao_report_state == ao_flight_state) ao_sleep(DATA_TO_XDATA(&ao_flight_state)); -- cgit v1.2.3 From 2b765728ce177e26899f6feef00bfdf6aeaf2678 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 10 Oct 2009 17:15:38 -0700 Subject: Add apogee igniter delay. Provide for a delay after apogee before the drogue charge is fired. This allows TM to be used as a back-up altimeter. Signed-off-by: Keith Packard --- src/ao.h | 3 ++- src/ao_config.c | 39 ++++++++++++++++++++++++++++++++++++--- src/ao_ignite.c | 4 ++++ 3 files changed, 42 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 4116be65..f89568f2 100644 --- a/src/ao.h +++ b/src/ao.h @@ -860,7 +860,7 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 0 +#define AO_CONFIG_MINOR 1 struct ao_config { uint8_t major; @@ -869,6 +869,7 @@ struct ao_config { int16_t accel_zero_g; uint8_t radio_channel; char callsign[AO_MAX_CALLSIGN + 1]; + uint8_t apogee_delay; }; extern __xdata struct ao_config ao_config; diff --git a/src/ao_config.c b/src/ao_config.c index 657c7a8a..021fb6f6 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -26,6 +26,7 @@ __xdata uint8_t ao_config_mutex; #define AO_CONFIG_DEFAULT_RADIO_CHANNEL 0 #define AO_CONFIG_DEFAULT_CALLSIGN "KD7SQG" #define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000 +#define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 static void _ao_config_put(void) @@ -48,9 +49,16 @@ _ao_config_get(void) memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); + ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; + ao_config_dirty = 1; + } + if (ao_config.minor < AO_CONFIG_MINOR) { + /* Fixups for major version 1 */ + if (ao_config.minor < 1) + ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; + ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } - /* deal with minor version issues here, at 0 we haven't any */ ao_config_loaded = 1; } @@ -124,7 +132,7 @@ ao_config_radio_channel_set(void) __reentrant void ao_config_main_deploy_show(void) __reentrant { - printf("Main deploy set to %d meters (%d feet)\n", + printf("Main deploy: %d meters (%d feet)\n", ao_config.main_deploy, (int16_t) ((int32_t) ao_config.main_deploy * 328 / 100)); } @@ -146,7 +154,7 @@ ao_config_main_deploy_set(void) __reentrant void ao_config_accel_zero_g_show(void) __reentrant { - printf("Accel zero g point set to %d\n", + printf("Accel zero g point: %d\n", ao_config.accel_zero_g); } @@ -189,6 +197,27 @@ ao_config_accel_zero_g_set(void) __reentrant ao_config_accel_zero_g_show(); } +void +ao_config_apogee_delay_show(void) __reentrant +{ + printf("Apogee delay: %d seconds\n", + ao_config.apogee_delay); +} + +void +ao_config_apogee_delay_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_mutex_get(&ao_config_mutex); + _ao_config_get(); + ao_config.apogee_delay = ao_cmd_lex_i; + ao_config_dirty = 1; + ao_mutex_put(&ao_config_mutex); + ao_config_apogee_delay_show(); +} + struct ao_config_var { char cmd; void (*set)(void) __reentrant; @@ -214,6 +243,8 @@ __code struct ao_config_var ao_config_vars[] = { "r Set radio channel (freq = 434.550 + channel * .1)" }, { 'c', ao_config_callsign_set, ao_config_callsign_show, "c Set callsign broadcast in each packet (8 char max)" }, + { 'd', ao_config_apogee_delay_set, ao_config_apogee_delay_show, + "d Set apogee igniter delay (in seconds)" }, { 's', ao_config_show, ao_config_show, "s Show current config values" }, { 'w', ao_config_write, ao_config_write, @@ -258,6 +289,8 @@ void ao_config_show(void) __reentrant { uint8_t cmd; + printf("Config version: %d.%d\n", + ao_config.major, ao_config.minor); for (cmd = 0; ao_config_vars[cmd].cmd != '\0'; cmd++) if (ao_config_vars[cmd].show != ao_config_vars[cmd].set) (*ao_config_vars[cmd].show)(); diff --git a/src/ao_ignite.c b/src/ao_ignite.c index be291523..8206e342 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -103,10 +103,14 @@ ao_igniter(void) __xdata enum ao_ignter igniter; __xdata enum ao_igniter_status status; + ao_config_get(); for (;;) { ao_sleep(&ao_ignition); for (igniter = ao_igniter_drogue; igniter <= ao_igniter_main; igniter++) { if (ao_ignition[igniter].request && !ao_ignition[igniter].fired) { + if (igniter == ao_igniter_drogue && ao_config.apogee_delay) + ao_delay(AO_SEC_TO_TICKS(ao_config.apogee_delay)); + ao_igniter_fire(igniter); ao_delay(AO_IGNITER_CHARGE_TIME); status = ao_igniter_status(igniter); -- cgit v1.2.3 From d709a0688eff84e25e24d755850ef045d6b0c3de Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 16 Oct 2009 12:56:45 +0900 Subject: Save some DSEG space by marking cmd functions __reentrant __reentrant causes the compiler to place args and locals on the stack instead of in the data segment. Signed-off-by: Keith Packard --- src/ao_adc.c | 4 ++-- src/ao_ee.c | 20 ++++++++++---------- src/ao_flight.c | 2 +- src/ao_gps_sirf.c | 2 +- src/ao_log.c | 2 +- src/ao_usb.c | 2 +- 6 files changed, 16 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/ao_adc.c b/src/ao_adc.c index 26209dcf..d9672671 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -61,9 +61,9 @@ ao_adc_isr(void) interrupt 1 } static void -ao_adc_dump(void) +ao_adc_dump(void) __reentrant { - __xdata struct ao_adc packet; + static __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, diff --git a/src/ao_ee.c b/src/ao_ee.c index 9b6db234..26cfb7fd 100644 --- a/src/ao_ee.c +++ b/src/ao_ee.c @@ -351,11 +351,11 @@ ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant } static void -ee_dump(void) +ee_dump(void) __reentrant { - __xdata uint8_t b; - __xdata uint16_t block; - __xdata uint8_t i; + uint8_t b; + uint16_t block; + uint8_t i; ao_cmd_hex(); block = ao_cmd_lex_i; @@ -377,13 +377,13 @@ ee_dump(void) } static void -ee_store(void) +ee_store(void) __reentrant { - __xdata uint16_t block; - __xdata uint8_t i; - __xdata uint16_t len; - __xdata uint8_t b; - __xdata uint32_t addr; + uint16_t block; + uint8_t i; + uint16_t len; + uint8_t b; + uint32_t addr; ao_cmd_hex(); block = ao_cmd_lex_i; diff --git a/src/ao_flight.c b/src/ao_flight.c index ec89e7c2..c43d0711 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -458,7 +458,7 @@ ao_flight(void) #define AO_VEL_COUNT_TO_MS(count) ((int16_t) ((count) / 2700)) static void -ao_flight_status(void) +ao_flight_status(void) __reentrant { printf("STATE: %7s accel: %d speed: %d altitude: %d main: %d\n", ao_state_names[ao_flight_state], diff --git a/src/ao_gps_sirf.c b/src/ao_gps_sirf.c index 2b3a5178..58438760 100644 --- a/src/ao_gps_sirf.c +++ b/src/ao_gps_sirf.c @@ -302,7 +302,7 @@ static const char ao_gps_set_message_rate[] = { }; void -ao_sirf_set_message_rate(uint8_t msg, uint8_t rate) +ao_sirf_set_message_rate(uint8_t msg, uint8_t rate) __reentrant { uint16_t cksum = 0x00a6; uint8_t i; diff --git a/src/ao_log.c b/src/ao_log.c index 7945ace4..b2bfbd6f 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -192,7 +192,7 @@ ao_log_stop(void) } static void -dump_log(void) +dump_log(void) __reentrant { uint8_t more; diff --git a/src/ao_usb.c b/src/ao_usb.c index 22665725..8926b9ca 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -72,7 +72,7 @@ uint8_t * __xdata ao_usb_ep0_in_data; __xdata uint8_t ao_usb_ep0_in_len; __xdata uint8_t ao_usb_ep0_in_buf[2]; __xdata uint8_t ao_usb_ep0_out_len; -__xdata uint8_t *__data ao_usb_ep0_out_data; +__xdata uint8_t *__xdata ao_usb_ep0_out_data; __xdata uint8_t ao_usb_configuration; /* Send an IN data packet */ -- cgit v1.2.3 From b657aa209b9ea3b3efd33a940283b3ba60a169af Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 16 Oct 2009 12:59:53 +0900 Subject: Add ao_wake_task and ao_exit ao_wake_task signals a specific task to wake up. ao_exit terminates the current task. Signed-off-by: Keith Packard --- src/ao.h | 8 ++++++++ src/ao_task.c | 22 +++++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index b6862a87..13271109 100644 --- a/src/ao.h +++ b/src/ao.h @@ -63,6 +63,10 @@ ao_sleep(__xdata void *wchan); void ao_wakeup(__xdata void *wchan); +/* Wake up a specific task */ +void +ao_wake_task(__xdata struct ao_task *task); + /* Yield the processor to another task */ void ao_yield(void) _naked; @@ -71,6 +75,10 @@ ao_yield(void) _naked; void ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant; +/* Terminate the current task */ +void +ao_exit(void); + /* Dump task info to console */ void ao_task_info(void); diff --git a/src/ao_task.c b/src/ao_task.c index 12b73943..136444b0 100644 --- a/src/ao_task.c +++ b/src/ao_task.c @@ -93,7 +93,9 @@ ao_yield(void) _naked push _bp _endasm; - if (ao_cur_task_index != AO_NO_TASK_INDEX) + if (ao_cur_task_index == AO_NO_TASK_INDEX) + ao_cur_task_index = ao_num_tasks-1; + else { uint8_t stack_len; __data uint8_t *stack_ptr; @@ -198,6 +200,24 @@ ao_wakeup(__xdata void *wchan) ao_tasks[i]->wchan = NULL; } +void +ao_wake_task(__xdata struct ao_task *task) +{ + task->wchan = NULL; +} + +void +ao_exit(void) +{ + uint8_t i; + ao_num_tasks--; + for (i = ao_cur_task_index; i < ao_num_tasks; i++) + ao_tasks[i] = ao_tasks[i+1]; + ao_cur_task_index = AO_NO_TASK_INDEX; + ao_yield(); + /* we'll never get back here */ +} + void ao_task_info(void) { -- cgit v1.2.3 From 7b14c3e609749f4fc00dbd660541375048535218 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Oct 2009 16:39:15 -0700 Subject: Initial packet bits. Just testing transmission --- src/Makefile | 1 + src/ao.h | 65 ++++++----- src/ao_dma.c | 6 +- src/ao_gps_skytraq.c | 6 + src/ao_monitor.c | 4 +- src/ao_packet.c | 308 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/ao_radio.c | 70 +++++++++++- src/ao_teledongle.c | 1 + src/ao_telemetrum.c | 1 + src/skytraq-cksum | 2 +- 10 files changed, 427 insertions(+), 37 deletions(-) create mode 100644 src/ao_packet.c (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 9891cdad..4575f443 100644 --- a/src/Makefile +++ b/src/Makefile @@ -44,6 +44,7 @@ ALTOS_DRIVER_SRC = \ TELE_COMMON_SRC = \ ao_gps_print.c \ + ao_packet.c \ ao_state.c # diff --git a/src/ao.h b/src/ao.h index 13271109..e86b4bf9 100644 --- a/src/ao.h +++ b/src/ao.h @@ -138,7 +138,7 @@ ao_clock_init(void); * ao_adc.c */ -#define AO_ADC_RING 64 +#define AO_ADC_RING 32 #define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) #define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) @@ -349,9 +349,15 @@ ao_cmd_init(void); * ao_dma.c */ -/* Allocate a DMA channel. the 'done' parameter will be set to 1 - * when the dma is finished and will be used to wakeup any waiters +/* Allocate a DMA channel. the 'done' parameter will be set + * when the dma is finished or aborted and will be used to + * wakeup any waiters */ + +#define AO_DMA_DONE 1 +#define AO_DMA_ABORTED 2 +#define AO_DMA_TIMEOUT 4 + uint8_t ao_dma_alloc(__xdata uint8_t * done); @@ -374,7 +380,7 @@ ao_dma_trigger(uint8_t id); /* Abort a running DMA transfer */ void -ao_dma_abort(uint8_t id); +ao_dma_abort(uint8_t id, uint8_t reason); /* DMA interrupt routine */ void @@ -796,6 +802,19 @@ ao_telemetry_init(void); * ao_radio.c */ +extern __xdata uint8_t ao_radio_dma; +extern __xdata uint8_t ao_radio_dma_done; +extern __xdata uint8_t ao_radio_mutex; + +void +ao_radio_set_telemetry(void); + +void +ao_radio_set_packet(void); + +void +ao_radio_set_rdf(void); + void ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant; @@ -805,15 +824,21 @@ struct ao_radio_recv { uint8_t status; }; -void +uint8_t ao_radio_recv(__xdata struct ao_radio_recv *recv) __reentrant; void ao_radio_rdf(int ms); +void +ao_radio_abort(uint8_t reason); + void ao_radio_rdf_abort(void); +void +ao_radio_idle(void); + void ao_radio_init(void); @@ -943,35 +968,21 @@ struct ao_fifo { * Packet-based command interface */ -#define AO_PACKET_MAX 32 -#define AO_PACKET_WIN 256 - -#define AO_PACKET_FIN (1 << 0) -#define AO_PACKET_SYN (1 << 1) -#define AO_PACKET_RST (1 << 2) -#define AO_PACKET_ACK (1 << 3) +#define AO_PACKET_MAX 8 struct ao_packet { uint8_t addr; - uint8_t flags; - uint16_t seq; - uint16_t ack; - uint16_t window; uint8_t len; + uint8_t seq; + uint8_t ack; uint8_t d[AO_PACKET_MAX]; }; -uint8_t -ao_packet_connect(uint8_t dest); - -uint8_t -ao_packet_accept(void); - -int -ao_packet_send(uint8_t *data, int len); - -int -ao_packet_recv(uint8_t *data, int len); +struct ao_packet_recv { + struct ao_packet packet; + int8_t rssi; + uint8_t status; +}; void ao_packet_init(void); diff --git a/src/ao_dma.c b/src/ao_dma.c index a4d45f14..704108e6 100644 --- a/src/ao_dma.c +++ b/src/ao_dma.c @@ -102,11 +102,13 @@ ao_dma_trigger(uint8_t id) } void -ao_dma_abort(uint8_t id) +ao_dma_abort(uint8_t id, uint8_t reason) { uint8_t mask = (1 << id); DMAARM = 0x80 | mask; DMAIRQ &= ~mask; + *(ao_dma_done[id]) |= reason; + ao_wakeup(ao_dma_done[id]); } void @@ -122,7 +124,7 @@ ao_dma_isr(void) interrupt 8 DMAIF = 0; /* Clear the completed ID */ DMAIRQ = ~mask; - *(ao_dma_done[id]) = 1; + *(ao_dma_done[id]) |= AO_DMA_DONE; ao_wakeup(ao_dma_done[id]); break; } diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index b397d975..cd5f78b9 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -46,6 +46,12 @@ static const char ao_gps_config[] = { 1, /* zda interval */ 0, /* attributes (0 = update to sram, 1 = update flash too) */ 0x09, 0x0d, 0x0a, + + 0xa0, 0xa1, 0x00, 0x03, /* length: 3 bytes */ + 0x3c, /* configure navigation mode */ + 0x00, /* 0 = car, 1 = pedestrian */ + 0x00, /* 0 = update to sram, 1 = update sram + flash */ + 0x3c, 0x0d, 0x0a, }; static void diff --git a/src/ao_monitor.c b/src/ao_monitor.c index e57ea145..9431f726 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -30,7 +30,8 @@ ao_monitor(void) for (;;) { __critical while (!ao_monitoring) ao_sleep(&ao_monitoring); - ao_radio_recv(&recv); + if (!ao_radio_recv(&recv)) + continue; state = recv.telemetry.flight_state; memcpy(callsign, recv.telemetry.callsign, AO_MAX_CALLSIGN); if (state > ao_flight_invalid) @@ -74,6 +75,7 @@ ao_set_monitor(uint8_t monitoring) { ao_monitoring = monitoring; ao_wakeup(&ao_monitoring); + ao_radio_abort(AO_DMA_ABORTED); } static void diff --git a/src/ao_packet.c b/src/ao_packet.c new file mode 100644 index 00000000..e3133b88 --- /dev/null +++ b/src/ao_packet.c @@ -0,0 +1,308 @@ +/* + * 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" + +static __xdata struct ao_packet_recv rx_packet; +static __xdata struct ao_packet tx_packet; +static __xdata char tx_data[AO_PACKET_MAX]; +static __xdata char rx_data[AO_PACKET_MAX]; +static __pdata uint8_t rx_len, rx_used, tx_used; +static __pdata uint8_t rx_seq; + +static __xdata uint16_t ao_packet_timer_delay; +static __xdata uint8_t ao_packet_timer_cancelled; + +static __xdata struct ao_task ao_packet_task; +static __xdata struct ao_task ao_packet_timer_task; +static __xdata uint8_t ao_packet_enable; +static __xdata uint8_t ao_packet_master_sleeping; + +void +ao_packet_timer(void) __reentrant +{ + uint16_t delay; + + while (ao_packet_enable) { + + /* wait until the timer task is needed + */ + while (!ao_packet_timer_delay && ao_packet_enable) + ao_sleep(&ao_packet_timer_delay); + + delay = ao_packet_timer_delay; + ao_packet_timer_delay = 0; + + /* pause waiting for either a timeout or + * a timer cancel + */ + ao_delay(delay); + + /* if not canceled, abort the receive + */ + if (!ao_packet_timer_cancelled) { + printf ("packet timeout\n"); flush(); + ao_radio_abort(AO_DMA_TIMEOUT); + } + } + ao_exit(); +} + +void +ao_packet_timer_set(uint16_t delay) +{ + ao_packet_timer_delay = delay; + ao_packet_timer_cancelled = 0; + ao_wakeup(&ao_packet_timer_delay); +} + +void +ao_packet_timer_cancel(void) +{ + ao_packet_timer_cancelled = 1; + ao_packet_timer_delay = 0; + ao_wake_task(&ao_packet_timer_task); +} + +void +ao_packet_send(void) +{ + ao_config_get(); + ao_mutex_get(&ao_radio_mutex); + ao_radio_idle(); + RF_CHANNR = ao_config.radio_channel; + ao_dma_set_transfer(ao_radio_dma, + &tx_packet, + &RFDXADDR, + sizeof (struct ao_packet), + 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; + __critical while (!ao_radio_dma_done) + ao_sleep(&ao_radio_dma_done); + ao_mutex_put(&ao_radio_mutex); +} + +uint8_t +ao_packet_recv(void) +{ + uint8_t dma_done; + + ao_config_get(); + ao_mutex_get(&ao_radio_mutex); + ao_radio_idle(); + RF_CHANNR = ao_config.radio_channel; + ao_dma_set_transfer(ao_radio_dma, + &RFDXADDR, + &rx_packet, + sizeof (struct ao_packet_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; + __critical while (!ao_radio_dma_done) + ao_sleep(&ao_radio_dma_done); + dma_done = ao_radio_dma_done; + ao_mutex_put(&ao_radio_mutex); + + if (dma_done & AO_DMA_DONE) { + printf ("rssi %d status %x\n", rx_packet.rssi, rx_packet.status); flush(); + if (!(rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) { + printf ("bad crc\n"); flush(); +// return AO_DMA_ABORTED; + } + if (rx_packet.packet.len) { + if (rx_packet.packet.seq == rx_seq + 1 && rx_used == rx_len) + { + memcpy(rx_data, rx_packet.packet.d, rx_packet.packet.len); + rx_used = 0; + rx_len = rx_packet.packet.len; + rx_seq = rx_packet.packet.seq; + tx_packet.ack = rx_seq; + ao_wakeup(&rx_data); + } + } + if (rx_packet.packet.ack == tx_packet.seq) { + tx_packet.len = 0; + ao_wakeup(&tx_packet); + } + } + return dma_done; +} + +void +ao_packet_slave(void) +{ + tx_packet.addr = ao_serial_number; + ao_radio_set_packet(); + while (ao_packet_enable) { + ao_packet_recv(); + ao_led_toggle(AO_LED_GREEN); + ao_delay(AO_MS_TO_TICKS(100)); + ao_packet_send(); + ao_led_toggle(AO_LED_RED); + } + ao_exit(); +} + +/* Thread for the master side of the packet link */ + +void +ao_packet_master(void) +{ + uint8_t status; + tx_packet.addr = ao_serial_number; + ao_radio_set_packet(); + while (ao_packet_enable) { + ao_delay(AO_MS_TO_TICKS(100)); + ao_packet_send(); + ao_led_toggle(AO_LED_RED); + ao_packet_timer_set(AO_MS_TO_TICKS(1000)); + status = ao_packet_recv(); + ao_packet_timer_cancel(); + if (status & AO_DMA_DONE) { + ao_led_toggle(AO_LED_GREEN); + ao_packet_master_sleeping = 1; + ao_sleep(AO_MS_TO_TICKS(1000)); + ao_packet_master_sleeping = 0; + } + } + ao_exit(); +} + +void +ao_packet_flush(void) +{ + if (!tx_used) + return; + + /* Wait for previous packet to be received + */ + while (tx_packet.len) + ao_sleep(&tx_packet); + + /* Prepare next packet + */ + if (tx_used) { + memcpy(&tx_packet.d, tx_data, tx_used); + tx_packet.len = tx_used; + tx_packet.seq++; + tx_used = 0; + + if (ao_packet_master_sleeping) + ao_wake_task(&ao_packet_task); + } +} + +void +ao_packet_putchar(char c) +{ + while (tx_used == AO_PACKET_MAX && ao_packet_enable) + ao_packet_flush(); + + if (ao_packet_enable) + tx_data[tx_used++] = c; +} + +char +ao_packet_getchar(void) __critical +{ + while (rx_used == rx_len && ao_packet_enable) + ao_sleep(&rx_data); + + if (!ao_packet_enable) + return 0; + + return rx_data[rx_used++]; +} + +static void +ao_packet_echo(void) __reentrant +{ + uint8_t c; + while (ao_packet_enable) { + c = ao_packet_getchar(); + if (ao_packet_enable) + putchar(c); + } + ao_exit(); +} + +static __xdata struct ao_task ao_packet_echo_task; + +static void +ao_packet_forward(void) __reentrant +{ + char c; + ao_packet_enable = 1; + ao_cmd_white(); + + ao_radio_set_packet(); + if (ao_cmd_lex_c == 'm') { + while ((c = getchar()) != '~') + ao_packet_send(); + } else { + for (;;) { + ao_packet_recv(); + ao_led_toggle(AO_LED_GREEN); + if (rx_packet.packet.d[0] == (uint8_t) '@') + break; + } + } + ao_packet_enable = 0; + return; +#if 0 + if (ao_cmd_lex_c == 'm') { + ao_add_task(&ao_packet_timer_task, ao_packet_timer, "timeout"); + ao_add_task(&ao_packet_task, ao_packet_master, "master"); + } + else + ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); + ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); + while ((c = getchar()) != '~') { + ao_packet_putchar(c); + if (c == '\n') + ao_packet_flush(); + } + ao_packet_enable = 0; + ao_radio_abort(AO_DMA_ABORTED); + while (ao_packet_echo_task.wchan || ao_packet_task.wchan) { + ao_wake_task(&ao_packet_echo_task); + ao_wake_task(&ao_packet_task); + } +#endif +} + +__code struct ao_cmds ao_packet_cmds[] = { + { 'p', ao_packet_forward, "p {m|s} Remote packet link. m=master, s=slave" }, + { 0, ao_packet_forward, NULL }, +}; + +void +ao_packet_init(void) +{ + ao_cmd_register(&ao_packet_cmds[0]); +} diff --git a/src/ao_radio.c b/src/ao_radio.c index a7fa682e..2dfa9279 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -255,11 +255,62 @@ static __code uint8_t telemetry_setup[] = { RF_PKTCTRL0_LENGTH_CONFIG_FIXED), }; +static __code uint8_t packet_setup[] = { + 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_DEVIATN_OFF, ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | + (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), + + /* max packet length */ + RF_PKTLEN_OFF, sizeof (struct ao_packet), + 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), +}; + + +void +ao_radio_set_telemetry(void) +{ + uint8_t i; + for (i = 0; i < sizeof (telemetry_setup); i += 2) + RF[telemetry_setup[i]] = telemetry_setup[i+1]; +} + +void +ao_radio_set_packet(void) +{ + uint8_t i; + for (i = 0; i < sizeof (packet_setup); i += 2) + RF[packet_setup[i]] = packet_setup[i+1]; +} + +void +ao_radio_set_rdf(void) +{ + uint8_t i; + for (i = 0; i < sizeof (rdf_setup); i += 2) + RF[rdf_setup[i]] = rdf_setup[i+1]; +} + __xdata uint8_t ao_radio_dma; __xdata uint8_t ao_radio_dma_done; __xdata uint8_t ao_radio_mutex; -static void +void ao_radio_idle(void) { if (RF_MARCSTATE != RF_MARCSTATE_IDLE) @@ -295,7 +346,7 @@ ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant ao_mutex_put(&ao_radio_mutex); } -void +uint8_t ao_radio_recv(__xdata struct ao_radio_recv *radio) __reentrant { ao_config_get(); @@ -317,6 +368,7 @@ ao_radio_recv(__xdata struct ao_radio_recv *radio) __reentrant __critical while (!ao_radio_dma_done) ao_sleep(&ao_radio_dma_done); ao_mutex_put(&ao_radio_mutex); + return (ao_radio_dma_done & AO_DMA_DONE); } __xdata ao_radio_rdf_running; @@ -367,13 +419,18 @@ ao_radio_rdf(int ms) ao_mutex_put(&ao_radio_mutex); } +void +ao_radio_abort(uint8_t reason) +{ + ao_dma_abort(ao_radio_dma, reason); + ao_radio_idle(); +} + void ao_radio_rdf_abort(void) { - if (ao_radio_rdf_running) { - ao_dma_abort(ao_radio_dma); - ao_radio_idle(); - } + if (ao_radio_rdf_running) + ao_radio_abort(AO_DMA_ABORTED); } void @@ -382,6 +439,7 @@ 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_set_telemetry(); ao_radio_dma_done = 1; ao_radio_dma = ao_dma_alloc(&ao_radio_dma_done); } diff --git a/src/ao_teledongle.c b/src/ao_teledongle.c index d7b4b75a..98642180 100644 --- a/src/ao_teledongle.c +++ b/src/ao_teledongle.c @@ -33,6 +33,7 @@ main(void) ao_monitor_init(AO_LED_GREEN, TRUE); ao_rssi_init(AO_LED_RED); ao_radio_init(); + ao_packet_init(); ao_config_init(); ao_start_scheduler(); } diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 1dbacf89..07737f30 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -40,6 +40,7 @@ main(void) ao_gps_report_init(); ao_telemetry_init(); ao_radio_init(); + ao_packet_init(); ao_igniter_init(); ao_config_init(); ao_start_scheduler(); diff --git a/src/skytraq-cksum b/src/skytraq-cksum index e4960bff..ab0464a7 100644 --- a/src/skytraq-cksum +++ b/src/skytraq-cksum @@ -32,7 +32,7 @@ void main() } } } - printf("\t0xa0, 0xa1, 0x02x, 0x%02x,\t\t/* length: %d bytes */\n", + printf("\t0xa0, 0xa1, 0x%02x, 0x%02x,\t\t/* length: %d bytes */\n", dim(msg) >> 8, dim(msg) & 0xff, dim(msg)); for (int i = 0; i < dim(input); i++) printf("%s\n", input[i]); -- cgit v1.2.3 From 9b31f07fe3556896b3e997bba156e30ef5777a80 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Oct 2009 23:43:52 -0700 Subject: Add radio carrier command --- src/ao_radio.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_radio.c b/src/ao_radio.c index 2dfa9279..55a0c297 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -430,9 +430,29 @@ void ao_radio_rdf_abort(void) { if (ao_radio_rdf_running) - ao_radio_abort(AO_DMA_ABORTED); + ao_radio_abort(); } +/* Output carrier */ +void +ao_radio_test(void) +{ + ao_config_get(); + ao_mutex_get(&ao_radio_mutex); + ao_radio_idle(); + printf ("Hit a character to stop..."); flush(); + RFST = RFST_STX; + getchar(); + ao_radio_idle(); + ao_mutex_put(&ao_radio_mutex); + putchar('\n'); +} + +__code struct ao_cmds ao_radio_cmds[] = { + { 'C', ao_radio_test, "C Radio carrier test" }, + { 0, ao_radio_test, NULL }, +}; + void ao_radio_init(void) { @@ -442,4 +462,5 @@ ao_radio_init(void) ao_radio_set_telemetry(); ao_radio_dma_done = 1; ao_radio_dma = ao_dma_alloc(&ao_radio_dma_done); + ao_cmd_register(&ao_radio_cmds[0]); } -- cgit v1.2.3 From 251b0971f049cbf2f8db79a32729d47441ce65f3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Oct 2009 23:45:43 -0700 Subject: Wait for TX to finish sending data --- src/ao.h | 4 ++++ src/ao_radio.c | 30 ++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index e86b4bf9..84e92f35 100644 --- a/src/ao.h +++ b/src/ao.h @@ -804,8 +804,12 @@ ao_telemetry_init(void); extern __xdata uint8_t ao_radio_dma; extern __xdata uint8_t ao_radio_dma_done; +extern __xdata uint8_t ao_radio_done; extern __xdata uint8_t ao_radio_mutex; +void +ao_radio_general_isr(void) interrupt 16; + void ao_radio_set_telemetry(void); diff --git a/src/ao_radio.c b/src/ao_radio.c index 55a0c297..43899f44 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -281,6 +281,24 @@ static __code uint8_t packet_setup[] = { RF_PKTCTRL0_LENGTH_CONFIG_FIXED), }; +__xdata uint8_t ao_radio_dma; +__xdata uint8_t ao_radio_dma_done; +__xdata uint8_t ao_radio_done; +__xdata uint8_t ao_radio_mutex; + +void +ao_radio_general_isr(void) interrupt 16 +{ + S1CON &= ~0x03; + if (RFIF & RFIF_IM_TIMEOUT) { + ao_dma_abort(ao_radio_dma); + RFIF &= ~ RFIF_IM_TIMEOUT; + } else if (RFIF & RFIF_IM_DONE) { + ao_radio_done = 1; + ao_wakeup(&ao_radio_done); + RFIF &= ~RFIF_IM_DONE; + } +} void ao_radio_set_telemetry(void) @@ -306,10 +324,6 @@ ao_radio_set_rdf(void) RF[rdf_setup[i]] = rdf_setup[i+1]; } -__xdata uint8_t ao_radio_dma; -__xdata uint8_t ao_radio_dma_done; -__xdata uint8_t ao_radio_mutex; - void ao_radio_idle(void) { @@ -328,6 +342,7 @@ ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant ao_config_get(); ao_mutex_get(&ao_radio_mutex); ao_radio_idle(); + ao_radio_done = 0; RF_CHANNR = ao_config.radio_channel; ao_dma_set_transfer(ao_radio_dma, telemetry, @@ -341,8 +356,8 @@ ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant DMA_CFG1_PRIORITY_HIGH); ao_dma_start(ao_radio_dma); RFST = RFST_STX; - __critical while (!ao_radio_dma_done) - ao_sleep(&ao_radio_dma_done); + __critical while (!ao_radio_done) + ao_sleep(&ao_radio_done); ao_mutex_put(&ao_radio_mutex); } @@ -462,5 +477,8 @@ ao_radio_init(void) ao_radio_set_telemetry(); ao_radio_dma_done = 1; ao_radio_dma = ao_dma_alloc(&ao_radio_dma_done); + RFIF = 0; + RFIM = RFIM_IM_TIMEOUT|RFIM_IM_DONE; + IEN2 |= IEN2_RFIE; ao_cmd_register(&ao_radio_cmds[0]); } -- cgit v1.2.3 From 73db30b2f9128c37dc7fa075793a8862814ce044 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Oct 2009 23:46:21 -0700 Subject: Add ao_alarm --- src/ao.h | 13 +++++++++++-- src/ao_task.c | 23 ++++++++++++++++++++++- 2 files changed, 33 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 84e92f35..b90befe5 100644 --- a/src/ao.h +++ b/src/ao.h @@ -40,6 +40,7 @@ /* An AltOS task */ struct ao_task { __xdata void *wchan; /* current wait channel (NULL if running) */ + uint16_t alarm; /* abort ao_sleep time */ uint8_t stack_count; /* amount of saved stack */ uint8_t task_id; /* index in the task array */ __code char *name; /* task name */ @@ -55,8 +56,12 @@ extern __xdata struct ao_task *__data ao_cur_task; ao_task.c */ -/* Suspend the current task until wchan is awoken */ -void +/* Suspend the current task until wchan is awoken. + * returns: + * 0 on normal wake + * 1 on alarm + */ +uint8_t ao_sleep(__xdata void *wchan); /* Wake all tasks sleeping on wchan */ @@ -67,6 +72,10 @@ ao_wakeup(__xdata void *wchan); void ao_wake_task(__xdata struct ao_task *task); +/* set an alarm to go off in 'delay' ticks */ +void +ao_alarm(uint16_t delay); + /* Yield the processor to another task */ void ao_yield(void) _naked; diff --git a/src/ao_task.c b/src/ao_task.c index 136444b0..14aa84c8 100644 --- a/src/ao_task.c +++ b/src/ao_task.c @@ -129,6 +129,13 @@ ao_yield(void) _naked break; } + /* Check if the alarm is set for a time which has passed */ + if (ao_cur_task->alarm && + (int16_t) (ao_time() - ao_cur_task->alarm) >= 0) { + ao_cur_task_index = ao_next_task_index; + break; + } + /* Enter lower power mode when there isn't anything to do */ if (ao_next_task_index == ao_cur_task_index) PCON = PCON_IDLE; @@ -181,13 +188,20 @@ ao_yield(void) _naked _endasm; } -void +uint8_t ao_sleep(__xdata void *wchan) { __critical { ao_cur_task->wchan = wchan; } ao_yield(); + if (ao_cur_task->wchan) { + ao_cur_task->wchan = NULL; + ao_cur_task->alarm = 0; + return 1; + } + ao_cur_task->alarm = 0; + return 0; } void @@ -200,6 +214,13 @@ ao_wakeup(__xdata void *wchan) ao_tasks[i]->wchan = NULL; } +void +ao_alarm(uint16_t delay) +{ + if (!(ao_cur_task->alarm = ao_time() + delay)) + ao_cur_task->alarm = 1; +} + void ao_wake_task(__xdata struct ao_task *task) { -- cgit v1.2.3 From b428faf74ae145126ec1da972028fcfe0b4b2b18 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Oct 2009 23:48:36 -0700 Subject: Remove reason from ao_dma_abort --- src/ao.h | 5 ++--- src/ao_dma.c | 4 ++-- src/ao_monitor.c | 2 +- src/ao_packet.c | 2 +- src/ao_radio.c | 4 ++-- 5 files changed, 8 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index b90befe5..2e2fb589 100644 --- a/src/ao.h +++ b/src/ao.h @@ -365,7 +365,6 @@ ao_cmd_init(void); #define AO_DMA_DONE 1 #define AO_DMA_ABORTED 2 -#define AO_DMA_TIMEOUT 4 uint8_t ao_dma_alloc(__xdata uint8_t * done); @@ -389,7 +388,7 @@ ao_dma_trigger(uint8_t id); /* Abort a running DMA transfer */ void -ao_dma_abort(uint8_t id, uint8_t reason); +ao_dma_abort(uint8_t id); /* DMA interrupt routine */ void @@ -844,7 +843,7 @@ void ao_radio_rdf(int ms); void -ao_radio_abort(uint8_t reason); +ao_radio_abort(void); void ao_radio_rdf_abort(void); diff --git a/src/ao_dma.c b/src/ao_dma.c index 704108e6..110138b5 100644 --- a/src/ao_dma.c +++ b/src/ao_dma.c @@ -102,12 +102,12 @@ ao_dma_trigger(uint8_t id) } void -ao_dma_abort(uint8_t id, uint8_t reason) +ao_dma_abort(uint8_t id) { uint8_t mask = (1 << id); DMAARM = 0x80 | mask; DMAIRQ &= ~mask; - *(ao_dma_done[id]) |= reason; + *(ao_dma_done[id]) |= AO_DMA_ABORTED; ao_wakeup(ao_dma_done[id]); } diff --git a/src/ao_monitor.c b/src/ao_monitor.c index 9431f726..d0c1da34 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -75,7 +75,7 @@ ao_set_monitor(uint8_t monitoring) { ao_monitoring = monitoring; ao_wakeup(&ao_monitoring); - ao_radio_abort(AO_DMA_ABORTED); + ao_radio_abort(); } static void diff --git a/src/ao_packet.c b/src/ao_packet.c index e3133b88..ccd83785 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -288,7 +288,7 @@ ao_packet_forward(void) __reentrant ao_packet_flush(); } ao_packet_enable = 0; - ao_radio_abort(AO_DMA_ABORTED); + ao_radio_abort(); while (ao_packet_echo_task.wchan || ao_packet_task.wchan) { ao_wake_task(&ao_packet_echo_task); ao_wake_task(&ao_packet_task); diff --git a/src/ao_radio.c b/src/ao_radio.c index 43899f44..c7c8dc8d 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -435,9 +435,9 @@ ao_radio_rdf(int ms) } void -ao_radio_abort(uint8_t reason) +ao_radio_abort(void) { - ao_dma_abort(ao_radio_dma, reason); + ao_dma_abort(ao_radio_dma); ao_radio_idle(); } -- cgit v1.2.3 From c5ec6fcfa1bd17aad0f85d2fbe603f1d125836e6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Oct 2009 23:50:54 -0700 Subject: Switch packet code from timer thread to ao_alarm --- src/ao_packet.c | 89 +++++++++------------------------------------------------ 1 file changed, 14 insertions(+), 75 deletions(-) (limited to 'src') diff --git a/src/ao_packet.c b/src/ao_packet.c index ccd83785..7d277d70 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -24,60 +24,10 @@ static __xdata char rx_data[AO_PACKET_MAX]; static __pdata uint8_t rx_len, rx_used, tx_used; static __pdata uint8_t rx_seq; -static __xdata uint16_t ao_packet_timer_delay; -static __xdata uint8_t ao_packet_timer_cancelled; - static __xdata struct ao_task ao_packet_task; -static __xdata struct ao_task ao_packet_timer_task; static __xdata uint8_t ao_packet_enable; static __xdata uint8_t ao_packet_master_sleeping; -void -ao_packet_timer(void) __reentrant -{ - uint16_t delay; - - while (ao_packet_enable) { - - /* wait until the timer task is needed - */ - while (!ao_packet_timer_delay && ao_packet_enable) - ao_sleep(&ao_packet_timer_delay); - - delay = ao_packet_timer_delay; - ao_packet_timer_delay = 0; - - /* pause waiting for either a timeout or - * a timer cancel - */ - ao_delay(delay); - - /* if not canceled, abort the receive - */ - if (!ao_packet_timer_cancelled) { - printf ("packet timeout\n"); flush(); - ao_radio_abort(AO_DMA_TIMEOUT); - } - } - ao_exit(); -} - -void -ao_packet_timer_set(uint16_t delay) -{ - ao_packet_timer_delay = delay; - ao_packet_timer_cancelled = 0; - ao_wakeup(&ao_packet_timer_delay); -} - -void -ao_packet_timer_cancel(void) -{ - ao_packet_timer_cancelled = 1; - ao_packet_timer_delay = 0; - ao_wake_task(&ao_packet_timer_task); -} - void ao_packet_send(void) { @@ -124,7 +74,10 @@ ao_packet_recv(void) ao_dma_start(ao_radio_dma); RFST = RFST_SRX; __critical while (!ao_radio_dma_done) - ao_sleep(&ao_radio_dma_done); + if (ao_sleep(&ao_radio_dma_done) != 0) { + printf("recv timeout\n"); flush(); + ao_radio_abort(); + } dma_done = ao_radio_dma_done; ao_mutex_put(&ao_radio_mutex); @@ -174,19 +127,22 @@ void ao_packet_master(void) { uint8_t status; - tx_packet.addr = ao_serial_number; + ao_radio_set_packet(); + tx_packet.addr = ao_serial_number; + tx_packet.len = AO_PACKET_SYN; while (ao_packet_enable) { + ao_led_on(AO_LED_RED); ao_delay(AO_MS_TO_TICKS(100)); ao_packet_send(); - ao_led_toggle(AO_LED_RED); - ao_packet_timer_set(AO_MS_TO_TICKS(1000)); + ao_led_off(AO_LED_RED); + ao_led_on(AO_LED_GREEN); + ao_alarm(AO_MS_TO_TICKS(1000)); status = ao_packet_recv(); - ao_packet_timer_cancel(); + ao_led_off(AO_LED_GREEN); if (status & AO_DMA_DONE) { - ao_led_toggle(AO_LED_GREEN); ao_packet_master_sleeping = 1; - ao_sleep(AO_MS_TO_TICKS(1000)); + ao_delay(AO_MS_TO_TICKS(1000)); ao_packet_master_sleeping = 0; } } @@ -260,25 +216,8 @@ ao_packet_forward(void) __reentrant ao_packet_enable = 1; ao_cmd_white(); - ao_radio_set_packet(); - if (ao_cmd_lex_c == 'm') { - while ((c = getchar()) != '~') - ao_packet_send(); - } else { - for (;;) { - ao_packet_recv(); - ao_led_toggle(AO_LED_GREEN); - if (rx_packet.packet.d[0] == (uint8_t) '@') - break; - } - } - ao_packet_enable = 0; - return; -#if 0 - if (ao_cmd_lex_c == 'm') { - ao_add_task(&ao_packet_timer_task, ao_packet_timer, "timeout"); + if (ao_cmd_lex_c == 'm') ao_add_task(&ao_packet_task, ao_packet_master, "master"); - } else ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); -- cgit v1.2.3 From d46797e5c08d4955d516458185e2cfb51ee2d567 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Oct 2009 23:51:38 -0700 Subject: Use ao_radio_done to wait for TX to completely finish with packet --- src/ao_packet.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao_packet.c b/src/ao_packet.c index 7d277d70..da33bb4c 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -34,6 +34,7 @@ ao_packet_send(void) ao_config_get(); ao_mutex_get(&ao_radio_mutex); ao_radio_idle(); + ao_radio_done = 0; RF_CHANNR = ao_config.radio_channel; ao_dma_set_transfer(ao_radio_dma, &tx_packet, @@ -47,8 +48,8 @@ ao_packet_send(void) DMA_CFG1_PRIORITY_HIGH); ao_dma_start(ao_radio_dma); RFST = RFST_STX; - __critical while (!ao_radio_dma_done) - ao_sleep(&ao_radio_dma_done); + __critical while (!ao_radio_done) + ao_sleep(&ao_radio_done); ao_mutex_put(&ao_radio_mutex); } -- cgit v1.2.3 From bf65e0b2a1299b49adc2d339ab9d9c7599aded9e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Oct 2009 23:52:22 -0700 Subject: Send SYN packet to set sequence numbers --- src/ao.h | 1 + src/ao_packet.c | 23 +++++++++++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 2e2fb589..e2f137bd 100644 --- a/src/ao.h +++ b/src/ao.h @@ -981,6 +981,7 @@ struct ao_fifo { */ #define AO_PACKET_MAX 8 +#define AO_PACKET_SYN 0xff struct ao_packet { uint8_t addr; diff --git a/src/ao_packet.c b/src/ao_packet.c index da33bb4c..620cd001 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -83,14 +83,22 @@ ao_packet_recv(void) ao_mutex_put(&ao_radio_mutex); if (dma_done & AO_DMA_DONE) { - printf ("rssi %d status %x\n", rx_packet.rssi, rx_packet.status); flush(); if (!(rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) { printf ("bad crc\n"); flush(); -// return AO_DMA_ABORTED; + return AO_DMA_ABORTED; } - if (rx_packet.packet.len) { + if (rx_packet.packet.len == AO_PACKET_SYN) { + rx_seq = rx_packet.packet.seq; + tx_packet.seq = rx_packet.packet.ack; + tx_packet.ack = rx_seq; + } else if (rx_packet.packet.len) { if (rx_packet.packet.seq == rx_seq + 1 && rx_used == rx_len) { + printf ("rx len %3d seq %3d ack %3d\n", + rx_packet.packet.len, + rx_packet.packet.seq, + rx_packet.packet.ack); + flush(); memcpy(rx_data, rx_packet.packet.d, rx_packet.packet.len); rx_used = 0; rx_len = rx_packet.packet.len; @@ -110,14 +118,17 @@ ao_packet_recv(void) void ao_packet_slave(void) { - tx_packet.addr = ao_serial_number; ao_radio_set_packet(); + tx_packet.addr = ao_serial_number; + tx_packet.len = AO_PACKET_SYN; while (ao_packet_enable) { + ao_led_on(AO_LED_GREEN); ao_packet_recv(); - ao_led_toggle(AO_LED_GREEN); + ao_led_off(AO_LED_GREEN); + ao_led_on(AO_LED_RED); ao_delay(AO_MS_TO_TICKS(100)); ao_packet_send(); - ao_led_toggle(AO_LED_RED); + ao_led_off(AO_LED_RED); } ao_exit(); } -- cgit v1.2.3 From 6a7aa1810a90a9216160aec55ec4bd02b3240e1b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Oct 2009 23:52:44 -0700 Subject: Add RFIM register --- src/cc1111.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/cc1111.h b/src/cc1111.h index 87b14485..ee4c9f09 100644 --- a/src/cc1111.h +++ b/src/cc1111.h @@ -882,6 +882,16 @@ sfr at 0xE9 RFIF; #define RFIF_IM_CCA (1 << 1) #define RFIF_IM_SFD (1 << 0) +sfr at 0x91 RFIM; +#define RFIM_IM_TXUNF (1 << 7) +#define RFIM_IM_RXOVF (1 << 6) +#define RFIM_IM_TIMEOUT (1 << 5) +#define RFIM_IM_DONE (1 << 4) +#define RFIM_IM_CS (1 << 3) +#define RFIM_IM_PQT (1 << 2) +#define RFIM_IM_CCA (1 << 1) +#define RFIM_IM_SFD (1 << 0) + sfr at 0xE1 RFST; #define RFST_SFSTXON 0x00 -- cgit v1.2.3 From 4f7ed9ff484778381db647c27d2a34d0cadec41e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Oct 2009 23:53:03 -0700 Subject: Do more flushing in packet test code --- src/ao_packet.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/ao_packet.c b/src/ao_packet.c index 620cd001..0dce326c 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -198,8 +198,10 @@ ao_packet_putchar(char c) char ao_packet_getchar(void) __critical { - while (rx_used == rx_len && ao_packet_enable) + while (rx_used == rx_len && ao_packet_enable) { + flush(); ao_sleep(&rx_data); + } if (!ao_packet_enable) return 0; @@ -213,8 +215,11 @@ ao_packet_echo(void) __reentrant uint8_t c; while (ao_packet_enable) { c = ao_packet_getchar(); - if (ao_packet_enable) + if (ao_packet_enable) { putchar(c); + if (c == (uint8_t) '\n') + flush(); + } } ao_exit(); } @@ -233,18 +238,14 @@ ao_packet_forward(void) __reentrant else ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); - while ((c = getchar()) != '~') { + while ((c = getchar()) != '~') ao_packet_putchar(c); - if (c == '\n') - ao_packet_flush(); - } ao_packet_enable = 0; ao_radio_abort(); while (ao_packet_echo_task.wchan || ao_packet_task.wchan) { ao_wake_task(&ao_packet_echo_task); ao_wake_task(&ao_packet_task); } -#endif } __code struct ao_cmds ao_packet_cmds[] = { -- cgit v1.2.3 From 442b1ef18c8320d4e5329dc92bb5268a36058fc5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 31 Oct 2009 01:19:41 -0700 Subject: Use ao_alarm for ao_delay so it can be easily interrupted --- src/ao_timer.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ao_timer.c b/src/ao_timer.c index 78c6e063..d7603435 100644 --- a/src/ao_timer.c +++ b/src/ao_timer.c @@ -24,13 +24,13 @@ uint16_t ao_time(void) __critical return ao_tick_count; } +static __xdata uint8_t ao_forever; + void ao_delay(uint16_t ticks) { - uint16_t until = ao_time() + ticks; - - while ((int16_t) (until - ao_time()) > 0) - ao_sleep(DATA_TO_XDATA(&ao_tick_count)); + ao_alarm(ticks); + ao_sleep(&ao_forever); } #define T1_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ -- cgit v1.2.3 From cd0d495d7ef276956e730196476daa70a4359918 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 31 Oct 2009 01:20:26 -0700 Subject: Poke master to speed up packet rate when things are busy --- src/ao.h | 2 +- src/ao_packet.c | 71 +++++++++++++++++++++++++-------------------------------- 2 files changed, 32 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index e2f137bd..aeceb870 100644 --- a/src/ao.h +++ b/src/ao.h @@ -981,7 +981,7 @@ struct ao_fifo { */ #define AO_PACKET_MAX 8 -#define AO_PACKET_SYN 0xff +#define AO_PACKET_SYN (uint8_t) 0xff struct ao_packet { uint8_t addr; diff --git a/src/ao_packet.c b/src/ao_packet.c index 0dce326c..ba559512 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -31,8 +31,16 @@ static __xdata uint8_t ao_packet_master_sleeping; void ao_packet_send(void) { + ao_led_on(AO_LED_RED); ao_config_get(); ao_mutex_get(&ao_radio_mutex); + if (tx_used && tx_packet.len == 0) { + memcpy(&tx_packet.d, tx_data, tx_used); + tx_packet.len = tx_used; + tx_packet.seq++; + tx_used = 0; + ao_wakeup(&tx_data); + } ao_radio_idle(); ao_radio_done = 0; RF_CHANNR = ao_config.radio_channel; @@ -51,6 +59,7 @@ ao_packet_send(void) __critical while (!ao_radio_done) ao_sleep(&ao_radio_done); ao_mutex_put(&ao_radio_mutex); + ao_led_off(AO_LED_RED); } uint8_t @@ -58,6 +67,7 @@ ao_packet_recv(void) { uint8_t dma_done; + ao_led_on(AO_LED_GREEN); ao_config_get(); ao_mutex_get(&ao_radio_mutex); ao_radio_idle(); @@ -75,30 +85,28 @@ ao_packet_recv(void) ao_dma_start(ao_radio_dma); RFST = RFST_SRX; __critical while (!ao_radio_dma_done) - if (ao_sleep(&ao_radio_dma_done) != 0) { - printf("recv timeout\n"); flush(); + if (ao_sleep(&ao_radio_dma_done) != 0) ao_radio_abort(); - } dma_done = ao_radio_dma_done; ao_mutex_put(&ao_radio_mutex); + ao_led_off(AO_LED_GREEN); if (dma_done & AO_DMA_DONE) { - if (!(rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) { - printf ("bad crc\n"); flush(); + if (!(rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) return AO_DMA_ABORTED; - } if (rx_packet.packet.len == AO_PACKET_SYN) { rx_seq = rx_packet.packet.seq; tx_packet.seq = rx_packet.packet.ack; tx_packet.ack = rx_seq; } else if (rx_packet.packet.len) { - if (rx_packet.packet.seq == rx_seq + 1 && rx_used == rx_len) - { + if (rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) && rx_used == rx_len) { +#if 0 printf ("rx len %3d seq %3d ack %3d\n", rx_packet.packet.len, rx_packet.packet.seq, rx_packet.packet.ack); flush(); +#endif memcpy(rx_data, rx_packet.packet.d, rx_packet.packet.len); rx_used = 0; rx_len = rx_packet.packet.len; @@ -122,13 +130,8 @@ ao_packet_slave(void) tx_packet.addr = ao_serial_number; tx_packet.len = AO_PACKET_SYN; while (ao_packet_enable) { - ao_led_on(AO_LED_GREEN); ao_packet_recv(); - ao_led_off(AO_LED_GREEN); - ao_led_on(AO_LED_RED); - ao_delay(AO_MS_TO_TICKS(100)); ao_packet_send(); - ao_led_off(AO_LED_RED); } ao_exit(); } @@ -144,15 +147,13 @@ ao_packet_master(void) tx_packet.addr = ao_serial_number; tx_packet.len = AO_PACKET_SYN; while (ao_packet_enable) { - ao_led_on(AO_LED_RED); - ao_delay(AO_MS_TO_TICKS(100)); ao_packet_send(); - ao_led_off(AO_LED_RED); - ao_led_on(AO_LED_GREEN); - ao_alarm(AO_MS_TO_TICKS(1000)); + ao_alarm(AO_MS_TO_TICKS(100)); status = ao_packet_recv(); - ao_led_off(AO_LED_GREEN); if (status & AO_DMA_DONE) { + /* if we can transmit data, do so */ + if (tx_used && tx_packet.len == 0) + continue; ao_packet_master_sleeping = 1; ao_delay(AO_MS_TO_TICKS(1000)); ao_packet_master_sleeping = 0; @@ -164,32 +165,20 @@ ao_packet_master(void) void ao_packet_flush(void) { - if (!tx_used) - return; - - /* Wait for previous packet to be received - */ - while (tx_packet.len) - ao_sleep(&tx_packet); - - /* Prepare next packet + /* If there is data to send, and this is the master, + * then poke the master to send all queued data */ - if (tx_used) { - memcpy(&tx_packet.d, tx_data, tx_used); - tx_packet.len = tx_used; - tx_packet.seq++; - tx_used = 0; - - if (ao_packet_master_sleeping) - ao_wake_task(&ao_packet_task); - } + if (tx_used && ao_packet_master_sleeping) + ao_wake_task(&ao_packet_task); } void ao_packet_putchar(char c) { - while (tx_used == AO_PACKET_MAX && ao_packet_enable) + while (tx_used == AO_PACKET_MAX && ao_packet_enable) { ao_packet_flush(); + ao_sleep(&tx_data); + } if (ao_packet_enable) tx_data[tx_used++] = c; @@ -199,7 +188,9 @@ char ao_packet_getchar(void) __critical { while (rx_used == rx_len && ao_packet_enable) { - flush(); + /* poke the master to get more data */ + if (ao_packet_master_sleeping) + ao_wake_task(&ao_packet_task); ao_sleep(&rx_data); } @@ -217,7 +208,7 @@ ao_packet_echo(void) __reentrant c = ao_packet_getchar(); if (ao_packet_enable) { putchar(c); - if (c == (uint8_t) '\n') + if (c == (uint8_t) '\n' || c == (uint8_t) '\r') flush(); } } -- cgit v1.2.3 From 6c1a9ce16b966a21c885bf3be31cbcb85368b3fa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 31 Oct 2009 01:30:22 -0700 Subject: No need to wakeup &ao_tick_count now --- src/ao_timer.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/ao_timer.c b/src/ao_timer.c index d7603435..e81f937d 100644 --- a/src/ao_timer.c +++ b/src/ao_timer.c @@ -46,7 +46,6 @@ void ao_timer_isr(void) interrupt 9 ao_adc_count = 0; ao_adc_poll(); } - ao_wakeup(DATA_TO_XDATA(&ao_tick_count)); } void -- cgit v1.2.3 From ca5d323a3d206050d95f52a61e92c69e1f54e7b5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 1 Nov 2009 20:57:03 -0800 Subject: Enable packet-based communcation to command processor This splits the packet code into master/slave halves and hooks the slave side up to the getchar/putchar/flush logic in ao_stdio.c Signed-off-by: Keith Packard --- src/Makefile | 2 + src/ao.h | 53 ++++++++++++++- src/ao_flight.c | 4 +- src/ao_flight_test.c | 1 + src/ao_packet.c | 177 +++++++++++-------------------------------------- src/ao_packet_master.c | 142 +++++++++++++++++++++++++++++++++++++++ src/ao_packet_slave.c | 58 ++++++++++++++++ src/ao_stdio.c | 44 ++++++++++-- src/ao_teledongle.c | 3 +- src/ao_telemetrum.c | 2 +- src/ao_usb.c | 28 +++++--- 11 files changed, 356 insertions(+), 158 deletions(-) create mode 100644 src/ao_packet_master.c create mode 100644 src/ao_packet_slave.c (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 4575f443..d984e9dc 100644 --- a/src/Makefile +++ b/src/Makefile @@ -45,6 +45,7 @@ ALTOS_DRIVER_SRC = \ TELE_COMMON_SRC = \ ao_gps_print.c \ ao_packet.c \ + ao_packet_slave.c \ ao_state.c # @@ -52,6 +53,7 @@ TELE_COMMON_SRC = \ # TELE_RECEIVER_SRC =\ ao_monitor.c \ + ao_packet_master.c \ ao_rssi.c # diff --git a/src/ao.h b/src/ao.h index aeceb870..65a594c0 100644 --- a/src/ao.h +++ b/src/ao.h @@ -106,6 +106,7 @@ ao_start_scheduler(void); #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 */ +#define AO_PANIC_STDIO 7 /* Too many stdio handlers registered */ /* Stop the operating system, beeping and blinking the reason */ void @@ -873,9 +874,24 @@ ao_monitor_init(uint8_t led, uint8_t monitoring) __reentrant; * ao_stdio.c */ +#define AO_READ_AGAIN ((char) -1) + +struct ao_stdio { + char (*pollchar)(void); + void (*putchar)(char c) __reentrant; + void (*flush)(void); +}; + void flush(void); +extern __xdata uint8_t ao_stdin_ready; + +void +ao_add_stdio(char (*pollchar)(void), + void (*putchar)(char) __reentrant, + void (*flush)(void)); + /* * ao_ignite.c */ @@ -997,7 +1013,42 @@ struct ao_packet_recv { uint8_t status; }; +extern __xdata struct ao_packet_recv ao_rx_packet; +extern __xdata struct ao_packet ao_tx_packet; +extern __xdata struct ao_task ao_packet_task; +extern __xdata uint8_t ao_packet_enable; +extern __xdata uint8_t ao_packet_master_sleeping; +extern __pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; + +void +ao_packet_send(void); + +uint8_t +ao_packet_recv(void); + +void +ao_packet_flush(void); + +void +ao_packet_putchar(char c) __reentrant; + +char +ao_packet_pollchar(void) __critical; + +/* ao_packet_master.c */ + +void +ao_packet_master_init(void); + +/* ao_packet_slave.c */ + +void +ao_packet_slave_start(void); + +void +ao_packet_slave_stop(void); + void -ao_packet_init(void); +ao_packet_slave_init(void); #endif /* _AO_H_ */ diff --git a/src/ao_flight.c b/src/ao_flight.c index c43d0711..e91a5daa 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -235,9 +235,9 @@ ao_flight(void) } else { ao_flight_state = ao_flight_idle; - /* Turn on the Green LED in idle mode + /* Turn on packet system in idle mode */ - ao_led_on(AO_LED_GREEN); + ao_packet_slave_start(); ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } /* signal successful initialization by turning off the LED */ diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 9fcb00c2..83c63016 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -69,6 +69,7 @@ uint8_t ao_adc_head; #define ao_usb_disable() #define ao_telemetry_set_interval(x) #define ao_rdf_set(rdf) +#define ao_packet_slave_start() enum ao_igniter { ao_igniter_drogue = 0, diff --git a/src/ao_packet.c b/src/ao_packet.c index ba559512..3ce7e9ab 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -17,16 +17,17 @@ #include "ao.h" -static __xdata struct ao_packet_recv rx_packet; -static __xdata struct ao_packet tx_packet; +__xdata struct ao_packet_recv ao_rx_packet; +__xdata struct ao_packet ao_tx_packet; +__pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; + static __xdata char tx_data[AO_PACKET_MAX]; static __xdata char rx_data[AO_PACKET_MAX]; -static __pdata uint8_t rx_len, rx_used, tx_used; static __pdata uint8_t rx_seq; -static __xdata struct ao_task ao_packet_task; -static __xdata uint8_t ao_packet_enable; -static __xdata uint8_t ao_packet_master_sleeping; +__xdata struct ao_task ao_packet_task; +__xdata uint8_t ao_packet_enable; +__xdata uint8_t ao_packet_master_sleeping; void ao_packet_send(void) @@ -34,18 +35,18 @@ ao_packet_send(void) ao_led_on(AO_LED_RED); ao_config_get(); ao_mutex_get(&ao_radio_mutex); - if (tx_used && tx_packet.len == 0) { - memcpy(&tx_packet.d, tx_data, tx_used); - tx_packet.len = tx_used; - tx_packet.seq++; - tx_used = 0; + if (ao_packet_tx_used && ao_tx_packet.len == 0) { + memcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); + ao_tx_packet.len = ao_packet_tx_used; + ao_tx_packet.seq++; + ao_packet_tx_used = 0; ao_wakeup(&tx_data); } ao_radio_idle(); ao_radio_done = 0; RF_CHANNR = ao_config.radio_channel; ao_dma_set_transfer(ao_radio_dma, - &tx_packet, + &ao_tx_packet, &RFDXADDR, sizeof (struct ao_packet), DMA_CFG0_WORDSIZE_8 | @@ -74,7 +75,7 @@ ao_packet_recv(void) RF_CHANNR = ao_config.radio_channel; ao_dma_set_transfer(ao_radio_dma, &RFDXADDR, - &rx_packet, + &ao_rx_packet, sizeof (struct ao_packet_recv), DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | @@ -92,160 +93,60 @@ ao_packet_recv(void) ao_led_off(AO_LED_GREEN); if (dma_done & AO_DMA_DONE) { - if (!(rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) + if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) return AO_DMA_ABORTED; - if (rx_packet.packet.len == AO_PACKET_SYN) { - rx_seq = rx_packet.packet.seq; - tx_packet.seq = rx_packet.packet.ack; - tx_packet.ack = rx_seq; - } else if (rx_packet.packet.len) { - if (rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) && rx_used == rx_len) { -#if 0 - printf ("rx len %3d seq %3d ack %3d\n", - rx_packet.packet.len, - rx_packet.packet.seq, - rx_packet.packet.ack); - flush(); -#endif - memcpy(rx_data, rx_packet.packet.d, rx_packet.packet.len); - rx_used = 0; - rx_len = rx_packet.packet.len; - rx_seq = rx_packet.packet.seq; - tx_packet.ack = rx_seq; - ao_wakeup(&rx_data); + if (ao_rx_packet.packet.len == AO_PACKET_SYN) { + rx_seq = ao_rx_packet.packet.seq; + ao_tx_packet.seq = ao_rx_packet.packet.ack; + ao_tx_packet.ack = rx_seq; + } else if (ao_rx_packet.packet.len) { + if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) && ao_packet_rx_used == ao_packet_rx_len) { + memcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); + ao_packet_rx_used = 0; + ao_packet_rx_len = ao_rx_packet.packet.len; + rx_seq = ao_rx_packet.packet.seq; + ao_tx_packet.ack = rx_seq; + ao_wakeup(&ao_stdin_ready); } } - if (rx_packet.packet.ack == tx_packet.seq) { - tx_packet.len = 0; - ao_wakeup(&tx_packet); + if (ao_rx_packet.packet.ack == ao_tx_packet.seq) { + ao_tx_packet.len = 0; + ao_wakeup(&ao_tx_packet); } } return dma_done; } -void -ao_packet_slave(void) -{ - ao_radio_set_packet(); - tx_packet.addr = ao_serial_number; - tx_packet.len = AO_PACKET_SYN; - while (ao_packet_enable) { - ao_packet_recv(); - ao_packet_send(); - } - ao_exit(); -} - -/* Thread for the master side of the packet link */ - -void -ao_packet_master(void) -{ - uint8_t status; - - ao_radio_set_packet(); - tx_packet.addr = ao_serial_number; - tx_packet.len = AO_PACKET_SYN; - while (ao_packet_enable) { - ao_packet_send(); - ao_alarm(AO_MS_TO_TICKS(100)); - status = ao_packet_recv(); - if (status & AO_DMA_DONE) { - /* if we can transmit data, do so */ - if (tx_used && tx_packet.len == 0) - continue; - ao_packet_master_sleeping = 1; - ao_delay(AO_MS_TO_TICKS(1000)); - ao_packet_master_sleeping = 0; - } - } - ao_exit(); -} - void ao_packet_flush(void) { /* If there is data to send, and this is the master, * then poke the master to send all queued data */ - if (tx_used && ao_packet_master_sleeping) + if (ao_packet_tx_used && ao_packet_master_sleeping) ao_wake_task(&ao_packet_task); } void -ao_packet_putchar(char c) +ao_packet_putchar(char c) __reentrant { - while (tx_used == AO_PACKET_MAX && ao_packet_enable) { + while (ao_packet_tx_used == AO_PACKET_MAX && ao_packet_enable) { ao_packet_flush(); ao_sleep(&tx_data); } if (ao_packet_enable) - tx_data[tx_used++] = c; + tx_data[ao_packet_tx_used++] = c; } char -ao_packet_getchar(void) __critical +ao_packet_pollchar(void) __critical { - while (rx_used == rx_len && ao_packet_enable) { - /* poke the master to get more data */ - if (ao_packet_master_sleeping) - ao_wake_task(&ao_packet_task); - ao_sleep(&rx_data); - } - if (!ao_packet_enable) - return 0; + return AO_READ_AGAIN; - return rx_data[rx_used++]; -} - -static void -ao_packet_echo(void) __reentrant -{ - uint8_t c; - while (ao_packet_enable) { - c = ao_packet_getchar(); - if (ao_packet_enable) { - putchar(c); - if (c == (uint8_t) '\n' || c == (uint8_t) '\r') - flush(); - } - } - ao_exit(); -} - -static __xdata struct ao_task ao_packet_echo_task; - -static void -ao_packet_forward(void) __reentrant -{ - char c; - ao_packet_enable = 1; - ao_cmd_white(); - - if (ao_cmd_lex_c == 'm') - ao_add_task(&ao_packet_task, ao_packet_master, "master"); - else - ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); - ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); - while ((c = getchar()) != '~') - ao_packet_putchar(c); - ao_packet_enable = 0; - ao_radio_abort(); - while (ao_packet_echo_task.wchan || ao_packet_task.wchan) { - ao_wake_task(&ao_packet_echo_task); - ao_wake_task(&ao_packet_task); - } -} - -__code struct ao_cmds ao_packet_cmds[] = { - { 'p', ao_packet_forward, "p {m|s} Remote packet link. m=master, s=slave" }, - { 0, ao_packet_forward, NULL }, -}; + if (ao_packet_rx_used == ao_packet_rx_len) + return AO_READ_AGAIN; -void -ao_packet_init(void) -{ - ao_cmd_register(&ao_packet_cmds[0]); + return rx_data[ao_packet_rx_used++]; } diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c new file mode 100644 index 00000000..2751f414 --- /dev/null +++ b/src/ao_packet_master.c @@ -0,0 +1,142 @@ +/* + * 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" + +static char +ao_packet_getchar(void) +{ + char c; + while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) + { + if (!ao_packet_enable) + break; + if (ao_packet_master_sleeping) + ao_wake_task(&ao_packet_task); + ao_sleep(&ao_stdin_ready); + } + return c; +} + +static void +ao_packet_echo(void) __reentrant +{ + uint8_t c; + while (ao_packet_enable) { + c = ao_packet_getchar(); + if (ao_packet_enable) + putchar(c); + } + ao_exit(); +} + +static __xdata struct ao_task ao_packet_echo_task; +static __xdata uint16_t ao_packet_master_delay; +static __xdata uint16_t ao_packet_master_time; + +#define AO_PACKET_MASTER_DELAY_SHORT AO_MS_TO_TICKS(100) +#define AO_PACKET_MASTER_DELAY_LONG AO_MS_TO_TICKS(1000) +#define AO_PACKET_MASTER_DELAY_TIMEOUT AO_MS_TO_TICKS(2000) + +static void +ao_packet_master_busy(void) +{ + ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; + ao_packet_master_time = ao_time(); +} + +static void +ao_packet_master_check_busy(void) +{ + int16_t idle; + if (ao_packet_master_delay != AO_PACKET_MASTER_DELAY_SHORT) + return; + idle = (int16_t) (ao_time() - ao_packet_master_time); + + if (idle > AO_PACKET_MASTER_DELAY_TIMEOUT) + ao_packet_master_delay = AO_PACKET_MASTER_DELAY_LONG; +} + +void +ao_packet_master(void) +{ + uint8_t status; + + ao_radio_set_packet(); + ao_tx_packet.addr = ao_serial_number; + ao_tx_packet.len = AO_PACKET_SYN; + ao_packet_master_time = ao_time(); + ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; + while (ao_packet_enable) { + ao_packet_send(); + if (ao_tx_packet.len) + ao_packet_master_busy(); + ao_packet_master_check_busy(); + ao_alarm(ao_packet_master_delay); + status = ao_packet_recv(); + if (status & AO_DMA_DONE) { + /* if we can transmit data, do so */ + if (ao_packet_tx_used && ao_tx_packet.len == 0) + continue; + if (ao_rx_packet.packet.len) + ao_packet_master_busy(); + else + flush(); + ao_packet_master_sleeping = 1; + ao_delay(ao_packet_master_delay); + ao_packet_master_sleeping = 0; + } + } + ao_exit(); +} + +static void +ao_packet_forward(void) __reentrant +{ + char c; + ao_packet_enable = 1; + ao_cmd_white(); + + flush(); + ao_set_monitor(0); + ao_add_task(&ao_packet_task, ao_packet_master, "master"); + ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); + while ((c = getchar()) != '~') { + if (c == '\r') c = '\n'; + ao_packet_putchar(c); + } + ao_packet_enable = 0; + ao_radio_abort(); + while (ao_packet_echo_task.wchan || ao_packet_task.wchan) { + ao_wake_task(&ao_packet_echo_task); + ao_wake_task(&ao_packet_task); + ao_yield(); + } +} + + + +__code struct ao_cmds ao_packet_master_cmds[] = { + { 'p', ao_packet_forward, "p Remote packet link." }, + { 0, ao_packet_forward, NULL }, +}; + +void +ao_packet_master_init(void) +{ + ao_cmd_register(&ao_packet_master_cmds[0]); +} diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c new file mode 100644 index 00000000..ba5ad1c1 --- /dev/null +++ b/src/ao_packet_slave.c @@ -0,0 +1,58 @@ +/* + * 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_packet_slave(void) +{ + ao_radio_set_packet(); + ao_tx_packet.addr = ao_serial_number; + ao_tx_packet.len = AO_PACKET_SYN; + while (ao_packet_enable) { + ao_packet_recv(); + ao_packet_send(); + } + ao_exit(); +} + +void +ao_packet_slave_start(void) +{ + ao_packet_enable = 1; + ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); +} + +void +ao_packet_slave_stop(void) +{ + ao_packet_enable = 0; + ao_radio_abort(); + while (ao_packet_task.wchan) { + ao_wake_task(&ao_packet_task); + ao_yield(); + } + ao_radio_set_telemetry(); +} + +void +ao_packet_slave_init(void) +{ + ao_add_stdio(ao_packet_pollchar, + ao_packet_putchar, + ao_packet_flush); +} diff --git a/src/ao_stdio.c b/src/ao_stdio.c index fb8ce093..7bc416e1 100644 --- a/src/ao_stdio.c +++ b/src/ao_stdio.c @@ -21,22 +21,56 @@ * Basic I/O functions to support SDCC stdio package */ +#define AO_NUM_STDIOS 2 + +static __xdata struct ao_stdio stdios[AO_NUM_STDIOS]; +static __data int8_t ao_cur_stdio; +static __data int8_t ao_num_stdios; + void putchar(char c) { if (c == '\n') - ao_usb_putchar('\r'); - ao_usb_putchar(c); + (*stdios[ao_cur_stdio].putchar)('\r'); + (*stdios[ao_cur_stdio].putchar)(c); } void flush(void) { - ao_usb_flush(); + stdios[ao_cur_stdio].flush(); } +__xdata uint8_t ao_stdin_ready; + char -getchar(void) +getchar(void) __reentrant +{ + char c; + int8_t stdio = ao_cur_stdio; + + for (;;) { + c = stdios[stdio].pollchar(); + if (c != AO_READ_AGAIN) + break; + if (++stdio == ao_num_stdios) + stdio = 0; + if (stdio == ao_cur_stdio) + ao_sleep(&ao_stdin_ready); + } + ao_cur_stdio = stdio; + return c; +} + +void +ao_add_stdio(char (*pollchar)(void), + void (*putchar)(char), + void (*flush)(void)) { - return ao_usb_getchar(); + if (ao_num_stdios == AO_NUM_STDIOS) + ao_panic(AO_PANIC_STDIO); + stdios[ao_num_stdios].pollchar = pollchar; + stdios[ao_num_stdios].putchar = putchar; + stdios[ao_num_stdios].flush = flush; + ao_num_stdios++; } diff --git a/src/ao_teledongle.c b/src/ao_teledongle.c index 98642180..e4828d80 100644 --- a/src/ao_teledongle.c +++ b/src/ao_teledongle.c @@ -33,7 +33,8 @@ main(void) ao_monitor_init(AO_LED_GREEN, TRUE); ao_rssi_init(AO_LED_RED); ao_radio_init(); - ao_packet_init(); + ao_packet_slave_init(); + ao_packet_master_init(); ao_config_init(); ao_start_scheduler(); } diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 07737f30..5250078e 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -40,7 +40,7 @@ main(void) ao_gps_report_init(); ao_telemetry_init(); ao_radio_init(); - ao_packet_init(); + ao_packet_slave_init(); ao_igniter_init(); ao_config_init(); ao_start_scheduler(); diff --git a/src/ao_usb.c b/src/ao_usb.c index 8926b9ca..daca71a7 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -53,7 +53,7 @@ ao_usb_isr(void) interrupt 6 ao_wakeup(&ao_usb_in_bytes); if (USBOIF & (1 << AO_USB_OUT_EP)) - ao_wakeup(&ao_usb_out_bytes); + ao_wakeup(&ao_stdin_ready); if (USBCIF & USBCIF_RSTIF) ao_usb_set_interrupts(); @@ -360,7 +360,7 @@ ao_usb_flush(void) __critical } void -ao_usb_putchar(char c) __critical +ao_usb_putchar(char c) __critical __reentrant { if (!ao_usb_running) return; @@ -374,16 +374,13 @@ ao_usb_putchar(char c) __critical } char -ao_usb_getchar(void) __critical +ao_usb_pollchar(void) __critical { - __xdata char c; + char c; while (ao_usb_out_bytes == 0) { - for (;;) { - USBINDEX = AO_USB_OUT_EP; - if ((USBCSOL & USBCSOL_OUTPKT_RDY) != 0) - break; - ao_sleep(&ao_usb_out_bytes); - } + USBINDEX = AO_USB_OUT_EP; + if ((USBCSOL & USBCSOL_OUTPKT_RDY) == 0) + return AO_READ_AGAIN; ao_usb_out_bytes = (USBCNTH << 8) | USBCNTL; } --ao_usb_out_bytes; @@ -395,6 +392,16 @@ ao_usb_getchar(void) __critical return c; } +char +ao_usb_getchar(void) +{ + char c; + + while ((c = ao_usb_pollchar()) == AO_READ_AGAIN) + ao_sleep(&ao_stdin_ready); + return c; +} + void ao_usb_enable(void) { @@ -438,4 +445,5 @@ ao_usb_init(void) ao_usb_enable(); ao_add_task(&ao_usb_task, ao_usb_ep0, "usb"); + ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); } -- cgit v1.2.3 From b92333ff5e75bf96804359e9fbf464d3b518bd95 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Nov 2009 15:45:42 -0800 Subject: Disable interrupts while removing tasks from task list --- src/ao_task.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_task.c b/src/ao_task.c index 14aa84c8..4664163d 100644 --- a/src/ao_task.c +++ b/src/ao_task.c @@ -228,7 +228,7 @@ ao_wake_task(__xdata struct ao_task *task) } void -ao_exit(void) +ao_exit(void) __critical { uint8_t i; ao_num_tasks--; -- cgit v1.2.3 From b219801fb0e5eaff7778d21701da977104522da3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Nov 2009 15:45:58 -0800 Subject: Add ao_usb_pollchar to ao.h --- src/ao.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 65a594c0..4cceefe1 100644 --- a/src/ao.h +++ b/src/ao.h @@ -291,6 +291,12 @@ ao_usb_putchar(char c); char ao_usb_getchar(void); +/* Poll for a charcter on the USB input queue. + * returns AO_READ_AGAIN if none are available + */ +char +ao_usb_pollchar(void); + /* Flush the USB output queue */ void ao_usb_flush(void); -- cgit v1.2.3 From 144db05f6b286a0450d486f69ce192632a2c0656 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Nov 2009 21:38:18 -0800 Subject: Add two-point accelerometer calibration. Calibration now uses two values, one upside right and the other upside down instead of a single horizontal value. This allows the use of other accelerometers and compensates for variations in the divider circuit to provide more accurate data. --- debian/rules | 2 +- src/ao.h | 10 +++++---- src/ao_config.c | 61 +++++++++++++++++++++++++++++++++++++--------------- src/ao_flight.c | 46 +++++++++++++++++++-------------------- src/ao_flight_test.c | 7 ++++-- 5 files changed, 79 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/debian/rules b/debian/rules index ac594c07..260ba773 100755 --- a/debian/rules +++ b/debian/rules @@ -9,7 +9,7 @@ DEB_VERSION := $(shell git describe | tr - +) prebuild: git-dch --release --new-version=$(DEB_VERSION) git log > ChangeLog - git commit ChangeLog debian/changelog \ + git commit -n ChangeLog debian/changelog \ -m "update changelogs for Debian build" git tag debian/$(DEB_VERSION) git push --tags origin master diff --git a/src/ao.h b/src/ao.h index 4cceefe1..22e8785f 100644 --- a/src/ao.h +++ b/src/ao.h @@ -117,8 +117,9 @@ ao_panic(uint8_t reason); */ /* Our timer runs at 100Hz */ -#define AO_MS_TO_TICKS(ms) ((ms) / 10) -#define AO_SEC_TO_TICKS(s) ((s) * 100) +#define AO_HERTZ 100 +#define AO_MS_TO_TICKS(ms) ((ms) / (1000 / AO_HERTZ)) +#define AO_SEC_TO_TICKS(s) ((s) * AO_HERTZ) /* Returns the current time in ticks */ uint16_t @@ -928,16 +929,17 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 1 +#define AO_CONFIG_MINOR 2 struct ao_config { uint8_t major; uint8_t minor; uint16_t main_deploy; - int16_t accel_zero_g; + int16_t accel_plus_g; uint8_t radio_channel; char callsign[AO_MAX_CALLSIGN + 1]; uint8_t apogee_delay; + int16_t accel_minus_g; }; extern __xdata struct ao_config ao_config; diff --git a/src/ao_config.c b/src/ao_config.c index 021fb6f6..85fcff8c 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -45,7 +45,8 @@ _ao_config_get(void) ao_config.minor = AO_CONFIG_MINOR; ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; - ao_config.accel_zero_g = AO_CONFIG_DEFAULT_ACCEL_ZERO_G; + ao_config.accel_plus_g = 0; + ao_config.accel_minus_g = 0; memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); @@ -53,9 +54,14 @@ _ao_config_get(void) ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { - /* Fixups for major version 1 */ + /* Fixups for mior version 1 */ if (ao_config.minor < 1) ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; + /* Fixupes for minor version 2 */ + if (ao_config.minor < 2) { + ao_config.accel_plus_g = 0; + ao_config.accel_minus_g = 0; + } ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -152,23 +158,28 @@ ao_config_main_deploy_set(void) __reentrant } void -ao_config_accel_zero_g_show(void) __reentrant +ao_config_accel_calibrate_show(void) __reentrant { - printf("Accel zero g point: %d\n", - ao_config.accel_zero_g); + printf("Accel cal +1g: %d -1g: %d\n", + ao_config.accel_plus_g, ao_config.accel_minus_g); } -#define ZERO_G_SAMPLES 1000 +#define ACCEL_CALIBRATE_SAMPLES 1024 +#define ACCEL_CALIBRATE_SHIFT 10 static int16_t -ao_config_accel_zero_g_auto(void) __reentrant +ao_config_accel_calibrate_auto(char *orientation) __reentrant { uint16_t i; int32_t accel_total; uint8_t cal_adc_ring; - puts("Calibrating accelerometer..."); flush(); - i = ZERO_G_SAMPLES; + printf("Orient %s and press a key...", orientation); + flush(); + (void) getchar(); + puts("\r\n"); flush(); + puts("Calibrating..."); flush(); + i = ACCEL_CALIBRATE_SAMPLES; accel_total = 0; cal_adc_ring = ao_adc_head; while (i) { @@ -179,22 +190,38 @@ ao_config_accel_zero_g_auto(void) __reentrant i--; } } - return (int16_t) (accel_total / ZERO_G_SAMPLES); + return accel_total >> ACCEL_CALIBRATE_SHIFT; } + void -ao_config_accel_zero_g_set(void) __reentrant +ao_config_accel_calibrate_set(void) __reentrant { + int16_t up, down; ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - if (ao_cmd_lex_i == 0) - ao_cmd_lex_i = ao_config_accel_zero_g_auto(); + if (ao_cmd_lex_i == 0) { + up = ao_config_accel_calibrate_auto("antenna up"); + down = ao_config_accel_calibrate_auto("antenna down"); + } else { + up = ao_cmd_lex_i; + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + down = ao_cmd_lex_i; + } + if (up >= down) { + printf("Invalid accel calibration: antenna up (%d) should be less than antenna down (%d)\n", + up, down); + return; + } ao_mutex_get(&ao_config_mutex); _ao_config_get(); - ao_config.accel_zero_g = ao_cmd_lex_i; + ao_config.accel_plus_g = up; + ao_config.accel_minus_g = down; ao_config_dirty = 1; ao_mutex_put(&ao_config_mutex); - ao_config_accel_zero_g_show(); + ao_config_accel_calibrate_show(); } void @@ -237,8 +264,8 @@ ao_config_write(void) __reentrant; __code struct ao_config_var ao_config_vars[] = { { 'm', ao_config_main_deploy_set, ao_config_main_deploy_show, "m Set height above launch for main deploy (in meters)" }, - { 'a', ao_config_accel_zero_g_set, ao_config_accel_zero_g_show, - "a Set accelerometer zero g point (0 for auto)" }, + { 'a', ao_config_accel_calibrate_set, ao_config_accel_calibrate_show, + "a <+g> <-g> Set accelerometer calibration (0 for auto)" }, { 'r', ao_config_radio_channel_set, ao_config_radio_channel_show, "r Set radio channel (freq = 434.550 + channel * .1)" }, { 'c', ao_config_callsign_set, ao_config_callsign_show, diff --git a/src/ao_flight.c b/src/ao_flight.c index e91a5daa..92c955fb 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -48,6 +48,7 @@ __pdata int16_t ao_interval_max_pres; __data uint8_t ao_flight_adc; __pdata int16_t ao_raw_accel, ao_raw_accel_prev, ao_raw_pres; +__pdata int16_t ao_accel_2g; /* Accelerometer calibration * @@ -72,19 +73,18 @@ __pdata int16_t ao_raw_accel, ao_raw_accel_prev, ao_raw_pres; #define GRAVITY 9.80665 /* convert m/s to velocity count */ -#define VEL_MPS_TO_COUNT(mps) ((int32_t) (((mps) / GRAVITY) * ACCEL_G * 100)) +#define VEL_MPS_TO_COUNT(mps) (((int32_t) (((mps) / GRAVITY) * (AO_HERTZ/2))) * (int32_t) ao_accel_2g) #define ACCEL_G 265 -#define ACCEL_ZERO_G 16000 -#define ACCEL_NOSE_UP (ACCEL_G * 2 /3) -#define ACCEL_BOOST ACCEL_G * 2 +#define ACCEL_NOSE_UP (ao_accel_2g / 4) +#define ACCEL_BOOST ao_accel_2g #define ACCEL_INT_LAND (ACCEL_G / 10) -#define ACCEL_VEL_LAND VEL_MPS_TO_COUNT(10) #define ACCEL_VEL_MACH VEL_MPS_TO_COUNT(200) -#define ACCEL_VEL_APOGEE VEL_MPS_TO_COUNT(2) -#define ACCEL_VEL_MAIN VEL_MPS_TO_COUNT(100) #define ACCEL_VEL_BOOST VEL_MPS_TO_COUNT(5) +int32_t accel_vel_mach; +int32_t accel_vel_boost; + /* * Barometer calibration * @@ -170,14 +170,14 @@ ao_flight(void) * so subtract instead of add. */ ticks = ao_flight_tick - ao_flight_prev_tick; - ao_vel_change = (((ao_raw_accel >> 1) + (ao_raw_accel_prev >> 1)) - ao_ground_accel); + ao_vel_change = ao_ground_accel - (((ao_raw_accel + 1) >> 1) + ((ao_raw_accel_prev + 1) >> 1)); ao_raw_accel_prev = ao_raw_accel; /* one is a common interval */ if (ticks == 1) - ao_flight_vel -= (int32_t) ao_vel_change; + ao_flight_vel += (int32_t) ao_vel_change; else - ao_flight_vel -= (int32_t) ao_vel_change * (int32_t) ticks; + ao_flight_vel += (int32_t) ao_vel_change * (int32_t) ticks; ao_flight_adc = ao_adc_ring_next(ao_flight_adc); } @@ -211,6 +211,9 @@ ao_flight(void) ao_min_pres = ao_ground_pres; ao_config_get(); ao_main_pres = ao_altitude_to_pres(ao_pres_to_altitude(ao_ground_pres) + ao_config.main_deploy); + ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; + accel_vel_mach = ACCEL_VEL_MACH; + accel_vel_boost = ACCEL_VEL_BOOST; ao_flight_vel = 0; ao_min_vel = 0; ao_old_vel = ao_flight_vel; @@ -218,8 +221,9 @@ ao_flight(void) /* Go to pad state if the nose is pointing up */ ao_config_get(); - if (ao_flight_accel < ao_config.accel_zero_g - ACCEL_NOSE_UP) { - + if (ao_config.accel_plus_g != 0 && ao_config.accel_minus_g != 0 && + ao_flight_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP) + { /* Disable the USB controller in flight mode * to save power */ @@ -337,19 +341,15 @@ ao_flight(void) /* apogee detect: coast to drogue deploy: * - * accelerometer: abs(velocity) > min_velocity + 2m/s - * OR * barometer: fall at least 10m * - * If the barometer saturates because the flight - * goes over its measuring range (about 53k'), - * requiring a 10m fall will avoid prematurely - * detecting apogee; the accelerometer will take - * over in that case and the integrated velocity - * measurement should suffice to find apogee + * It would be nice to use the accelerometer + * to detect apogee as well, but tests have + * shown that flights far from vertical would + * grossly mis-detect apogee. So, for now, + * we'll trust to a single sensor for this test */ - if (/* abs(ao_flight_vel) > ao_min_vel + ACCEL_VEL_APOGEE || */ - ao_flight_pres > ao_min_pres + BARO_APOGEE) + if (ao_flight_pres > ao_min_pres + BARO_APOGEE) { /* ignite the drogue charge */ ao_ignite(ao_igniter_drogue); @@ -462,7 +462,7 @@ ao_flight_status(void) __reentrant { printf("STATE: %7s accel: %d speed: %d altitude: %d main: %d\n", ao_state_names[ao_flight_state], - AO_ACCEL_COUNT_TO_MSS(ACCEL_ZERO_G - ao_flight_accel), + AO_ACCEL_COUNT_TO_MSS( - ao_flight_accel), AO_VEL_COUNT_TO_MS(ao_flight_vel), ao_pres_to_altitude(ao_flight_pres), ao_pres_to_altitude(ao_main_pres)); diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 83c63016..61f48cb6 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -22,6 +22,8 @@ #include #include +#define AO_HERTZ 100 + #define AO_ADC_RING 64 #define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) #define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) @@ -144,12 +146,13 @@ ao_altitude_to_pres(int16_t alt) __reentrant struct ao_config { uint16_t main_deploy; - int16_t accel_zero_g; + int16_t accel_plus_g; + int16_t accel_minus_g; }; #define ao_config_get() -struct ao_config ao_config = { 250, 16000 }; +struct ao_config ao_config = { 250, 15937, 16467 }; #include "ao_flight.c" -- cgit v1.2.3 From 47f510464907d2b9488109c96ade87a41d878842 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Nov 2009 21:46:39 -0800 Subject: Remove "l" command as ao-dumplong no longer uses it --- src/ao_log.c | 24 ------------------------ 1 file changed, 24 deletions(-) (limited to 'src') diff --git a/src/ao_log.c b/src/ao_log.c index b2bfbd6f..50778f55 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -191,29 +191,6 @@ ao_log_stop(void) ao_log_flush(); } -static void -dump_log(void) __reentrant -{ - 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); - if (ao_log_dump.type == AO_LOG_STATE && - ao_log_dump.u.state.state == ao_flight_landed) - break; - } - printf("end\n"); -} - -__code struct ao_cmds ao_log_cmds[] = { - { 'l', dump_log, "l Dump last flight log" }, - { 0, dump_log, NULL }, -}; - static __xdata struct ao_task ao_log_task; void @@ -228,5 +205,4 @@ 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]); } -- cgit v1.2.3 From a4137263b69864c524d39c6ff88a0225fd06e79b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Nov 2009 21:47:15 -0800 Subject: Remove "d" command --- src/ao_cmd.c | 28 ---------------------------- 1 file changed, 28 deletions(-) (limited to 'src') diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 33619b24..e3f85bc9 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -178,33 +178,6 @@ eol(void) ao_cmd_lex(); } -static void -dump(void) -{ - __xdata uint16_t c; - __xdata uint8_t * __xdata start, * __xdata end; - - 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) - putchar('\n'); - ao_cmd_put16((uint16_t) start); - } - putchar(' '); - ao_cmd_put8(*start); - ++c; - start++; - } - putchar('\n'); -} - static void echo(void) { @@ -305,7 +278,6 @@ __code struct ao_cmds ao_base_cmds[] = { { '?', help, "? Print this message" }, { 'T', ao_task_info, "T Show task states" }, { 'E', echo, "E <0 off, 1 on> Set command echo mode" }, - { 'd', dump, "d Dump memory" }, { 'v', version, "v Show version" }, { 0, help, NULL }, }; -- cgit v1.2.3 From 79718e798e96567f0ba11c61f187e432fdcf95ee Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Nov 2009 21:48:16 -0800 Subject: Remove "f" command --- src/ao_flight.c | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index 92c955fb..f50491d9 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -454,27 +454,8 @@ ao_flight(void) } } -#define AO_ACCEL_COUNT_TO_MSS(count) ((count) / 27) -#define AO_VEL_COUNT_TO_MS(count) ((int16_t) ((count) / 2700)) - -static void -ao_flight_status(void) __reentrant -{ - printf("STATE: %7s accel: %d speed: %d altitude: %d main: %d\n", - ao_state_names[ao_flight_state], - AO_ACCEL_COUNT_TO_MSS( - ao_flight_accel), - AO_VEL_COUNT_TO_MS(ao_flight_vel), - ao_pres_to_altitude(ao_flight_pres), - ao_pres_to_altitude(ao_main_pres)); -} - static __xdata struct ao_task flight_task; -__code struct ao_cmds ao_flight_cmds[] = { - { 'f', ao_flight_status, "f Display current flight state" }, - { 0, ao_flight_status, NULL } -}; - void ao_flight_init(void) { @@ -486,5 +467,4 @@ ao_flight_init(void) ao_interval_end = AO_INTERVAL_TICKS; ao_add_task(&flight_task, ao_flight, "flight"); - ao_cmd_register(&ao_flight_cmds[0]); } -- cgit v1.2.3 From f57bea012d4fbca097df0d98fcd30eb4abd9701a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Nov 2009 21:47:41 -0800 Subject: Reformat ADC values to show all 16 bits --- src/ao_adc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ao_adc.c b/src/ao_adc.c index d9672671..a8784667 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -65,9 +65,9 @@ ao_adc_dump(void) __reentrant { static __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.v_batt >> 4, packet.sense_d >> 4, packet.sense_m >> 4); + printf("tick: %5u accel: %5d pres: %5d temp: %5d batt: %5d drogue: %5d main: %5d\n", + packet.tick, packet.accel, packet.pres, packet.temp, + packet.v_batt, packet.sense_d, packet.sense_m); } __code struct ao_cmds ao_adc_cmds[] = { -- cgit v1.2.3 From b529e5e8998702986909111a457f3ce9932e1ccf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Nov 2009 23:48:29 -0800 Subject: ao_flight_test was using accel value for pressure too --- src/ao_flight_test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 61f48cb6..2bf7f2b2 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -217,7 +217,7 @@ ao_sleep(void *wchan) type = words[0][0]; tick = strtoul(words[1], NULL, 16); a = strtoul(words[2], NULL, 16); - b = strtoul(words[2], NULL, 16); + b = strtoul(words[3], NULL, 16); } else if (nword >= 36 && strcmp(words[0], "CALL") == 0) { tick = atoi(words[10]); if (!ao_flight_started) { -- cgit v1.2.3 From 1de322b960005c9a16051afa1881fadb00f4bcd6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Nov 2009 00:40:38 -0800 Subject: Pass accel calibration over telemetry stream. Telemetry data format change. This allows the ground station to convert the accelerometer sensor values into acceleration and speed data. This requires a new telemetry data structure, and so TeleMetrum and TeleDongle units must be updated synchronously. ao-view will parse either telemetry stream, and the serial format from TeleDongle now has a version number to allow for future changes. Signed-off-by: Keith Packard --- ao-tools/ao-view/aoview.h | 2 ++ ao-tools/ao-view/aoview_monitor.c | 23 ++++++++++++++++++++--- ao-tools/ao-view/aoview_state.c | 6 ++++-- src/ao.h | 3 +++ src/ao_monitor.c | 18 +++++++++++------- src/ao_telemetry.c | 2 ++ 6 files changed, 42 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/ao-tools/ao-view/aoview.h b/ao-tools/ao-view/aoview.h index c582159c..b6d5bcdf 100644 --- a/ao-tools/ao-view/aoview.h +++ b/ao-tools/ao-view/aoview.h @@ -104,6 +104,8 @@ struct aodata { int flight_vel; int flight_pres; int ground_pres; + int accel_plus_g; + int accel_minus_g; struct aogps gps; struct aogps_tracking gps_tracking; }; diff --git a/ao-tools/ao-view/aoview_monitor.c b/ao-tools/ao-view/aoview_monitor.c index 48e20320..6d57f556 100644 --- a/ao-tools/ao-view/aoview_monitor.c +++ b/ao-tools/ao-view/aoview_monitor.c @@ -77,7 +77,9 @@ gboolean aoview_monitor_parse(const char *input_line) { char *saveptr; - char *words[PARSE_MAX_WORDS]; + char *raw_words[PARSE_MAX_WORDS]; + char **words; + int version = 0; int nword; char line_buf[8192], *line; struct aodata data; @@ -89,13 +91,19 @@ aoview_monitor_parse(const char *input_line) line_buf[sizeof(line_buf) - 1] = '\0'; line = line_buf; for (nword = 0; nword < PARSE_MAX_WORDS; nword++) { - words[nword] = strtok_r(line, " \t\n", &saveptr); + raw_words[nword] = strtok_r(line, " \t\n", &saveptr); line = NULL; - if (words[nword] == NULL) + if (raw_words[nword] == NULL) break; } if (nword < 36) return FALSE; + words = raw_words; + if (strcmp(words[0], "VERSION") == 0) { + aoview_parse_int(&version, words[1]); + words += 2; + nword -= 2; + } if (strcmp(words[0], "CALL") != 0) return FALSE; aoview_parse_string(data.callsign, sizeof (data.callsign), words[1]); @@ -115,6 +123,15 @@ aoview_monitor_parse(const char *input_line) aoview_parse_int(&data.flight_vel, words[28]); aoview_parse_int(&data.flight_pres, words[30]); aoview_parse_int(&data.ground_pres, words[32]); + if (version >= 1) { + aoview_parse_int(&data.accel_plus_g, words[34]); + aoview_parse_int(&data.accel_minus_g, words[36]); + words += 4; + nword -= 4; + } else { + data.accel_plus_g = data.ground_accel; + data.accel_minus_g = data.ground_accel + 530; + } aoview_parse_int(&data.gps.nsat, words[34]); if (strcmp (words[36], "unlocked") == 0) { data.gps.gps_connected = 1; diff --git a/ao-tools/ao-view/aoview_state.c b/ao-tools/ao-view/aoview_state.c index f75066dd..f8f01685 100644 --- a/ao-tools/ao-view/aoview_state.c +++ b/ao-tools/ao-view/aoview_state.c @@ -105,6 +105,7 @@ aoview_state_derive(struct aodata *data, struct aostate *state) double new_height; double height_change; double time_change; + double accel_counts_per_mss; int tick_count; state->report_time = aoview_time(); @@ -123,8 +124,9 @@ aoview_state_derive(struct aodata *data, struct aostate *state) state->height = new_height; if (time_change) state->baro_speed = (state->baro_speed * 3 + (height_change / time_change)) / 4.0; - state->acceleration = (data->ground_accel - data->flight_accel) / 27.0; - state->speed = data->flight_vel / 2700.0; + accel_counts_per_mss = ((data->accel_minus_g - data->accel_plus_g) / 2.0) / 9.80665; + state->acceleration = (data->ground_accel - data->flight_accel) / accel_counts_per_mss; + state->speed = data->flight_vel / (accel_counts_per_mss * 100.0); state->temperature = ((data->temp / 32767.0 * 3.3) - 0.5) / 0.01; state->drogue_sense = data->drogue / 32767.0 * 15.0; state->main_sense = data->main / 32767.0 * 15.0; diff --git a/src/ao.h b/src/ao.h index 22e8785f..bc9afcc3 100644 --- a/src/ao.h +++ b/src/ao.h @@ -784,6 +784,7 @@ ao_gps_report_init(void); */ #define AO_MAX_CALLSIGN 8 +#define AO_TELEMETRY_VERSION 1 struct ao_telemetry { uint8_t addr; @@ -793,6 +794,8 @@ struct ao_telemetry { int32_t flight_vel; int16_t flight_pres; int16_t ground_pres; + int16_t accel_plus_g; + int16_t accel_minus_g; struct ao_adc adc; struct ao_gps_data gps; char callsign[AO_MAX_CALLSIGN]; diff --git a/src/ao_monitor.c b/src/ao_monitor.c index d0c1da34..cd0d693e 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -37,12 +37,14 @@ ao_monitor(void) if (state > ao_flight_invalid) state = ao_flight_invalid; if (recv.status & PKT_APPEND_STATUS_1_CRC_OK) { - printf ("CALL %s SERIAL %3d RSSI %4d STATUS %02x STATE %7s ", - callsign, - recv.telemetry.addr, - (int) recv.rssi - 74, recv.status, - ao_state_names[state]); - printf("%5u a: %5d p: %5d t: %5d v: %5d d: %5d m: %5d fa: %5d ga: %d fv: %7ld fp: %5d gp: %5d ", + printf("VERSION %d CALL %s SERIAL %3d RSSI %4d STATUS %02x STATE %7s ", + AO_TELEMETRY_VERSION, + callsign, + recv.telemetry.addr, + (int) recv.rssi - 74, recv.status, + ao_state_names[state]); + printf("%5u a: %5d p: %5d t: %5d v: %5d d: %5d m: %5d " + "fa: %5d ga: %d fv: %7ld fp: %5d gp: %5d a+: %5d a-: %5d ", recv.telemetry.adc.tick, recv.telemetry.adc.accel, recv.telemetry.adc.pres, @@ -54,7 +56,9 @@ ao_monitor(void) recv.telemetry.ground_accel, recv.telemetry.flight_vel, recv.telemetry.flight_pres, - recv.telemetry.ground_pres); + recv.telemetry.ground_pres, + recv.telemetry.accel_plus_g, + recv.telemetry.accel_minus_g); ao_gps_print(&recv.telemetry.gps); putchar(' '); ao_gps_tracking_print(&recv.telemetry.gps_tracking); diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index d52e589c..9c923984 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -32,6 +32,8 @@ ao_telemetry(void) ao_config_get(); memcpy(telemetry.callsign, ao_config.callsign, AO_MAX_CALLSIGN); telemetry.addr = ao_serial_number; + telemetry.accel_plus_g = ao_config.accel_plus_g; + telemetry.accel_minus_g = ao_config.accel_minus_g; ao_rdf_time = ao_time(); for (;;) { while (ao_telemetry_interval == 0) -- cgit v1.2.3 From bc62bb254085cc705203b57260c04ac5e14c6611 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 4 Nov 2009 21:29:37 -0800 Subject: In packet master, move USB flush from packet thread to echo thread This keeps the packet thread from blocking on USB and also makes the flush happen after every packet (slightly more USB traffic, but packets are slow anyway). Signed-off-by: Keith Packard --- src/ao_packet_master.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index 2751f414..d03899d1 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -27,6 +27,7 @@ ao_packet_getchar(void) break; if (ao_packet_master_sleeping) ao_wake_task(&ao_packet_task); + flush(); ao_sleep(&ao_stdin_ready); } return c; @@ -94,8 +95,6 @@ ao_packet_master(void) continue; if (ao_rx_packet.packet.len) ao_packet_master_busy(); - else - flush(); ao_packet_master_sleeping = 1; ao_delay(ao_packet_master_delay); ao_packet_master_sleeping = 0; -- cgit v1.2.3 From 3ece984f4d72b4f720a5efdfaad7cff77a93d676 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 4 Nov 2009 21:32:07 -0800 Subject: In USB pollchar, wait for packet before re-checking USB out len This probably wouldn't actually cause a problem, but it seems more reliable to wait for a packet interrupt before re-reading the packet OUT len register. This could avoid spinning while waiting for a USB packet, which seems like a good thing. Signed-off-by: Keith Packard --- src/ao_usb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_usb.c b/src/ao_usb.c index daca71a7..527e9b30 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -377,11 +377,13 @@ char ao_usb_pollchar(void) __critical { char c; - while (ao_usb_out_bytes == 0) { + if (ao_usb_out_bytes == 0) { USBINDEX = AO_USB_OUT_EP; if ((USBCSOL & USBCSOL_OUTPKT_RDY) == 0) return AO_READ_AGAIN; ao_usb_out_bytes = (USBCNTH << 8) | USBCNTL; + if (ao_usb_out_bytes == 0) + return AO_READ_AGAIN; } --ao_usb_out_bytes; c = USBFIFO[AO_USB_OUT_EP << 1]; -- cgit v1.2.3 From 036400a2db303f3db3be7cc0426f88359c6bd2b1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 4 Nov 2009 21:42:51 -0800 Subject: Explicitly use USB I/O routines in packet code Using the implicit stdio functions (putchar/getchar/flush) would result in essentially random redirection of each, depending on whether the packet code had characters available when getchar was called. This would cause lockups in putchar. Signed-off-by: Keith Packard --- src/ao_packet_master.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index d03899d1..f3a024ca 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -27,7 +27,7 @@ ao_packet_getchar(void) break; if (ao_packet_master_sleeping) ao_wake_task(&ao_packet_task); - flush(); + ao_usb_flush(); ao_sleep(&ao_stdin_ready); } return c; @@ -40,7 +40,7 @@ ao_packet_echo(void) __reentrant while (ao_packet_enable) { c = ao_packet_getchar(); if (ao_packet_enable) - putchar(c); + ao_usb_putchar(c); } ao_exit(); } @@ -114,7 +114,7 @@ ao_packet_forward(void) __reentrant ao_set_monitor(0); ao_add_task(&ao_packet_task, ao_packet_master, "master"); ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); - while ((c = getchar()) != '~') { + while ((c = ao_usb_getchar()) != '~') { if (c == '\r') c = '\n'; ao_packet_putchar(c); } -- cgit v1.2.3 From 4114210e0b813f4af99d0cb7755ad2ac2c4b120e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Nov 2009 21:43:21 -0800 Subject: Move ao_match_word from ao_ignite.c to ao_cmd.c This is a generally useful command line utility. Signed-off-by: Keith Packard --- src/ao.h | 3 +++ src/ao_cmd.c | 14 ++++++++++++++ src/ao_ignite.c | 14 -------------- 3 files changed, 17 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index bc9afcc3..508ed37a 100644 --- a/src/ao.h +++ b/src/ao.h @@ -350,6 +350,9 @@ ao_cmd_hex(void); void ao_cmd_decimal(void); +uint8_t +ao_match_word(__code char *word); + struct ao_cmds { char cmd; void (*func)(void); diff --git a/src/ao_cmd.c b/src/ao_cmd.c index e3f85bc9..81a52708 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -171,6 +171,20 @@ ao_cmd_decimal(void) ao_cmd_status = r; } +uint8_t +ao_match_word(__code char *word) +{ + while (*word) { + if (ao_cmd_lex_c != *word) { + ao_cmd_status = ao_cmd_syntax_error; + return 0; + } + word++; + ao_cmd_lex(); + } + return 1; +} + static void eol(void) { diff --git a/src/ao_ignite.c b/src/ao_ignite.c index 8206e342..981cf0ce 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -121,20 +121,6 @@ ao_igniter(void) } } -static uint8_t -ao_match_word(__code char *word) -{ - while (*word) { - if (ao_cmd_lex_c != *word) { - ao_cmd_status = ao_cmd_syntax_error; - return 0; - } - word++; - ao_cmd_lex(); - } - return 1; -} - void ao_ignite_manual(void) { -- cgit v1.2.3 From 0358988ac0ee25a564d48af79b1c3fb0c0fe0a88 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Nov 2009 21:44:31 -0800 Subject: Add Watchdog Timer Control register definitions Signed-off-by: Keith Packard --- src/cc1111.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src') diff --git a/src/cc1111.h b/src/cc1111.h index ee4c9f09..e8302df2 100644 --- a/src/cc1111.h +++ b/src/cc1111.h @@ -535,6 +535,23 @@ sfr at 0xB6 ADCCON3; */ sfr at 0xF2 ADCCFG; +/* + * Watchdog timer + */ + +sfr at 0xc9 WDCTL; + +#define WDCTL_CLEAR_FIRST (0xa << 4) +#define WDCTL_CLEAR_SECOND (0x5 << 4) +#define WDCTL_EN (1 << 3) +#define WDCTL_MODE_WATCHDOG (0 << 2) +#define WDCTL_MODE_TIMER (1 << 2) +#define WDCTL_MODE_MASK (1 << 2) +#define WDCTL_INT_32768 (0 << 0) +#define WDCTL_INT_8192 (1 << 0) +#define WDCTL_INT_512 (2 << 0) +#define WDCTL_INT_64 (3 << 0) + /* * Pin selectors, these set which pins are * using their peripheral function -- cgit v1.2.3 From 83afdbdc154fe013bfe35ce5ecf1d61570b04ed6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Nov 2009 21:45:00 -0800 Subject: Add reboot command. This resets the processor using the watchdog timer. Signed-off-by: Keith Packard --- src/ao.h | 1 + src/ao_cmd.c | 12 ++++++++++++ 2 files changed, 13 insertions(+) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 508ed37a..2df81d2a 100644 --- a/src/ao.h +++ b/src/ao.h @@ -107,6 +107,7 @@ ao_start_scheduler(void); #define AO_PANIC_LOG 5 /* Failing to read/write log data */ #define AO_PANIC_CMD 6 /* Too many command sets registered */ #define AO_PANIC_STDIO 7 /* Too many stdio handlers registered */ +#define AO_PANIC_REBOOT 8 /* Reboot failed */ /* Stop the operating system, beeping and blinking the reason */ void diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 81a52708..58039f3a 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -199,6 +199,17 @@ echo(void) lex_echo = ao_cmd_lex_i != 0; } +static void +ao_reboot(void) +{ + ao_cmd_white(); + if (!ao_match_word("eboot")) + return; + WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; + ao_sleep(AO_SEC_TO_TICKS(2)); + ao_panic(AO_PANIC_REBOOT); +} + static void version(void) { @@ -292,6 +303,7 @@ __code struct ao_cmds ao_base_cmds[] = { { '?', help, "? Print this message" }, { 'T', ao_task_info, "T Show task states" }, { 'E', echo, "E <0 off, 1 on> Set command echo mode" }, + { 'r', ao_reboot, "r eboot Reboot" }, { 'v', version, "v Show version" }, { 0, help, NULL }, }; -- cgit v1.2.3 From adf656192441eb7f44792955c86e469145477e29 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 Nov 2009 22:11:59 -0800 Subject: Return radio to telemetry settings when packet system closed. To receive telemetry after disabling the packet system, the radio must be reconfigured for telemetry mode. Signed-off-by: Keith Packard --- src/ao_packet_master.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index f3a024ca..a499ce59 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -100,6 +100,7 @@ ao_packet_master(void) ao_packet_master_sleeping = 0; } } + ao_radio_set_telemetry(); ao_exit(); } -- cgit v1.2.3 From 1c654a9369294c9b8066c33f91161d8005b96680 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Nov 2009 22:17:24 -0800 Subject: Loosen tolerances for main->landed transition Detecting that the rocket has landed is required for the system to flush the eeprom log and re-enable the RDF beacon. This patch changes the landed state entry requirements for the accelerometer to require only that the accelerometer stay within a quarter of a g (down from 1/10g) and changes the testing interval from 20 seconds to 5 seconds. The requirement that the barometric altitude be within 1000m of the launch altitude and that the barometer change by no more than 0.05kPa are unchanged. Signed-off-by: Keith Packard --- src/ao_flight.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index f50491d9..f57573d0 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -75,10 +75,10 @@ __pdata int16_t ao_accel_2g; /* convert m/s to velocity count */ #define VEL_MPS_TO_COUNT(mps) (((int32_t) (((mps) / GRAVITY) * (AO_HERTZ/2))) * (int32_t) ao_accel_2g) -#define ACCEL_G 265 -#define ACCEL_NOSE_UP (ao_accel_2g / 4) +#define ACCEL_NOSE_UP (ao_accel_2g >> 2) #define ACCEL_BOOST ao_accel_2g -#define ACCEL_INT_LAND (ACCEL_G / 10) +#define ACCEL_COAST (ao_accel_2g >> 3) +#define ACCEL_INT_LAND (ao_accel_2g >> 3) #define ACCEL_VEL_MACH VEL_MPS_TO_COUNT(200) #define ACCEL_VEL_BOOST VEL_MPS_TO_COUNT(5) @@ -132,7 +132,7 @@ __xdata int32_t ao_raw_accel_sum, ao_raw_pres_sum; /* Landing is detected by getting constant readings from both pressure and accelerometer * for a fairly long time (AO_INTERVAL_TICKS) */ -#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(20) +#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(5) #define abs(a) ((a) < 0 ? -(a) : (a)) @@ -301,7 +301,7 @@ ao_flight(void) * deceleration, or by waiting until the maximum burn duration * (15 seconds) has past. */ - if (ao_flight_accel > ao_ground_accel + (ACCEL_G >> 2) || + if (ao_flight_accel > ao_ground_accel + ACCEL_COAST || (int16_t) (ao_flight_tick - ao_launch_tick) > BOOST_TICKS_MAX) { ao_flight_state = ao_flight_fast; @@ -432,20 +432,20 @@ ao_flight(void) ao_interval_end = ao_flight_tick + AO_INTERVAL_TICKS; ao_interval_cur_min_pres = ao_interval_cur_max_pres = ao_flight_pres; ao_interval_cur_min_accel = ao_interval_cur_max_accel = ao_flight_accel; - } - if ((uint16_t) (ao_interval_max_accel - ao_interval_min_accel) < (uint16_t) ACCEL_INT_LAND && - ao_flight_pres > ao_ground_pres - BARO_LAND && - (uint16_t) (ao_interval_max_pres - ao_interval_min_pres) < (uint16_t) BARO_INT_LAND) - { - ao_flight_state = ao_flight_landed; + if ((uint16_t) (ao_interval_max_accel - ao_interval_min_accel) < (uint16_t) ACCEL_INT_LAND && + ao_flight_pres > ao_ground_pres - BARO_LAND && + (uint16_t) (ao_interval_max_pres - ao_interval_min_pres) < (uint16_t) BARO_INT_LAND) + { + ao_flight_state = ao_flight_landed; - /* turn off the ADC capture */ - ao_timer_set_adc_interval(0); - /* Enable RDF beacon */ - ao_rdf_set(1); + /* turn off the ADC capture */ + ao_timer_set_adc_interval(0); + /* Enable RDF beacon */ + ao_rdf_set(1); - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } } break; case ao_flight_landed: -- cgit v1.2.3 From 0e0db8ca3af4c07bae909938486766c646bf580b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Nov 2009 22:24:09 -0800 Subject: Provide a dummy 'uninstall' target in the src directory. Signed-off-by: Keith Packard --- src/Makefile | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index d984e9dc..8c24e6f4 100644 --- a/src/Makefile +++ b/src/Makefile @@ -298,6 +298,8 @@ clean: install: +uninstall: + ao_flight_test: ao_flight.c ao_flight_test.c ao_host.h cc -g -o $@ ao_flight_test.c -- cgit v1.2.3 From 3ee279ba76c2a79d142c466f19ef758cf4c01d70 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 15 Nov 2009 15:59:01 -0800 Subject: Add flight number to telemetry stream. This makes it easier to tie the telemetry and eeprom files together as they're now both labeled with serial and flight numbers, which should be unique. Signed-off-by: Keith Packard --- ao-tools/ao-view/aoview_state.c | 1 + ao-tools/lib/cc-telem.c | 7 ++++++ ao-tools/lib/cc.h | 1 + src/ao.h | 11 +++++---- src/ao_log.c | 51 +++++++++++------------------------------ src/ao_monitor.c | 3 ++- src/ao_telemetry.c | 3 +++ 7 files changed, 34 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/ao-tools/ao-view/aoview_state.c b/ao-tools/ao-view/aoview_state.c index a7545c51..2f613d44 100644 --- a/ao-tools/ao-view/aoview_state.c +++ b/ao-tools/ao-view/aoview_state.c @@ -288,6 +288,7 @@ aoview_state_notify(struct cc_telem *data) aoview_table_add_row(0, "Rocket state", "%s", state->data.state); aoview_table_add_row(0, "Callsign", "%s", state->data.callsign); aoview_table_add_row(0, "Rocket serial", "%d", state->data.serial); + aoview_table_add_row(0, "Rocket flight", "%d", state->data.flight); aoview_table_add_row(0, "RSSI", "%6ddBm", state->data.rssi); aoview_table_add_row(0, "Height", "%6dm", state->height); diff --git a/ao-tools/lib/cc-telem.c b/ao-tools/lib/cc-telem.c index f82ab961..0e1483f7 100644 --- a/ao-tools/lib/cc-telem.c +++ b/ao-tools/lib/cc-telem.c @@ -93,6 +93,13 @@ cc_telem_parse(const char *input_line, struct cc_telem *telem) cc_parse_string(telem->callsign, sizeof (telem->callsign), words[1]); cc_parse_int(&telem->serial, words[3]); + if (version >= 2) { + cc_parse_int(&telem->flight, words[5]); + words += 2; + nword -= 2; + } else + telem->flight = 0; + cc_parse_int(&telem->rssi, words[5]); cc_parse_string(telem->state, sizeof (telem->state), words[9]); cc_parse_int(&telem->tick, words[10]); diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index fd461e5c..b8e3c061 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -238,6 +238,7 @@ struct cc_gps_tracking { struct cc_telem { char callsign[16]; int serial; + int flight; int rssi; char state[16]; int tick; diff --git a/src/ao.h b/src/ao.h index 2df81d2a..f266ac64 100644 --- a/src/ao.h +++ b/src/ao.h @@ -553,11 +553,11 @@ ao_log_data(struct ao_log_record *log); void ao_log_flush(void); -/* Log dumping API: - * ao_log_dump_first() - get first log record - * ao_log_dump_next() - get next log record +/* We record flight numbers in the first record of + * the log. Tasks may wait for this to be initialized + * by sleeping on this variable. */ -extern __xdata struct ao_log_record ao_log_dump; +extern __xdata uint16_t ao_flight_number; /* Retrieve first log record for the current flight */ uint8_t @@ -788,10 +788,11 @@ ao_gps_report_init(void); */ #define AO_MAX_CALLSIGN 8 -#define AO_TELEMETRY_VERSION 1 +#define AO_TELEMETRY_VERSION 2 struct ao_telemetry { uint8_t addr; + uint16_t flight; uint8_t flight_state; int16_t flight_accel; int16_t ground_accel; diff --git a/src/ao_log.c b/src/ao_log.c index 50778f55..44ce90e0 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -59,51 +59,30 @@ ao_log_flush(void) ao_ee_flush(); } -__xdata struct ao_log_record ao_log_dump; -static __xdata uint16_t ao_log_dump_flight; -static __xdata uint32_t ao_log_dump_pos; +__xdata struct ao_log_record log; +__xdata uint16_t ao_flight_number; static uint8_t ao_log_dump_check_data(void) { - if (ao_log_csum((uint8_t *) &ao_log_dump) != 0) + if (ao_log_csum((uint8_t *) &log) != 0) return 0; return 1; } -static uint8_t -ao_log_dump_scan(void) +static void +ao_log_scan(void) { - if (!ao_ee_read(0, (uint8_t *) &ao_log_dump, sizeof (struct ao_log_record))) + if (!ao_ee_read(0, (uint8_t *) &log, sizeof (struct ao_log_record))) ao_panic(AO_PANIC_LOG); - if (ao_log_dump_check_data() && ao_log_dump.type == AO_LOG_FLIGHT) { - ao_log_dump_flight = ao_log_dump.u.flight.flight; - return 1; + if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) { + ao_flight_number = log.u.flight.flight + 1; + if (ao_flight_number == 0) + ao_flight_number = 1; } else { - ao_log_dump_flight = 0; - return 0; + ao_flight_number = 1; } -} - -uint8_t -ao_log_dump_first(void) -{ - ao_log_dump_pos = 0; - if (!ao_log_dump_scan()) - return 0; - return 1; -} - -uint8_t -ao_log_dump_next(void) -{ - ao_log_dump_pos += sizeof (struct ao_log_record); - if (ao_log_dump_pos >= AO_EE_DEVICE_SIZE) - return 0; - if (!ao_ee_read(ao_log_dump_pos, (uint8_t *) &ao_log_dump, - sizeof (struct ao_log_record))) - return 0; - return ao_log_dump_check_data(); + ao_wakeup(&ao_flight_number); } __xdata uint8_t ao_log_adc_pos; @@ -115,9 +94,7 @@ typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; void ao_log(void) { - static __xdata struct ao_log_record log; - - ao_log_dump_scan(); + ao_log_scan(); while (!ao_log_running) ao_sleep(&ao_log_running); @@ -125,7 +102,7 @@ ao_log(void) log.type = AO_LOG_FLIGHT; log.tick = ao_flight_tick; log.u.flight.ground_accel = ao_ground_accel; - log.u.flight.flight = ao_log_dump_flight + 1; + log.u.flight.flight = ao_flight_number; ao_log_data(&log); /* Write the whole contents of the ring to the log diff --git a/src/ao_monitor.c b/src/ao_monitor.c index cd0d693e..628b6e67 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -37,10 +37,11 @@ ao_monitor(void) if (state > ao_flight_invalid) state = ao_flight_invalid; if (recv.status & PKT_APPEND_STATUS_1_CRC_OK) { - printf("VERSION %d CALL %s SERIAL %3d RSSI %4d STATUS %02x STATE %7s ", + printf("VERSION %d CALL %s SERIAL %3d FLIGHT %5u RSSI %4d STATUS %02x STATE %7s ", AO_TELEMETRY_VERSION, callsign, recv.telemetry.addr, + recv.telemetry.flight, (int) recv.rssi - 74, recv.status, ao_state_names[state]); printf("%5u a: %5d p: %5d t: %5d v: %5d d: %5d m: %5d " diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 9c923984..88ac142c 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -30,8 +30,11 @@ ao_telemetry(void) static __xdata struct ao_telemetry telemetry; ao_config_get(); + while (!ao_flight_number) + ao_sleep(&ao_flight_number); memcpy(telemetry.callsign, ao_config.callsign, AO_MAX_CALLSIGN); telemetry.addr = ao_serial_number; + telemetry.flight = ao_flight_number; telemetry.accel_plus_g = ao_config.accel_plus_g; telemetry.accel_minus_g = ao_config.accel_minus_g; ao_rdf_time = ao_time(); -- cgit v1.2.3 From 524665fc221b0d483453c67b7211e282cebc8980 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 15 Nov 2009 16:04:41 -0800 Subject: Add date to GPS data, captured from GPRMC packet. Pull the date out of the GPS stream and send it over the telemetry link and write it to the eeprom. Signed-off-by: Keith Packard --- ao-tools/ao-view/aoview_state.c | 4 +++ ao-tools/lib/cc-telem.c | 12 ++++++++ ao-tools/lib/cc.h | 3 ++ src/ao.h | 10 ++++++ src/ao_gps_print.c | 4 +++ src/ao_gps_report.c | 12 ++++++-- src/ao_gps_skytraq.c | 67 ++++++++++++++++++++++++++++++++++++----- src/ao_gps_test.c | 4 +++ src/ao_gps_test_skytraq.c | 4 +++ 9 files changed, 111 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/ao-tools/ao-view/aoview_state.c b/ao-tools/ao-view/aoview_state.c index 2f613d44..21cea99a 100644 --- a/ao-tools/ao-view/aoview_state.c +++ b/ao-tools/ao-view/aoview_state.c @@ -315,6 +315,10 @@ aoview_state_notify(struct cc_telem *data) aoview_state_add_deg(1, "Longitude", state->gps.lon, 'E', 'W'); aoview_table_add_row(1, "GPS altitude", "%d", state->gps.alt); aoview_table_add_row(1, "GPS height", "%d", state->gps_height); + aoview_table_add_row(1, "GPS date", "%04d-%02d-%02d", + state->gps.gps_time.year, + state->gps.gps_time.month, + state->gps.gps_time.day); aoview_table_add_row(1, "GPS time", "%02d:%02d:%02d", state->gps.gps_time.hour, state->gps.gps_time.minute, diff --git a/ao-tools/lib/cc-telem.c b/ao-tools/lib/cc-telem.c index 0e1483f7..9a2f6155 100644 --- a/ao-tools/lib/cc-telem.c +++ b/ao-tools/lib/cc-telem.c @@ -127,6 +127,7 @@ cc_telem_parse(const char *input_line, struct cc_telem *telem) if (strcmp (words[36], "unlocked") == 0) { telem->gps.gps_connected = 1; telem->gps.gps_locked = 0; + telem->gps.gps_time.year = telem->gps.gps_time.month = telem->gps.gps_time.day = 0; telem->gps.gps_time.hour = telem->gps.gps_time.minute = telem->gps.gps_time.second = 0; telem->gps.lat = telem->gps.lon = 0; telem->gps.alt = 0; @@ -134,6 +135,16 @@ cc_telem_parse(const char *input_line, struct cc_telem *telem) } else if (nword >= 40) { telem->gps.gps_locked = 1; telem->gps.gps_connected = 1; + if (version >= 2) { + sscanf(words[36], "%d-%d-%d", + &telem->gps.gps_time.year, + &telem->gps.gps_time.month, + &telem->gps.gps_time.day); + words += 1; + nword -= 1; + } else { + telem->gps.gps_time.year = telem->gps.gps_time.month = telem->gps.gps_time.day = 0; + } sscanf(words[36], "%d:%d:%d", &telem->gps.gps_time.hour, &telem->gps.gps_time.minute, &telem->gps.gps_time.second); cc_parse_pos(&telem->gps.lat, words[37]); cc_parse_pos(&telem->gps.lon, words[38]); @@ -142,6 +153,7 @@ cc_telem_parse(const char *input_line, struct cc_telem *telem) } else { telem->gps.gps_connected = 0; telem->gps.gps_locked = 0; + telem->gps.gps_time.year = telem->gps.gps_time.month = telem->gps.gps_time.day = 0; telem->gps.gps_time.hour = telem->gps.gps_time.minute = telem->gps.gps_time.second = 0; telem->gps.lat = telem->gps.lon = 0; telem->gps.alt = 0; diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index b8e3c061..ebc0db7d 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -192,6 +192,9 @@ struct cc_flightcooked { struct cc_gps_time { + int year; + int month; + int day; int hour; int minute; int second; diff --git a/src/ao.h b/src/ao.h index f266ac64..c1a0f6e3 100644 --- a/src/ao.h +++ b/src/ao.h @@ -493,6 +493,7 @@ ao_ee_init(void); #define AO_LOG_GPS_LON 'W' #define AO_LOG_GPS_ALT 'H' #define AO_LOG_GPS_SAT 'V' +#define AO_LOG_GPS_DATE 'Y' #define AO_LOG_POS_NONE (~0UL) @@ -538,6 +539,11 @@ struct ao_log_record { uint8_t state; uint8_t c_n; } gps_sat; + struct { + uint8_t year; + uint8_t month; + uint8_t day; + } gps_date; struct { uint16_t d0; uint16_t d1; @@ -720,8 +726,12 @@ ao_serial_init(void); #define AO_GPS_VALID (1 << 4) #define AO_GPS_RUNNING (1 << 5) +#define AO_GPS_DATE_VALID (1 << 6) struct ao_gps_data { + uint8_t year; + uint8_t month; + uint8_t day; uint8_t hour; uint8_t minute; uint8_t second; diff --git a/src/ao_gps_print.c b/src/ao_gps_print.c index cc751337..95439ec7 100644 --- a/src/ao_gps_print.c +++ b/src/ao_gps_print.c @@ -53,6 +53,10 @@ ao_gps_print(__xdata struct ao_gps_data *gps_data) __reentrant ao_gps_split(gps_data->latitude, &lat); ao_gps_split(gps_data->longitude, &lon); + printf(" 20%02d-%02d-%02d", + gps_data->year, + gps_data->month, + gps_data->day); printf(" %2d:%02d:%02d", gps_data->hour, gps_data->minute, diff --git a/src/ao_gps_report.c b/src/ao_gps_report.c index 75c944f5..e3e27523 100644 --- a/src/ao_gps_report.c +++ b/src/ao_gps_report.c @@ -22,6 +22,7 @@ ao_gps_report(void) { static __xdata struct ao_log_record gps_log; static __xdata struct ao_gps_data gps_data; + uint8_t date_reported = 0; for (;;) { ao_sleep(&ao_gps_data); @@ -49,6 +50,14 @@ ao_gps_report(void) gps_log.u.gps_altitude.altitude = gps_data.altitude; gps_log.u.gps_altitude.unused = 0xffff; ao_log_data(&gps_log); + if (!date_reported && (gps_data.flags & AO_GPS_DATE_VALID)) { + date_reported = 1; + gps_log.type = AO_LOG_GPS_DATE; + gps_log.u.gps_date.year = gps_data.year; + gps_log.u.gps_date.month = gps_data.month; + gps_log.u.gps_date.day = gps_data.day; + ao_log_data(&gps_log); + } } } @@ -71,8 +80,7 @@ ao_gps_tracking_report(void) gps_log.tick = ao_time(); gps_log.type = AO_LOG_GPS_SAT; for (c = 0; c < n; c++) - if ((gps_log.u.gps_sat.svid = gps_tracking_data.sats[c].svid) && - (gps_log.u.gps_sat.state = gps_tracking_data.sats[c].state)) + if ((gps_log.u.gps_sat.svid = gps_tracking_data.sats[c].svid)) { gps_log.u.gps_sat.c_n = gps_tracking_data.sats[c].c_n_1; ao_log_data(&gps_log); diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index cd5f78b9..b2eef04b 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -19,9 +19,9 @@ #include "ao.h" #endif -#define AO_GPS_LEADER 3 +#define AO_GPS_LEADER 2 -static const char ao_gps_header[] = "GPG"; +static const char ao_gps_header[] = "GP"; __xdata uint8_t ao_gps_mutex; static __xdata char ao_gps_char; @@ -32,6 +32,7 @@ __xdata struct ao_gps_data ao_gps_data; __xdata struct ao_gps_tracking_data ao_gps_tracking_data; static __xdata struct ao_gps_data ao_gps_next; +static __xdata uint8_t ao_gps_date_flags; static __xdata struct ao_gps_tracking_data ao_gps_tracking_next; static const char ao_gps_config[] = { @@ -181,7 +182,7 @@ ao_gps_parse_flag(char no_c, char yes_c) __reentrant void ao_gps(void) __reentrant { - char c; + char a, c; uint8_t i; ao_serial_set_speed(AO_SERIAL_SPEED_9600); @@ -198,7 +199,7 @@ ao_gps(void) __reentrant ao_gps_cksum = 0; ao_gps_error = 0; - /* Skip anything other than GPG */ + /* Skip anything other than GP */ for (i = 0; i < AO_GPS_LEADER; i++) { ao_gps_lexchar(); if (ao_gps_char != ao_gps_header[i]) @@ -209,6 +210,8 @@ ao_gps(void) __reentrant /* pull the record identifier characters off the link */ ao_gps_lexchar(); + a = ao_gps_char; + ao_gps_lexchar(); c = ao_gps_char; ao_gps_lexchar(); i = ao_gps_char; @@ -216,7 +219,7 @@ ao_gps(void) __reentrant if (ao_gps_char != ',') continue; - if (c == (uint8_t) 'G' && i == (uint8_t) 'A') { + if (a == (uint8_t) 'G' && c == (uint8_t) 'G' && i == (uint8_t) 'A') { /* Now read the data into the gps data record * * $GPGGA,025149.000,4528.1723,N,12244.2480,W,1,05,2.0,103.5,M,-19.5,M,,0000*66 @@ -245,7 +248,7 @@ ao_gps(void) __reentrant * *66 checksum */ - ao_gps_next.flags = AO_GPS_RUNNING; + ao_gps_next.flags = AO_GPS_RUNNING | ao_gps_date_flags; ao_gps_next.hour = ao_gps_decimal(2); ao_gps_next.minute = ao_gps_decimal(2); ao_gps_next.second = ao_gps_decimal(2); @@ -290,7 +293,7 @@ ao_gps(void) __reentrant ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_data); } - } else if (c == (uint8_t) 'S' && i == (uint8_t) 'V') { + } else if (a == (uint8_t) 'G' && c == (uint8_t) 'S' && i == (uint8_t) 'V') { uint8_t done; /* Now read the data into the GPS tracking data record * @@ -345,6 +348,56 @@ ao_gps(void) __reentrant ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_tracking_data); } + } else if (a == (uint8_t) 'R' && c == (uint8_t) 'M' && i == (uint8_t) 'C') { + /* Parse the RMC record to read out the current date */ + + /* $GPRMC,111636.932,A,2447.0949,N,12100.5223,E,000.0,000.0,030407,,,A*61 + * + * Recommended Minimum Specific GNSS Data + * + * 111636.932 UTC time 11:16:36.932 + * A Data Valid (V = receiver warning) + * 2447.0949 Latitude + * N North/south indicator + * 12100.5223 Longitude + * E East/west indicator + * 000.0 Speed over ground + * 000.0 Course over ground + * 030407 UTC date (ddmmyy format) + * A Mode indicator: + * N = data not valid + * A = autonomous mode + * D = differential mode + * E = estimated (dead reckoning) mode + * M = manual input mode + * S = simulator mode + * 61 checksum + */ + ao_gps_skip_field(); + for (i = 0; i < 8; i++) { + ao_gps_lexchar(); + ao_gps_skip_field(); + } + a = ao_gps_decimal(2); + c = ao_gps_decimal(2); + i = ao_gps_decimal(2); + /* Skip remaining fields */ + while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { + ao_gps_lexchar(); + ao_gps_skip_field(); + } + if (ao_gps_char == '*') { + uint8_t cksum = ao_gps_cksum ^ '*'; + if (cksum != ao_gps_hex(2)) + ao_gps_error = 1; + } else + ao_gps_error = 1; + if (!ao_gps_error) { + ao_gps_next.year = i; + ao_gps_next.month = c; + ao_gps_next.day = a; + ao_gps_date_flags = AO_GPS_DATE_VALID; + } } } } diff --git a/src/ao_gps_test.c b/src/ao_gps_test.c index 366bca71..3692f0e5 100644 --- a/src/ao_gps_test.c +++ b/src/ao_gps_test.c @@ -27,8 +27,12 @@ #define AO_GPS_VALID (1 << 4) #define AO_GPS_RUNNING (1 << 5) +#define AO_GPS_DATE_VALID (1 << 6) struct ao_gps_data { + uint8_t year; + uint8_t month; + uint8_t day; uint8_t hour; uint8_t minute; uint8_t second; diff --git a/src/ao_gps_test_skytraq.c b/src/ao_gps_test_skytraq.c index 510bc419..ccf96378 100644 --- a/src/ao_gps_test_skytraq.c +++ b/src/ao_gps_test_skytraq.c @@ -27,8 +27,12 @@ #define AO_GPS_VALID (1 << 4) #define AO_GPS_RUNNING (1 << 5) +#define AO_GPS_DATE_VALID (1 << 6) struct ao_gps_data { + uint8_t year; + uint8_t month; + uint8_t day; uint8_t hour; uint8_t minute; uint8_t second; -- cgit v1.2.3 From b0d7e3f9c9322542e9b649bb6ad7f7e5bb99dffa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 15 Nov 2009 16:20:18 -0800 Subject: Stop using SiRF state info. With the switch to the skytraq GPS unit, we don't have the same level of detail in the GPS stream, so stop reporting that in the telemetry stream, in the UI and writing it to eeprom. Signed-off-by: Keith Packard --- ao-tools/ao-postflight/ao-postflight.c | 4 ++-- ao-tools/lib/cc-logfile.c | 1 - ao-tools/lib/cc-telem.c | 17 ++++++++++++----- ao-tools/lib/cc.h | 1 - src/ao.h | 12 +----------- src/ao_gps_print.c | 7 +++---- src/ao_gps_sirf.c | 5 +---- src/ao_gps_skytraq.c | 6 ++---- src/ao_gps_test.c | 5 ++--- 9 files changed, 23 insertions(+), 35 deletions(-) (limited to 'src') diff --git a/ao-tools/ao-postflight/ao-postflight.c b/ao-tools/ao-postflight/ao-postflight.c index 733eb38c..c12939aa 100644 --- a/ao-tools/ao-postflight/ao-postflight.c +++ b/ao-tools/ao-postflight/ao-postflight.c @@ -360,7 +360,7 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, nsat = 0; for (k = 0; k < f->gps.sats[j].nsat; k++) { fprintf (gps_file, " %12.7f", (double) f->gps.sats[j].sat[k].c_n); - if (f->gps.sats[j].sat[k].state == 0xbf) + if (f->gps.sats[j].sat[k].svid != 0) nsat++; } fprintf(gps_file, " %d\n", nsat); @@ -381,7 +381,7 @@ analyse_flight(struct cc_flightraw *f, FILE *summary_file, FILE *detail_file, } nsat = 0; for (k = 0; k < f->gps.sats[j].nsat; k++) - if (f->gps.sats[j].sat[k].state == 0xbf) + if (f->gps.sats[j].sat[k].svid != 0) nsat++; fprintf(kml_file, "%12.7f, %12.7f, %12.7f ", diff --git a/ao-tools/lib/cc-logfile.c b/ao-tools/lib/cc-logfile.c index 3d346bcc..9d086c82 100644 --- a/ao-tools/lib/cc-logfile.c +++ b/ao-tools/lib/cc-logfile.c @@ -212,7 +212,6 @@ read_eeprom(const char *line, struct cc_flightraw *f, double *ground_pres, int * case AO_LOG_GPS_SAT: sat.time = tick; sat.svid = a; - sat.state = (b & 0xff); sat.c_n = (b >> 8) & 0xff; gpssat_add(&f->gps, &sat); break; diff --git a/ao-tools/lib/cc-telem.c b/ao-tools/lib/cc-telem.c index 9a2f6155..ccd40ac2 100644 --- a/ao-tools/lib/cc-telem.c +++ b/ao-tools/lib/cc-telem.c @@ -178,18 +178,25 @@ cc_telem_parse(const char *input_line, struct cc_telem *telem) } if (tracking_pos >= 0 && nword >= tracking_pos + 2 && strcmp(words[tracking_pos], "SAT") == 0) { int c, n, pos; + int per_sat; + int state; + + if (version >= 2) + per_sat = 2; + else + per_sat = 3; cc_parse_int(&n, words[tracking_pos + 1]); pos = tracking_pos + 2; - if (nword >= pos + n * 3) { + if (nword >= pos + n * per_sat) { telem->gps_tracking.channels = n; for (c = 0; c < n; c++) { cc_parse_int(&telem->gps_tracking.sats[c].svid, words[pos + 0]); - cc_parse_hex(&telem->gps_tracking.sats[c].state, - words[pos + 1]); + if (version < 2) + cc_parse_hex(&state, words[pos + 1]); cc_parse_int(&telem->gps_tracking.sats[c].c_n0, - words[pos + 2]); - pos += 3; + words[pos + per_sat - 1]); + pos += per_sat; } } else { telem->gps_tracking.channels = 0; diff --git a/ao-tools/lib/cc.h b/ao-tools/lib/cc.h index ebc0db7d..0e8ced8a 100644 --- a/ao-tools/lib/cc.h +++ b/ao-tools/lib/cc.h @@ -103,7 +103,6 @@ struct cc_gpselt { struct cc_gpssat { double time; uint16_t svid; - uint8_t state; uint8_t c_n; }; diff --git a/src/ao.h b/src/ao.h index c1a0f6e3..b72cac5c 100644 --- a/src/ao.h +++ b/src/ao.h @@ -536,7 +536,7 @@ struct ao_log_record { } gps_altitude; struct { uint16_t svid; - uint8_t state; + uint8_t unused; uint8_t c_n; } gps_sat; struct { @@ -747,18 +747,8 @@ struct ao_gps_data { uint16_t v_error; /* m */ }; -#define SIRF_SAT_STATE_ACQUIRED (1 << 0) -#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) -#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) -#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) -#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) -#define SIRF_SAT_CODE_LOCKED (1 << 5) -#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) -#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) - struct ao_gps_sat_data { uint8_t svid; - uint8_t state; uint8_t c_n_1; }; diff --git a/src/ao_gps_print.c b/src/ao_gps_print.c index 95439ec7..b8b73cd2 100644 --- a/src/ao_gps_print.c +++ b/src/ao_gps_print.c @@ -112,17 +112,16 @@ ao_gps_tracking_print(__xdata struct ao_gps_tracking_data *gps_tracking_data) __ sat = gps_tracking_data->sats; v = 0; for (c = 0; c < n; c++) { - if (sat->svid && sat->state) + if (sat->svid) v++; sat++; } printf("%d ", v); sat = gps_tracking_data->sats; for (c = 0; c < n; c++) { - if (sat->svid && sat->state) - printf (" %3d %02x %3d", + if (sat->svid) + printf (" %3d %3d", sat->svid, - sat->state, sat->c_n_1); sat++; } diff --git a/src/ao_gps_sirf.c b/src/ao_gps_sirf.c index 58438760..eb00224c 100644 --- a/src/ao_gps_sirf.c +++ b/src/ao_gps_sirf.c @@ -108,7 +108,6 @@ static __xdata struct sirf_geodetic_nav_data ao_sirf_data; struct sirf_measured_sat_data { uint8_t svid; - uint16_t state; uint8_t c_n_1; }; @@ -264,8 +263,7 @@ static const struct sirf_packet_parse measured_tracker_data_packet[] = { static const struct sirf_packet_parse measured_sat_data_packet[] = { { SIRF_U8, offsetof (struct sirf_measured_sat_data, svid) }, /* 0 SV id */ - { SIRF_DISCARD, 2 }, /* 1 azimuth, 2 elevation */ - { SIRF_U16, offsetof (struct sirf_measured_sat_data, state) }, /* 2 state */ + { SIRF_DISCARD, 4 }, /* 1 azimuth, 2 elevation, 3 state */ { SIRF_U8, offsetof (struct sirf_measured_sat_data, c_n_1) }, /* C/N0 1 */ { SIRF_DISCARD, 9 }, /* C/N0 2-10 */ { SIRF_END, 0 }, @@ -421,7 +419,6 @@ ao_gps(void) __reentrant ao_gps_tracking_data.channels = ao_sirf_tracker_data.channels; for (i = 0; i < 12; i++) { ao_gps_tracking_data.sats[i].svid = ao_sirf_tracker_data.sats[i].svid; - ao_gps_tracking_data.sats[i].state = (uint8_t) ao_sirf_tracker_data.sats[i].state; ao_gps_tracking_data.sats[i].c_n_1 = ao_sirf_tracker_data.sats[i].c_n_1; } ao_mutex_put(&ao_gps_mutex); diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index b2eef04b..bf192f28 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -326,10 +326,8 @@ ao_gps(void) __reentrant ao_gps_skip_field(); /* elevation */ ao_gps_lexchar(); ao_gps_skip_field(); /* azimuth */ - if (ao_gps_tracking_next.sats[i].c_n_1 = ao_gps_decimal(2)) /* C/N0 */ - ao_gps_tracking_next.sats[i].state = 0xbf; - else - ao_gps_tracking_next.sats[i].state = 0; + if (!(ao_gps_tracking_next.sats[i].c_n_1 = ao_gps_decimal(2))) /* C/N0 */ + ao_gps_tracking_next.sats[i].svid = 0; ao_gps_tracking_next.channels = i + 1; } if (ao_gps_char == '*') { diff --git a/src/ao_gps_test.c b/src/ao_gps_test.c index 3692f0e5..fddfedfd 100644 --- a/src/ao_gps_test.c +++ b/src/ao_gps_test.c @@ -59,7 +59,6 @@ struct ao_gps_data { struct ao_gps_sat_data { uint8_t svid; - uint8_t state; uint8_t c_n_1; }; @@ -435,9 +434,9 @@ ao_dump_state(void *wchan) printf("\n"); printf ("\t"); for (i = 0; i < 12; i++) - printf (" %2d(%02x)", + printf (" %2d(%02d)", ao_gps_tracking_data.sats[i].svid, - ao_gps_tracking_data.sats[i].state); + ao_gps_tracking_data.sats[i].c_n_1); printf ("\n"); } -- cgit v1.2.3 From b75aa1c825b84bd7fa1578320fbc7e904c373a7d Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 19 Nov 2009 21:43:13 -0700 Subject: fix typo in comment --- src/ao_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_config.c b/src/ao_config.c index 85fcff8c..e82aa015 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -54,7 +54,7 @@ _ao_config_get(void) ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { - /* Fixups for mior version 1 */ + /* Fixups for minor version 1 */ if (ao_config.minor < 1) ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; /* Fixupes for minor version 2 */ -- cgit v1.2.3 From 6894541e0ee144bfc689cc02d4ed333711d3b500 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 20 Nov 2009 11:55:28 -0800 Subject: Reduce igniter firing time from 500ms to 50ms. Given that the system will brown-out with the longer pulse, it doesn't make sense to even try; failure at 50ms probably indicates a short. Signed-off-by: Keith Packard --- src/ao_ignite.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_ignite.c b/src/ao_ignite.c index 981cf0ce..4093b6a7 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -26,7 +26,7 @@ /* test these values with real igniters */ #define AO_IGNITER_OPEN 1000 #define AO_IGNITER_CLOSED 7000 -#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(500) +#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) #define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) struct ao_ignition { -- cgit v1.2.3 From 80b23f3044a654d61212891a61fadb8a3a4e5572 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 21 Nov 2009 18:57:45 -0800 Subject: Decode HDOP data from skytraq GPS The hdop data was getting dropped on the floor, but is rather useful when deciding if the GPS position is crazy or not. This reports HDOP * 5 (giving a useful range of .2-50). Signed-off-by: Keith Packard --- src/ao_gps_skytraq.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index bf192f28..ef581349 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -271,7 +271,15 @@ ao_gps(void) __reentrant ao_gps_next.flags |= i; ao_gps_lexchar(); - ao_gps_skip_field(); /* Horizontal dilution */ + ao_gps_next.hdop = ao_gps_decimal(0xff); + if (ao_gps_next.hdop <= 50) { + ao_gps_next.hdop = (uint8_t) 5 * ao_gps_next.hdop; + if (ao_gps_char == '.') + ao_gps_next.hdop = (ao_gps_next.hdop + + ((uint8_t) ao_gps_decimal(1) >> 1)); + } else + ao_gps_next.hdop = 255; + ao_gps_skip_field(); ao_gps_next.altitude = ao_gps_decimal(0xff); ao_gps_skip_field(); /* skip any fractional portion */ -- cgit v1.2.3 From 199f0cecae22645140185238682b9e1aba0e5715 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 21 Nov 2009 20:36:20 -0800 Subject: Make TD print 0000-00-00 for invalid dates. This 'shouldn't' happen, but in case it does, I want to know about it. Signed-off-by: Keith Packard --- src/ao_gps_print.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ao_gps_print.c b/src/ao_gps_print.c index b8b73cd2..11213174 100644 --- a/src/ao_gps_print.c +++ b/src/ao_gps_print.c @@ -53,10 +53,13 @@ ao_gps_print(__xdata struct ao_gps_data *gps_data) __reentrant ao_gps_split(gps_data->latitude, &lat); ao_gps_split(gps_data->longitude, &lon); - printf(" 20%02d-%02d-%02d", - gps_data->year, - gps_data->month, - gps_data->day); + if (gps_data->flags & AO_GPS_DATE_VALID) + printf(" 20%02d-%02d-%02d", + gps_data->year, + gps_data->month, + gps_data->day); + else + printf (" 0000-00-00"); printf(" %2d:%02d:%02d", gps_data->hour, gps_data->minute, -- cgit v1.2.3 From 9a1d7dd78c07d18954ef620b6ed25d6701df21e2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 4 Dec 2009 14:35:39 -0800 Subject: Change default callsign to "N0CALL" --- src/ao_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_config.c b/src/ao_config.c index e82aa015..7f76a585 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -24,7 +24,7 @@ __xdata uint8_t ao_config_mutex; #define AO_CONFIG_DEFAULT_MAIN_DEPLOY 250 #define AO_CONFIG_DEFAULT_RADIO_CHANNEL 0 -#define AO_CONFIG_DEFAULT_CALLSIGN "KD7SQG" +#define AO_CONFIG_DEFAULT_CALLSIGN "N0CALL" #define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000 #define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 -- cgit v1.2.3 From e6d6ad66ce177eb6e49eaa04b1ecc6426f4bbdbf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 4 Dec 2009 23:35:40 -0800 Subject: Remove send_serial and serial_baud commands. No longer useful, and they take up space. Signed-off-by: Keith Packard --- src/ao_serial.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) (limited to 'src') diff --git a/src/ao_serial.c b/src/ao_serial.c index 1e3ea3e3..3f103766 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -85,16 +85,6 @@ ao_serial_drain(void) __critical ao_sleep(&ao_usart1_tx_fifo); } -static void -send_serial(void) -{ - ao_cmd_white(); - while (ao_cmd_lex_c != '\n') { - ao_serial_putchar(ao_cmd_lex_c); - ao_cmd_lex(); - } -} - static void monitor_serial(void) { @@ -102,18 +92,9 @@ monitor_serial(void) serial_echo = ao_cmd_lex_i != 0; } -static void -serial_baud(void) -{ - ao_cmd_hex(); - ao_serial_set_speed(ao_cmd_lex_i); -} - __code struct ao_cmds ao_serial_cmds[] = { - { 'S', send_serial, "S Send data to serial line" }, { 'M', monitor_serial, "M Monitor serial data" }, - { 'B', serial_baud, "B <0 = 4800, 1 = 57600> Set serial baud rate" }, - { 0, send_serial, NULL }, + { 0, monitor_serial, NULL }, }; static const struct { -- cgit v1.2.3 From c671a3f31f54715284beef5baa4a72ca922e4018 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 4 Dec 2009 23:36:54 -0800 Subject: Make ao_cmd_decimal produce both 32 and 16 bit values. ao_cmd_lex_u32 is produced in addition to ao_cmd_lex_i so that functions can easily read 32-bit values from the command line. Signed-off-by: Keith Packard --- src/ao.h | 1 + src/ao_cmd.c | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index b72cac5c..287c912d 100644 --- a/src/ao.h +++ b/src/ao.h @@ -330,6 +330,7 @@ enum ao_cmd_status { }; extern __xdata uint16_t ao_cmd_lex_i; +extern __xdata uint32_t ao_cmd_lex_u32; extern __xdata char ao_cmd_lex_c; extern __xdata enum ao_cmd_status ao_cmd_status; diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 58039f3a..b6d2b886 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -18,6 +18,7 @@ #include "ao.h" __xdata uint16_t ao_cmd_lex_i; +__xdata uint32_t ao_cmd_lex_u32; __xdata char ao_cmd_lex_c; __xdata enum ao_cmd_status ao_cmd_status; static __xdata uint8_t lex_echo; @@ -157,11 +158,11 @@ ao_cmd_decimal(void) { __xdata uint8_t r = ao_cmd_lex_error; - ao_cmd_lex_i = 0; + ao_cmd_lex_u32 = 0; ao_cmd_white(); for(;;) { 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'); + ao_cmd_lex_u32 = (ao_cmd_lex_u32 * 10) + (ao_cmd_lex_c - '0'); else break; r = ao_cmd_success; @@ -169,6 +170,7 @@ ao_cmd_decimal(void) } if (r != ao_cmd_success) ao_cmd_status = r; + ao_cmd_lex_i = (uint16_t) ao_cmd_lex_u32; } uint8_t -- cgit v1.2.3 From cd49847f3125df1733f298b56a43e8027ab5ce05 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 4 Dec 2009 23:38:26 -0800 Subject: Add radio calibration configuration. The crystal we use is only good for 20ppm, which generates a fairly significant error bounds at our RF frequency. This commit adds a configuration variable that sets the RF frequency control variable so that the output frequency can be adjusted. Signed-off-by: Keith Packard --- src/ao.h | 9 +++++---- src/ao_config.c | 34 +++++++++++++++++++++++++++++++++- src/ao_radio.c | 52 ++++++++++++++++++++++++---------------------------- 3 files changed, 62 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 287c912d..d8e1b92a 100644 --- a/src/ao.h +++ b/src/ao.h @@ -938,17 +938,18 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 2 +#define AO_CONFIG_MINOR 3 struct ao_config { uint8_t major; uint8_t minor; uint16_t main_deploy; - int16_t accel_plus_g; + int16_t accel_plus_g; /* changed for minor version 2 */ uint8_t radio_channel; char callsign[AO_MAX_CALLSIGN + 1]; - uint8_t apogee_delay; - int16_t accel_minus_g; + uint8_t apogee_delay; /* minor version 1 */ + int16_t accel_minus_g; /* minor version 2 */ + uint32_t radio_frequency; /* minor version 3 */ }; extern __xdata struct ao_config ao_config; diff --git a/src/ao_config.c b/src/ao_config.c index 7f76a585..27a60ac1 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -27,6 +27,12 @@ __xdata uint8_t ao_config_mutex; #define AO_CONFIG_DEFAULT_CALLSIGN "N0CALL" #define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000 #define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 +/* + * For 434.550MHz, the frequency value is: + * + * 434.550e6 / (24e6 / 2**16) = 1186611.2 + */ +#define AO_CONFIG_DEFAULT_RADIO_FREQUENCY 1186611 static void _ao_config_put(void) @@ -51,17 +57,21 @@ _ao_config_get(void) memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; + ao_config.radio_frequency = AO_CONFIG_DEFAULT_RADIO_FREQUENCY; ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { /* Fixups for minor version 1 */ if (ao_config.minor < 1) ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; - /* Fixupes for minor version 2 */ + /* Fixups for minor version 2 */ if (ao_config.minor < 2) { ao_config.accel_plus_g = 0; ao_config.accel_minus_g = 0; } + /* Fixups for minor version 3 */ + if (ao_config.minor < 3) + ao_config.radio_frequency = AO_CONFIG_DEFAULT_RADIO_FREQUENCY; ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -245,6 +255,26 @@ ao_config_apogee_delay_set(void) __reentrant ao_config_apogee_delay_show(); } +void +ao_config_radio_frequency_show(void) __reentrant +{ + printf("Radio frequency: %ld\n", ao_config.radio_frequency); +} + +void +ao_config_radio_frequency_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_mutex_get(&ao_config_mutex); + _ao_config_get(); + ao_config.radio_frequency = ao_cmd_lex_u32; + ao_config_dirty = 1; + ao_mutex_put(&ao_config_mutex); + ao_config_radio_frequency_show(); +} + struct ao_config_var { char cmd; void (*set)(void) __reentrant; @@ -268,6 +298,8 @@ __code struct ao_config_var ao_config_vars[] = { "a <+g> <-g> Set accelerometer calibration (0 for auto)" }, { 'r', ao_config_radio_channel_set, ao_config_radio_channel_show, "r Set radio channel (freq = 434.550 + channel * .1)" }, + { 'f', ao_config_radio_frequency_set, ao_config_radio_frequency_show, + "f Set radio calibration value (cal = rf/(xtal/2^16))" }, { 'c', ao_config_callsign_set, ao_config_callsign_show, "c Set callsign broadcast in each packet (8 char max)" }, { 'd', ao_config_apogee_delay_set, ao_config_apogee_delay_show, diff --git a/src/ao_radio.c b/src/ao_radio.c index c7c8dc8d..6d25df39 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -28,14 +28,6 @@ * 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: * @@ -124,10 +116,6 @@ static __code uint8_t radio_setup[] = { 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), @@ -336,14 +324,25 @@ ao_radio_idle(void) } } -void -ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant +static void +ao_radio_get(void) { ao_config_get(); ao_mutex_get(&ao_radio_mutex); ao_radio_idle(); - ao_radio_done = 0; RF_CHANNR = ao_config.radio_channel; + RF_FREQ2 = (uint8_t) (ao_config.radio_frequency >> 16); + RF_FREQ1 = (uint8_t) (ao_config.radio_frequency >> 8); + RF_FREQ0 = (uint8_t) (ao_config.radio_frequency); +} + +#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) + +void +ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant +{ + ao_radio_get(); + ao_radio_done = 0; ao_dma_set_transfer(ao_radio_dma, telemetry, &RFDXADDR, @@ -358,16 +357,13 @@ ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant RFST = RFST_STX; __critical while (!ao_radio_done) ao_sleep(&ao_radio_done); - ao_mutex_put(&ao_radio_mutex); + ao_radio_put(); } uint8_t ao_radio_recv(__xdata struct ao_radio_recv *radio) __reentrant { - ao_config_get(); - ao_mutex_get(&ao_radio_mutex); - ao_radio_idle(); - RF_CHANNR = ao_config.radio_channel; + ao_radio_get(); ao_dma_set_transfer(ao_radio_dma, &RFDXADDR, radio, @@ -382,7 +378,7 @@ ao_radio_recv(__xdata struct ao_radio_recv *radio) __reentrant RFST = RFST_SRX; __critical while (!ao_radio_dma_done) ao_sleep(&ao_radio_dma_done); - ao_mutex_put(&ao_radio_mutex); + ao_radio_put(); return (ao_radio_dma_done & AO_DMA_DONE); } @@ -394,8 +390,8 @@ ao_radio_rdf(int ms) { uint8_t i; uint8_t pkt_len; - ao_mutex_get(&ao_radio_mutex); - ao_radio_idle(); + + ao_radio_get(); ao_radio_rdf_running = 1; for (i = 0; i < sizeof (rdf_setup); i += 2) RF[rdf_setup[i]] = rdf_setup[i+1]; @@ -431,7 +427,7 @@ ao_radio_rdf(int ms) ao_radio_idle(); for (i = 0; i < sizeof (telemetry_setup); i += 2) RF[telemetry_setup[i]] = telemetry_setup[i+1]; - ao_mutex_put(&ao_radio_mutex); + ao_radio_put(); } void @@ -448,18 +444,18 @@ ao_radio_rdf_abort(void) ao_radio_abort(); } + /* Output carrier */ void ao_radio_test(void) { - ao_config_get(); - ao_mutex_get(&ao_radio_mutex); - ao_radio_idle(); + ao_packet_slave_stop(); + ao_radio_get(); printf ("Hit a character to stop..."); flush(); RFST = RFST_STX; getchar(); ao_radio_idle(); - ao_mutex_put(&ao_radio_mutex); + ao_radio_put(); putchar('\n'); } -- cgit v1.2.3 From 46f03ab3145a61139c8ca6fc99e8f2798728b5a9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 5 Dec 2009 15:36:12 -0800 Subject: Re-order config values. Change frequency to cal Place more often used values at top, and consistently call the radio value 'calibration' instead of 'frequency'. Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_config.c | 28 ++++++++++++++-------------- src/ao_radio.c | 6 +++--- 3 files changed, 18 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index d8e1b92a..39f7bea2 100644 --- a/src/ao.h +++ b/src/ao.h @@ -949,7 +949,7 @@ struct ao_config { char callsign[AO_MAX_CALLSIGN + 1]; uint8_t apogee_delay; /* minor version 1 */ int16_t accel_minus_g; /* minor version 2 */ - uint32_t radio_frequency; /* minor version 3 */ + uint32_t radio_cal; /* minor version 3 */ }; extern __xdata struct ao_config ao_config; diff --git a/src/ao_config.c b/src/ao_config.c index 27a60ac1..3609ec06 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -32,7 +32,7 @@ __xdata uint8_t ao_config_mutex; * * 434.550e6 / (24e6 / 2**16) = 1186611.2 */ -#define AO_CONFIG_DEFAULT_RADIO_FREQUENCY 1186611 +#define AO_CONFIG_DEFAULT_RADIO_CAL 1186611 static void _ao_config_put(void) @@ -57,7 +57,7 @@ _ao_config_get(void) memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; - ao_config.radio_frequency = AO_CONFIG_DEFAULT_RADIO_FREQUENCY; + ao_config.radio_cal = AO_CONFIG_DEFAULT_RADIO_CAL; ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { @@ -71,7 +71,7 @@ _ao_config_get(void) } /* Fixups for minor version 3 */ if (ao_config.minor < 3) - ao_config.radio_frequency = AO_CONFIG_DEFAULT_RADIO_FREQUENCY; + ao_config.radio_cal = AO_CONFIG_DEFAULT_RADIO_CAL; ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -256,23 +256,23 @@ ao_config_apogee_delay_set(void) __reentrant } void -ao_config_radio_frequency_show(void) __reentrant +ao_config_radio_cal_show(void) __reentrant { - printf("Radio frequency: %ld\n", ao_config.radio_frequency); + printf("Radio cal: %ld\n", ao_config.radio_cal); } void -ao_config_radio_frequency_set(void) __reentrant +ao_config_radio_cal_set(void) __reentrant { ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; ao_mutex_get(&ao_config_mutex); _ao_config_get(); - ao_config.radio_frequency = ao_cmd_lex_u32; + ao_config.radio_cal = ao_cmd_lex_u32; ao_config_dirty = 1; ao_mutex_put(&ao_config_mutex); - ao_config_radio_frequency_show(); + ao_config_radio_cal_show(); } struct ao_config_var { @@ -294,16 +294,16 @@ ao_config_write(void) __reentrant; __code struct ao_config_var ao_config_vars[] = { { 'm', ao_config_main_deploy_set, ao_config_main_deploy_show, "m Set height above launch for main deploy (in meters)" }, - { 'a', ao_config_accel_calibrate_set, ao_config_accel_calibrate_show, - "a <+g> <-g> Set accelerometer calibration (0 for auto)" }, + { 'd', ao_config_apogee_delay_set, ao_config_apogee_delay_show, + "d Set apogee igniter delay (in seconds)" }, { 'r', ao_config_radio_channel_set, ao_config_radio_channel_show, "r Set radio channel (freq = 434.550 + channel * .1)" }, - { 'f', ao_config_radio_frequency_set, ao_config_radio_frequency_show, - "f Set radio calibration value (cal = rf/(xtal/2^16))" }, { 'c', ao_config_callsign_set, ao_config_callsign_show, "c Set callsign broadcast in each packet (8 char max)" }, - { 'd', ao_config_apogee_delay_set, ao_config_apogee_delay_show, - "d Set apogee igniter delay (in seconds)" }, + { 'a', ao_config_accel_calibrate_set, ao_config_accel_calibrate_show, + "a <+g> <-g> Set accelerometer calibration (0 for auto)" }, + { 'f', ao_config_radio_cal_set, ao_config_radio_cal_show, + "f Set radio calibration value (cal = rf/(xtal/2^16))" }, { 's', ao_config_show, ao_config_show, "s Show current config values" }, { 'w', ao_config_write, ao_config_write, diff --git a/src/ao_radio.c b/src/ao_radio.c index 6d25df39..4dea6dce 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -331,9 +331,9 @@ ao_radio_get(void) ao_mutex_get(&ao_radio_mutex); ao_radio_idle(); RF_CHANNR = ao_config.radio_channel; - RF_FREQ2 = (uint8_t) (ao_config.radio_frequency >> 16); - RF_FREQ1 = (uint8_t) (ao_config.radio_frequency >> 8); - RF_FREQ0 = (uint8_t) (ao_config.radio_frequency); + RF_FREQ2 = (uint8_t) (ao_config.radio_cal >> 16); + RF_FREQ1 = (uint8_t) (ao_config.radio_cal >> 8); + RF_FREQ0 = (uint8_t) (ao_config.radio_cal); } #define ao_radio_put() ao_mutex_put(&ao_radio_mutex) -- cgit v1.2.3 From 5481082b18226a0de6b377215b3b330bdbc4a6c6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 5 Dec 2009 19:50:38 -0800 Subject: Allow radio calibration to be set from ao-load This moves the initial radio calibration value into const memory where it will be used if no eeprom configuration value is available, either on an unprogrammed board with eeprom or a device without an eeprom. Signed-off-by: Keith Packard --- ao-tools/ao-load/ao-load.c | 46 ++++++++++++++++++++++++++++++++++++---------- src/ao_config.c | 10 +++++++--- 2 files changed, 43 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/ao-tools/ao-load/ao-load.c b/ao-tools/ao-load/ao-load.c index f5466612..4aa91b29 100644 --- a/ao-tools/ao-load/ao-load.c +++ b/ao-tools/ao-load/ao-load.c @@ -29,14 +29,17 @@ struct sym { unsigned addr; char *name; -} serial_symbols[] = { +} ao_symbols[] = { { 0, "_ao_serial_number" }, -#define AO_SERIAL_NUMBER (serial_symbols[0].addr) +#define AO_SERIAL_NUMBER (ao_symbols[0].addr) { 0, "_ao_usb_descriptors" }, -#define AO_USB_DESCRIPTORS (serial_symbols[1].addr) +#define AO_USB_DESCRIPTORS (ao_symbols[1].addr) + { 0, "_ao_radio_cal" }, +#define AO_RADIO_CAL (ao_symbols[2].addr) }; -#define NUM_SERIAL_SYMBOLS (sizeof(serial_symbols)/sizeof(serial_symbols[0])) +#define NUM_SERIAL_SYMBOLS 2 +#define NUM_SYMBOLS 3 static int find_symbols(FILE *map) @@ -64,14 +67,14 @@ find_symbols(FILE *map) a = strtoul(colon+1, &addr_end, 16); if (a == ULONG_MAX || addr_end == addr) continue; - for (s = 0; s < NUM_SERIAL_SYMBOLS; s++) - if (!strcmp(serial_symbols[s].name, name)) { - serial_symbols[s].addr = (unsigned) a; + for (s = 0; s < NUM_SYMBOLS; s++) + if (!strcmp(ao_symbols[s].name, name)) { + ao_symbols[s].addr = (unsigned) a; ++found; break; } } - return found == NUM_SERIAL_SYMBOLS; + return found >= NUM_SERIAL_SYMBOLS; } static int @@ -93,12 +96,13 @@ rewrite(struct hex_image *image, unsigned addr, char *data, int len) static const struct option options[] = { { .name = "tty", .has_arg = 1, .val = 'T' }, { .name = "device", .has_arg = 1, .val = 'D' }, + { .name = "cal", .has_arg = 1, .val = 'c' }, { 0, 0, 0, 0}, }; static void usage(char *program) { - fprintf(stderr, "usage: %s [--tty ] [--device ] file.ihx serial-number\n", program); + fprintf(stderr, "usage: %s [--tty ] [--device ] [--cal ] file.ihx serial-number\n", program); exit(1); } @@ -125,9 +129,12 @@ main (int argc, char **argv) int string_num; char *tty = NULL; char *device = NULL; + uint32_t cal = 0; + char cal_int[4]; + char *cal_end; int c; - while ((c = getopt_long(argc, argv, "T:D:", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "T:D:c:", options, NULL)) != -1) { switch (c) { case 'T': tty = optarg; @@ -135,6 +142,11 @@ main (int argc, char **argv) case 'D': device = optarg; break; + case 'c': + cal = strtoul(optarg, &cal_end, 10); + if (cal_end == optarg || *cal_end != '\0') + usage(argv[0]); + break; default: usage(argv[0]); break; @@ -225,6 +237,20 @@ main (int argc, char **argv) if (!rewrite(image, usb_descriptors + 2 + image->address, serial_ucs2, serial_ucs2_len)) usage(argv[0]); + if (cal) { + cal_int[0] = cal & 0xff; + cal_int[1] = (cal >> 8) & 0xff; + cal_int[2] = (cal >> 16) & 0xff; + cal_int[3] = (cal >> 24) & 0xff; + if (!AO_RADIO_CAL) { + fprintf(stderr, "Cannot find radio calibration location in image\n"); + exit(1); + } + if (!rewrite(image, AO_RADIO_CAL, cal_int, sizeof (cal_int))) { + fprintf(stderr, "Cannot rewrite radio calibration at %04x\n", AO_RADIO_CAL); + exit(1); + } + } if (!tty) tty = cc_usbdevs_find_by_arg(device, "TIDongle"); dbg = ccdbg_open(tty); diff --git a/src/ao_config.c b/src/ao_config.c index 3609ec06..4349bca8 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -31,8 +31,12 @@ __xdata uint8_t ao_config_mutex; * For 434.550MHz, the frequency value is: * * 434.550e6 / (24e6 / 2**16) = 1186611.2 + * + * This value is stored in a const variable so that + * ao-load can change it during programming for + * devices that have no eeprom for config data. */ -#define AO_CONFIG_DEFAULT_RADIO_CAL 1186611 +const uint32_t ao_radio_cal = 1186611; static void _ao_config_put(void) @@ -57,7 +61,7 @@ _ao_config_get(void) memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; - ao_config.radio_cal = AO_CONFIG_DEFAULT_RADIO_CAL; + ao_config.radio_cal = ao_radio_cal; ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { @@ -71,7 +75,7 @@ _ao_config_get(void) } /* Fixups for minor version 3 */ if (ao_config.minor < 3) - ao_config.radio_cal = AO_CONFIG_DEFAULT_RADIO_CAL; + ao_config.radio_cal = ao_radio_cal; ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } -- cgit v1.2.3 From 7ac8efea5d60b81adccdc1e38ac4c13facfae7c9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 15 Dec 2009 23:58:29 -0800 Subject: Add --cal to man page --- ao-tools/ao-load/ao-load.1 | 11 +++++++++++ ao-tools/ao-rawload/ao-rawload.c | 12 +++++++++++- src/Makefile | 3 ++- src/ao_gps_sirf.c | 17 ----------------- src/ao_gps_skytraq.c | 17 ----------------- 5 files changed, 24 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/ao-tools/ao-load/ao-load.1 b/ao-tools/ao-load/ao-load.1 index eb2bc0d8..79b76a79 100644 --- a/ao-tools/ao-load/ao-load.1 +++ b/ao-tools/ao-load/ao-load.1 @@ -25,6 +25,7 @@ ao-load \- flash a program to a AltOS device [\--tty \fItty-device\fP] [\-D \fIaltos-device\fP] [\--device \fIaltos-device\fP] +[\--cal \fIradio-calibration\fP] \fIfile.ihx\fP \fIdevice serial number\fP .SH DESCRIPTION @@ -52,6 +53,16 @@ TeleMetrum Leaving out the product name will cause the tool to select a suitable product, leaving out the serial number will cause the tool to match one of the available devices. +.TP +\-c radio-calibration | --cal radio-calibration +This programs the radio calibration value into the image for hardware +which doesn't have any eeprom storage for this value. The value here +can be computed given the current radio calibration value, the +measured frequency and the desired frequency: +.IP + cal' = cal * (desired/measured) +.IP +The default calibration value is 1186611. .SH USAGE .I ao-load reads the specified .ihx file into memory, locates the matching .map diff --git a/ao-tools/ao-rawload/ao-rawload.c b/ao-tools/ao-rawload/ao-rawload.c index d9ee5718..0098b658 100644 --- a/ao-tools/ao-rawload/ao-rawload.c +++ b/ao-tools/ao-rawload/ao-rawload.c @@ -19,16 +19,18 @@ #include #include #include "ccdbg.h" +#include "cc.h" static const struct option options[] = { { .name = "tty", .has_arg = 1, .val = 'T' }, { .name = "device", .has_arg = 1, .val = 'D' }, + { .name = "run", .has_arg = 0, .val = 'r' }, { 0, 0, 0, 0}, }; static void usage(char *program) { - fprintf(stderr, "usage: %s [--tty ] [--device ] file.ihx\n", program); + fprintf(stderr, "usage: %s [--tty ] [--device ] [--run] file.ihx\n", program); exit(1); } @@ -45,6 +47,7 @@ main (int argc, char **argv) char *tty = NULL; char *device = NULL; int c; + int run = 0; while ((c = getopt_long(argc, argv, "T:D:", options, NULL)) != -1) { switch (c) { @@ -54,6 +57,9 @@ main (int argc, char **argv) case 'D': device = optarg; break; + case 'r': + run = 1; + break; default: usage(argv[0]); break; @@ -105,6 +111,10 @@ main (int argc, char **argv) ccdbg_close(dbg); exit(1); } + if (run) { + ccdbg_set_pc(dbg, image->address); + ccdbg_resume(dbg); + } ccdbg_close(dbg); exit (0); } diff --git a/src/Makefile b/src/Makefile index 8c24e6f4..8074d42d 100644 --- a/src/Makefile +++ b/src/Makefile @@ -43,7 +43,7 @@ ALTOS_DRIVER_SRC = \ ao_usb.c TELE_COMMON_SRC = \ - ao_gps_print.c \ + ao_dbg.c \ ao_packet.c \ ao_packet_slave.c \ ao_state.c @@ -53,6 +53,7 @@ TELE_COMMON_SRC = \ # TELE_RECEIVER_SRC =\ ao_monitor.c \ + ao_gps_print.c \ ao_packet_master.c \ ao_rssi.c diff --git a/src/ao_gps_sirf.c b/src/ao_gps_sirf.c index eb00224c..64b66c95 100644 --- a/src/ao_gps_sirf.c +++ b/src/ao_gps_sirf.c @@ -430,25 +430,8 @@ ao_gps(void) __reentrant __xdata struct ao_task ao_gps_task; -static void -gps_dump(void) __reentrant -{ - ao_mutex_get(&ao_gps_mutex); - ao_gps_print(&ao_gps_data); - putchar('\n'); - ao_gps_tracking_print(&ao_gps_tracking_data); - putchar('\n'); - ao_mutex_put(&ao_gps_mutex); -} - -__code struct ao_cmds ao_gps_cmds[] = { - { 'g', gps_dump, "g Display current GPS values" }, - { 0, gps_dump, NULL }, -}; - void ao_gps_init(void) { ao_add_task(&ao_gps_task, ao_gps, "gps"); - ao_cmd_register(&ao_gps_cmds[0]); } diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index ef581349..361c77ce 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -410,25 +410,8 @@ ao_gps(void) __reentrant __xdata struct ao_task ao_gps_task; -static void -gps_dump(void) __reentrant -{ - ao_mutex_get(&ao_gps_mutex); - ao_gps_print(&ao_gps_data); - putchar('\n'); - ao_gps_tracking_print(&ao_gps_tracking_data); - putchar('\n'); - ao_mutex_put(&ao_gps_mutex); -} - -__code struct ao_cmds ao_gps_cmds[] = { - { 'g', gps_dump, "g Display current GPS values" }, - { 0, gps_dump, NULL }, -}; - void ao_gps_init(void) { ao_add_task(&ao_gps_task, ao_gps, "gps"); - ao_cmd_register(&ao_gps_cmds[0]); } -- cgit v1.2.3 From 10d1bbcd9709a5eee8d50989215242b16feb7232 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Dec 2009 11:34:16 -0800 Subject: Use ao_radio_get/ao_radio_put in packet code. The ao_radio_get function both acquires the mutex *and* configures the radio channel and frequency. Failing to use this in the packet code would leave the radio frequency unconfigured. Signed-off-by: Keith Packard --- src/ao.h | 5 +++++ src/ao_packet.c | 16 ++++++---------- src/ao_radio.c | 3 +-- 3 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 39f7bea2..096a4d80 100644 --- a/src/ao.h +++ b/src/ao.h @@ -835,6 +835,11 @@ extern __xdata uint8_t ao_radio_mutex; void ao_radio_general_isr(void) interrupt 16; +void +ao_radio_get(void); + +#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) + void ao_radio_set_telemetry(void); diff --git a/src/ao_packet.c b/src/ao_packet.c index 3ce7e9ab..98fdcb90 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -33,8 +33,9 @@ void ao_packet_send(void) { ao_led_on(AO_LED_RED); - ao_config_get(); - ao_mutex_get(&ao_radio_mutex); + ao_radio_get(); + + /* If any tx data is pending then copy it into the tx packet */ if (ao_packet_tx_used && ao_tx_packet.len == 0) { memcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); ao_tx_packet.len = ao_packet_tx_used; @@ -42,9 +43,7 @@ ao_packet_send(void) ao_packet_tx_used = 0; ao_wakeup(&tx_data); } - ao_radio_idle(); ao_radio_done = 0; - RF_CHANNR = ao_config.radio_channel; ao_dma_set_transfer(ao_radio_dma, &ao_tx_packet, &RFDXADDR, @@ -59,7 +58,7 @@ ao_packet_send(void) RFST = RFST_STX; __critical while (!ao_radio_done) ao_sleep(&ao_radio_done); - ao_mutex_put(&ao_radio_mutex); + ao_radio_put(); ao_led_off(AO_LED_RED); } @@ -69,10 +68,7 @@ ao_packet_recv(void) uint8_t dma_done; ao_led_on(AO_LED_GREEN); - ao_config_get(); - ao_mutex_get(&ao_radio_mutex); - ao_radio_idle(); - RF_CHANNR = ao_config.radio_channel; + ao_radio_get(); ao_dma_set_transfer(ao_radio_dma, &RFDXADDR, &ao_rx_packet, @@ -89,7 +85,7 @@ ao_packet_recv(void) if (ao_sleep(&ao_radio_dma_done) != 0) ao_radio_abort(); dma_done = ao_radio_dma_done; - ao_mutex_put(&ao_radio_mutex); + ao_radio_put(); ao_led_off(AO_LED_GREEN); if (dma_done & AO_DMA_DONE) { diff --git a/src/ao_radio.c b/src/ao_radio.c index 4dea6dce..1a0cf4fa 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -324,7 +324,7 @@ ao_radio_idle(void) } } -static void +void ao_radio_get(void) { ao_config_get(); @@ -336,7 +336,6 @@ ao_radio_get(void) RF_FREQ0 = (uint8_t) (ao_config.radio_cal); } -#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) void ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant -- cgit v1.2.3 From 598d168bd6552c3756e4b0267de44147eadab9f6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Dec 2009 14:03:11 -0800 Subject: Disable monitor mode before attempting radio test. If monitor mode is left active, then the radio lock will not be able to be acquired for the radio test. Signed-off-by: Keith Packard --- src/ao_packet_slave.c | 14 ++++++++------ src/ao_radio.c | 1 + src/ao_telemetrum.c | 7 +++++++ 3 files changed, 16 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index ba5ad1c1..122c4da0 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -40,13 +40,15 @@ ao_packet_slave_start(void) void ao_packet_slave_stop(void) { - ao_packet_enable = 0; - ao_radio_abort(); - while (ao_packet_task.wchan) { - ao_wake_task(&ao_packet_task); - ao_yield(); + if (ao_packet_enable) { + ao_packet_enable = 0; + ao_radio_abort(); + while (ao_packet_task.wchan) { + ao_wake_task(&ao_packet_task); + ao_yield(); + } + ao_radio_set_telemetry(); } - ao_radio_set_telemetry(); } void diff --git a/src/ao_radio.c b/src/ao_radio.c index 1a0cf4fa..bb19c6a9 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -448,6 +448,7 @@ ao_radio_rdf_abort(void) void ao_radio_test(void) { + ao_set_monitor(0); ao_packet_slave_stop(); ao_radio_get(); printf ("Hit a character to stop..."); flush(); diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 5250078e..990b0d77 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -17,6 +17,13 @@ #include "ao.h" +/* stub so as telemetrum doesn't have monitor mode */ +void +ao_set_monitor(uint8_t monitoring) +{ + (void) monitoring; +} + void main(void) { -- cgit v1.2.3 From eddb82390a0ecb07ef83c04861993842906b03ab Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Dec 2009 15:31:36 -0800 Subject: Ensure that ao_alarm waits at least the specified time Because the timer tick may happen soon, it's important to delay by another tick to ensure that we don't wake up early. Signed-off-by: Keith Packard --- src/ao_task.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_task.c b/src/ao_task.c index 4664163d..4a78766e 100644 --- a/src/ao_task.c +++ b/src/ao_task.c @@ -217,7 +217,10 @@ ao_wakeup(__xdata void *wchan) void ao_alarm(uint16_t delay) { - if (!(ao_cur_task->alarm = ao_time() + delay)) + /* Make sure we sleep *at least* delay ticks, which means adding + * one to account for the fact that we may be close to the next tick + */ + if (!(ao_cur_task->alarm = ao_time() + delay + 1)) ao_cur_task->alarm = 1; } -- cgit v1.2.3 From 3bab7e66d25988f5d63ec139c8814a85b983f8f3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Dec 2009 20:32:18 -0800 Subject: Remove dbg driver code from telemetrum/teledongle The only board with debug outputs is the TI dongle at this point, so the debug modules were disabled in TM and TD some time ago. Unfortunately, the code was not removed then. Signed-off-by: Keith Packard --- src/Makefile | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 8074d42d..39599753 100644 --- a/src/Makefile +++ b/src/Makefile @@ -43,7 +43,6 @@ ALTOS_DRIVER_SRC = \ ao_usb.c TELE_COMMON_SRC = \ - ao_dbg.c \ ao_packet.c \ ao_packet_slave.c \ ao_state.c -- cgit v1.2.3 From dc8d18736239b14c2ec48a40a01515912c5c25e6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jan 2010 01:22:06 -0800 Subject: Add AT45DBxx1D driver This driver supports the AT45DB011D through AT45DB321D DataFlash parts as found in TeleMetrum v0.2 Signed-off-by: Keith Packard --- src/Makefile | 2 +- src/ao.h | 1 + src/ao_flash.c | 536 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 538 insertions(+), 1 deletion(-) create mode 100644 src/ao_flash.c (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 39599753..dcd41718 100644 --- a/src/Makefile +++ b/src/Makefile @@ -82,7 +82,7 @@ DBG_DONGLE_SRC = \ # TM_DRIVER_SRC = \ ao_adc.c \ - ao_ee.c \ + ao_flash.c \ ao_gps_report.c \ ao_ignite.c diff --git a/src/ao.h b/src/ao.h index 096a4d80..1f27fe92 100644 --- a/src/ao.h +++ b/src/ao.h @@ -108,6 +108,7 @@ ao_start_scheduler(void); #define AO_PANIC_CMD 6 /* Too many command sets registered */ #define AO_PANIC_STDIO 7 /* Too many stdio handlers registered */ #define AO_PANIC_REBOOT 8 /* Reboot failed */ +#define AO_PANIC_FLASH 9 /* Invalid flash part (or wrong blocksize) */ /* Stop the operating system, beeping and blinking the reason */ void diff --git a/src/ao_flash.c b/src/ao_flash.c new file mode 100644 index 00000000..86b94765 --- /dev/null +++ b/src/ao_flash.c @@ -0,0 +1,536 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "at45db161d.h" + +/* + * Using SPI on USART 0, with P1_1 as the chip select + */ + +#define FLASH_CS P1_1 +#define FLASH_CS_INDEX 1 + +__xdata uint8_t ao_flash_dma_in_done; +__xdata uint8_t ao_flash_dma_out_done; +__xdata uint8_t ao_flash_mutex; + +uint8_t ao_flash_dma_out_id; +uint8_t ao_flash_dma_in_id; + +static __xdata uint8_t ao_flash_const = 0xff; + +#define ao_flash_delay() do { \ + _asm nop _endasm; \ + _asm nop _endasm; \ + _asm nop _endasm; \ +} while(0) + +void ao_flash_cs_low(void) +{ + ao_flash_delay(); + FLASH_CS = 0; + ao_flash_delay(); +} + +void ao_flash_cs_high(void) +{ + ao_flash_delay(); + FLASH_CS = 1; + ao_flash_delay(); +} + +/* Send bytes over SPI. + * + * This sets up two DMA engines, one writing the data and another reading + * bytes coming back. We use the bytes coming back to tell when the transfer + * is complete, as the transmit register is double buffered and hence signals + * completion one byte before the transfer is actually complete + */ +static void +ao_flash_send(void __xdata *block, uint16_t len) +{ + ao_dma_set_transfer(ao_flash_dma_in_id, + &U0DBUFXADDR, + &ao_flash_const, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_URX0, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_set_transfer(ao_flash_dma_out_id, + block, + &U0DBUFXADDR, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_UTX0, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_start(ao_flash_dma_in_id); + ao_dma_start(ao_flash_dma_out_id); + ao_dma_trigger(ao_flash_dma_out_id); + __critical while (!ao_flash_dma_in_done) + ao_sleep(&ao_flash_dma_in_done); +} + +/* Receive bytes over SPI. + * + * This sets up tow DMA engines, one reading the data and another + * writing constant values to the SPI transmitter as that is what + * clocks the data coming in. + */ +static void +ao_flash_recv(void __xdata *block, uint16_t len) +{ + ao_dma_set_transfer(ao_flash_dma_in_id, + &U0DBUFXADDR, + block, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_URX0, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_1 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_set_transfer(ao_flash_dma_out_id, + &ao_flash_const, + &U0DBUFXADDR, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_UTX0, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_start(ao_flash_dma_in_id); + ao_dma_start(ao_flash_dma_out_id); + ao_dma_trigger(ao_flash_dma_out_id); + __critical while (!ao_flash_dma_in_done) + ao_sleep(&ao_flash_dma_in_done); +} + +struct ao_flash_instruction { + uint8_t instruction; + uint8_t address[3]; +} __xdata ao_flash_instruction; + +static void +ao_flash_set_pagesize_512(void) +{ + ao_flash_cs_low(); + ao_flash_instruction.instruction = FLASH_SET_CONFIG; + ao_flash_instruction.address[0] = FLASH_SET_512_BYTE_0; + ao_flash_instruction.address[1] = FLASH_SET_512_BYTE_1; + ao_flash_instruction.address[2] = FLASH_SET_512_BYTE_2; + ao_flash_send(&ao_flash_instruction, 4); + ao_flash_cs_high(); +} + + +static uint8_t +ao_flash_read_status(void) +{ + ao_flash_cs_low(); + ao_flash_instruction.instruction = FLASH_READ_STATUS; + ao_flash_send(&ao_flash_instruction, 1); + ao_flash_recv(&ao_flash_instruction, 1); + ao_flash_cs_high(); + return ao_flash_instruction.instruction; +} + +#define FLASH_BLOCK_NONE 0xffff + +static __xdata uint8_t ao_flash_data[FLASH_BLOCK_SIZE_MAX]; +static __pdata uint16_t ao_flash_block = FLASH_BLOCK_NONE; +static __pdata uint8_t ao_flash_block_dirty; +static __pdata uint8_t ao_flash_write_pending; +static __pdata uint8_t ao_flash_setup_done; +static __data uint32_t ao_flash_device_size; +static __data uint8_t ao_flash_block_shift; + +static void +ao_flash_setup(void) +{ + uint8_t status; + + if (ao_flash_setup_done) + return; + + ao_mutex_get(&ao_flash_mutex); + if (ao_flash_setup_done) { + ao_mutex_put(&ao_flash_mutex); + return; + } + ao_flash_setup_done = 1; + + /* On first use, check to see if the flash chip has + * been programmed to use 512 byte pages. If not, do so. + * And then, because the flash part must be power cycled + * for that change to take effect, panic. + */ + status = ao_flash_read_status(); + + if (!(status & FLASH_STATUS_PAGESIZE_512)) { + ao_flash_set_pagesize_512(); + ao_panic(AO_PANIC_FLASH); + } + + switch (status & 0x3c) { + + /* AT45DB321D */ + case 0x34: + ao_flash_block_shift = 9; + ao_flash_device_size = ((uint32_t) 4 * (uint32_t) 1024 * (uint32_t) 1024); + break; + + /* AT45DB161D */ + case 0x2c: + ao_flash_block_shift = 9; + ao_flash_device_size = ((uint32_t) 2 * (uint32_t) 1024 * (uint32_t) 1024); + break; + + /* AT45DB081D */ + case 0x24: + ao_flash_block_shift = 8; + ao_flash_device_size = ((uint32_t) 1024 * (uint32_t) 1024); + break; + + /* AT45DB041D */ + case 0x1c: + ao_flash_block_shift = 8; + ao_flash_device_size = ((uint32_t) 512 * (uint32_t) 1024); + break; + + /* AT45DB021D */ + case 0x14: + ao_flash_block_shift = 8; + ao_flash_device_size = ((uint32_t) 256 * (uint32_t) 1024); + break; + + /* AT45DB011D */ + case 0x0c: + ao_flash_block_shift = 8; + ao_flash_device_size = ((uint32_t) 128 * (uint32_t) 1024); + break; + + default: + ao_panic(AO_PANIC_FLASH); + } + ao_mutex_put(&ao_flash_mutex); +} + +static void +ao_flash_wait_write(void) +{ + if (ao_flash_write_pending) { + for (;;) { + uint8_t status = ao_flash_read_status(); + if ((status & FLASH_STATUS_RDY)) + break; + } + ao_flash_write_pending = 0; + } +} + +/* Write the current block to the FLASHPROM */ +static void +ao_flash_write_block(void) +{ + ao_flash_wait_write(); + ao_flash_cs_low(); + ao_flash_instruction.instruction = FLASH_WRITE; + + /* 13/14 block bits + 9/8 byte bits (always 0) */ + ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift); + ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); + ao_flash_instruction.address[2] = 0; + ao_flash_send(&ao_flash_instruction, 4); + ao_flash_send(ao_flash_data, FLASH_BLOCK_SIZE); + ao_flash_cs_high(); + ao_flash_write_pending = 1; +} + +/* Read the current block from the FLASHPROM */ +static void +ao_flash_read_block(void) +{ + ao_flash_wait_write(); + ao_flash_cs_low(); + ao_flash_instruction.instruction = FLASH_READ; + + /* 13/14 block bits + 9/8 byte bits (always 0) */ + ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift); + ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); + ao_flash_instruction.address[2] = 0; + ao_flash_send(&ao_flash_instruction, 4); + ao_flash_recv(ao_flash_data, FLASH_BLOCK_SIZE); + ao_flash_cs_high(); +} + +static void +ao_flash_flush_internal(void) +{ + if (ao_flash_block_dirty) { + ao_flash_write_block(); + ao_flash_block_dirty = 0; + } +} + +static void +ao_flash_fill(uint16_t block) +{ + if (block != ao_flash_block) { + ao_flash_flush_internal(); + ao_flash_block = block; + ao_flash_read_block(); + } +} + +uint8_t +ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant +{ + uint16_t block; + uint16_t this_len; + uint16_t this_off; + + ao_flash_setup(); + if (pos >= FLASH_DATA_SIZE || pos + len > FLASH_DATA_SIZE) + return 0; + while (len) { + + /* Compute portion of transfer within + * a single block + */ + this_off = (uint16_t) pos & FLASH_BLOCK_MASK; + this_len = FLASH_BLOCK_SIZE - this_off; + block = (uint16_t) (pos >> FLASH_BLOCK_SHIFT); + if (this_len > len) + this_len = len; + + /* Transfer the data */ + ao_mutex_get(&ao_flash_mutex); { + if (this_len != FLASH_BLOCK_SIZE) + ao_flash_fill(block); + else { + ao_flash_flush_internal(); + ao_flash_block = block; + } + memcpy(ao_flash_data + this_off, buf, this_len); + ao_flash_block_dirty = 1; + } ao_mutex_put(&ao_flash_mutex); + + /* See how much is left */ + buf += this_len; + len -= this_len; + pos += this_len; + } + return 1; +} + +uint8_t +ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant +{ + uint16_t block; + uint16_t this_len; + uint16_t this_off; + + ao_flash_setup(); + if (pos >= FLASH_DATA_SIZE || pos + len > FLASH_DATA_SIZE) + return 0; + while (len) { + + + /* Compute portion of transfer within + * a single block + */ + this_off = (uint16_t) pos & FLASH_BLOCK_MASK; + this_len = FLASH_BLOCK_SIZE - this_off; + block = (uint16_t) (pos >> FLASH_BLOCK_SHIFT); + if (this_len > len) + this_len = len; + + /* Transfer the data */ + ao_mutex_get(&ao_flash_mutex); { + ao_flash_fill(block); + memcpy(buf, ao_flash_data + this_off, this_len); + } ao_mutex_put(&ao_flash_mutex); + + /* See how much is left */ + buf += this_len; + len -= this_len; + pos += this_len; + } + return 1; +} + +void +ao_ee_flush(void) __reentrant +{ + ao_mutex_get(&ao_flash_mutex); { + ao_flash_flush_internal(); + } ao_mutex_put(&ao_flash_mutex); +} + +/* + * Read/write the config block, which is in + * the last block of the flash + */ +uint8_t +ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant +{ + ao_flash_setup(); + if (len > FLASH_BLOCK_SIZE) + return 0; + ao_mutex_get(&ao_flash_mutex); { + ao_flash_fill(FLASH_CONFIG_BLOCK); + memcpy(ao_flash_data, buf, len); + ao_flash_block_dirty = 1; + ao_flash_flush_internal(); + } ao_mutex_put(&ao_flash_mutex); + return 1; +} + +uint8_t +ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant +{ + ao_flash_setup(); + if (len > FLASH_BLOCK_SIZE) + return 0; + ao_mutex_get(&ao_flash_mutex); { + ao_flash_fill(FLASH_CONFIG_BLOCK); + memcpy(buf, ao_flash_data, len); + } ao_mutex_put(&ao_flash_mutex); + return 1; +} + +static void +flash_dump(void) __reentrant +{ + uint8_t b; + uint16_t block; + 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 +flash_store(void) __reentrant +{ + uint16_t block; + uint8_t i; + uint16_t len; + uint8_t b; + 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_flash_cmds[] = { + { 'e', flash_dump, "e Dump a block of flash data" }, + { 'w', flash_store, "w ... Write data to flash" }, + { 0, flash_store, NULL }, +}; + +/* + * To initialize the chip, set up the CS line and + * the SPI interface + */ +void +ao_ee_init(void) +{ + /* set up CS */ + FLASH_CS = 1; + P1DIR |= (1 << FLASH_CS_INDEX); + P1SEL &= ~(1 << FLASH_CS_INDEX); + + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2; + + /* Ensure that USART0 takes precidence over USART1 for pins that + * they share + */ + P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | P2SEL_PRI3P1_USART0; + + /* Make the SPI pins be controlled by the USART peripheral */ + P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3)); + + /* Set up OUT DMA */ + ao_flash_dma_out_id = ao_dma_alloc(&ao_flash_dma_out_done); + + /* Set up IN DMA */ + ao_flash_dma_in_id = ao_dma_alloc(&ao_flash_dma_in_done); + + /* Set up the USART. + * + * SPI master mode + */ + U0CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_MASTER); + + /* Set the baud rate and signal parameters + * + * The cc1111 is limited to a 24/8 MHz SPI clock, + * while the at45db161d.h is limited to 20MHz. So, + * use the 3MHz clock (BAUD_E 17, BAUD_M 0) + */ + U0BAUD = 0; + U0GCR = (UxGCR_CPOL_NEGATIVE | + UxGCR_CPHA_FIRST_EDGE | + UxGCR_ORDER_MSB | + (17 << UxGCR_BAUD_E_SHIFT)); + ao_cmd_register(&ao_flash_cmds[0]); +} -- cgit v1.2.3 From a0d4c1b06d27e850d233f8ddf8fe32912bf0ec8f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jan 2010 01:29:41 -0800 Subject: Remove green LED and temp sensor from v0.2 code Signed-off-by: Keith Packard --- src/ao_adc.c | 8 ++++++-- src/ao_telemetrum.c | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ao_adc.c b/src/ao_adc.c index a8784667..b0bfceb1 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -51,7 +51,11 @@ ao_adc_isr(void) interrupt 1 a[1] = ADCH; if (sequence < 5) { /* start next channel conversion */ - ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | (sequence + 1); + sequence++; + /* skip channel 2, we don't have a temp sensor on v0.2 */ + if (sequence == 2) + sequence++; + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | sequence; } else { /* record this conversion series */ ao_adc_ring[ao_adc_head].tick = ao_time(); @@ -80,7 +84,7 @@ ao_adc_init(void) { ADCCFG = ((1 << 0) | /* acceleration */ (1 << 1) | /* pressure */ - (1 << 2) | /* temperature */ +/* (1 << 2) | v0.1 temperature */ (1 << 3) | /* battery voltage */ (1 << 4) | /* drogue sense */ (1 << 5)); /* main sense */ diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 990b0d77..0de3572a 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -30,7 +30,7 @@ main(void) ao_clock_init(); /* Turn on the red LED until the system is stable */ - ao_led_init(AO_LED_RED|AO_LED_GREEN); + ao_led_init(AO_LED_RED); ao_led_on(AO_LED_RED); ao_timer_init(); -- cgit v1.2.3 From c1334f712f01543adb10809bc1a3ca120e27290b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jan 2010 09:55:04 -0800 Subject: Add at45db161d.h header file for new flash part. Forgot to add this when I added the driver. Signed-off-by: Keith Packard --- src/at45db161d.h | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 src/at45db161d.h (limited to 'src') diff --git a/src/at45db161d.h b/src/at45db161d.h new file mode 100644 index 00000000..66869733 --- /dev/null +++ b/src/at45db161d.h @@ -0,0 +1,51 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +/* Defines for the Atmel AT45DB161D 16Mbit SPI Bus DataFlash® */ + +#ifndef _AT45DB161D_H_ +#define _AT45DB161D_H_ + +/* + * We reserve the last block on the device for + * configuration space. Writes and reads in this + * area return errors. + */ + +#define FLASH_BLOCK_SIZE_MAX 512 +#define FLASH_BLOCK_SHIFT (ao_flash_block_shift) +#define FLASH_BLOCK_SIZE (1 << FLASH_BLOCK_SHIFT) +#define FLASH_BLOCK_MASK (FLASH_BLOCK_SIZE - 1) +#define FLASH_DEVICE_SIZE (ao_flash_device_size) +#define FLASH_DATA_SIZE (FLASH_DEVICE_SIZE - (uint32_t) FLASH_BLOCK_SIZE) +#define FLASH_CONFIG_BLOCK ((uint16_t) (FLASH_DATA_SIZE / FLASH_BLOCK_SIZE)) + +#define FLASH_READ 0x03 +#define FLASH_WRITE 0x82 +#define FLASH_READ_STATUS 0xd7 +#define FLASH_SET_CONFIG 0x3d + +#define FLASH_SET_512_BYTE_0 0x2a +#define FLASH_SET_512_BYTE_1 0x80 +#define FLASH_SET_512_BYTE_2 0xa6 + +#define FLASH_STATUS_RDY (1 << 7) +#define FLASH_STATUS_COMP (1 << 6) +#define FLASH_STATUS_PROTECT (1 << 1) +#define FLASH_STATUS_PAGESIZE_512 (1 << 0) + +#endif /* _AT45DB161D_H_ */ -- cgit v1.2.3 From d4c8895b349998e02e03ed83466a0ca7afb3d99b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jan 2010 17:57:52 -0800 Subject: Add 'f' command to display flash status register contents Signed-off-by: Keith Packard --- src/ao_flash.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src') diff --git a/src/ao_flash.c b/src/ao_flash.c index 86b94765..153015c6 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -480,9 +480,21 @@ flash_store(void) __reentrant ao_ee_flush(); } +static void +flash_status(void) __reentrant +{ + uint8_t status; + + ao_mutex_get(&ao_flash_mutex); { + status = ao_flash_read_status(); + printf ("Flash status: 0x%02x\n", status); + } ao_mutex_put(&ao_flash_mutex); +} + __code struct ao_cmds ao_flash_cmds[] = { { 'e', flash_dump, "e Dump a block of flash data" }, { 'w', flash_store, "w ... Write data to flash" }, + { 'f', flash_status, "f Show flash status register" }, { 0, flash_store, NULL }, }; -- cgit v1.2.3 From 05e5bb2d330b755967d06fb859585c81f5f5fbb5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jan 2010 19:46:46 -0800 Subject: Dump more flash parameters for the flash_status command --- src/ao_flash.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/ao_flash.c b/src/ao_flash.c index 153015c6..01d371bb 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -404,6 +404,7 @@ ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant if (len > FLASH_BLOCK_SIZE) return 0; ao_mutex_get(&ao_flash_mutex); { + printf("FLASH_CONFIG_BLOCK: %d\n", FLASH_CONFIG_BLOCK); ao_flash_fill(FLASH_CONFIG_BLOCK); memcpy(ao_flash_data, buf, len); ao_flash_block_dirty = 1; @@ -485,9 +486,16 @@ flash_status(void) __reentrant { uint8_t status; + ao_flash_setup(); ao_mutex_get(&ao_flash_mutex); { status = ao_flash_read_status(); printf ("Flash status: 0x%02x\n", status); + printf ("Flash block shift: %d\n", FLASH_BLOCK_SHIFT); + printf ("Flash block size: %d\n", FLASH_BLOCK_SIZE); + printf ("Flash block mask: %d\n", FLASH_BLOCK_MASK); + printf ("Flash device size: %ld\n", FLASH_DEVICE_SIZE); + printf ("Flash data size: %ld\n", FLASH_DATA_SIZE); + printf ("Flash config block: %d\n", FLASH_CONFIG_BLOCK); } ao_mutex_put(&ao_flash_mutex); } -- cgit v1.2.3 From 327e5e782958e516a7b7a786ab6c176b0decb8b8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jan 2010 20:04:42 -0800 Subject: Dump config block from read/write config and flash_status commands --- src/ao_flash.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'src') diff --git a/src/ao_flash.c b/src/ao_flash.c index 01d371bb..0120382d 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -397,6 +397,30 @@ ao_ee_flush(void) __reentrant * Read/write the config block, which is in * the last block of the flash */ + +void +ao_ee_dump_config(void) __reentrant +{ + uint16_t i; + printf("Configuration block %d\n", FLASH_CONFIG_BLOCK); + ao_mutex_get(&ao_flash_mutex); { + ao_flash_flush_internal(); + ao_flash_block = FLASH_BLOCK_NONE; + ao_flash_fill(FLASH_CONFIG_BLOCK); + i = 0; + do { + if ((i & 7) == 0) { + if (i) + putchar('\n'); + ao_cmd_put16((uint16_t) i); + } + putchar(' '); + ao_cmd_put8(ao_flash_data[i]); + ++i; + } while (i < sizeof (ao_config)); + } ao_mutex_put(&ao_flash_mutex); +} + uint8_t ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant { @@ -410,6 +434,7 @@ ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant ao_flash_block_dirty = 1; ao_flash_flush_internal(); } ao_mutex_put(&ao_flash_mutex); + ao_ee_dump_config(); return 1; } @@ -419,6 +444,7 @@ ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant ao_flash_setup(); if (len > FLASH_BLOCK_SIZE) return 0; + ao_ee_dump_config(); ao_mutex_get(&ao_flash_mutex); { ao_flash_fill(FLASH_CONFIG_BLOCK); memcpy(buf, ao_flash_data, len); @@ -497,6 +523,7 @@ flash_status(void) __reentrant printf ("Flash data size: %ld\n", FLASH_DATA_SIZE); printf ("Flash config block: %d\n", FLASH_CONFIG_BLOCK); } ao_mutex_put(&ao_flash_mutex); + ao_ee_dump_config(); } __code struct ao_cmds ao_flash_cmds[] = { -- cgit v1.2.3 From 05bb953830604721c9a49dd56256b86f3666b5ff Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jan 2010 20:42:57 -0800 Subject: Don't set ao_flash_setup_done until we're actually done. Because we're accessing this variable outside of the mutex, we need to make sure it isn't set until the data it covers has been initialized. Signed-off-by: Keith Packard --- src/ao_flash.c | 4 +++- src/at45db161d.h | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao_flash.c b/src/ao_flash.c index 0120382d..3ea3e40b 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -169,6 +169,7 @@ static __pdata uint8_t ao_flash_write_pending; static __pdata uint8_t ao_flash_setup_done; static __data uint32_t ao_flash_device_size; static __data uint8_t ao_flash_block_shift; +static __data uint16_t ao_flash_block_size; static void ao_flash_setup(void) @@ -183,7 +184,6 @@ ao_flash_setup(void) ao_mutex_put(&ao_flash_mutex); return; } - ao_flash_setup_done = 1; /* On first use, check to see if the flash chip has * been programmed to use 512 byte pages. If not, do so. @@ -238,6 +238,8 @@ ao_flash_setup(void) default: ao_panic(AO_PANIC_FLASH); } + ao_flash_block_size = 1 << ao_flash_block_shift; + ao_flash_setup_done = 1; ao_mutex_put(&ao_flash_mutex); } diff --git a/src/at45db161d.h b/src/at45db161d.h index 66869733..8b72e647 100644 --- a/src/at45db161d.h +++ b/src/at45db161d.h @@ -28,7 +28,7 @@ #define FLASH_BLOCK_SIZE_MAX 512 #define FLASH_BLOCK_SHIFT (ao_flash_block_shift) -#define FLASH_BLOCK_SIZE (1 << FLASH_BLOCK_SHIFT) +#define FLASH_BLOCK_SIZE (ao_flash_block_size) #define FLASH_BLOCK_MASK (FLASH_BLOCK_SIZE - 1) #define FLASH_DEVICE_SIZE (ao_flash_device_size) #define FLASH_DATA_SIZE (FLASH_DEVICE_SIZE - (uint32_t) FLASH_BLOCK_SIZE) -- cgit v1.2.3 From a6082a8b4501ac4cb18584ace1f0c40e088e5484 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jan 2010 20:57:29 -0800 Subject: Remove flash debugging printfs Signed-off-by: Keith Packard --- src/ao_flash.c | 49 +++++++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/ao_flash.c b/src/ao_flash.c index 3ea3e40b..638e51e0 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -400,29 +400,6 @@ ao_ee_flush(void) __reentrant * the last block of the flash */ -void -ao_ee_dump_config(void) __reentrant -{ - uint16_t i; - printf("Configuration block %d\n", FLASH_CONFIG_BLOCK); - ao_mutex_get(&ao_flash_mutex); { - ao_flash_flush_internal(); - ao_flash_block = FLASH_BLOCK_NONE; - ao_flash_fill(FLASH_CONFIG_BLOCK); - i = 0; - do { - if ((i & 7) == 0) { - if (i) - putchar('\n'); - ao_cmd_put16((uint16_t) i); - } - putchar(' '); - ao_cmd_put8(ao_flash_data[i]); - ++i; - } while (i < sizeof (ao_config)); - } ao_mutex_put(&ao_flash_mutex); -} - uint8_t ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant { @@ -430,13 +407,11 @@ ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant if (len > FLASH_BLOCK_SIZE) return 0; ao_mutex_get(&ao_flash_mutex); { - printf("FLASH_CONFIG_BLOCK: %d\n", FLASH_CONFIG_BLOCK); ao_flash_fill(FLASH_CONFIG_BLOCK); memcpy(ao_flash_data, buf, len); ao_flash_block_dirty = 1; ao_flash_flush_internal(); } ao_mutex_put(&ao_flash_mutex); - ao_ee_dump_config(); return 1; } @@ -446,7 +421,6 @@ ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant ao_flash_setup(); if (len > FLASH_BLOCK_SIZE) return 0; - ao_ee_dump_config(); ao_mutex_get(&ao_flash_mutex); { ao_flash_fill(FLASH_CONFIG_BLOCK); memcpy(buf, ao_flash_data, len); @@ -509,6 +483,29 @@ flash_store(void) __reentrant ao_ee_flush(); } +void +ao_ee_dump_config(void) __reentrant +{ + uint16_t i; + printf("Configuration block %d\n", FLASH_CONFIG_BLOCK); + ao_mutex_get(&ao_flash_mutex); { + ao_flash_flush_internal(); + ao_flash_block = FLASH_BLOCK_NONE; + ao_flash_fill(FLASH_CONFIG_BLOCK); + i = 0; + do { + if ((i & 7) == 0) { + if (i) + putchar('\n'); + ao_cmd_put16((uint16_t) i); + } + putchar(' '); + ao_cmd_put8(ao_flash_data[i]); + ++i; + } while (i < sizeof (ao_config)); + } ao_mutex_put(&ao_flash_mutex); +} + static void flash_status(void) __reentrant { -- cgit v1.2.3 From 28346736a7799c0767e54511d9949cd61d35e471 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jan 2010 20:57:48 -0800 Subject: Add simple gps dump command 'g' This just dumps out the data in a very simple format to verify the GPS receiver. Signed-off-by: Keith Packard --- src/ao_gps_skytraq.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src') diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index 361c77ce..2392dacf 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -410,8 +410,24 @@ ao_gps(void) __reentrant __xdata struct ao_task ao_gps_task; +static void +gps_dump(void) __reentrant +{ + ao_mutex_get(&ao_gps_mutex); + printf ("Date: %02d/%02d/%02d\n", ao_gps_data.year, ao_gps_data.month, ao_gps_data.day); + printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second); + printf ("Lat/Lon: %ld %ld\n", ao_gps_data.latitude, ao_gps_data.longitude); + printf ("Alt: %d\n", ao_gps_data.altitude); +} + +__code struct ao_cmds ao_gps_cmds[] = { + { 'g', gps_dump, "g Display current GPS values" }, + { 0, gps_dump, NULL }, +}; + void ao_gps_init(void) { ao_add_task(&ao_gps_task, ao_gps, "gps"); + ao_cmd_register(&ao_gps_cmds[0]); } -- cgit v1.2.3 From 0c2533be15858774ef9381aa8c8344356fd5b971 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jan 2010 22:06:19 -0800 Subject: Force idle mode by shorting the SPI clock to ground at boot time. This allows you to override the flight mode detection code in case the accelerometer calibration is broken somehow. Hold the SPI clock shoted to ground until the LED comes on, then remove it. Signed-off-by: Keith Packard --- src/ao.h | 1 + src/ao_flight.c | 8 ++++++-- src/ao_telemetrum.c | 10 ++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 1f27fe92..2c6eb2b9 100644 --- a/src/ao.h +++ b/src/ao.h @@ -618,6 +618,7 @@ extern __pdata int16_t ao_ground_pres; extern __pdata int16_t ao_ground_accel; extern __pdata int16_t ao_min_pres; extern __pdata uint16_t ao_launch_time; +extern __xdata uint8_t ao_flight_force_idle; /* Flight thread */ void diff --git a/src/ao_flight.c b/src/ao_flight.c index f57573d0..e0fd97f2 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -50,6 +50,8 @@ __data uint8_t ao_flight_adc; __pdata int16_t ao_raw_accel, ao_raw_accel_prev, ao_raw_pres; __pdata int16_t ao_accel_2g; +__xdata uint8_t ao_flight_force_idle; + /* Accelerometer calibration * * We're sampling the accelerometer through a resistor divider which @@ -221,8 +223,10 @@ ao_flight(void) /* Go to pad state if the nose is pointing up */ ao_config_get(); - if (ao_config.accel_plus_g != 0 && ao_config.accel_minus_g != 0 && - ao_flight_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP) + if (ao_config.accel_plus_g != 0 && + ao_config.accel_minus_g != 0 && + ao_flight_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP && + !ao_flight_force_idle) { /* Disable the USB controller in flight mode * to save power diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 0de3572a..89743837 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -29,10 +29,20 @@ main(void) { ao_clock_init(); + /* Turn on the red LED until the system is stable */ ao_led_init(AO_LED_RED); ao_led_on(AO_LED_RED); + /* A hack -- look at the SPI clock pin, if it's sitting at + * ground, then we force the computer to idle mode instead of + * flight mode + */ + if (P1_3 == 0) { + ao_flight_force_idle = 1; + while (P1_3 == 0) + ; + } ao_timer_init(); ao_adc_init(); ao_beep_init(); -- cgit v1.2.3 From 9856b7c4397afcecc8f541af9a83824e817b3612 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 10 Jan 2010 16:31:50 -0800 Subject: Switch to using internal cc1111 temperature sensor v0.2 has no temperature sensor, and several of the v0.1 boards didn't get a temperature sensor loaded. Use the internal temperature sensor on the cc1111 in all cases instead. Signed-off-by: Keith Packard --- ao-tools/ao-view/aoview_state.c | 8 ++++---- ao-tools/lib/cc-convert.c | 11 ++++++++++- src/ao_adc.c | 12 +++++++----- src/ao_convert.c | 10 +++++++++- 4 files changed, 30 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/ao-tools/ao-view/aoview_state.c b/ao-tools/ao-view/aoview_state.c index 838899a7..505bcddc 100644 --- a/ao-tools/ao-view/aoview_state.c +++ b/ao-tools/ao-view/aoview_state.c @@ -127,10 +127,10 @@ aoview_state_derive(struct cc_telem *data, struct aostate *state) accel_counts_per_mss = ((data->accel_minus_g - data->accel_plus_g) / 2.0) / 9.80665; state->acceleration = (data->ground_accel - data->flight_accel) / accel_counts_per_mss; state->speed = data->flight_vel / (accel_counts_per_mss * 100.0); - state->temperature = ((data->temp / 32767.0 * 3.3) - 0.5) / 0.01; - state->drogue_sense = data->drogue / 32767.0 * 15.0; - state->main_sense = data->main / 32767.0 * 15.0; - state->battery = data->batt / 32767.0 * 5.0; + state->temperature = cc_thermometer_to_temperature(data->temp); + state->drogue_sense = cc_ignitor_to_voltage(data->drogue); + state->main_sense = cc_ignitor_to_voltage(data->main); + state->battery = cc_battery_to_voltage(data->batt); if (!strcmp(data->state, "pad")) { if (data->gps.gps_locked && data->gps.nsat >= 4) { state->npad++; diff --git a/ao-tools/lib/cc-convert.c b/ao-tools/lib/cc-convert.c index ac6962ba..8d6876a0 100644 --- a/ao-tools/lib/cc-convert.c +++ b/ao-tools/lib/cc-convert.c @@ -213,10 +213,19 @@ cc_accelerometer_to_acceleration(double accel, double ground_accel) return (ground_accel - accel) / count_per_mss; } +/* Value for the CC1111 built-in temperature sensor + * Output voltage at 0°C = 0.755V + * Coefficient = 0.00247V/°C + * Reference voltage = 1.25V + * + * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247 + * = (value - 19791.268) / 32768 * 1.25 / 0.00247 + */ + double cc_thermometer_to_temperature(double thermo) { - return ((thermo / 32767 * 3.3) - 0.5) / 0.01; + return (thermo - 19791.268) / 32728.0 * 1.25 / 0.00247; } double diff --git a/src/ao_adc.c b/src/ao_adc.c index b0bfceb1..2b972e6c 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -46,16 +46,18 @@ ao_adc_isr(void) interrupt 1 uint8_t __xdata *a; sequence = (ADCCON2 & ADCCON2_SCH_MASK) >> ADCCON2_SCH_SHIFT; + if (sequence == ADCCON3_ECH_TEMP) + sequence = 2; a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].accel + sequence); a[0] = ADCL; a[1] = ADCH; if (sequence < 5) { /* start next channel conversion */ - sequence++; - /* skip channel 2, we don't have a temp sensor on v0.2 */ - if (sequence == 2) - sequence++; - ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | sequence; + /* v0.2 replaces external temp sensor with internal one */ + if (sequence == 1) + ADCCON3 = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP; + else + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | (sequence + 1); } else { /* record this conversion series */ ao_adc_ring[ao_adc_head].tick = ao_time(); diff --git a/src/ao_convert.c b/src/ao_convert.c index 57ed7370..f29ce9e9 100644 --- a/src/ao_convert.c +++ b/src/ao_convert.c @@ -49,7 +49,15 @@ ao_temp_to_dC(int16_t temp) __reentrant int16_t ret; ao_mutex_get(&ao_temp_mutex); - ret = (int16_t) ((temp >> 4) * 3300L / 2047L) - 500; + /* Output voltage at 0°C = 0.755V + * Coefficient = 0.00247V/°C + * Reference voltage = 1.25V + * + * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247 + * = (value - 19791.268) / 32768 * 1.25 / 0.00247 + * ≃ (value - 19791) * 1012 / 65536 + */ + ret = ((temp - 19791) * 1012L) >> 16; ao_mutex_put(&ao_temp_mutex); return ret; } -- cgit v1.2.3 From 2a6350149407c7d2e7d143906c40c5e331248aeb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 11 Feb 2010 18:48:56 -0800 Subject: Missing ao_mutex_put in gps_dump --- src/ao_gps_skytraq.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index 2392dacf..0dd45c0c 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -418,6 +418,7 @@ gps_dump(void) __reentrant printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second); printf ("Lat/Lon: %ld %ld\n", ao_gps_data.latitude, ao_gps_data.longitude); printf ("Alt: %d\n", ao_gps_data.altitude); + ao_mutex_put(&ao_gps_mutex); } __code struct ao_cmds ao_gps_cmds[] = { -- cgit v1.2.3 From 876e9a10b9096ead85fbe08ec9a6a0329cf7cbd4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Feb 2010 16:42:27 -0800 Subject: Log GPS data on pad after boost detect. This wakes up the two GPS reporting tasks and gets them to report out any existing GPS data to the log file. To make sure the timestamps in that GPS data are accurate, this also records GPS time on receipt of the GPS data instead of when that is logged. Signed-off-by: Keith Packard --- src/ao.h | 2 ++ src/ao_flight.c | 4 ++++ src/ao_gps_report.c | 4 ++-- src/ao_gps_sirf.c | 2 ++ src/ao_gps_skytraq.c | 4 ++++ src/ao_gps_test.c | 2 ++ src/ao_gps_test_skytraq.c | 2 ++ 7 files changed, 18 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 2c6eb2b9..d6be2223 100644 --- a/src/ao.h +++ b/src/ao.h @@ -731,6 +731,8 @@ ao_serial_init(void); #define AO_GPS_RUNNING (1 << 5) #define AO_GPS_DATE_VALID (1 << 6) +extern __xdata uint16_t ao_gps_tick; + struct ao_gps_data { uint8_t year; uint8_t month; diff --git a/src/ao_flight.c b/src/ao_flight.c index e0fd97f2..980c16be 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -289,6 +289,10 @@ ao_flight(void) /* disable RDF beacon */ ao_rdf_set(0); + /* Record current GPS position by waking up GPS log tasks */ + ao_wakeup(&ao_gps_data); + ao_wakeup(&ao_gps_tracking_data); + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); break; } diff --git a/src/ao_gps_report.c b/src/ao_gps_report.c index e3e27523..cceb79ff 100644 --- a/src/ao_gps_report.c +++ b/src/ao_gps_report.c @@ -33,7 +33,7 @@ ao_gps_report(void) if (!(gps_data.flags & AO_GPS_VALID)) continue; - gps_log.tick = ao_time(); + gps_log.tick = ao_gps_tick; gps_log.type = AO_LOG_GPS_TIME; gps_log.u.gps_time.hour = gps_data.hour; gps_log.u.gps_time.minute = gps_data.minute; @@ -71,13 +71,13 @@ ao_gps_tracking_report(void) for (;;) { ao_sleep(&ao_gps_tracking_data); ao_mutex_get(&ao_gps_mutex); + gps_log.tick = ao_gps_tick; memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data)); ao_mutex_put(&ao_gps_mutex); if (!(n = gps_tracking_data.channels)) continue; - gps_log.tick = ao_time(); gps_log.type = AO_LOG_GPS_SAT; for (c = 0; c < n; c++) if ((gps_log.u.gps_sat.svid = gps_tracking_data.sats[c].svid)) diff --git a/src/ao_gps_sirf.c b/src/ao_gps_sirf.c index 64b66c95..a6167e6b 100644 --- a/src/ao_gps_sirf.c +++ b/src/ao_gps_sirf.c @@ -20,6 +20,7 @@ #endif __xdata uint8_t ao_gps_mutex; +__xdata uint16_t ao_gps_tick; __xdata struct ao_gps_data ao_gps_data; __xdata struct ao_gps_tracking_data ao_gps_tracking_data; @@ -390,6 +391,7 @@ ao_gps(void) __reentrant switch (i) { case 41: ao_mutex_get(&ao_gps_mutex); + ao_gps_tick = ao_time(); ao_gps_data.hour = ao_sirf_data.utc_hour; ao_gps_data.minute = ao_sirf_data.utc_minute; ao_gps_data.second = ao_sirf_data.utc_second / 1000; diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index 0dd45c0c..ae8c7ef7 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -28,9 +28,11 @@ static __xdata char ao_gps_char; static __xdata uint8_t ao_gps_cksum; static __xdata uint8_t ao_gps_error; +__xdata uint16_t ao_gps_tick; __xdata struct ao_gps_data ao_gps_data; __xdata struct ao_gps_tracking_data ao_gps_tracking_data; +static __xdata uint16_t ao_gps_next_tick; static __xdata struct ao_gps_data ao_gps_next; static __xdata uint8_t ao_gps_date_flags; static __xdata struct ao_gps_tracking_data ao_gps_tracking_next; @@ -248,6 +250,7 @@ ao_gps(void) __reentrant * *66 checksum */ + ao_gps_next_tick = ao_time(); ao_gps_next.flags = AO_GPS_RUNNING | ao_gps_date_flags; ao_gps_next.hour = ao_gps_decimal(2); ao_gps_next.minute = ao_gps_decimal(2); @@ -297,6 +300,7 @@ ao_gps(void) __reentrant ao_gps_error = 1; if (!ao_gps_error) { ao_mutex_get(&ao_gps_mutex); + ao_gps_tick = ao_gps_next_tick; memcpy(&ao_gps_data, &ao_gps_next, sizeof (struct ao_gps_data)); ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_data); diff --git a/src/ao_gps_test.c b/src/ao_gps_test.c index fddfedfd..cdcc6f4c 100644 --- a/src/ao_gps_test.c +++ b/src/ao_gps_test.c @@ -400,6 +400,8 @@ ao_serial_set_speed(uint8_t speed) tcflush(fd, TCIFLUSH); } +#define ao_time() 0 + #include "ao_gps_print.c" #include "ao_gps_sirf.c" diff --git a/src/ao_gps_test_skytraq.c b/src/ao_gps_test_skytraq.c index ccf96378..7fa10eaa 100644 --- a/src/ao_gps_test_skytraq.c +++ b/src/ao_gps_test_skytraq.c @@ -408,6 +408,8 @@ ao_serial_set_speed(uint8_t speed) tcflush(fd, TCIFLUSH); } +#define ao_time() 0 + #include "ao_gps_print.c" #include "ao_gps_skytraq.c" -- cgit v1.2.3 From fd0a42e0e96dcb8ecc9e999f70bcf70692692af9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Feb 2010 20:21:07 -0800 Subject: Change barometer conversion code to shrink conversion table --- src/altitude.h | 2180 +++---------------------------------------------- src/ao_convert.c | 50 +- src/ao_convert_test.c | 75 ++ src/make-altitude | 103 ++- 4 files changed, 340 insertions(+), 2068 deletions(-) create mode 100644 src/ao_convert_test.c (limited to 'src') diff --git a/src/altitude.h b/src/altitude.h index 5225df4d..a278bbc6 100644 --- a/src/altitude.h +++ b/src/altitude.h @@ -1,2048 +1,132 @@ - 15837, /* 10.56 kPa 0 count */ - 15804, /* 10.61 kPa 1 count */ - 15772, /* 10.66 kPa 2 count */ - 15740, /* 10.72 kPa 3 count */ - 15708, /* 10.77 kPa 4 count */ - 15676, /* 10.83 kPa 5 count */ - 15644, /* 10.88 kPa 6 count */ - 15613, /* 10.94 kPa 7 count */ - 15581, /* 10.99 kPa 8 count */ - 15550, /* 11.04 kPa 9 count */ - 15519, /* 11.10 kPa 10 count */ - 15488, /* 11.15 kPa 11 count */ - 15457, /* 11.21 kPa 12 count */ - 15426, /* 11.26 kPa 13 count */ - 15396, /* 11.32 kPa 14 count */ - 15366, /* 11.37 kPa 15 count */ - 15335, /* 11.42 kPa 16 count */ - 15305, /* 11.48 kPa 17 count */ - 15275, /* 11.53 kPa 18 count */ - 15246, /* 11.59 kPa 19 count */ - 15216, /* 11.64 kPa 20 count */ - 15187, /* 11.70 kPa 21 count */ - 15157, /* 11.75 kPa 22 count */ - 15128, /* 11.80 kPa 23 count */ - 15099, /* 11.86 kPa 24 count */ - 15070, /* 11.91 kPa 25 count */ - 15041, /* 11.97 kPa 26 count */ - 15012, /* 12.02 kPa 27 count */ - 14984, /* 12.08 kPa 28 count */ - 14955, /* 12.13 kPa 29 count */ - 14927, /* 12.18 kPa 30 count */ - 14899, /* 12.24 kPa 31 count */ - 14871, /* 12.29 kPa 32 count */ - 14843, /* 12.35 kPa 33 count */ - 14815, /* 12.40 kPa 34 count */ - 14787, /* 12.46 kPa 35 count */ - 14760, /* 12.51 kPa 36 count */ - 14732, /* 12.56 kPa 37 count */ - 14705, /* 12.62 kPa 38 count */ - 14678, /* 12.67 kPa 39 count */ - 14651, /* 12.73 kPa 40 count */ - 14624, /* 12.78 kPa 41 count */ - 14597, /* 12.84 kPa 42 count */ - 14570, /* 12.89 kPa 43 count */ - 14543, /* 12.94 kPa 44 count */ - 14517, /* 13.00 kPa 45 count */ - 14490, /* 13.05 kPa 46 count */ - 14464, /* 13.11 kPa 47 count */ - 14438, /* 13.16 kPa 48 count */ - 14412, /* 13.22 kPa 49 count */ - 14386, /* 13.27 kPa 50 count */ - 14360, /* 13.32 kPa 51 count */ - 14334, /* 13.38 kPa 52 count */ - 14308, /* 13.43 kPa 53 count */ - 14283, /* 13.49 kPa 54 count */ - 14257, /* 13.54 kPa 55 count */ - 14232, /* 13.60 kPa 56 count */ - 14207, /* 13.65 kPa 57 count */ - 14182, /* 13.70 kPa 58 count */ - 14156, /* 13.76 kPa 59 count */ - 14132, /* 13.81 kPa 60 count */ - 14107, /* 13.87 kPa 61 count */ - 14082, /* 13.92 kPa 62 count */ - 14057, /* 13.98 kPa 63 count */ - 14033, /* 14.03 kPa 64 count */ - 14008, /* 14.08 kPa 65 count */ - 13984, /* 14.14 kPa 66 count */ - 13959, /* 14.19 kPa 67 count */ - 13935, /* 14.25 kPa 68 count */ - 13911, /* 14.30 kPa 69 count */ - 13887, /* 14.36 kPa 70 count */ - 13863, /* 14.41 kPa 71 count */ - 13839, /* 14.46 kPa 72 count */ - 13816, /* 14.52 kPa 73 count */ - 13792, /* 14.57 kPa 74 count */ - 13768, /* 14.63 kPa 75 count */ - 13745, /* 14.68 kPa 76 count */ - 13721, /* 14.74 kPa 77 count */ - 13698, /* 14.79 kPa 78 count */ - 13675, /* 14.84 kPa 79 count */ - 13652, /* 14.90 kPa 80 count */ - 13629, /* 14.95 kPa 81 count */ - 13606, /* 15.01 kPa 82 count */ - 13583, /* 15.06 kPa 83 count */ - 13560, /* 15.12 kPa 84 count */ - 13537, /* 15.17 kPa 85 count */ - 13515, /* 15.22 kPa 86 count */ - 13492, /* 15.28 kPa 87 count */ - 13470, /* 15.33 kPa 88 count */ - 13447, /* 15.39 kPa 89 count */ - 13425, /* 15.44 kPa 90 count */ - 13403, /* 15.50 kPa 91 count */ - 13380, /* 15.55 kPa 92 count */ - 13358, /* 15.60 kPa 93 count */ - 13336, /* 15.66 kPa 94 count */ - 13314, /* 15.71 kPa 95 count */ - 13292, /* 15.77 kPa 96 count */ - 13271, /* 15.82 kPa 97 count */ - 13249, /* 15.87 kPa 98 count */ - 13227, /* 15.93 kPa 99 count */ - 13206, /* 15.98 kPa 100 count */ - 13184, /* 16.04 kPa 101 count */ - 13163, /* 16.09 kPa 102 count */ - 13141, /* 16.15 kPa 103 count */ - 13120, /* 16.20 kPa 104 count */ - 13099, /* 16.25 kPa 105 count */ - 13078, /* 16.31 kPa 106 count */ - 13057, /* 16.36 kPa 107 count */ - 13036, /* 16.42 kPa 108 count */ - 13015, /* 16.47 kPa 109 count */ - 12994, /* 16.53 kPa 110 count */ - 12973, /* 16.58 kPa 111 count */ - 12952, /* 16.63 kPa 112 count */ - 12932, /* 16.69 kPa 113 count */ - 12911, /* 16.74 kPa 114 count */ - 12891, /* 16.80 kPa 115 count */ - 12870, /* 16.85 kPa 116 count */ - 12850, /* 16.91 kPa 117 count */ - 12829, /* 16.96 kPa 118 count */ - 12809, /* 17.01 kPa 119 count */ - 12789, /* 17.07 kPa 120 count */ - 12769, /* 17.12 kPa 121 count */ - 12749, /* 17.18 kPa 122 count */ - 12729, /* 17.23 kPa 123 count */ - 12709, /* 17.29 kPa 124 count */ - 12689, /* 17.34 kPa 125 count */ - 12669, /* 17.39 kPa 126 count */ - 12649, /* 17.45 kPa 127 count */ - 12630, /* 17.50 kPa 128 count */ - 12610, /* 17.56 kPa 129 count */ - 12590, /* 17.61 kPa 130 count */ - 12571, /* 17.67 kPa 131 count */ - 12551, /* 17.72 kPa 132 count */ - 12532, /* 17.77 kPa 133 count */ - 12513, /* 17.83 kPa 134 count */ - 12493, /* 17.88 kPa 135 count */ - 12474, /* 17.94 kPa 136 count */ - 12455, /* 17.99 kPa 137 count */ - 12436, /* 18.05 kPa 138 count */ - 12417, /* 18.10 kPa 139 count */ - 12398, /* 18.15 kPa 140 count */ - 12379, /* 18.21 kPa 141 count */ - 12360, /* 18.26 kPa 142 count */ - 12341, /* 18.32 kPa 143 count */ - 12323, /* 18.37 kPa 144 count */ - 12304, /* 18.43 kPa 145 count */ - 12285, /* 18.48 kPa 146 count */ - 12267, /* 18.53 kPa 147 count */ - 12248, /* 18.59 kPa 148 count */ - 12230, /* 18.64 kPa 149 count */ - 12211, /* 18.70 kPa 150 count */ - 12193, /* 18.75 kPa 151 count */ - 12174, /* 18.81 kPa 152 count */ - 12156, /* 18.86 kPa 153 count */ - 12138, /* 18.91 kPa 154 count */ - 12120, /* 18.97 kPa 155 count */ - 12102, /* 19.02 kPa 156 count */ - 12084, /* 19.08 kPa 157 count */ - 12065, /* 19.13 kPa 158 count */ - 12048, /* 19.19 kPa 159 count */ - 12030, /* 19.24 kPa 160 count */ - 12012, /* 19.29 kPa 161 count */ - 11994, /* 19.35 kPa 162 count */ - 11976, /* 19.40 kPa 163 count */ - 11958, /* 19.46 kPa 164 count */ - 11941, /* 19.51 kPa 165 count */ - 11923, /* 19.57 kPa 166 count */ - 11906, /* 19.62 kPa 167 count */ - 11888, /* 19.67 kPa 168 count */ - 11871, /* 19.73 kPa 169 count */ - 11853, /* 19.78 kPa 170 count */ - 11836, /* 19.84 kPa 171 count */ - 11818, /* 19.89 kPa 172 count */ - 11801, /* 19.95 kPa 173 count */ - 11784, /* 20.00 kPa 174 count */ - 11767, /* 20.05 kPa 175 count */ - 11750, /* 20.11 kPa 176 count */ - 11733, /* 20.16 kPa 177 count */ - 11715, /* 20.22 kPa 178 count */ - 11698, /* 20.27 kPa 179 count */ - 11682, /* 20.33 kPa 180 count */ - 11665, /* 20.38 kPa 181 count */ - 11648, /* 20.43 kPa 182 count */ - 11631, /* 20.49 kPa 183 count */ - 11614, /* 20.54 kPa 184 count */ - 11597, /* 20.60 kPa 185 count */ - 11581, /* 20.65 kPa 186 count */ - 11564, /* 20.71 kPa 187 count */ - 11547, /* 20.76 kPa 188 count */ - 11531, /* 20.81 kPa 189 count */ - 11514, /* 20.87 kPa 190 count */ - 11498, /* 20.92 kPa 191 count */ - 11481, /* 20.98 kPa 192 count */ - 11465, /* 21.03 kPa 193 count */ - 11449, /* 21.09 kPa 194 count */ - 11432, /* 21.14 kPa 195 count */ - 11416, /* 21.19 kPa 196 count */ - 11400, /* 21.25 kPa 197 count */ - 11384, /* 21.30 kPa 198 count */ - 11368, /* 21.36 kPa 199 count */ - 11352, /* 21.41 kPa 200 count */ - 11336, /* 21.47 kPa 201 count */ - 11319, /* 21.52 kPa 202 count */ - 11304, /* 21.57 kPa 203 count */ - 11288, /* 21.63 kPa 204 count */ - 11272, /* 21.68 kPa 205 count */ - 11256, /* 21.74 kPa 206 count */ - 11240, /* 21.79 kPa 207 count */ - 11224, /* 21.85 kPa 208 count */ - 11208, /* 21.90 kPa 209 count */ - 11193, /* 21.95 kPa 210 count */ - 11177, /* 22.01 kPa 211 count */ - 11162, /* 22.06 kPa 212 count */ - 11146, /* 22.12 kPa 213 count */ - 11130, /* 22.17 kPa 214 count */ - 11115, /* 22.23 kPa 215 count */ - 11099, /* 22.28 kPa 216 count */ - 11084, /* 22.33 kPa 217 count */ - 11069, /* 22.39 kPa 218 count */ - 11053, /* 22.44 kPa 219 count */ - 11038, /* 22.50 kPa 220 count */ - 11023, /* 22.55 kPa 221 count */ - 11007, /* 22.61 kPa 222 count */ - 10992, /* 22.66 kPa 223 count */ - 10977, /* 22.71 kPa 224 count */ - 10962, /* 22.77 kPa 225 count */ - 10947, /* 22.82 kPa 226 count */ - 10932, /* 22.88 kPa 227 count */ - 10917, /* 22.93 kPa 228 count */ - 10902, /* 22.99 kPa 229 count */ - 10887, /* 23.04 kPa 230 count */ - 10872, /* 23.09 kPa 231 count */ - 10857, /* 23.15 kPa 232 count */ - 10842, /* 23.20 kPa 233 count */ - 10827, /* 23.26 kPa 234 count */ - 10812, /* 23.31 kPa 235 count */ - 10797, /* 23.37 kPa 236 count */ - 10782, /* 23.42 kPa 237 count */ - 10768, /* 23.47 kPa 238 count */ - 10753, /* 23.53 kPa 239 count */ - 10738, /* 23.58 kPa 240 count */ - 10723, /* 23.64 kPa 241 count */ - 10709, /* 23.69 kPa 242 count */ - 10694, /* 23.75 kPa 243 count */ - 10679, /* 23.80 kPa 244 count */ - 10665, /* 23.85 kPa 245 count */ - 10650, /* 23.91 kPa 246 count */ - 10636, /* 23.96 kPa 247 count */ - 10621, /* 24.02 kPa 248 count */ - 10607, /* 24.07 kPa 249 count */ - 10592, /* 24.13 kPa 250 count */ - 10578, /* 24.18 kPa 251 count */ - 10563, /* 24.23 kPa 252 count */ - 10549, /* 24.29 kPa 253 count */ - 10535, /* 24.34 kPa 254 count */ - 10520, /* 24.40 kPa 255 count */ - 10506, /* 24.45 kPa 256 count */ - 10492, /* 24.51 kPa 257 count */ - 10478, /* 24.56 kPa 258 count */ - 10463, /* 24.61 kPa 259 count */ - 10449, /* 24.67 kPa 260 count */ - 10435, /* 24.72 kPa 261 count */ - 10421, /* 24.78 kPa 262 count */ - 10407, /* 24.83 kPa 263 count */ - 10393, /* 24.89 kPa 264 count */ - 10379, /* 24.94 kPa 265 count */ - 10364, /* 24.99 kPa 266 count */ - 10350, /* 25.05 kPa 267 count */ - 10336, /* 25.10 kPa 268 count */ - 10322, /* 25.16 kPa 269 count */ - 10309, /* 25.21 kPa 270 count */ - 10295, /* 25.27 kPa 271 count */ - 10281, /* 25.32 kPa 272 count */ - 10267, /* 25.37 kPa 273 count */ - 10253, /* 25.43 kPa 274 count */ - 10239, /* 25.48 kPa 275 count */ - 10225, /* 25.54 kPa 276 count */ - 10212, /* 25.59 kPa 277 count */ - 10198, /* 25.65 kPa 278 count */ - 10184, /* 25.70 kPa 279 count */ - 10170, /* 25.75 kPa 280 count */ - 10157, /* 25.81 kPa 281 count */ - 10143, /* 25.86 kPa 282 count */ - 10129, /* 25.92 kPa 283 count */ - 10116, /* 25.97 kPa 284 count */ - 10102, /* 26.03 kPa 285 count */ - 10089, /* 26.08 kPa 286 count */ - 10075, /* 26.13 kPa 287 count */ - 10062, /* 26.19 kPa 288 count */ - 10048, /* 26.24 kPa 289 count */ - 10035, /* 26.30 kPa 290 count */ - 10021, /* 26.35 kPa 291 count */ - 10008, /* 26.41 kPa 292 count */ - 9994, /* 26.46 kPa 293 count */ - 9981, /* 26.51 kPa 294 count */ - 9967, /* 26.57 kPa 295 count */ - 9954, /* 26.62 kPa 296 count */ - 9941, /* 26.68 kPa 297 count */ - 9928, /* 26.73 kPa 298 count */ - 9914, /* 26.79 kPa 299 count */ - 9901, /* 26.84 kPa 300 count */ - 9888, /* 26.89 kPa 301 count */ - 9875, /* 26.95 kPa 302 count */ - 9861, /* 27.00 kPa 303 count */ - 9848, /* 27.06 kPa 304 count */ - 9835, /* 27.11 kPa 305 count */ - 9822, /* 27.17 kPa 306 count */ - 9809, /* 27.22 kPa 307 count */ - 9796, /* 27.27 kPa 308 count */ - 9783, /* 27.33 kPa 309 count */ - 9770, /* 27.38 kPa 310 count */ - 9757, /* 27.44 kPa 311 count */ - 9744, /* 27.49 kPa 312 count */ - 9731, /* 27.55 kPa 313 count */ - 9718, /* 27.60 kPa 314 count */ - 9705, /* 27.65 kPa 315 count */ - 9692, /* 27.71 kPa 316 count */ - 9679, /* 27.76 kPa 317 count */ - 9666, /* 27.82 kPa 318 count */ - 9653, /* 27.87 kPa 319 count */ - 9640, /* 27.93 kPa 320 count */ - 9627, /* 27.98 kPa 321 count */ - 9615, /* 28.03 kPa 322 count */ - 9602, /* 28.09 kPa 323 count */ - 9589, /* 28.14 kPa 324 count */ - 9576, /* 28.20 kPa 325 count */ - 9564, /* 28.25 kPa 326 count */ - 9551, /* 28.31 kPa 327 count */ - 9538, /* 28.36 kPa 328 count */ - 9526, /* 28.41 kPa 329 count */ - 9513, /* 28.47 kPa 330 count */ - 9500, /* 28.52 kPa 331 count */ - 9488, /* 28.58 kPa 332 count */ - 9475, /* 28.63 kPa 333 count */ - 9463, /* 28.69 kPa 334 count */ - 9450, /* 28.74 kPa 335 count */ - 9438, /* 28.79 kPa 336 count */ - 9425, /* 28.85 kPa 337 count */ - 9413, /* 28.90 kPa 338 count */ - 9400, /* 28.96 kPa 339 count */ - 9388, /* 29.01 kPa 340 count */ - 9375, /* 29.07 kPa 341 count */ - 9363, /* 29.12 kPa 342 count */ - 9350, /* 29.17 kPa 343 count */ - 9338, /* 29.23 kPa 344 count */ - 9326, /* 29.28 kPa 345 count */ - 9313, /* 29.34 kPa 346 count */ - 9301, /* 29.39 kPa 347 count */ - 9289, /* 29.44 kPa 348 count */ - 9276, /* 29.50 kPa 349 count */ - 9264, /* 29.55 kPa 350 count */ - 9252, /* 29.61 kPa 351 count */ - 9240, /* 29.66 kPa 352 count */ - 9227, /* 29.72 kPa 353 count */ - 9215, /* 29.77 kPa 354 count */ - 9203, /* 29.82 kPa 355 count */ - 9191, /* 29.88 kPa 356 count */ - 9179, /* 29.93 kPa 357 count */ - 9167, /* 29.99 kPa 358 count */ - 9155, /* 30.04 kPa 359 count */ - 9142, /* 30.10 kPa 360 count */ - 9130, /* 30.15 kPa 361 count */ - 9118, /* 30.20 kPa 362 count */ - 9106, /* 30.26 kPa 363 count */ - 9094, /* 30.31 kPa 364 count */ - 9082, /* 30.37 kPa 365 count */ - 9070, /* 30.42 kPa 366 count */ - 9058, /* 30.48 kPa 367 count */ - 9046, /* 30.53 kPa 368 count */ - 9035, /* 30.58 kPa 369 count */ - 9023, /* 30.64 kPa 370 count */ - 9011, /* 30.69 kPa 371 count */ - 8999, /* 30.75 kPa 372 count */ - 8987, /* 30.80 kPa 373 count */ - 8975, /* 30.86 kPa 374 count */ - 8963, /* 30.91 kPa 375 count */ - 8952, /* 30.96 kPa 376 count */ - 8940, /* 31.02 kPa 377 count */ - 8928, /* 31.07 kPa 378 count */ - 8916, /* 31.13 kPa 379 count */ - 8904, /* 31.18 kPa 380 count */ - 8893, /* 31.24 kPa 381 count */ - 8881, /* 31.29 kPa 382 count */ - 8869, /* 31.34 kPa 383 count */ - 8858, /* 31.40 kPa 384 count */ - 8846, /* 31.45 kPa 385 count */ - 8834, /* 31.51 kPa 386 count */ - 8823, /* 31.56 kPa 387 count */ - 8811, /* 31.62 kPa 388 count */ - 8800, /* 31.67 kPa 389 count */ - 8788, /* 31.72 kPa 390 count */ - 8776, /* 31.78 kPa 391 count */ - 8765, /* 31.83 kPa 392 count */ - 8753, /* 31.89 kPa 393 count */ - 8742, /* 31.94 kPa 394 count */ - 8730, /* 32.00 kPa 395 count */ - 8719, /* 32.05 kPa 396 count */ - 8707, /* 32.10 kPa 397 count */ - 8696, /* 32.16 kPa 398 count */ - 8684, /* 32.21 kPa 399 count */ - 8673, /* 32.27 kPa 400 count */ - 8662, /* 32.32 kPa 401 count */ - 8650, /* 32.38 kPa 402 count */ - 8639, /* 32.43 kPa 403 count */ - 8628, /* 32.48 kPa 404 count */ - 8616, /* 32.54 kPa 405 count */ - 8605, /* 32.59 kPa 406 count */ - 8594, /* 32.65 kPa 407 count */ - 8582, /* 32.70 kPa 408 count */ - 8571, /* 32.76 kPa 409 count */ - 8560, /* 32.81 kPa 410 count */ - 8548, /* 32.86 kPa 411 count */ - 8537, /* 32.92 kPa 412 count */ - 8526, /* 32.97 kPa 413 count */ - 8515, /* 33.03 kPa 414 count */ - 8504, /* 33.08 kPa 415 count */ - 8492, /* 33.14 kPa 416 count */ - 8481, /* 33.19 kPa 417 count */ - 8470, /* 33.24 kPa 418 count */ - 8459, /* 33.30 kPa 419 count */ - 8448, /* 33.35 kPa 420 count */ - 8437, /* 33.41 kPa 421 count */ - 8426, /* 33.46 kPa 422 count */ - 8415, /* 33.52 kPa 423 count */ - 8403, /* 33.57 kPa 424 count */ - 8392, /* 33.62 kPa 425 count */ - 8381, /* 33.68 kPa 426 count */ - 8370, /* 33.73 kPa 427 count */ - 8359, /* 33.79 kPa 428 count */ - 8348, /* 33.84 kPa 429 count */ - 8337, /* 33.90 kPa 430 count */ - 8326, /* 33.95 kPa 431 count */ - 8316, /* 34.00 kPa 432 count */ - 8305, /* 34.06 kPa 433 count */ - 8294, /* 34.11 kPa 434 count */ - 8283, /* 34.17 kPa 435 count */ - 8272, /* 34.22 kPa 436 count */ - 8261, /* 34.28 kPa 437 count */ - 8250, /* 34.33 kPa 438 count */ - 8239, /* 34.38 kPa 439 count */ - 8228, /* 34.44 kPa 440 count */ - 8218, /* 34.49 kPa 441 count */ - 8207, /* 34.55 kPa 442 count */ - 8196, /* 34.60 kPa 443 count */ - 8185, /* 34.66 kPa 444 count */ - 8175, /* 34.71 kPa 445 count */ - 8164, /* 34.76 kPa 446 count */ - 8153, /* 34.82 kPa 447 count */ - 8142, /* 34.87 kPa 448 count */ - 8132, /* 34.93 kPa 449 count */ - 8121, /* 34.98 kPa 450 count */ - 8110, /* 35.04 kPa 451 count */ - 8100, /* 35.09 kPa 452 count */ - 8089, /* 35.14 kPa 453 count */ - 8078, /* 35.20 kPa 454 count */ - 8068, /* 35.25 kPa 455 count */ - 8057, /* 35.31 kPa 456 count */ - 8046, /* 35.36 kPa 457 count */ - 8036, /* 35.42 kPa 458 count */ - 8025, /* 35.47 kPa 459 count */ - 8015, /* 35.52 kPa 460 count */ - 8004, /* 35.58 kPa 461 count */ - 7994, /* 35.63 kPa 462 count */ - 7983, /* 35.69 kPa 463 count */ - 7973, /* 35.74 kPa 464 count */ - 7962, /* 35.80 kPa 465 count */ - 7952, /* 35.85 kPa 466 count */ - 7941, /* 35.90 kPa 467 count */ - 7931, /* 35.96 kPa 468 count */ - 7920, /* 36.01 kPa 469 count */ - 7910, /* 36.07 kPa 470 count */ - 7899, /* 36.12 kPa 471 count */ - 7889, /* 36.18 kPa 472 count */ - 7879, /* 36.23 kPa 473 count */ - 7868, /* 36.28 kPa 474 count */ - 7858, /* 36.34 kPa 475 count */ - 7847, /* 36.39 kPa 476 count */ - 7837, /* 36.45 kPa 477 count */ - 7827, /* 36.50 kPa 478 count */ - 7816, /* 36.56 kPa 479 count */ - 7806, /* 36.61 kPa 480 count */ - 7796, /* 36.66 kPa 481 count */ - 7785, /* 36.72 kPa 482 count */ - 7775, /* 36.77 kPa 483 count */ - 7765, /* 36.83 kPa 484 count */ - 7755, /* 36.88 kPa 485 count */ - 7744, /* 36.94 kPa 486 count */ - 7734, /* 36.99 kPa 487 count */ - 7724, /* 37.04 kPa 488 count */ - 7714, /* 37.10 kPa 489 count */ - 7704, /* 37.15 kPa 490 count */ - 7693, /* 37.21 kPa 491 count */ - 7683, /* 37.26 kPa 492 count */ - 7673, /* 37.32 kPa 493 count */ - 7663, /* 37.37 kPa 494 count */ - 7653, /* 37.42 kPa 495 count */ - 7643, /* 37.48 kPa 496 count */ - 7633, /* 37.53 kPa 497 count */ - 7623, /* 37.59 kPa 498 count */ - 7613, /* 37.64 kPa 499 count */ - 7602, /* 37.70 kPa 500 count */ - 7592, /* 37.75 kPa 501 count */ - 7582, /* 37.80 kPa 502 count */ - 7572, /* 37.86 kPa 503 count */ - 7562, /* 37.91 kPa 504 count */ - 7552, /* 37.97 kPa 505 count */ - 7542, /* 38.02 kPa 506 count */ - 7532, /* 38.08 kPa 507 count */ - 7522, /* 38.13 kPa 508 count */ - 7512, /* 38.18 kPa 509 count */ - 7502, /* 38.24 kPa 510 count */ - 7492, /* 38.29 kPa 511 count */ - 7483, /* 38.35 kPa 512 count */ - 7473, /* 38.40 kPa 513 count */ - 7463, /* 38.46 kPa 514 count */ - 7453, /* 38.51 kPa 515 count */ - 7443, /* 38.56 kPa 516 count */ - 7433, /* 38.62 kPa 517 count */ - 7423, /* 38.67 kPa 518 count */ - 7413, /* 38.73 kPa 519 count */ - 7403, /* 38.78 kPa 520 count */ - 7394, /* 38.84 kPa 521 count */ - 7384, /* 38.89 kPa 522 count */ - 7374, /* 38.94 kPa 523 count */ - 7364, /* 39.00 kPa 524 count */ - 7354, /* 39.05 kPa 525 count */ - 7345, /* 39.11 kPa 526 count */ - 7335, /* 39.16 kPa 527 count */ - 7325, /* 39.22 kPa 528 count */ - 7315, /* 39.27 kPa 529 count */ - 7306, /* 39.32 kPa 530 count */ - 7296, /* 39.38 kPa 531 count */ - 7286, /* 39.43 kPa 532 count */ - 7277, /* 39.49 kPa 533 count */ - 7267, /* 39.54 kPa 534 count */ - 7257, /* 39.60 kPa 535 count */ - 7248, /* 39.65 kPa 536 count */ - 7238, /* 39.70 kPa 537 count */ - 7228, /* 39.76 kPa 538 count */ - 7219, /* 39.81 kPa 539 count */ - 7209, /* 39.87 kPa 540 count */ - 7199, /* 39.92 kPa 541 count */ - 7190, /* 39.98 kPa 542 count */ - 7180, /* 40.03 kPa 543 count */ - 7171, /* 40.08 kPa 544 count */ - 7161, /* 40.14 kPa 545 count */ - 7152, /* 40.19 kPa 546 count */ - 7142, /* 40.25 kPa 547 count */ - 7132, /* 40.30 kPa 548 count */ - 7123, /* 40.36 kPa 549 count */ - 7113, /* 40.41 kPa 550 count */ - 7104, /* 40.46 kPa 551 count */ - 7094, /* 40.52 kPa 552 count */ - 7085, /* 40.57 kPa 553 count */ - 7075, /* 40.63 kPa 554 count */ - 7066, /* 40.68 kPa 555 count */ - 7056, /* 40.74 kPa 556 count */ - 7047, /* 40.79 kPa 557 count */ - 7038, /* 40.84 kPa 558 count */ - 7028, /* 40.90 kPa 559 count */ - 7019, /* 40.95 kPa 560 count */ - 7009, /* 41.01 kPa 561 count */ - 7000, /* 41.06 kPa 562 count */ - 6991, /* 41.12 kPa 563 count */ - 6981, /* 41.17 kPa 564 count */ - 6972, /* 41.22 kPa 565 count */ - 6962, /* 41.28 kPa 566 count */ - 6953, /* 41.33 kPa 567 count */ - 6944, /* 41.39 kPa 568 count */ - 6934, /* 41.44 kPa 569 count */ - 6925, /* 41.50 kPa 570 count */ - 6916, /* 41.55 kPa 571 count */ - 6907, /* 41.60 kPa 572 count */ - 6897, /* 41.66 kPa 573 count */ - 6888, /* 41.71 kPa 574 count */ - 6879, /* 41.77 kPa 575 count */ - 6869, /* 41.82 kPa 576 count */ - 6860, /* 41.88 kPa 577 count */ - 6851, /* 41.93 kPa 578 count */ - 6842, /* 41.98 kPa 579 count */ - 6833, /* 42.04 kPa 580 count */ - 6823, /* 42.09 kPa 581 count */ - 6814, /* 42.15 kPa 582 count */ - 6805, /* 42.20 kPa 583 count */ - 6796, /* 42.26 kPa 584 count */ - 6787, /* 42.31 kPa 585 count */ - 6777, /* 42.36 kPa 586 count */ - 6768, /* 42.42 kPa 587 count */ - 6759, /* 42.47 kPa 588 count */ - 6750, /* 42.53 kPa 589 count */ - 6741, /* 42.58 kPa 590 count */ - 6732, /* 42.64 kPa 591 count */ - 6723, /* 42.69 kPa 592 count */ - 6714, /* 42.74 kPa 593 count */ - 6705, /* 42.80 kPa 594 count */ - 6695, /* 42.85 kPa 595 count */ - 6686, /* 42.91 kPa 596 count */ - 6677, /* 42.96 kPa 597 count */ - 6668, /* 43.01 kPa 598 count */ - 6659, /* 43.07 kPa 599 count */ - 6650, /* 43.12 kPa 600 count */ - 6641, /* 43.18 kPa 601 count */ - 6632, /* 43.23 kPa 602 count */ - 6623, /* 43.29 kPa 603 count */ - 6614, /* 43.34 kPa 604 count */ - 6605, /* 43.39 kPa 605 count */ - 6596, /* 43.45 kPa 606 count */ - 6587, /* 43.50 kPa 607 count */ - 6578, /* 43.56 kPa 608 count */ - 6569, /* 43.61 kPa 609 count */ - 6560, /* 43.67 kPa 610 count */ - 6552, /* 43.72 kPa 611 count */ - 6543, /* 43.77 kPa 612 count */ - 6534, /* 43.83 kPa 613 count */ - 6525, /* 43.88 kPa 614 count */ - 6516, /* 43.94 kPa 615 count */ - 6507, /* 43.99 kPa 616 count */ - 6498, /* 44.05 kPa 617 count */ - 6489, /* 44.10 kPa 618 count */ - 6480, /* 44.15 kPa 619 count */ - 6472, /* 44.21 kPa 620 count */ - 6463, /* 44.26 kPa 621 count */ - 6454, /* 44.32 kPa 622 count */ - 6445, /* 44.37 kPa 623 count */ - 6436, /* 44.43 kPa 624 count */ - 6427, /* 44.48 kPa 625 count */ - 6419, /* 44.53 kPa 626 count */ - 6410, /* 44.59 kPa 627 count */ - 6401, /* 44.64 kPa 628 count */ - 6392, /* 44.70 kPa 629 count */ - 6384, /* 44.75 kPa 630 count */ - 6375, /* 44.81 kPa 631 count */ - 6366, /* 44.86 kPa 632 count */ - 6357, /* 44.91 kPa 633 count */ - 6349, /* 44.97 kPa 634 count */ - 6340, /* 45.02 kPa 635 count */ - 6331, /* 45.08 kPa 636 count */ - 6322, /* 45.13 kPa 637 count */ - 6314, /* 45.19 kPa 638 count */ - 6305, /* 45.24 kPa 639 count */ - 6296, /* 45.29 kPa 640 count */ - 6288, /* 45.35 kPa 641 count */ - 6279, /* 45.40 kPa 642 count */ - 6270, /* 45.46 kPa 643 count */ - 6262, /* 45.51 kPa 644 count */ - 6253, /* 45.57 kPa 645 count */ - 6245, /* 45.62 kPa 646 count */ - 6236, /* 45.67 kPa 647 count */ - 6227, /* 45.73 kPa 648 count */ - 6219, /* 45.78 kPa 649 count */ - 6210, /* 45.84 kPa 650 count */ - 6202, /* 45.89 kPa 651 count */ - 6193, /* 45.95 kPa 652 count */ - 6184, /* 46.00 kPa 653 count */ - 6176, /* 46.05 kPa 654 count */ - 6167, /* 46.11 kPa 655 count */ - 6159, /* 46.16 kPa 656 count */ - 6150, /* 46.22 kPa 657 count */ - 6142, /* 46.27 kPa 658 count */ - 6133, /* 46.33 kPa 659 count */ - 6125, /* 46.38 kPa 660 count */ - 6116, /* 46.43 kPa 661 count */ - 6108, /* 46.49 kPa 662 count */ - 6099, /* 46.54 kPa 663 count */ - 6091, /* 46.60 kPa 664 count */ - 6082, /* 46.65 kPa 665 count */ - 6074, /* 46.71 kPa 666 count */ - 6065, /* 46.76 kPa 667 count */ - 6057, /* 46.81 kPa 668 count */ - 6048, /* 46.87 kPa 669 count */ - 6040, /* 46.92 kPa 670 count */ - 6032, /* 46.98 kPa 671 count */ - 6023, /* 47.03 kPa 672 count */ - 6015, /* 47.09 kPa 673 count */ - 6006, /* 47.14 kPa 674 count */ - 5998, /* 47.19 kPa 675 count */ - 5990, /* 47.25 kPa 676 count */ - 5981, /* 47.30 kPa 677 count */ - 5973, /* 47.36 kPa 678 count */ - 5964, /* 47.41 kPa 679 count */ - 5956, /* 47.47 kPa 680 count */ - 5948, /* 47.52 kPa 681 count */ - 5939, /* 47.57 kPa 682 count */ - 5931, /* 47.63 kPa 683 count */ - 5923, /* 47.68 kPa 684 count */ - 5914, /* 47.74 kPa 685 count */ - 5906, /* 47.79 kPa 686 count */ - 5898, /* 47.85 kPa 687 count */ - 5890, /* 47.90 kPa 688 count */ - 5881, /* 47.95 kPa 689 count */ - 5873, /* 48.01 kPa 690 count */ - 5865, /* 48.06 kPa 691 count */ - 5856, /* 48.12 kPa 692 count */ - 5848, /* 48.17 kPa 693 count */ - 5840, /* 48.23 kPa 694 count */ - 5832, /* 48.28 kPa 695 count */ - 5823, /* 48.33 kPa 696 count */ - 5815, /* 48.39 kPa 697 count */ - 5807, /* 48.44 kPa 698 count */ - 5799, /* 48.50 kPa 699 count */ - 5791, /* 48.55 kPa 700 count */ - 5782, /* 48.61 kPa 701 count */ - 5774, /* 48.66 kPa 702 count */ - 5766, /* 48.71 kPa 703 count */ - 5758, /* 48.77 kPa 704 count */ - 5750, /* 48.82 kPa 705 count */ - 5742, /* 48.88 kPa 706 count */ - 5733, /* 48.93 kPa 707 count */ - 5725, /* 48.99 kPa 708 count */ - 5717, /* 49.04 kPa 709 count */ - 5709, /* 49.09 kPa 710 count */ - 5701, /* 49.15 kPa 711 count */ - 5693, /* 49.20 kPa 712 count */ - 5685, /* 49.26 kPa 713 count */ - 5677, /* 49.31 kPa 714 count */ - 5668, /* 49.37 kPa 715 count */ - 5660, /* 49.42 kPa 716 count */ - 5652, /* 49.47 kPa 717 count */ - 5644, /* 49.53 kPa 718 count */ - 5636, /* 49.58 kPa 719 count */ - 5628, /* 49.64 kPa 720 count */ - 5620, /* 49.69 kPa 721 count */ - 5612, /* 49.75 kPa 722 count */ - 5604, /* 49.80 kPa 723 count */ - 5596, /* 49.85 kPa 724 count */ - 5588, /* 49.91 kPa 725 count */ - 5580, /* 49.96 kPa 726 count */ - 5572, /* 50.02 kPa 727 count */ - 5564, /* 50.07 kPa 728 count */ - 5556, /* 50.13 kPa 729 count */ - 5548, /* 50.18 kPa 730 count */ - 5540, /* 50.23 kPa 731 count */ - 5532, /* 50.29 kPa 732 count */ - 5524, /* 50.34 kPa 733 count */ - 5516, /* 50.40 kPa 734 count */ - 5508, /* 50.45 kPa 735 count */ - 5500, /* 50.51 kPa 736 count */ - 5492, /* 50.56 kPa 737 count */ - 5484, /* 50.61 kPa 738 count */ - 5476, /* 50.67 kPa 739 count */ - 5468, /* 50.72 kPa 740 count */ - 5461, /* 50.78 kPa 741 count */ - 5453, /* 50.83 kPa 742 count */ - 5445, /* 50.89 kPa 743 count */ - 5437, /* 50.94 kPa 744 count */ - 5429, /* 50.99 kPa 745 count */ - 5421, /* 51.05 kPa 746 count */ - 5413, /* 51.10 kPa 747 count */ - 5405, /* 51.16 kPa 748 count */ - 5398, /* 51.21 kPa 749 count */ - 5390, /* 51.27 kPa 750 count */ - 5382, /* 51.32 kPa 751 count */ - 5374, /* 51.37 kPa 752 count */ - 5366, /* 51.43 kPa 753 count */ - 5358, /* 51.48 kPa 754 count */ - 5351, /* 51.54 kPa 755 count */ - 5343, /* 51.59 kPa 756 count */ - 5335, /* 51.65 kPa 757 count */ - 5327, /* 51.70 kPa 758 count */ - 5319, /* 51.75 kPa 759 count */ - 5312, /* 51.81 kPa 760 count */ - 5304, /* 51.86 kPa 761 count */ - 5296, /* 51.92 kPa 762 count */ - 5288, /* 51.97 kPa 763 count */ - 5281, /* 52.03 kPa 764 count */ - 5273, /* 52.08 kPa 765 count */ - 5265, /* 52.13 kPa 766 count */ - 5257, /* 52.19 kPa 767 count */ - 5250, /* 52.24 kPa 768 count */ - 5242, /* 52.30 kPa 769 count */ - 5234, /* 52.35 kPa 770 count */ - 5226, /* 52.41 kPa 771 count */ - 5219, /* 52.46 kPa 772 count */ - 5211, /* 52.51 kPa 773 count */ - 5203, /* 52.57 kPa 774 count */ - 5196, /* 52.62 kPa 775 count */ - 5188, /* 52.68 kPa 776 count */ - 5180, /* 52.73 kPa 777 count */ - 5173, /* 52.79 kPa 778 count */ - 5165, /* 52.84 kPa 779 count */ - 5157, /* 52.89 kPa 780 count */ - 5150, /* 52.95 kPa 781 count */ - 5142, /* 53.00 kPa 782 count */ - 5134, /* 53.06 kPa 783 count */ - 5127, /* 53.11 kPa 784 count */ - 5119, /* 53.17 kPa 785 count */ - 5112, /* 53.22 kPa 786 count */ - 5104, /* 53.27 kPa 787 count */ - 5096, /* 53.33 kPa 788 count */ - 5089, /* 53.38 kPa 789 count */ - 5081, /* 53.44 kPa 790 count */ - 5074, /* 53.49 kPa 791 count */ - 5066, /* 53.55 kPa 792 count */ - 5058, /* 53.60 kPa 793 count */ - 5051, /* 53.65 kPa 794 count */ - 5043, /* 53.71 kPa 795 count */ - 5036, /* 53.76 kPa 796 count */ - 5028, /* 53.82 kPa 797 count */ - 5021, /* 53.87 kPa 798 count */ - 5013, /* 53.93 kPa 799 count */ - 5006, /* 53.98 kPa 800 count */ - 4998, /* 54.03 kPa 801 count */ - 4991, /* 54.09 kPa 802 count */ - 4983, /* 54.14 kPa 803 count */ - 4976, /* 54.20 kPa 804 count */ - 4968, /* 54.25 kPa 805 count */ - 4961, /* 54.31 kPa 806 count */ - 4953, /* 54.36 kPa 807 count */ - 4946, /* 54.41 kPa 808 count */ - 4938, /* 54.47 kPa 809 count */ - 4931, /* 54.52 kPa 810 count */ - 4923, /* 54.58 kPa 811 count */ - 4916, /* 54.63 kPa 812 count */ - 4908, /* 54.69 kPa 813 count */ - 4901, /* 54.74 kPa 814 count */ - 4893, /* 54.79 kPa 815 count */ - 4886, /* 54.85 kPa 816 count */ - 4879, /* 54.90 kPa 817 count */ - 4871, /* 54.96 kPa 818 count */ - 4864, /* 55.01 kPa 819 count */ - 4856, /* 55.07 kPa 820 count */ - 4849, /* 55.12 kPa 821 count */ - 4842, /* 55.17 kPa 822 count */ - 4834, /* 55.23 kPa 823 count */ - 4827, /* 55.28 kPa 824 count */ - 4819, /* 55.34 kPa 825 count */ - 4812, /* 55.39 kPa 826 count */ - 4805, /* 55.45 kPa 827 count */ - 4797, /* 55.50 kPa 828 count */ - 4790, /* 55.55 kPa 829 count */ - 4783, /* 55.61 kPa 830 count */ - 4775, /* 55.66 kPa 831 count */ - 4768, /* 55.72 kPa 832 count */ - 4761, /* 55.77 kPa 833 count */ - 4753, /* 55.83 kPa 834 count */ - 4746, /* 55.88 kPa 835 count */ - 4739, /* 55.93 kPa 836 count */ - 4731, /* 55.99 kPa 837 count */ - 4724, /* 56.04 kPa 838 count */ - 4717, /* 56.10 kPa 839 count */ - 4709, /* 56.15 kPa 840 count */ - 4702, /* 56.21 kPa 841 count */ - 4695, /* 56.26 kPa 842 count */ - 4688, /* 56.31 kPa 843 count */ - 4680, /* 56.37 kPa 844 count */ - 4673, /* 56.42 kPa 845 count */ - 4666, /* 56.48 kPa 846 count */ - 4659, /* 56.53 kPa 847 count */ - 4651, /* 56.58 kPa 848 count */ - 4644, /* 56.64 kPa 849 count */ - 4637, /* 56.69 kPa 850 count */ - 4630, /* 56.75 kPa 851 count */ - 4622, /* 56.80 kPa 852 count */ - 4615, /* 56.86 kPa 853 count */ - 4608, /* 56.91 kPa 854 count */ - 4601, /* 56.96 kPa 855 count */ - 4594, /* 57.02 kPa 856 count */ - 4586, /* 57.07 kPa 857 count */ - 4579, /* 57.13 kPa 858 count */ - 4572, /* 57.18 kPa 859 count */ - 4565, /* 57.24 kPa 860 count */ - 4558, /* 57.29 kPa 861 count */ - 4550, /* 57.34 kPa 862 count */ - 4543, /* 57.40 kPa 863 count */ - 4536, /* 57.45 kPa 864 count */ - 4529, /* 57.51 kPa 865 count */ - 4522, /* 57.56 kPa 866 count */ - 4515, /* 57.62 kPa 867 count */ - 4508, /* 57.67 kPa 868 count */ - 4500, /* 57.72 kPa 869 count */ - 4493, /* 57.78 kPa 870 count */ - 4486, /* 57.83 kPa 871 count */ - 4479, /* 57.89 kPa 872 count */ - 4472, /* 57.94 kPa 873 count */ - 4465, /* 58.00 kPa 874 count */ - 4458, /* 58.05 kPa 875 count */ - 4451, /* 58.10 kPa 876 count */ - 4444, /* 58.16 kPa 877 count */ - 4437, /* 58.21 kPa 878 count */ - 4429, /* 58.27 kPa 879 count */ - 4422, /* 58.32 kPa 880 count */ - 4415, /* 58.38 kPa 881 count */ - 4408, /* 58.43 kPa 882 count */ - 4401, /* 58.48 kPa 883 count */ - 4394, /* 58.54 kPa 884 count */ - 4387, /* 58.59 kPa 885 count */ - 4380, /* 58.65 kPa 886 count */ - 4373, /* 58.70 kPa 887 count */ - 4366, /* 58.76 kPa 888 count */ - 4359, /* 58.81 kPa 889 count */ - 4352, /* 58.86 kPa 890 count */ - 4345, /* 58.92 kPa 891 count */ - 4338, /* 58.97 kPa 892 count */ - 4331, /* 59.03 kPa 893 count */ - 4324, /* 59.08 kPa 894 count */ - 4317, /* 59.14 kPa 895 count */ - 4310, /* 59.19 kPa 896 count */ - 4303, /* 59.24 kPa 897 count */ - 4296, /* 59.30 kPa 898 count */ - 4289, /* 59.35 kPa 899 count */ - 4282, /* 59.41 kPa 900 count */ - 4275, /* 59.46 kPa 901 count */ - 4268, /* 59.52 kPa 902 count */ - 4261, /* 59.57 kPa 903 count */ - 4254, /* 59.62 kPa 904 count */ - 4247, /* 59.68 kPa 905 count */ - 4240, /* 59.73 kPa 906 count */ - 4234, /* 59.79 kPa 907 count */ - 4227, /* 59.84 kPa 908 count */ - 4220, /* 59.90 kPa 909 count */ - 4213, /* 59.95 kPa 910 count */ - 4206, /* 60.00 kPa 911 count */ - 4199, /* 60.06 kPa 912 count */ - 4192, /* 60.11 kPa 913 count */ - 4185, /* 60.17 kPa 914 count */ - 4178, /* 60.22 kPa 915 count */ - 4171, /* 60.28 kPa 916 count */ - 4164, /* 60.33 kPa 917 count */ - 4158, /* 60.38 kPa 918 count */ - 4151, /* 60.44 kPa 919 count */ - 4144, /* 60.49 kPa 920 count */ - 4137, /* 60.55 kPa 921 count */ - 4130, /* 60.60 kPa 922 count */ - 4123, /* 60.66 kPa 923 count */ - 4116, /* 60.71 kPa 924 count */ - 4110, /* 60.76 kPa 925 count */ - 4103, /* 60.82 kPa 926 count */ - 4096, /* 60.87 kPa 927 count */ - 4089, /* 60.93 kPa 928 count */ - 4082, /* 60.98 kPa 929 count */ - 4076, /* 61.04 kPa 930 count */ - 4069, /* 61.09 kPa 931 count */ - 4062, /* 61.14 kPa 932 count */ - 4055, /* 61.20 kPa 933 count */ - 4048, /* 61.25 kPa 934 count */ - 4042, /* 61.31 kPa 935 count */ - 4035, /* 61.36 kPa 936 count */ - 4028, /* 61.42 kPa 937 count */ - 4021, /* 61.47 kPa 938 count */ - 4014, /* 61.52 kPa 939 count */ - 4008, /* 61.58 kPa 940 count */ - 4001, /* 61.63 kPa 941 count */ - 3994, /* 61.69 kPa 942 count */ - 3987, /* 61.74 kPa 943 count */ - 3981, /* 61.80 kPa 944 count */ - 3974, /* 61.85 kPa 945 count */ - 3967, /* 61.90 kPa 946 count */ - 3960, /* 61.96 kPa 947 count */ - 3954, /* 62.01 kPa 948 count */ - 3947, /* 62.07 kPa 949 count */ - 3940, /* 62.12 kPa 950 count */ - 3934, /* 62.18 kPa 951 count */ - 3927, /* 62.23 kPa 952 count */ - 3920, /* 62.28 kPa 953 count */ - 3913, /* 62.34 kPa 954 count */ - 3907, /* 62.39 kPa 955 count */ - 3900, /* 62.45 kPa 956 count */ - 3893, /* 62.50 kPa 957 count */ - 3887, /* 62.56 kPa 958 count */ - 3880, /* 62.61 kPa 959 count */ - 3873, /* 62.66 kPa 960 count */ - 3867, /* 62.72 kPa 961 count */ - 3860, /* 62.77 kPa 962 count */ - 3853, /* 62.83 kPa 963 count */ - 3847, /* 62.88 kPa 964 count */ - 3840, /* 62.94 kPa 965 count */ - 3833, /* 62.99 kPa 966 count */ - 3827, /* 63.04 kPa 967 count */ - 3820, /* 63.10 kPa 968 count */ - 3814, /* 63.15 kPa 969 count */ - 3807, /* 63.21 kPa 970 count */ - 3800, /* 63.26 kPa 971 count */ - 3794, /* 63.32 kPa 972 count */ - 3787, /* 63.37 kPa 973 count */ - 3780, /* 63.42 kPa 974 count */ - 3774, /* 63.48 kPa 975 count */ - 3767, /* 63.53 kPa 976 count */ - 3761, /* 63.59 kPa 977 count */ - 3754, /* 63.64 kPa 978 count */ - 3748, /* 63.70 kPa 979 count */ - 3741, /* 63.75 kPa 980 count */ - 3734, /* 63.80 kPa 981 count */ - 3728, /* 63.86 kPa 982 count */ - 3721, /* 63.91 kPa 983 count */ - 3715, /* 63.97 kPa 984 count */ - 3708, /* 64.02 kPa 985 count */ - 3702, /* 64.08 kPa 986 count */ - 3695, /* 64.13 kPa 987 count */ - 3688, /* 64.18 kPa 988 count */ - 3682, /* 64.24 kPa 989 count */ - 3675, /* 64.29 kPa 990 count */ - 3669, /* 64.35 kPa 991 count */ - 3662, /* 64.40 kPa 992 count */ - 3656, /* 64.46 kPa 993 count */ - 3649, /* 64.51 kPa 994 count */ - 3643, /* 64.56 kPa 995 count */ - 3636, /* 64.62 kPa 996 count */ - 3630, /* 64.67 kPa 997 count */ - 3623, /* 64.73 kPa 998 count */ - 3617, /* 64.78 kPa 999 count */ - 3610, /* 64.84 kPa 1000 count */ - 3604, /* 64.89 kPa 1001 count */ - 3597, /* 64.94 kPa 1002 count */ - 3591, /* 65.00 kPa 1003 count */ - 3584, /* 65.05 kPa 1004 count */ - 3578, /* 65.11 kPa 1005 count */ - 3571, /* 65.16 kPa 1006 count */ - 3565, /* 65.22 kPa 1007 count */ - 3559, /* 65.27 kPa 1008 count */ - 3552, /* 65.32 kPa 1009 count */ - 3546, /* 65.38 kPa 1010 count */ - 3539, /* 65.43 kPa 1011 count */ - 3533, /* 65.49 kPa 1012 count */ - 3526, /* 65.54 kPa 1013 count */ - 3520, /* 65.60 kPa 1014 count */ - 3514, /* 65.65 kPa 1015 count */ - 3507, /* 65.70 kPa 1016 count */ - 3501, /* 65.76 kPa 1017 count */ - 3494, /* 65.81 kPa 1018 count */ - 3488, /* 65.87 kPa 1019 count */ - 3481, /* 65.92 kPa 1020 count */ - 3475, /* 65.98 kPa 1021 count */ - 3469, /* 66.03 kPa 1022 count */ - 3462, /* 66.08 kPa 1023 count */ - 3456, /* 66.14 kPa 1024 count */ - 3450, /* 66.19 kPa 1025 count */ - 3443, /* 66.25 kPa 1026 count */ - 3437, /* 66.30 kPa 1027 count */ - 3430, /* 66.36 kPa 1028 count */ - 3424, /* 66.41 kPa 1029 count */ - 3418, /* 66.46 kPa 1030 count */ - 3411, /* 66.52 kPa 1031 count */ - 3405, /* 66.57 kPa 1032 count */ - 3399, /* 66.63 kPa 1033 count */ - 3392, /* 66.68 kPa 1034 count */ - 3386, /* 66.74 kPa 1035 count */ - 3380, /* 66.79 kPa 1036 count */ - 3373, /* 66.84 kPa 1037 count */ - 3367, /* 66.90 kPa 1038 count */ - 3361, /* 66.95 kPa 1039 count */ - 3354, /* 67.01 kPa 1040 count */ - 3348, /* 67.06 kPa 1041 count */ - 3342, /* 67.12 kPa 1042 count */ - 3335, /* 67.17 kPa 1043 count */ - 3329, /* 67.22 kPa 1044 count */ - 3323, /* 67.28 kPa 1045 count */ - 3316, /* 67.33 kPa 1046 count */ - 3310, /* 67.39 kPa 1047 count */ - 3304, /* 67.44 kPa 1048 count */ - 3298, /* 67.50 kPa 1049 count */ - 3291, /* 67.55 kPa 1050 count */ - 3285, /* 67.60 kPa 1051 count */ - 3279, /* 67.66 kPa 1052 count */ - 3273, /* 67.71 kPa 1053 count */ - 3266, /* 67.77 kPa 1054 count */ - 3260, /* 67.82 kPa 1055 count */ - 3254, /* 67.88 kPa 1056 count */ - 3248, /* 67.93 kPa 1057 count */ - 3241, /* 67.98 kPa 1058 count */ - 3235, /* 68.04 kPa 1059 count */ - 3229, /* 68.09 kPa 1060 count */ - 3223, /* 68.15 kPa 1061 count */ - 3216, /* 68.20 kPa 1062 count */ - 3210, /* 68.26 kPa 1063 count */ - 3204, /* 68.31 kPa 1064 count */ - 3198, /* 68.36 kPa 1065 count */ - 3191, /* 68.42 kPa 1066 count */ - 3185, /* 68.47 kPa 1067 count */ - 3179, /* 68.53 kPa 1068 count */ - 3173, /* 68.58 kPa 1069 count */ - 3167, /* 68.64 kPa 1070 count */ - 3160, /* 68.69 kPa 1071 count */ - 3154, /* 68.74 kPa 1072 count */ - 3148, /* 68.80 kPa 1073 count */ - 3142, /* 68.85 kPa 1074 count */ - 3136, /* 68.91 kPa 1075 count */ - 3130, /* 68.96 kPa 1076 count */ - 3123, /* 69.02 kPa 1077 count */ - 3117, /* 69.07 kPa 1078 count */ - 3111, /* 69.12 kPa 1079 count */ - 3105, /* 69.18 kPa 1080 count */ - 3099, /* 69.23 kPa 1081 count */ - 3093, /* 69.29 kPa 1082 count */ - 3087, /* 69.34 kPa 1083 count */ - 3080, /* 69.40 kPa 1084 count */ - 3074, /* 69.45 kPa 1085 count */ - 3068, /* 69.50 kPa 1086 count */ - 3062, /* 69.56 kPa 1087 count */ - 3056, /* 69.61 kPa 1088 count */ - 3050, /* 69.67 kPa 1089 count */ - 3044, /* 69.72 kPa 1090 count */ - 3037, /* 69.78 kPa 1091 count */ - 3031, /* 69.83 kPa 1092 count */ - 3025, /* 69.88 kPa 1093 count */ - 3019, /* 69.94 kPa 1094 count */ - 3013, /* 69.99 kPa 1095 count */ - 3007, /* 70.05 kPa 1096 count */ - 3001, /* 70.10 kPa 1097 count */ - 2995, /* 70.15 kPa 1098 count */ - 2989, /* 70.21 kPa 1099 count */ - 2983, /* 70.26 kPa 1100 count */ - 2977, /* 70.32 kPa 1101 count */ - 2970, /* 70.37 kPa 1102 count */ - 2964, /* 70.43 kPa 1103 count */ - 2958, /* 70.48 kPa 1104 count */ - 2952, /* 70.53 kPa 1105 count */ - 2946, /* 70.59 kPa 1106 count */ - 2940, /* 70.64 kPa 1107 count */ - 2934, /* 70.70 kPa 1108 count */ - 2928, /* 70.75 kPa 1109 count */ - 2922, /* 70.81 kPa 1110 count */ - 2916, /* 70.86 kPa 1111 count */ - 2910, /* 70.91 kPa 1112 count */ - 2904, /* 70.97 kPa 1113 count */ - 2898, /* 71.02 kPa 1114 count */ - 2892, /* 71.08 kPa 1115 count */ - 2886, /* 71.13 kPa 1116 count */ - 2880, /* 71.19 kPa 1117 count */ - 2874, /* 71.24 kPa 1118 count */ - 2868, /* 71.29 kPa 1119 count */ - 2862, /* 71.35 kPa 1120 count */ - 2856, /* 71.40 kPa 1121 count */ - 2850, /* 71.46 kPa 1122 count */ - 2844, /* 71.51 kPa 1123 count */ - 2838, /* 71.57 kPa 1124 count */ - 2832, /* 71.62 kPa 1125 count */ - 2826, /* 71.67 kPa 1126 count */ - 2820, /* 71.73 kPa 1127 count */ - 2814, /* 71.78 kPa 1128 count */ - 2808, /* 71.84 kPa 1129 count */ - 2802, /* 71.89 kPa 1130 count */ - 2796, /* 71.95 kPa 1131 count */ - 2790, /* 72.00 kPa 1132 count */ - 2784, /* 72.05 kPa 1133 count */ - 2778, /* 72.11 kPa 1134 count */ - 2772, /* 72.16 kPa 1135 count */ - 2766, /* 72.22 kPa 1136 count */ - 2760, /* 72.27 kPa 1137 count */ - 2754, /* 72.33 kPa 1138 count */ - 2748, /* 72.38 kPa 1139 count */ - 2743, /* 72.43 kPa 1140 count */ - 2737, /* 72.49 kPa 1141 count */ - 2731, /* 72.54 kPa 1142 count */ - 2725, /* 72.60 kPa 1143 count */ - 2719, /* 72.65 kPa 1144 count */ - 2713, /* 72.71 kPa 1145 count */ - 2707, /* 72.76 kPa 1146 count */ - 2701, /* 72.81 kPa 1147 count */ - 2695, /* 72.87 kPa 1148 count */ - 2689, /* 72.92 kPa 1149 count */ - 2683, /* 72.98 kPa 1150 count */ - 2678, /* 73.03 kPa 1151 count */ - 2672, /* 73.09 kPa 1152 count */ - 2666, /* 73.14 kPa 1153 count */ - 2660, /* 73.19 kPa 1154 count */ - 2654, /* 73.25 kPa 1155 count */ - 2648, /* 73.30 kPa 1156 count */ - 2642, /* 73.36 kPa 1157 count */ - 2636, /* 73.41 kPa 1158 count */ - 2631, /* 73.47 kPa 1159 count */ - 2625, /* 73.52 kPa 1160 count */ - 2619, /* 73.57 kPa 1161 count */ - 2613, /* 73.63 kPa 1162 count */ - 2607, /* 73.68 kPa 1163 count */ - 2601, /* 73.74 kPa 1164 count */ - 2595, /* 73.79 kPa 1165 count */ - 2590, /* 73.85 kPa 1166 count */ - 2584, /* 73.90 kPa 1167 count */ - 2578, /* 73.95 kPa 1168 count */ - 2572, /* 74.01 kPa 1169 count */ - 2566, /* 74.06 kPa 1170 count */ - 2560, /* 74.12 kPa 1171 count */ - 2555, /* 74.17 kPa 1172 count */ - 2549, /* 74.23 kPa 1173 count */ - 2543, /* 74.28 kPa 1174 count */ - 2537, /* 74.33 kPa 1175 count */ - 2531, /* 74.39 kPa 1176 count */ - 2526, /* 74.44 kPa 1177 count */ - 2520, /* 74.50 kPa 1178 count */ - 2514, /* 74.55 kPa 1179 count */ - 2508, /* 74.61 kPa 1180 count */ - 2502, /* 74.66 kPa 1181 count */ - 2497, /* 74.71 kPa 1182 count */ - 2491, /* 74.77 kPa 1183 count */ - 2485, /* 74.82 kPa 1184 count */ - 2479, /* 74.88 kPa 1185 count */ - 2473, /* 74.93 kPa 1186 count */ - 2468, /* 74.99 kPa 1187 count */ - 2462, /* 75.04 kPa 1188 count */ - 2456, /* 75.09 kPa 1189 count */ - 2450, /* 75.15 kPa 1190 count */ - 2445, /* 75.20 kPa 1191 count */ - 2439, /* 75.26 kPa 1192 count */ - 2433, /* 75.31 kPa 1193 count */ - 2427, /* 75.37 kPa 1194 count */ - 2422, /* 75.42 kPa 1195 count */ - 2416, /* 75.47 kPa 1196 count */ - 2410, /* 75.53 kPa 1197 count */ - 2405, /* 75.58 kPa 1198 count */ - 2399, /* 75.64 kPa 1199 count */ - 2393, /* 75.69 kPa 1200 count */ - 2387, /* 75.75 kPa 1201 count */ - 2382, /* 75.80 kPa 1202 count */ - 2376, /* 75.85 kPa 1203 count */ - 2370, /* 75.91 kPa 1204 count */ - 2364, /* 75.96 kPa 1205 count */ - 2359, /* 76.02 kPa 1206 count */ - 2353, /* 76.07 kPa 1207 count */ - 2347, /* 76.13 kPa 1208 count */ - 2342, /* 76.18 kPa 1209 count */ - 2336, /* 76.23 kPa 1210 count */ - 2330, /* 76.29 kPa 1211 count */ - 2325, /* 76.34 kPa 1212 count */ - 2319, /* 76.40 kPa 1213 count */ - 2313, /* 76.45 kPa 1214 count */ - 2308, /* 76.51 kPa 1215 count */ - 2302, /* 76.56 kPa 1216 count */ - 2296, /* 76.61 kPa 1217 count */ - 2291, /* 76.67 kPa 1218 count */ - 2285, /* 76.72 kPa 1219 count */ - 2279, /* 76.78 kPa 1220 count */ - 2274, /* 76.83 kPa 1221 count */ - 2268, /* 76.89 kPa 1222 count */ - 2262, /* 76.94 kPa 1223 count */ - 2257, /* 76.99 kPa 1224 count */ - 2251, /* 77.05 kPa 1225 count */ - 2245, /* 77.10 kPa 1226 count */ - 2240, /* 77.16 kPa 1227 count */ - 2234, /* 77.21 kPa 1228 count */ - 2228, /* 77.27 kPa 1229 count */ - 2223, /* 77.32 kPa 1230 count */ - 2217, /* 77.37 kPa 1231 count */ - 2212, /* 77.43 kPa 1232 count */ - 2206, /* 77.48 kPa 1233 count */ - 2200, /* 77.54 kPa 1234 count */ - 2195, /* 77.59 kPa 1235 count */ - 2189, /* 77.65 kPa 1236 count */ - 2184, /* 77.70 kPa 1237 count */ - 2178, /* 77.75 kPa 1238 count */ - 2172, /* 77.81 kPa 1239 count */ - 2167, /* 77.86 kPa 1240 count */ - 2161, /* 77.92 kPa 1241 count */ - 2156, /* 77.97 kPa 1242 count */ - 2150, /* 78.03 kPa 1243 count */ - 2144, /* 78.08 kPa 1244 count */ - 2139, /* 78.13 kPa 1245 count */ - 2133, /* 78.19 kPa 1246 count */ - 2128, /* 78.24 kPa 1247 count */ - 2122, /* 78.30 kPa 1248 count */ - 2117, /* 78.35 kPa 1249 count */ - 2111, /* 78.41 kPa 1250 count */ - 2105, /* 78.46 kPa 1251 count */ - 2100, /* 78.51 kPa 1252 count */ - 2094, /* 78.57 kPa 1253 count */ - 2089, /* 78.62 kPa 1254 count */ - 2083, /* 78.68 kPa 1255 count */ - 2078, /* 78.73 kPa 1256 count */ - 2072, /* 78.79 kPa 1257 count */ - 2067, /* 78.84 kPa 1258 count */ - 2061, /* 78.89 kPa 1259 count */ - 2056, /* 78.95 kPa 1260 count */ - 2050, /* 79.00 kPa 1261 count */ - 2045, /* 79.06 kPa 1262 count */ - 2039, /* 79.11 kPa 1263 count */ - 2033, /* 79.17 kPa 1264 count */ - 2028, /* 79.22 kPa 1265 count */ - 2022, /* 79.27 kPa 1266 count */ - 2017, /* 79.33 kPa 1267 count */ - 2011, /* 79.38 kPa 1268 count */ - 2006, /* 79.44 kPa 1269 count */ - 2000, /* 79.49 kPa 1270 count */ - 1995, /* 79.55 kPa 1271 count */ - 1989, /* 79.60 kPa 1272 count */ - 1984, /* 79.65 kPa 1273 count */ - 1978, /* 79.71 kPa 1274 count */ - 1973, /* 79.76 kPa 1275 count */ - 1967, /* 79.82 kPa 1276 count */ - 1962, /* 79.87 kPa 1277 count */ - 1957, /* 79.93 kPa 1278 count */ - 1951, /* 79.98 kPa 1279 count */ - 1946, /* 80.03 kPa 1280 count */ - 1940, /* 80.09 kPa 1281 count */ - 1935, /* 80.14 kPa 1282 count */ - 1929, /* 80.20 kPa 1283 count */ - 1924, /* 80.25 kPa 1284 count */ - 1918, /* 80.31 kPa 1285 count */ - 1913, /* 80.36 kPa 1286 count */ - 1907, /* 80.41 kPa 1287 count */ - 1902, /* 80.47 kPa 1288 count */ - 1896, /* 80.52 kPa 1289 count */ - 1891, /* 80.58 kPa 1290 count */ - 1886, /* 80.63 kPa 1291 count */ - 1880, /* 80.69 kPa 1292 count */ - 1875, /* 80.74 kPa 1293 count */ - 1869, /* 80.79 kPa 1294 count */ - 1864, /* 80.85 kPa 1295 count */ - 1858, /* 80.90 kPa 1296 count */ - 1853, /* 80.96 kPa 1297 count */ - 1848, /* 81.01 kPa 1298 count */ - 1842, /* 81.07 kPa 1299 count */ - 1837, /* 81.12 kPa 1300 count */ - 1831, /* 81.17 kPa 1301 count */ - 1826, /* 81.23 kPa 1302 count */ - 1821, /* 81.28 kPa 1303 count */ - 1815, /* 81.34 kPa 1304 count */ - 1810, /* 81.39 kPa 1305 count */ - 1804, /* 81.45 kPa 1306 count */ - 1799, /* 81.50 kPa 1307 count */ - 1794, /* 81.55 kPa 1308 count */ - 1788, /* 81.61 kPa 1309 count */ - 1783, /* 81.66 kPa 1310 count */ - 1777, /* 81.72 kPa 1311 count */ - 1772, /* 81.77 kPa 1312 count */ - 1767, /* 81.83 kPa 1313 count */ - 1761, /* 81.88 kPa 1314 count */ - 1756, /* 81.93 kPa 1315 count */ - 1751, /* 81.99 kPa 1316 count */ - 1745, /* 82.04 kPa 1317 count */ - 1740, /* 82.10 kPa 1318 count */ - 1735, /* 82.15 kPa 1319 count */ - 1729, /* 82.21 kPa 1320 count */ - 1724, /* 82.26 kPa 1321 count */ - 1718, /* 82.31 kPa 1322 count */ - 1713, /* 82.37 kPa 1323 count */ - 1708, /* 82.42 kPa 1324 count */ - 1702, /* 82.48 kPa 1325 count */ - 1697, /* 82.53 kPa 1326 count */ - 1692, /* 82.59 kPa 1327 count */ - 1686, /* 82.64 kPa 1328 count */ - 1681, /* 82.69 kPa 1329 count */ - 1676, /* 82.75 kPa 1330 count */ - 1670, /* 82.80 kPa 1331 count */ - 1665, /* 82.86 kPa 1332 count */ - 1660, /* 82.91 kPa 1333 count */ - 1655, /* 82.97 kPa 1334 count */ - 1649, /* 83.02 kPa 1335 count */ - 1644, /* 83.07 kPa 1336 count */ - 1639, /* 83.13 kPa 1337 count */ - 1633, /* 83.18 kPa 1338 count */ - 1628, /* 83.24 kPa 1339 count */ - 1623, /* 83.29 kPa 1340 count */ - 1617, /* 83.35 kPa 1341 count */ - 1612, /* 83.40 kPa 1342 count */ - 1607, /* 83.45 kPa 1343 count */ - 1602, /* 83.51 kPa 1344 count */ - 1596, /* 83.56 kPa 1345 count */ - 1591, /* 83.62 kPa 1346 count */ - 1586, /* 83.67 kPa 1347 count */ - 1580, /* 83.72 kPa 1348 count */ - 1575, /* 83.78 kPa 1349 count */ - 1570, /* 83.83 kPa 1350 count */ - 1565, /* 83.89 kPa 1351 count */ - 1559, /* 83.94 kPa 1352 count */ - 1554, /* 84.00 kPa 1353 count */ - 1549, /* 84.05 kPa 1354 count */ - 1544, /* 84.10 kPa 1355 count */ - 1538, /* 84.16 kPa 1356 count */ - 1533, /* 84.21 kPa 1357 count */ - 1528, /* 84.27 kPa 1358 count */ - 1523, /* 84.32 kPa 1359 count */ - 1517, /* 84.38 kPa 1360 count */ - 1512, /* 84.43 kPa 1361 count */ - 1507, /* 84.48 kPa 1362 count */ - 1502, /* 84.54 kPa 1363 count */ - 1496, /* 84.59 kPa 1364 count */ - 1491, /* 84.65 kPa 1365 count */ - 1486, /* 84.70 kPa 1366 count */ - 1481, /* 84.76 kPa 1367 count */ - 1475, /* 84.81 kPa 1368 count */ - 1470, /* 84.86 kPa 1369 count */ - 1465, /* 84.92 kPa 1370 count */ - 1460, /* 84.97 kPa 1371 count */ - 1455, /* 85.03 kPa 1372 count */ - 1449, /* 85.08 kPa 1373 count */ - 1444, /* 85.14 kPa 1374 count */ - 1439, /* 85.19 kPa 1375 count */ - 1434, /* 85.24 kPa 1376 count */ - 1429, /* 85.30 kPa 1377 count */ - 1423, /* 85.35 kPa 1378 count */ - 1418, /* 85.41 kPa 1379 count */ - 1413, /* 85.46 kPa 1380 count */ - 1408, /* 85.52 kPa 1381 count */ - 1403, /* 85.57 kPa 1382 count */ - 1398, /* 85.62 kPa 1383 count */ - 1392, /* 85.68 kPa 1384 count */ - 1387, /* 85.73 kPa 1385 count */ - 1382, /* 85.79 kPa 1386 count */ - 1377, /* 85.84 kPa 1387 count */ - 1372, /* 85.90 kPa 1388 count */ - 1366, /* 85.95 kPa 1389 count */ - 1361, /* 86.00 kPa 1390 count */ - 1356, /* 86.06 kPa 1391 count */ - 1351, /* 86.11 kPa 1392 count */ - 1346, /* 86.17 kPa 1393 count */ - 1341, /* 86.22 kPa 1394 count */ - 1336, /* 86.28 kPa 1395 count */ - 1330, /* 86.33 kPa 1396 count */ - 1325, /* 86.38 kPa 1397 count */ - 1320, /* 86.44 kPa 1398 count */ - 1315, /* 86.49 kPa 1399 count */ - 1310, /* 86.55 kPa 1400 count */ - 1305, /* 86.60 kPa 1401 count */ - 1300, /* 86.66 kPa 1402 count */ - 1294, /* 86.71 kPa 1403 count */ - 1289, /* 86.76 kPa 1404 count */ - 1284, /* 86.82 kPa 1405 count */ - 1279, /* 86.87 kPa 1406 count */ - 1274, /* 86.93 kPa 1407 count */ - 1269, /* 86.98 kPa 1408 count */ - 1264, /* 87.04 kPa 1409 count */ - 1259, /* 87.09 kPa 1410 count */ - 1254, /* 87.14 kPa 1411 count */ - 1248, /* 87.20 kPa 1412 count */ - 1243, /* 87.25 kPa 1413 count */ - 1238, /* 87.31 kPa 1414 count */ - 1233, /* 87.36 kPa 1415 count */ - 1228, /* 87.42 kPa 1416 count */ - 1223, /* 87.47 kPa 1417 count */ - 1218, /* 87.52 kPa 1418 count */ - 1213, /* 87.58 kPa 1419 count */ - 1208, /* 87.63 kPa 1420 count */ - 1203, /* 87.69 kPa 1421 count */ - 1198, /* 87.74 kPa 1422 count */ - 1192, /* 87.80 kPa 1423 count */ - 1187, /* 87.85 kPa 1424 count */ - 1182, /* 87.90 kPa 1425 count */ - 1177, /* 87.96 kPa 1426 count */ - 1172, /* 88.01 kPa 1427 count */ - 1167, /* 88.07 kPa 1428 count */ - 1162, /* 88.12 kPa 1429 count */ - 1157, /* 88.18 kPa 1430 count */ - 1152, /* 88.23 kPa 1431 count */ - 1147, /* 88.28 kPa 1432 count */ - 1142, /* 88.34 kPa 1433 count */ - 1137, /* 88.39 kPa 1434 count */ - 1132, /* 88.45 kPa 1435 count */ - 1127, /* 88.50 kPa 1436 count */ - 1122, /* 88.56 kPa 1437 count */ - 1117, /* 88.61 kPa 1438 count */ - 1112, /* 88.66 kPa 1439 count */ - 1107, /* 88.72 kPa 1440 count */ - 1102, /* 88.77 kPa 1441 count */ - 1097, /* 88.83 kPa 1442 count */ - 1091, /* 88.88 kPa 1443 count */ - 1086, /* 88.94 kPa 1444 count */ - 1081, /* 88.99 kPa 1445 count */ - 1076, /* 89.04 kPa 1446 count */ - 1071, /* 89.10 kPa 1447 count */ - 1066, /* 89.15 kPa 1448 count */ - 1061, /* 89.21 kPa 1449 count */ - 1056, /* 89.26 kPa 1450 count */ - 1051, /* 89.32 kPa 1451 count */ - 1046, /* 89.37 kPa 1452 count */ - 1041, /* 89.42 kPa 1453 count */ - 1036, /* 89.48 kPa 1454 count */ - 1031, /* 89.53 kPa 1455 count */ - 1026, /* 89.59 kPa 1456 count */ - 1021, /* 89.64 kPa 1457 count */ - 1016, /* 89.70 kPa 1458 count */ - 1011, /* 89.75 kPa 1459 count */ - 1006, /* 89.80 kPa 1460 count */ - 1001, /* 89.86 kPa 1461 count */ - 996, /* 89.91 kPa 1462 count */ - 992, /* 89.97 kPa 1463 count */ - 987, /* 90.02 kPa 1464 count */ - 982, /* 90.08 kPa 1465 count */ - 977, /* 90.13 kPa 1466 count */ - 972, /* 90.18 kPa 1467 count */ - 967, /* 90.24 kPa 1468 count */ - 962, /* 90.29 kPa 1469 count */ - 957, /* 90.35 kPa 1470 count */ - 952, /* 90.40 kPa 1471 count */ - 947, /* 90.46 kPa 1472 count */ - 942, /* 90.51 kPa 1473 count */ - 937, /* 90.56 kPa 1474 count */ - 932, /* 90.62 kPa 1475 count */ - 927, /* 90.67 kPa 1476 count */ - 922, /* 90.73 kPa 1477 count */ - 917, /* 90.78 kPa 1478 count */ - 912, /* 90.84 kPa 1479 count */ - 907, /* 90.89 kPa 1480 count */ - 902, /* 90.94 kPa 1481 count */ - 897, /* 91.00 kPa 1482 count */ - 892, /* 91.05 kPa 1483 count */ - 888, /* 91.11 kPa 1484 count */ - 883, /* 91.16 kPa 1485 count */ - 878, /* 91.22 kPa 1486 count */ - 873, /* 91.27 kPa 1487 count */ - 868, /* 91.32 kPa 1488 count */ - 863, /* 91.38 kPa 1489 count */ - 858, /* 91.43 kPa 1490 count */ - 853, /* 91.49 kPa 1491 count */ - 848, /* 91.54 kPa 1492 count */ - 843, /* 91.60 kPa 1493 count */ - 838, /* 91.65 kPa 1494 count */ - 834, /* 91.70 kPa 1495 count */ - 829, /* 91.76 kPa 1496 count */ - 824, /* 91.81 kPa 1497 count */ - 819, /* 91.87 kPa 1498 count */ - 814, /* 91.92 kPa 1499 count */ - 809, /* 91.98 kPa 1500 count */ - 804, /* 92.03 kPa 1501 count */ - 799, /* 92.08 kPa 1502 count */ - 794, /* 92.14 kPa 1503 count */ - 790, /* 92.19 kPa 1504 count */ - 785, /* 92.25 kPa 1505 count */ - 780, /* 92.30 kPa 1506 count */ - 775, /* 92.36 kPa 1507 count */ - 770, /* 92.41 kPa 1508 count */ - 765, /* 92.46 kPa 1509 count */ - 760, /* 92.52 kPa 1510 count */ - 755, /* 92.57 kPa 1511 count */ - 751, /* 92.63 kPa 1512 count */ - 746, /* 92.68 kPa 1513 count */ - 741, /* 92.74 kPa 1514 count */ - 736, /* 92.79 kPa 1515 count */ - 731, /* 92.84 kPa 1516 count */ - 726, /* 92.90 kPa 1517 count */ - 721, /* 92.95 kPa 1518 count */ - 717, /* 93.01 kPa 1519 count */ - 712, /* 93.06 kPa 1520 count */ - 707, /* 93.12 kPa 1521 count */ - 702, /* 93.17 kPa 1522 count */ - 697, /* 93.22 kPa 1523 count */ - 692, /* 93.28 kPa 1524 count */ - 688, /* 93.33 kPa 1525 count */ - 683, /* 93.39 kPa 1526 count */ - 678, /* 93.44 kPa 1527 count */ - 673, /* 93.50 kPa 1528 count */ - 668, /* 93.55 kPa 1529 count */ - 664, /* 93.60 kPa 1530 count */ - 659, /* 93.66 kPa 1531 count */ - 654, /* 93.71 kPa 1532 count */ - 649, /* 93.77 kPa 1533 count */ - 644, /* 93.82 kPa 1534 count */ - 639, /* 93.88 kPa 1535 count */ - 635, /* 93.93 kPa 1536 count */ - 630, /* 93.98 kPa 1537 count */ - 625, /* 94.04 kPa 1538 count */ - 620, /* 94.09 kPa 1539 count */ - 615, /* 94.15 kPa 1540 count */ - 611, /* 94.20 kPa 1541 count */ - 606, /* 94.26 kPa 1542 count */ - 601, /* 94.31 kPa 1543 count */ - 596, /* 94.36 kPa 1544 count */ - 591, /* 94.42 kPa 1545 count */ - 587, /* 94.47 kPa 1546 count */ - 582, /* 94.53 kPa 1547 count */ - 577, /* 94.58 kPa 1548 count */ - 572, /* 94.64 kPa 1549 count */ - 568, /* 94.69 kPa 1550 count */ - 563, /* 94.74 kPa 1551 count */ - 558, /* 94.80 kPa 1552 count */ - 553, /* 94.85 kPa 1553 count */ - 549, /* 94.91 kPa 1554 count */ - 544, /* 94.96 kPa 1555 count */ - 539, /* 95.02 kPa 1556 count */ - 534, /* 95.07 kPa 1557 count */ - 529, /* 95.12 kPa 1558 count */ - 525, /* 95.18 kPa 1559 count */ - 520, /* 95.23 kPa 1560 count */ - 515, /* 95.29 kPa 1561 count */ - 510, /* 95.34 kPa 1562 count */ - 506, /* 95.40 kPa 1563 count */ - 501, /* 95.45 kPa 1564 count */ - 496, /* 95.50 kPa 1565 count */ - 492, /* 95.56 kPa 1566 count */ - 487, /* 95.61 kPa 1567 count */ - 482, /* 95.67 kPa 1568 count */ - 477, /* 95.72 kPa 1569 count */ - 473, /* 95.78 kPa 1570 count */ - 468, /* 95.83 kPa 1571 count */ - 463, /* 95.88 kPa 1572 count */ - 458, /* 95.94 kPa 1573 count */ - 454, /* 95.99 kPa 1574 count */ - 449, /* 96.05 kPa 1575 count */ - 444, /* 96.10 kPa 1576 count */ - 440, /* 96.16 kPa 1577 count */ - 435, /* 96.21 kPa 1578 count */ - 430, /* 96.26 kPa 1579 count */ - 425, /* 96.32 kPa 1580 count */ - 421, /* 96.37 kPa 1581 count */ - 416, /* 96.43 kPa 1582 count */ - 411, /* 96.48 kPa 1583 count */ - 407, /* 96.54 kPa 1584 count */ - 402, /* 96.59 kPa 1585 count */ - 397, /* 96.64 kPa 1586 count */ - 392, /* 96.70 kPa 1587 count */ - 388, /* 96.75 kPa 1588 count */ - 383, /* 96.81 kPa 1589 count */ - 378, /* 96.86 kPa 1590 count */ - 374, /* 96.91 kPa 1591 count */ - 369, /* 96.97 kPa 1592 count */ - 364, /* 97.02 kPa 1593 count */ - 360, /* 97.08 kPa 1594 count */ - 355, /* 97.13 kPa 1595 count */ - 350, /* 97.19 kPa 1596 count */ - 346, /* 97.24 kPa 1597 count */ - 341, /* 97.29 kPa 1598 count */ - 336, /* 97.35 kPa 1599 count */ - 332, /* 97.40 kPa 1600 count */ - 327, /* 97.46 kPa 1601 count */ - 322, /* 97.51 kPa 1602 count */ - 318, /* 97.57 kPa 1603 count */ - 313, /* 97.62 kPa 1604 count */ - 308, /* 97.67 kPa 1605 count */ - 304, /* 97.73 kPa 1606 count */ - 299, /* 97.78 kPa 1607 count */ - 294, /* 97.84 kPa 1608 count */ - 290, /* 97.89 kPa 1609 count */ - 285, /* 97.95 kPa 1610 count */ - 280, /* 98.00 kPa 1611 count */ - 276, /* 98.05 kPa 1612 count */ - 271, /* 98.11 kPa 1613 count */ - 267, /* 98.16 kPa 1614 count */ - 262, /* 98.22 kPa 1615 count */ - 257, /* 98.27 kPa 1616 count */ - 253, /* 98.33 kPa 1617 count */ - 248, /* 98.38 kPa 1618 count */ - 243, /* 98.43 kPa 1619 count */ - 239, /* 98.49 kPa 1620 count */ - 234, /* 98.54 kPa 1621 count */ - 230, /* 98.60 kPa 1622 count */ - 225, /* 98.65 kPa 1623 count */ - 220, /* 98.71 kPa 1624 count */ - 216, /* 98.76 kPa 1625 count */ - 211, /* 98.81 kPa 1626 count */ - 206, /* 98.87 kPa 1627 count */ - 202, /* 98.92 kPa 1628 count */ - 197, /* 98.98 kPa 1629 count */ - 193, /* 99.03 kPa 1630 count */ - 188, /* 99.09 kPa 1631 count */ - 183, /* 99.14 kPa 1632 count */ - 179, /* 99.19 kPa 1633 count */ - 174, /* 99.25 kPa 1634 count */ - 170, /* 99.30 kPa 1635 count */ - 165, /* 99.36 kPa 1636 count */ - 160, /* 99.41 kPa 1637 count */ - 156, /* 99.47 kPa 1638 count */ - 151, /* 99.52 kPa 1639 count */ - 147, /* 99.57 kPa 1640 count */ - 142, /* 99.63 kPa 1641 count */ - 138, /* 99.68 kPa 1642 count */ - 133, /* 99.74 kPa 1643 count */ - 128, /* 99.79 kPa 1644 count */ - 124, /* 99.85 kPa 1645 count */ - 119, /* 99.90 kPa 1646 count */ - 115, /* 99.95 kPa 1647 count */ - 110, /* 100.01 kPa 1648 count */ - 106, /* 100.06 kPa 1649 count */ - 101, /* 100.12 kPa 1650 count */ - 96, /* 100.17 kPa 1651 count */ - 92, /* 100.23 kPa 1652 count */ - 87, /* 100.28 kPa 1653 count */ - 83, /* 100.33 kPa 1654 count */ - 78, /* 100.39 kPa 1655 count */ - 74, /* 100.44 kPa 1656 count */ - 69, /* 100.50 kPa 1657 count */ - 65, /* 100.55 kPa 1658 count */ - 60, /* 100.61 kPa 1659 count */ - 55, /* 100.66 kPa 1660 count */ - 51, /* 100.71 kPa 1661 count */ - 46, /* 100.77 kPa 1662 count */ - 42, /* 100.82 kPa 1663 count */ - 37, /* 100.88 kPa 1664 count */ - 33, /* 100.93 kPa 1665 count */ - 28, /* 100.99 kPa 1666 count */ - 24, /* 101.04 kPa 1667 count */ - 19, /* 101.09 kPa 1668 count */ - 15, /* 101.15 kPa 1669 count */ - 10, /* 101.20 kPa 1670 count */ - 6, /* 101.26 kPa 1671 count */ - 1, /* 101.31 kPa 1672 count */ - -3, /* 101.37 kPa 1673 count */ - -8, /* 101.42 kPa 1674 count */ - -12, /* 101.47 kPa 1675 count */ - -17, /* 101.53 kPa 1676 count */ - -21, /* 101.58 kPa 1677 count */ - -26, /* 101.64 kPa 1678 count */ - -30, /* 101.69 kPa 1679 count */ - -35, /* 101.75 kPa 1680 count */ - -39, /* 101.80 kPa 1681 count */ - -44, /* 101.85 kPa 1682 count */ - -48, /* 101.91 kPa 1683 count */ - -53, /* 101.96 kPa 1684 count */ - -57, /* 102.02 kPa 1685 count */ - -62, /* 102.07 kPa 1686 count */ - -66, /* 102.13 kPa 1687 count */ - -71, /* 102.18 kPa 1688 count */ - -75, /* 102.23 kPa 1689 count */ - -80, /* 102.29 kPa 1690 count */ - -84, /* 102.34 kPa 1691 count */ - -89, /* 102.40 kPa 1692 count */ - -93, /* 102.45 kPa 1693 count */ - -98, /* 102.51 kPa 1694 count */ - -102, /* 102.56 kPa 1695 count */ - -107, /* 102.61 kPa 1696 count */ - -111, /* 102.67 kPa 1697 count */ - -116, /* 102.72 kPa 1698 count */ - -120, /* 102.78 kPa 1699 count */ - -125, /* 102.83 kPa 1700 count */ - -129, /* 102.89 kPa 1701 count */ - -134, /* 102.94 kPa 1702 count */ - -138, /* 102.99 kPa 1703 count */ - -143, /* 103.05 kPa 1704 count */ - -147, /* 103.10 kPa 1705 count */ - -151, /* 103.16 kPa 1706 count */ - -156, /* 103.21 kPa 1707 count */ - -160, /* 103.27 kPa 1708 count */ - -165, /* 103.32 kPa 1709 count */ - -169, /* 103.37 kPa 1710 count */ - -174, /* 103.43 kPa 1711 count */ - -178, /* 103.48 kPa 1712 count */ - -183, /* 103.54 kPa 1713 count */ - -187, /* 103.59 kPa 1714 count */ - -191, /* 103.65 kPa 1715 count */ - -196, /* 103.70 kPa 1716 count */ - -200, /* 103.75 kPa 1717 count */ - -205, /* 103.81 kPa 1718 count */ - -209, /* 103.86 kPa 1719 count */ - -214, /* 103.92 kPa 1720 count */ - -218, /* 103.97 kPa 1721 count */ - -222, /* 104.03 kPa 1722 count */ - -227, /* 104.08 kPa 1723 count */ - -231, /* 104.13 kPa 1724 count */ - -236, /* 104.19 kPa 1725 count */ - -240, /* 104.24 kPa 1726 count */ - -245, /* 104.30 kPa 1727 count */ - -249, /* 104.35 kPa 1728 count */ - -253, /* 104.41 kPa 1729 count */ - -258, /* 104.46 kPa 1730 count */ - -262, /* 104.51 kPa 1731 count */ - -267, /* 104.57 kPa 1732 count */ - -271, /* 104.62 kPa 1733 count */ - -275, /* 104.68 kPa 1734 count */ - -280, /* 104.73 kPa 1735 count */ - -284, /* 104.79 kPa 1736 count */ - -289, /* 104.84 kPa 1737 count */ - -293, /* 104.89 kPa 1738 count */ - -297, /* 104.95 kPa 1739 count */ - -302, /* 105.00 kPa 1740 count */ - -306, /* 105.06 kPa 1741 count */ - -311, /* 105.11 kPa 1742 count */ - -315, /* 105.17 kPa 1743 count */ - -319, /* 105.22 kPa 1744 count */ - -324, /* 105.27 kPa 1745 count */ - -328, /* 105.33 kPa 1746 count */ - -332, /* 105.38 kPa 1747 count */ - -337, /* 105.44 kPa 1748 count */ - -341, /* 105.49 kPa 1749 count */ - -346, /* 105.55 kPa 1750 count */ - -350, /* 105.60 kPa 1751 count */ - -354, /* 105.65 kPa 1752 count */ - -359, /* 105.71 kPa 1753 count */ - -363, /* 105.76 kPa 1754 count */ - -367, /* 105.82 kPa 1755 count */ - -372, /* 105.87 kPa 1756 count */ - -376, /* 105.93 kPa 1757 count */ - -380, /* 105.98 kPa 1758 count */ - -385, /* 106.03 kPa 1759 count */ - -389, /* 106.09 kPa 1760 count */ - -394, /* 106.14 kPa 1761 count */ - -398, /* 106.20 kPa 1762 count */ - -402, /* 106.25 kPa 1763 count */ - -407, /* 106.31 kPa 1764 count */ - -411, /* 106.36 kPa 1765 count */ - -415, /* 106.41 kPa 1766 count */ - -420, /* 106.47 kPa 1767 count */ - -424, /* 106.52 kPa 1768 count */ - -428, /* 106.58 kPa 1769 count */ - -433, /* 106.63 kPa 1770 count */ - -437, /* 106.69 kPa 1771 count */ - -441, /* 106.74 kPa 1772 count */ - -446, /* 106.79 kPa 1773 count */ - -450, /* 106.85 kPa 1774 count */ - -454, /* 106.90 kPa 1775 count */ - -459, /* 106.96 kPa 1776 count */ - -463, /* 107.01 kPa 1777 count */ - -467, /* 107.07 kPa 1778 count */ - -472, /* 107.12 kPa 1779 count */ - -476, /* 107.17 kPa 1780 count */ - -480, /* 107.23 kPa 1781 count */ - -485, /* 107.28 kPa 1782 count */ - -489, /* 107.34 kPa 1783 count */ - -493, /* 107.39 kPa 1784 count */ - -497, /* 107.45 kPa 1785 count */ - -502, /* 107.50 kPa 1786 count */ - -506, /* 107.55 kPa 1787 count */ - -510, /* 107.61 kPa 1788 count */ - -515, /* 107.66 kPa 1789 count */ - -519, /* 107.72 kPa 1790 count */ - -523, /* 107.77 kPa 1791 count */ - -528, /* 107.83 kPa 1792 count */ - -532, /* 107.88 kPa 1793 count */ - -536, /* 107.93 kPa 1794 count */ - -540, /* 107.99 kPa 1795 count */ - -545, /* 108.04 kPa 1796 count */ - -549, /* 108.10 kPa 1797 count */ - -553, /* 108.15 kPa 1798 count */ - -558, /* 108.21 kPa 1799 count */ - -562, /* 108.26 kPa 1800 count */ - -566, /* 108.31 kPa 1801 count */ - -570, /* 108.37 kPa 1802 count */ - -575, /* 108.42 kPa 1803 count */ - -579, /* 108.48 kPa 1804 count */ - -583, /* 108.53 kPa 1805 count */ - -588, /* 108.59 kPa 1806 count */ - -592, /* 108.64 kPa 1807 count */ - -596, /* 108.69 kPa 1808 count */ - -600, /* 108.75 kPa 1809 count */ - -605, /* 108.80 kPa 1810 count */ - -609, /* 108.86 kPa 1811 count */ - -613, /* 108.91 kPa 1812 count */ - -617, /* 108.97 kPa 1813 count */ - -622, /* 109.02 kPa 1814 count */ - -626, /* 109.07 kPa 1815 count */ - -630, /* 109.13 kPa 1816 count */ - -634, /* 109.18 kPa 1817 count */ - -639, /* 109.24 kPa 1818 count */ - -643, /* 109.29 kPa 1819 count */ - -647, /* 109.35 kPa 1820 count */ - -651, /* 109.40 kPa 1821 count */ - -656, /* 109.45 kPa 1822 count */ - -660, /* 109.51 kPa 1823 count */ - -664, /* 109.56 kPa 1824 count */ - -668, /* 109.62 kPa 1825 count */ - -673, /* 109.67 kPa 1826 count */ - -677, /* 109.73 kPa 1827 count */ - -681, /* 109.78 kPa 1828 count */ - -685, /* 109.83 kPa 1829 count */ - -690, /* 109.89 kPa 1830 count */ - -694, /* 109.94 kPa 1831 count */ - -698, /* 110.00 kPa 1832 count */ - -702, /* 110.05 kPa 1833 count */ - -706, /* 110.11 kPa 1834 count */ - -711, /* 110.16 kPa 1835 count */ - -715, /* 110.21 kPa 1836 count */ - -719, /* 110.27 kPa 1837 count */ - -723, /* 110.32 kPa 1838 count */ - -728, /* 110.38 kPa 1839 count */ - -732, /* 110.43 kPa 1840 count */ - -736, /* 110.48 kPa 1841 count */ - -740, /* 110.54 kPa 1842 count */ - -744, /* 110.59 kPa 1843 count */ - -749, /* 110.65 kPa 1844 count */ - -753, /* 110.70 kPa 1845 count */ - -757, /* 110.76 kPa 1846 count */ - -761, /* 110.81 kPa 1847 count */ - -765, /* 110.86 kPa 1848 count */ - -770, /* 110.92 kPa 1849 count */ - -774, /* 110.97 kPa 1850 count */ - -778, /* 111.03 kPa 1851 count */ - -782, /* 111.08 kPa 1852 count */ - -786, /* 111.14 kPa 1853 count */ - -791, /* 111.19 kPa 1854 count */ - -795, /* 111.24 kPa 1855 count */ - -799, /* 111.30 kPa 1856 count */ - -803, /* 111.35 kPa 1857 count */ - -807, /* 111.41 kPa 1858 count */ - -812, /* 111.46 kPa 1859 count */ - -816, /* 111.52 kPa 1860 count */ - -820, /* 111.57 kPa 1861 count */ - -824, /* 111.62 kPa 1862 count */ - -828, /* 111.68 kPa 1863 count */ - -832, /* 111.73 kPa 1864 count */ - -837, /* 111.79 kPa 1865 count */ - -841, /* 111.84 kPa 1866 count */ - -845, /* 111.90 kPa 1867 count */ - -849, /* 111.95 kPa 1868 count */ - -853, /* 112.00 kPa 1869 count */ - -857, /* 112.06 kPa 1870 count */ - -862, /* 112.11 kPa 1871 count */ - -866, /* 112.17 kPa 1872 count */ - -870, /* 112.22 kPa 1873 count */ - -874, /* 112.28 kPa 1874 count */ - -878, /* 112.33 kPa 1875 count */ - -882, /* 112.38 kPa 1876 count */ - -887, /* 112.44 kPa 1877 count */ - -891, /* 112.49 kPa 1878 count */ - -895, /* 112.55 kPa 1879 count */ - -899, /* 112.60 kPa 1880 count */ - -903, /* 112.66 kPa 1881 count */ - -907, /* 112.71 kPa 1882 count */ - -911, /* 112.76 kPa 1883 count */ - -916, /* 112.82 kPa 1884 count */ - -920, /* 112.87 kPa 1885 count */ - -924, /* 112.93 kPa 1886 count */ - -928, /* 112.98 kPa 1887 count */ - -932, /* 113.04 kPa 1888 count */ - -936, /* 113.09 kPa 1889 count */ - -940, /* 113.14 kPa 1890 count */ - -945, /* 113.20 kPa 1891 count */ - -949, /* 113.25 kPa 1892 count */ - -953, /* 113.31 kPa 1893 count */ - -957, /* 113.36 kPa 1894 count */ - -961, /* 113.42 kPa 1895 count */ - -965, /* 113.47 kPa 1896 count */ - -969, /* 113.52 kPa 1897 count */ - -973, /* 113.58 kPa 1898 count */ - -978, /* 113.63 kPa 1899 count */ - -982, /* 113.69 kPa 1900 count */ - -986, /* 113.74 kPa 1901 count */ - -990, /* 113.80 kPa 1902 count */ - -994, /* 113.85 kPa 1903 count */ - -998, /* 113.90 kPa 1904 count */ - -1002, /* 113.96 kPa 1905 count */ - -1006, /* 114.01 kPa 1906 count */ - -1010, /* 114.07 kPa 1907 count */ - -1015, /* 114.12 kPa 1908 count */ - -1019, /* 114.18 kPa 1909 count */ - -1023, /* 114.23 kPa 1910 count */ - -1027, /* 114.28 kPa 1911 count */ - -1031, /* 114.34 kPa 1912 count */ - -1035, /* 114.39 kPa 1913 count */ - -1039, /* 114.45 kPa 1914 count */ - -1043, /* 114.50 kPa 1915 count */ - -1047, /* 114.56 kPa 1916 count */ - -1051, /* 114.61 kPa 1917 count */ - -1056, /* 114.66 kPa 1918 count */ - -1060, /* 114.72 kPa 1919 count */ - -1064, /* 114.77 kPa 1920 count */ - -1068, /* 114.83 kPa 1921 count */ - -1072, /* 114.88 kPa 1922 count */ - -1076, /* 114.94 kPa 1923 count */ - -1080, /* 114.99 kPa 1924 count */ - -1084, /* 115.04 kPa 1925 count */ - -1088, /* 115.10 kPa 1926 count */ - -1092, /* 115.15 kPa 1927 count */ - -1096, /* 115.21 kPa 1928 count */ - -1100, /* 115.26 kPa 1929 count */ - -1104, /* 115.32 kPa 1930 count */ - -1109, /* 115.37 kPa 1931 count */ - -1113, /* 115.42 kPa 1932 count */ - -1117, /* 115.48 kPa 1933 count */ - -1121, /* 115.53 kPa 1934 count */ - -1125, /* 115.59 kPa 1935 count */ - -1129, /* 115.64 kPa 1936 count */ - -1133, /* 115.70 kPa 1937 count */ - -1137, /* 115.75 kPa 1938 count */ - -1141, /* 115.80 kPa 1939 count */ - -1145, /* 115.86 kPa 1940 count */ - -1149, /* 115.91 kPa 1941 count */ - -1153, /* 115.97 kPa 1942 count */ - -1157, /* 116.02 kPa 1943 count */ - -1161, /* 116.08 kPa 1944 count */ - -1165, /* 116.13 kPa 1945 count */ - -1169, /* 116.18 kPa 1946 count */ - -1173, /* 116.24 kPa 1947 count */ - -1177, /* 116.29 kPa 1948 count */ - -1182, /* 116.35 kPa 1949 count */ - -1186, /* 116.40 kPa 1950 count */ - -1190, /* 116.46 kPa 1951 count */ - -1194, /* 116.51 kPa 1952 count */ - -1198, /* 116.56 kPa 1953 count */ - -1202, /* 116.62 kPa 1954 count */ - -1206, /* 116.67 kPa 1955 count */ - -1210, /* 116.73 kPa 1956 count */ - -1214, /* 116.78 kPa 1957 count */ - -1218, /* 116.84 kPa 1958 count */ - -1222, /* 116.89 kPa 1959 count */ - -1226, /* 116.94 kPa 1960 count */ - -1230, /* 117.00 kPa 1961 count */ - -1234, /* 117.05 kPa 1962 count */ - -1238, /* 117.11 kPa 1963 count */ - -1242, /* 117.16 kPa 1964 count */ - -1246, /* 117.22 kPa 1965 count */ - -1250, /* 117.27 kPa 1966 count */ - -1254, /* 117.32 kPa 1967 count */ - -1258, /* 117.38 kPa 1968 count */ - -1262, /* 117.43 kPa 1969 count */ - -1266, /* 117.49 kPa 1970 count */ - -1270, /* 117.54 kPa 1971 count */ - -1274, /* 117.60 kPa 1972 count */ - -1278, /* 117.65 kPa 1973 count */ - -1282, /* 117.70 kPa 1974 count */ - -1286, /* 117.76 kPa 1975 count */ - -1290, /* 117.81 kPa 1976 count */ - -1294, /* 117.87 kPa 1977 count */ - -1298, /* 117.92 kPa 1978 count */ - -1302, /* 117.98 kPa 1979 count */ - -1306, /* 118.03 kPa 1980 count */ - -1310, /* 118.08 kPa 1981 count */ - -1314, /* 118.14 kPa 1982 count */ - -1318, /* 118.19 kPa 1983 count */ - -1322, /* 118.25 kPa 1984 count */ - -1326, /* 118.30 kPa 1985 count */ - -1330, /* 118.36 kPa 1986 count */ - -1334, /* 118.41 kPa 1987 count */ - -1338, /* 118.46 kPa 1988 count */ - -1342, /* 118.52 kPa 1989 count */ - -1346, /* 118.57 kPa 1990 count */ - -1350, /* 118.63 kPa 1991 count */ - -1354, /* 118.68 kPa 1992 count */ - -1358, /* 118.74 kPa 1993 count */ - -1362, /* 118.79 kPa 1994 count */ - -1366, /* 118.84 kPa 1995 count */ - -1370, /* 118.90 kPa 1996 count */ - -1374, /* 118.95 kPa 1997 count */ - -1378, /* 119.01 kPa 1998 count */ - -1382, /* 119.06 kPa 1999 count */ - -1386, /* 119.12 kPa 2000 count */ - -1390, /* 119.17 kPa 2001 count */ - -1394, /* 119.22 kPa 2002 count */ - -1397, /* 119.28 kPa 2003 count */ - -1401, /* 119.33 kPa 2004 count */ - -1405, /* 119.39 kPa 2005 count */ - -1409, /* 119.44 kPa 2006 count */ - -1413, /* 119.50 kPa 2007 count */ - -1417, /* 119.55 kPa 2008 count */ - -1421, /* 119.60 kPa 2009 count */ - -1425, /* 119.66 kPa 2010 count */ - -1429, /* 119.71 kPa 2011 count */ - -1433, /* 119.77 kPa 2012 count */ - -1437, /* 119.82 kPa 2013 count */ - -1441, /* 119.88 kPa 2014 count */ - -1445, /* 119.93 kPa 2015 count */ - -1449, /* 119.98 kPa 2016 count */ - -1453, /* 120.04 kPa 2017 count */ - -1457, /* 120.09 kPa 2018 count */ - -1461, /* 120.15 kPa 2019 count */ - -1465, /* 120.20 kPa 2020 count */ - -1469, /* 120.26 kPa 2021 count */ - -1472, /* 120.31 kPa 2022 count */ - -1476, /* 120.36 kPa 2023 count */ - -1480, /* 120.42 kPa 2024 count */ - -1484, /* 120.47 kPa 2025 count */ - -1488, /* 120.53 kPa 2026 count */ - -1492, /* 120.58 kPa 2027 count */ - -1496, /* 120.64 kPa 2028 count */ - -1500, /* 120.69 kPa 2029 count */ - -1504, /* 120.74 kPa 2030 count */ - -1508, /* 120.80 kPa 2031 count */ - -1512, /* 120.85 kPa 2032 count */ - -1516, /* 120.91 kPa 2033 count */ - -1520, /* 120.96 kPa 2034 count */ - -1523, /* 121.02 kPa 2035 count */ - -1527, /* 121.07 kPa 2036 count */ - -1531, /* 121.12 kPa 2037 count */ - -1535, /* 121.18 kPa 2038 count */ - -1539, /* 121.23 kPa 2039 count */ - -1543, /* 121.29 kPa 2040 count */ - -1547, /* 121.34 kPa 2041 count */ - -1551, /* 121.40 kPa 2042 count */ - -1555, /* 121.45 kPa 2043 count */ - -1559, /* 121.50 kPa 2044 count */ - -1562, /* 121.56 kPa 2045 count */ - -1566, /* 121.61 kPa 2046 count */ - -1570, /* 121.67 kPa 2047 count */ +/*max error 3.197865153490684 at 0.782%. Average error 0.260150920474668*/ +#define NALT 129 +#define ALT_FRAC_BITS 8 + 15835, /* 10.56 kPa 0.000% */ + 15332, /* 11.42 kPa 0.781% */ + 14868, /* 12.29 kPa 1.563% */ + 14435, /* 13.16 kPa 2.344% */ + 14030, /* 14.02 kPa 3.125% */ + 13649, /* 14.90 kPa 3.906% */ + 13290, /* 15.76 kPa 4.688% */ + 12950, /* 16.63 kPa 5.469% */ + 12627, /* 17.50 kPa 6.250% */ + 12320, /* 18.37 kPa 7.031% */ + 12027, /* 19.24 kPa 7.813% */ + 11747, /* 20.10 kPa 8.594% */ + 11479, /* 20.97 kPa 9.375% */ + 11222, /* 21.84 kPa 10.156% */ + 10975, /* 22.71 kPa 10.938% */ + 10736, /* 23.58 kPa 11.719% */ + 10504, /* 24.44 kPa 12.500% */ + 10278, /* 25.31 kPa 13.281% */ + 10059, /* 26.18 kPa 14.063% */ + 9846, /* 27.05 kPa 14.844% */ + 9638, /* 27.91 kPa 15.625% */ + 9435, /* 28.78 kPa 16.406% */ + 9237, /* 29.65 kPa 17.188% */ + 9044, /* 30.52 kPa 17.969% */ + 8855, /* 31.39 kPa 18.750% */ + 8670, /* 32.26 kPa 19.531% */ + 8490, /* 33.13 kPa 20.313% */ + 8313, /* 33.99 kPa 21.094% */ + 8140, /* 34.86 kPa 21.875% */ + 7970, /* 35.73 kPa 22.656% */ + 7803, /* 36.60 kPa 23.438% */ + 7640, /* 37.47 kPa 24.219% */ + 7480, /* 38.33 kPa 25.000% */ + 7322, /* 39.20 kPa 25.781% */ + 7168, /* 40.07 kPa 26.563% */ + 7016, /* 40.94 kPa 27.344% */ + 6867, /* 41.80 kPa 28.125% */ + 6720, /* 42.67 kPa 28.906% */ + 6575, /* 43.54 kPa 29.688% */ + 6433, /* 44.41 kPa 30.469% */ + 6294, /* 45.28 kPa 31.250% */ + 6156, /* 46.15 kPa 32.031% */ + 6020, /* 47.01 kPa 32.813% */ + 5887, /* 47.88 kPa 33.594% */ + 5755, /* 48.75 kPa 34.375% */ + 5625, /* 49.62 kPa 35.156% */ + 5497, /* 50.49 kPa 35.938% */ + 5371, /* 51.35 kPa 36.719% */ + 5247, /* 52.22 kPa 37.500% */ + 5124, /* 53.09 kPa 38.281% */ + 5003, /* 53.96 kPa 39.063% */ + 4883, /* 54.83 kPa 39.844% */ + 4765, /* 55.69 kPa 40.625% */ + 4648, /* 56.56 kPa 41.406% */ + 4533, /* 57.43 kPa 42.188% */ + 4419, /* 58.30 kPa 42.969% */ + 4307, /* 59.17 kPa 43.750% */ + 4196, /* 60.03 kPa 44.531% */ + 4086, /* 60.90 kPa 45.313% */ + 3977, /* 61.77 kPa 46.094% */ + 3870, /* 62.63 kPa 46.875% */ + 3764, /* 63.51 kPa 47.656% */ + 3659, /* 64.38 kPa 48.438% */ + 3555, /* 65.24 kPa 49.219% */ + 3453, /* 66.11 kPa 50.000% */ + 3351, /* 66.98 kPa 50.781% */ + 3250, /* 67.85 kPa 51.563% */ + 3151, /* 68.72 kPa 52.344% */ + 3052, /* 69.58 kPa 53.125% */ + 2955, /* 70.45 kPa 53.906% */ + 2858, /* 71.32 kPa 54.688% */ + 2763, /* 72.19 kPa 55.469% */ + 2668, /* 73.06 kPa 56.250% */ + 2574, /* 73.92 kPa 57.031% */ + 2482, /* 74.79 kPa 57.813% */ + 2390, /* 75.66 kPa 58.594% */ + 2298, /* 76.52 kPa 59.375% */ + 2208, /* 77.40 kPa 60.156% */ + 2119, /* 78.26 kPa 60.938% */ + 2030, /* 79.13 kPa 61.719% */ + 1942, /* 80.00 kPa 62.500% */ + 1855, /* 80.87 kPa 63.281% */ + 1769, /* 81.74 kPa 64.063% */ + 1683, /* 82.60 kPa 64.844% */ + 1598, /* 83.47 kPa 65.625% */ + 1514, /* 84.34 kPa 66.406% */ + 1430, /* 85.21 kPa 67.188% */ + 1347, /* 86.08 kPa 67.969% */ + 1265, /* 86.94 kPa 68.750% */ + 1184, /* 87.81 kPa 69.531% */ + 1103, /* 88.68 kPa 70.313% */ + 1023, /* 89.55 kPa 71.094% */ + 943, /* 90.41 kPa 71.875% */ + 864, /* 91.28 kPa 72.656% */ + 786, /* 92.15 kPa 73.438% */ + 708, /* 93.02 kPa 74.219% */ + 631, /* 93.89 kPa 75.000% */ + 554, /* 94.76 kPa 75.781% */ + 478, /* 95.63 kPa 76.563% */ + 403, /* 96.49 kPa 77.344% */ + 328, /* 97.36 kPa 78.125% */ + 254, /* 98.23 kPa 78.906% */ + 180, /* 99.10 kPa 79.688% */ + 106, /* 99.97 kPa 80.469% */ + 34, /* 100.83 kPa 81.250% */ + -39, /* 101.70 kPa 82.031% */ + -111, /* 102.57 kPa 82.813% */ + -182, /* 103.44 kPa 83.594% */ + -253, /* 104.30 kPa 84.375% */ + -323, /* 105.17 kPa 85.156% */ + -393, /* 106.04 kPa 85.938% */ + -462, /* 106.91 kPa 86.719% */ + -531, /* 107.78 kPa 87.500% */ + -600, /* 108.65 kPa 88.281% */ + -668, /* 109.51 kPa 89.063% */ + -736, /* 110.38 kPa 89.844% */ + -803, /* 111.25 kPa 90.625% */ + -870, /* 112.12 kPa 91.406% */ + -936, /* 112.99 kPa 92.188% */ + -1002, /* 113.85 kPa 92.969% */ + -1068, /* 114.72 kPa 93.750% */ + -1133, /* 115.59 kPa 94.531% */ + -1198, /* 116.46 kPa 95.313% */ + -1262, /* 117.33 kPa 96.094% */ + -1326, /* 118.19 kPa 96.875% */ + -1389, /* 119.06 kPa 97.656% */ + -1453, /* 119.93 kPa 98.438% */ + -1516, /* 120.80 kPa 99.219% */ + -1578, /* 121.67 kPa 100.000% */ diff --git a/src/ao_convert.c b/src/ao_convert.c index f29ce9e9..cec4c29f 100644 --- a/src/ao_convert.c +++ b/src/ao_convert.c @@ -15,40 +15,63 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ +#ifndef AO_CONVERT_TEST #include "ao.h" +#endif -static const int16_t altitude_table[2048] = { +static const int16_t altitude_table[] = { #include "altitude.h" }; +#define ALT_FRAC_SCALE (1 << ALT_FRAC_BITS) +#define ALT_FRAC_MASK (ALT_FRAC_SCALE - 1) + int16_t ao_pres_to_altitude(int16_t pres) __reentrant { - pres = pres >> 4; - if (pres < 0) pres = 0; - if (pres > 2047) pres = 2047; - return altitude_table[pres]; + uint8_t o; + int16_t part; + + if (pres < 0) + pres = 0; + o = pres >> ALT_FRAC_BITS; + part = pres & ALT_FRAC_MASK; + + return ((int32_t) altitude_table[o] * (ALT_FRAC_SCALE - part) + + (int32_t) altitude_table[o+1] * part + (ALT_FRAC_SCALE >> 1)) >> ALT_FRAC_BITS; } int16_t ao_altitude_to_pres(int16_t alt) __reentrant { - int16_t pres; + int16_t span, sub_span; + uint8_t l, h, m; + int32_t pres; - for (pres = 0; pres < 2047; pres++) - if (altitude_table[pres] <= alt) - break; - return pres << 4; + l = 0; + h = NALT - 1; + while ((h - l) != 1) { + m = (l + h) >> 1; + if (altitude_table[m] < alt) + h = m; + else + l = m; + } + span = altitude_table[l] - altitude_table[h]; + sub_span = altitude_table[l] - alt; + pres = ((((int32_t) l * (span - sub_span) + (int32_t) h * sub_span) << ALT_FRAC_BITS) + (span >> 1)) / span; + if (pres > 32767) + pres = 32767; + if (pres < 0) + pres = 0; + return (int16_t) pres; } -static __xdata uint8_t ao_temp_mutex; - int16_t ao_temp_to_dC(int16_t temp) __reentrant { int16_t ret; - ao_mutex_get(&ao_temp_mutex); /* Output voltage at 0°C = 0.755V * Coefficient = 0.00247V/°C * Reference voltage = 1.25V @@ -58,6 +81,5 @@ ao_temp_to_dC(int16_t temp) __reentrant * ≃ (value - 19791) * 1012 / 65536 */ ret = ((temp - 19791) * 1012L) >> 16; - ao_mutex_put(&ao_temp_mutex); return ret; } diff --git a/src/ao_convert_test.c b/src/ao_convert_test.c new file mode 100644 index 00000000..e2c28b73 --- /dev/null +++ b/src/ao_convert_test.c @@ -0,0 +1,75 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#define AO_CONVERT_TEST +#include "ao_host.h" +#include "ao_convert.c" + +#define STEP 1 + +static inline i_abs(int i) { return i < 0 ? -i : i; } + +main () +{ + int i; + int16_t p_to_a, p_to_a_to_p; + int16_t a_to_p, a_to_p_to_a; + int max_p_error = 0, max_p_error_p = -1; + int max_a_error = 0, max_a_error_a = -1; + int p_error; + int a_error; + int ret = 0; + + for (i = 0; i < 32767 + STEP; i += STEP) { + if (i > 32767) + i = 32767; + p_to_a = ao_pres_to_altitude(i); + p_to_a_to_p = ao_altitude_to_pres(p_to_a); + p_error = i_abs(p_to_a_to_p - i); + if (p_error > max_p_error) { + max_p_error = p_error; + max_p_error_p = i; + } +// printf ("pres %d alt %d pres %d\n", +// i, p_to_a, p_to_a_to_p); + } + for (i = -1578; i < 15835 + STEP; i += STEP) { + if (i > 15835) + i = 15835; + a_to_p = ao_altitude_to_pres(i); + a_to_p_to_a = ao_pres_to_altitude(a_to_p); + a_error = i_abs(a_to_p_to_a - i); + if (a_error > max_a_error) { + max_a_error = a_error; + max_a_error_a = i; + } +// printf ("alt %d pres %d alt %d\n", +// i, a_to_p, a_to_p_to_a); + } + if (max_p_error > 2) { + printf ("max p error %d at %d\n", max_p_error, + max_p_error_p); + ret++; + } + if (max_a_error > 1) { + printf ("max a error %d at %d\n", max_a_error, + max_a_error_a); + ret++; + } + return ret; +} diff --git a/src/make-altitude b/src/make-altitude index ac04e84f..716aa8a8 100644 --- a/src/make-altitude +++ b/src/make-altitude @@ -179,14 +179,105 @@ real meters_to_feet(real meters) real counts_per_kPa = 27 * 2047 / 3300; real counts_at_101_3kPa = 1674; -real count_to_kPa(real count) +real fraction_to_kPa(real fraction) { - return (count / 2047 + 0.095) / 0.009; + return (fraction + 0.095) / 0.009; } -for (real count = 0; count <= 2047; count++) { - real kPa = count_to_kPa(count); + +real count_to_kPa(real count) = fraction_to_kPa(count / 2047); + +typedef struct { + real m, b; + int m_i, b_i; +} line_t; + +line_t best_fit(real[] values, int first, int last) { + real sum_x = 0, sum_x2 = 0, sum_y = 0, sum_xy = 0; + int n = last - first + 1; + real m, b; + int m_i, b_i; + + for (int i = first; i <= last; i++) { + sum_x += i; + sum_x2 += i**2; + sum_y += values[i]; + sum_xy += values[i] * i; + } + m = (n*sum_xy - sum_y*sum_x) / (n*sum_x2 - sum_x**2); + b = sum_y/n - m*(sum_x/n); + return (line_t) { m = m, b = b }; +} + +real count_to_altitude(real count) { + return pressure_to_altitude(count_to_kPa(count) * 1000); +} + +real fraction_to_altitude(real frac) = pressure_to_altitude(fraction_to_kPa(frac) * 1000); + +int num_samples = 1024; + +real[num_samples] alt = { [n] = fraction_to_altitude(n/(num_samples - 1)) }; + +int num_part = 128; +int seg_len = num_samples / num_part; + +line_t [dim(alt) / seg_len] fit = { + [n] = best_fit(alt, n * seg_len, n * seg_len + seg_len - 1) +}; + +int[num_samples/seg_len + 1] alt_part; + +alt_part[0] = floor (fit[0].b + 0.5); +alt_part[dim(fit)] = floor(fit[dim(fit)-1].m * dim(fit) * seg_len + fit[dim(fit)-1].b + 0.5); + +for (int i = 0; i < dim(fit) - 1; i++) { + real here, there; + here = fit[i].m * (i+1) * seg_len + fit[i].b; + there = fit[i+1].m * (i+1) * seg_len + fit[i+1].b; + alt_part[i+1] = floor ((here + there) / 2 + 0.5); +} + +real count_to_fit_altitude(int count) { + int sub = count // seg_len; + int off = count % seg_len; + line_t l = fit[sub]; + real r_v; + real i_v; + + r_v = count * l.m + l.b; + i_v = (alt_part[sub] * (seg_len - off) + alt_part[sub+1] * off) / seg_len; + return i_v; +} + +real max_error = 0; +int max_error_count = 0; +real total_error = 0; + +for (int count = 0; count < num_samples; count++) { + real kPa = fraction_to_kPa(count / (num_samples - 1)); real meters = pressure_to_altitude(kPa * 1000); - printf (" %d, /* %6.2g kPa %d count */\n", - floor (meters + 0.5), kPa, count); + + real meters_approx = count_to_fit_altitude(count); + real error = abs(meters - meters_approx); + + total_error += error; + if (error > max_error) { + max_error = error; + max_error_count = count; + } +# printf (" %7d, /* %6.2g kPa %5d count approx %d */\n", +# floor (meters + 0.5), kPa, count, floor(count_to_fit_altitude(count) + 0.5)); +} + +printf ("/*max error %f at %7.3f%%. Average error %f*/\n", max_error, max_error_count / (num_samples - 1) * 100, total_error / num_samples); + +printf ("#define NALT %d\n", dim(alt_part)); +printf ("#define ALT_FRAC_BITS %d\n", floor (log2(32768/(dim(alt_part)-1)) + 0.1)); + +for (int i = 0; i < dim(alt_part); i++) { + real fraction = i / (dim(alt_part) - 1); + real kPa = fraction_to_kPa(fraction); + printf ("%9d, /* %6.2f kPa %7.3f%% */\n", + alt_part[i], kPa, fraction * 100); } -- cgit v1.2.3 From 84c93bb2fc4558a5e4654794ba90e730a84eaf67 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Feb 2010 20:22:16 -0800 Subject: Change altos build process to support per-product compile-time changes This creates per-product subdirectories and recompiles everything for each product, allowing per-product compile-time changes for things like peripheral pin assignments and attached serial devices. Signed-off-by: Keith Packard --- src/Makefile | 306 ++------------------------------- src/Makefile.proto | 217 +++++++++++++++++++++++ src/ao.h | 38 ++-- src/ao_adc.c | 7 +- src/ao_config.c | 18 +- src/ao_dbg.c | 32 ++-- src/ao_host.h | 24 --- src/ao_packet.c | 8 + src/ao_packet_slave.c | 2 +- src/ao_pins.h | 144 ++++++++++++++++ src/ao_reboot.c | 28 +++ src/ao_stdio.c | 3 +- src/ao_teledongle.c | 5 +- src/ao_telemetrum.c | 6 +- src/ao_timer.c | 6 + src/teledongle-v0.1/Makefile | 1 + src/teledongle-v0.1/Makefile.defs | 9 + src/teledongle-v0.2/Makefile | 1 + src/teledongle-v0.2/Makefile.defs | 9 + src/telemetrum-v0.1-sirf/Makefile | 1 + src/telemetrum-v0.1-sirf/Makefile.defs | 11 ++ src/telemetrum-v0.1-sky/Makefile | 1 + src/telemetrum-v0.1-sky/Makefile.defs | 11 ++ src/telemetrum-v0.2/Makefile | 1 + src/telemetrum-v0.2/Makefile.defs | 11 ++ src/test/Makefile | 24 +++ src/tidongle/Makefile | 1 + src/tidongle/Makefile.defs | 8 + 28 files changed, 572 insertions(+), 361 deletions(-) create mode 100644 src/Makefile.proto create mode 100644 src/ao_pins.h create mode 100644 src/ao_reboot.c create mode 100644 src/teledongle-v0.1/Makefile create mode 100644 src/teledongle-v0.1/Makefile.defs create mode 100644 src/teledongle-v0.2/Makefile create mode 100644 src/teledongle-v0.2/Makefile.defs create mode 100644 src/telemetrum-v0.1-sirf/Makefile create mode 100644 src/telemetrum-v0.1-sirf/Makefile.defs create mode 100644 src/telemetrum-v0.1-sky/Makefile create mode 100644 src/telemetrum-v0.1-sky/Makefile.defs create mode 100644 src/telemetrum-v0.2/Makefile create mode 100644 src/telemetrum-v0.2/Makefile.defs create mode 100644 src/test/Makefile create mode 100644 src/tidongle/Makefile create mode 100644 src/tidongle/Makefile.defs (limited to 'src') diff --git a/src/Makefile b/src/Makefile index dcd41718..e2699ee6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,307 +4,23 @@ # CC=sdcc -ifndef VERSION -VERSION=$(shell git describe) -endif +SUBDIRS=telemetrum-v0.2 teledongle-v0.2 telemetrum-v0.1-sky telemetrum-v0.1-sirf teledongle-v0.1 tidongle test -CFLAGS=--model-small --debug --opt-code-speed +all: all-recursive -LDFLAGS=--out-fmt-ihx --code-loc 0x0000 --code-size 0x8000 \ - --xram-loc 0xf000 --xram-size 0xda2 --iram-size 0xff +RECURSIVE_TARGETS = all-recursive clean-recursive install-recursive -INC = \ - ao.h \ - cc1111.h \ - altitude.h \ - 25lc1024.h - -# -# Common AltOS sources -# -ALTOS_SRC = \ - ao_cmd.c \ - ao_dma.c \ - ao_mutex.c \ - ao_panic.c \ - ao_task.c \ - ao_timer.c \ - _bp.c - -# -# Shared AltOS drivers -# -ALTOS_DRIVER_SRC = \ - ao_beep.c \ - ao_config.c \ - ao_led.c \ - ao_radio.c \ - ao_stdio.c \ - ao_usb.c - -TELE_COMMON_SRC = \ - ao_packet.c \ - ao_packet_slave.c \ - ao_state.c - -# -# Receiver code -# -TELE_RECEIVER_SRC =\ - ao_monitor.c \ - ao_gps_print.c \ - ao_packet_master.c \ - ao_rssi.c - -# -# Shared Tele drivers (on TeleMetrum, TeleTerra, TeleDongle) -# - -TELE_DRIVER_SRC = \ - ao_convert.c \ - ao_serial.c - -# -# Drivers for partially-flled boards (TT, TD and TI) -# -TELE_FAKE_SRC = \ - ao_adc_fake.c \ - ao_ee_fake.c - -# -# Debug dongle driver (only on TI) -# -DBG_DONGLE_SRC = \ - ao_dbg.c - -# -# Drivers only on TeleMetrum -# -TM_DRIVER_SRC = \ - ao_adc.c \ - ao_flash.c \ - ao_gps_report.c \ - ao_ignite.c - -# -# Drivers only on TeleMetrum -# -TM_SIRF_DRIVER_SRC = \ - ao_gps_sirf.c -# -# Drivers only on TeleMetrum -# -TM_SKY_DRIVER_SRC = \ - ao_gps_skytraq.c - -# -# Tasks run on TeleMetrum -# -TM_TASK_SRC = \ - ao_flight.c \ - ao_log.c \ - ao_report.c \ - ao_telemetry.c - -TM_MAIN_SRC = \ - 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) \ - $(TM_MAIN_SRC) - -TM_SIRF_SRC = \ - $(TM_SRC) \ - $(TM_SIRF_DRIVER_SRC) - -TM_SKY_SRC = \ - $(TM_SRC) \ - $(TM_SKY_DRIVER_SRC) - -TI_MAIN_SRC = \ - ao_tidongle.c - -# -# All sources for the TI debug dongle -# -TI_SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_RECEIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(TELE_FAKE_SRC) \ - $(TI_MAIN_SRC) \ - $(DBG_DONGLE_SRC) - -TT_MAIN_SRC = \ - ao_teleterra.c -# -# All sources for TeleTerra -# -TT_SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_RECEIVER_SRC) \ - $(TELE_DRIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(TELE_FAKE_SRC) \ - $(TT_MAIN_SRC) - - -# -# Sources for TeleDongle -# - -TD_MAIN_SRC = \ - ao_teledongle.c - -TD_SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_RECEIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(TELE_FAKE_SRC) \ - $(TD_MAIN_SRC) - -SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_DRIVER_SRC) \ - $(TELE_RECEIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(TELE_FAKE_SRC) \ - $(TM_DRIVER_SRC) \ - $(TM_SIRF_DRIVER_SRC) \ - $(TM_SKY_DRIVER_SRC) \ - $(TM_TASK_SRC) \ - $(TM_MAIN_SRC) \ - $(TI_MAIN_SRC) \ - $(TD_MAIN_SRC) \ - $(TT_MAIN_SRC) - -TM_SIRF_REL=$(TM_SIRF_SRC:.c=.rel) ao_product-telemetrum.rel -TM_SKY_REL=$(TM_SKY_SRC:.c=.rel) ao_product-telemetrum.rel -TI_REL=$(TI_SRC:.c=.rel) ao_product-tidongle.rel -TT_REL=$(TT_SRC:.c=.rel) ao_product-teleterra.rel -TD_REL=$(TD_SRC:.c=.rel) ao_product-teledongle.rel - -PROD_REL=\ - ao_product-telemetrum.rel \ - ao_product-tidongle.rel \ - ao_product-teleterra.rel \ - ao_product-teledongle.rel - -REL=$(SRC:.c=.rel) $(PROD_REL) -ADB=$(REL:.rel=.adb) -ASM=$(REL:.rel=.asm) -LNK=$(REL:.rel=.lnk) -LST=$(REL:.rel=.lst) -RST=$(REL:.rel=.rst) -SYM=$(REL:.rel=.sym) - -PROGS= telemetrum-sirf.ihx telemetrum-sky.ihx tidongle.ihx \ - teleterra.ihx teledongle.ihx - -HOST_PROGS=ao_flight_test ao_gps_test ao_gps_test_skytraq - -PCDB=$(PROGS:.ihx=.cdb) -PLNK=$(PROGS:.ihx=.lnk) -PMAP=$(PROGS:.ihx=.map) -PMEM=$(PROGS:.ihx=.mem) -PAOM=$(PROGS:.ihx=) - -%.rel : %.c $(INC) - $(CC) -c $(CFLAGS) -o$*.rel $*.c - -all: $(PROGS) $(HOST_PROGS) - -telemetrum-sirf.ihx: $(TM_SIRF_REL) Makefile - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TM_SIRF_REL) - sh check-stack ao.h telemetrum-sirf.mem - -telemetrum-sky.ihx: $(TM_SKY_REL) Makefile - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TM_SKY_REL) - sh check-stack ao.h telemetrum-sky.mem - -telemetrum-sky.ihx: telemetrum-sirf.ihx - -tidongle.ihx: $(TI_REL) Makefile - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TI_REL) - sh check-stack ao.h tidongle.mem - -tidongle.ihx: telemetrum-sky.ihx - -teleterra.ihx: $(TT_REL) Makefile - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TT_REL) - sh check-stack ao.h teleterra.mem - -teleterra.ihx: tidongle.ihx - -teledongle.ihx: $(TD_REL) Makefile - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(TD_REL) - sh check-stack ao.h teledongle.mem - -teledongle.ihx: teleterra.ihx - -altitude.h: make-altitude - nickle make-altitude > altitude.h - -TELEMETRUM_DEFS=ao-telemetrum.h -TELETERRA_DEFS=ao-teleterra.h -TELEDONGLE_DEFS=ao-teledongle.h -TIDONGLE_DEFS=ao-tidongle.h - -ALL_DEFS=$(TELEMETRUM_DEFS) $(TELETERRA_DEFS) \ - $(TELEDONGLE_DEFS) $(TIDONGLE_DEFS) -ao_product-telemetrum.rel: ao_product.c $(TELEMETRUM_DEFS) - $(CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"$(TELEMETRUM_DEFS)\"' -o$@ ao_product.c - -ao_product-teleterra.rel: ao_product.c $(TELETERRA_DEFS) - $(CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"$(TELETERRA_DEFS)\"' -o$@ ao_product.c - -ao_product-teledongle.rel: ao_product.c $(TELEDONGLE_DEFS) - $(CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"$(TELEDONGLE_DEFS)\"' -o$@ ao_product.c - -ao_product-tidongle.rel: ao_product.c $(TIDONGLE_DEFS) - $(CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"$(TIDONGLE_DEFS)\"' -o$@ ao_product.c - -$(TELEMETRUM_DEFS): ao-make-product.5c - nickle ao-make-product.5c -m altusmetrum.org -p TeleMetrum -v $(VERSION) > $@ - -$(TELETERRA_DEFS): ao-make-product.5c - nickle ao-make-product.5c -m altusmetrum.org -p TeleTerra -v $(VERSION) > $@ - -$(TELEDONGLE_DEFS): ao-make-product.5c - nickle ao-make-product.5c -m altusmetrum.org -p TeleDongle -v $(VERSION) > $@ - -$(TIDONGLE_DEFS): ao-make-product.5c - nickle ao-make-product.5c -m altusmetrum.org -p TIDongle -v $(VERSION) > $@ +$(RECURSIVE_TARGETS): + @target=`echo $@ | sed 's/-recursive//'`; \ + for subdir in $(SUBDIRS); do \ + echo "Making $$target in $$subdir"; \ + (cd $$subdir && $(MAKE) $$target) || exit 1; \ + done distclean: clean -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROGS) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f $(ALL_DEFS) $(HOST_PROGS) - rm -f $(TELEMETRUM_DEFS) $(TELETERRA_DEFS) $(TELEDONGLE_DEFS) $(TIDONGLE_DEFS) +clean: clean-recursive -install: +install: install-recursive uninstall: - -ao_flight_test: ao_flight.c ao_flight_test.c ao_host.h - cc -g -o $@ ao_flight_test.c - -ao_gps_test: ao_gps_sirf.c ao_gps_test.c ao_gps_print.c ao_host.h - cc -g -o $@ ao_gps_test.c - -ao_gps_test_skytraq: ao_gps_skytraq.c ao_gps_test_skytraq.c ao_gps_print.c ao_host.h - cc -g -o $@ ao_gps_test_skytraq.c diff --git a/src/Makefile.proto b/src/Makefile.proto new file mode 100644 index 00000000..958b7572 --- /dev/null +++ b/src/Makefile.proto @@ -0,0 +1,217 @@ +# +# AltOS build +# +# +vpath %.c .. +vpath %.h .. +vpath make-altitude .. +vpath ao-make-product.5c .. + +CC=sdcc + +ifndef VERSION +VERSION=$(shell git describe) +endif + +CFLAGS=--model-small --debug --opt-code-speed + +LDFLAGS=--out-fmt-ihx --code-loc 0x0000 --code-size 0x8000 \ + --xram-loc 0xf000 --xram-size 0xda2 --iram-size 0xff + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + altitude.h \ + 25lc1024.h + +# +# Common AltOS sources +# +ALTOS_SRC = \ + ao_cmd.c \ + ao_dma.c \ + ao_mutex.c \ + ao_panic.c \ + ao_task.c \ + ao_timer.c \ + _bp.c + +# +# Shared AltOS drivers +# +ALTOS_DRIVER_SRC = \ + ao_beep.c \ + ao_config.c \ + ao_led.c \ + ao_radio.c \ + ao_stdio.c \ + ao_usb.c + +TELE_COMMON_SRC = \ + ao_packet.c \ + ao_packet_slave.c \ + ao_state.c + +# +# Receiver code +# +TELE_RECEIVER_SRC =\ + ao_monitor.c \ + ao_gps_print.c \ + ao_packet_master.c \ + ao_rssi.c + +# +# Shared Tele drivers (on TeleMetrum, TeleTerra, TeleDongle) +# + +TELE_DRIVER_SRC = \ + ao_convert.c \ + ao_serial.c + +# +# Debug dongle driver (only on TI) +# +DBG_SRC = \ + ao_dbg.c + +# +# Drivers only on TeleMetrum +# +TM_DRIVER_SRC = \ + ao_adc.c \ + ao_gps_report.c \ + ao_ignite.c + +# +# 25LC1024 driver source +EE_DRIVER_SRC = \ + ao_ee.c + +# +# AT45DB161D driver source + +FLASH_DRIVER_SRC = \ + ao_flash.c + +# +# SiRF driver source +# +SIRF_DRIVER_SRC = \ + ao_gps_sirf.c +# +# Skytraq driver source +# +SKY_DRIVER_SRC = \ + ao_gps_skytraq.c + +# +# Tasks run on TeleMetrum +# +TM_TASK_SRC = \ + ao_flight.c \ + ao_log.c \ + ao_report.c \ + ao_telemetry.c + +TM_MAIN_SRC = \ + ao_telemetrum.c + +# +# Base sources for TeleMetrum +# +TM_BASE_SRC = \ + $(ALTOS_SRC) \ + $(ALTOS_DRIVER_SRC) \ + $(TELE_DRIVER_SRC) \ + $(TELE_COMMON_SRC) \ + $(TM_DRIVER_SRC) \ + $(TM_TASK_SRC) \ + $(TM_MAIN_SRC) + +TI_MAIN_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_MAIN_SRC) \ + $(DBG_SRC) + +TT_MAIN_SRC = \ + ao_teleterra.c +# +# All sources for TeleTerra +# +TT_SRC = \ + $(ALTOS_SRC) \ + $(ALTOS_DRIVER_SRC) \ + $(TELE_RECEIVER_SRC) \ + $(TELE_DRIVER_SRC) \ + $(TELE_COMMON_SRC) \ + $(TT_MAIN_SRC) + + +# +# Sources for TeleDongle +# + +TD_MAIN_SRC = \ + ao_teledongle.c + +TD_SRC = \ + $(ALTOS_SRC) \ + $(ALTOS_DRIVER_SRC) \ + $(TELE_RECEIVER_SRC) \ + $(TELE_COMMON_SRC) \ + $(TD_MAIN_SRC) + +include Makefile.defs + +REL=$(SRC:.c=.rel) ao_product.rel +ADB=$(REL:.rel=.adb) +ASM=$(REL:.rel=.asm) +LNK=$(REL:.rel=.lnk) +LST=$(REL:.rel=.lst) +RST=$(REL:.rel=.rst) +SYM=$(REL:.rel=.sym) + +PCDB=$(PROG:.ihx=.cdb) +PLNK=$(PROG:.ihx=.lnk) +PMAP=$(PROG:.ihx=.map) +PMEM=$(PROG:.ihx=.mem) +PAOM=$(PROG:.ihx=) + +%.rel : %.c $(INC) + $(CC) -c $(CFLAGS) -o$@ $< + +all: $(PROG) + +$(PROG): $(REL) Makefile Makefile.defs ../Makefile.proto + $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(REL) + +../altitude.h: make-altitude + nickle $< > $@ + +ao_product.h: ao-make-product.5c + nickle $< -m altusmetrum.org -p $(PRODUCT) -v $(VERSION) > $@ + +ao_product.rel: ao_product.c ao_product.h + $(CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/ao.h b/src/ao.h index d6be2223..b43f5ecd 100644 --- a/src/ao.h +++ b/src/ao.h @@ -23,6 +23,7 @@ #include #include #include "cc1111.h" +#include "ao_pins.h" #define TRUE 1 #define FALSE 0 @@ -148,15 +149,7 @@ void ao_clock_init(void); /* - * ao_adc.c - */ - -#define AO_ADC_RING 32 -#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) -#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) - -/* - * One set of samples read from the A/D converter + * One set of samples read from the A/D converter or telemetry */ struct ao_adc { uint16_t tick; /* tick when the sample was read */ @@ -168,6 +161,20 @@ struct ao_adc { int16_t sense_m; /* main continuity sense */ }; +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#if HAS_ADC +/* + * ao_adc.c + */ + +#define AO_ADC_RING 32 +#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) +#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) + + /* * A/D data is stored in a ring, with the next sample to be written * at ao_adc_head @@ -188,15 +195,16 @@ 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 ao_adc_init(void); +#endif /* HAS_ADC */ + /* * ao_beep.c */ @@ -696,13 +704,16 @@ ao_dbg_init(void); * ao_serial.c */ -#if !AO_NO_SERIAL_ISR +#ifndef HAS_SERIAL_1 +#error Please define HAS_SERIAL_1 +#endif + +#if HAS_SERIAL_1 void ao_serial_rx1_isr(void) interrupt 3; void ao_serial_tx1_isr(void) interrupt 14; -#endif char ao_serial_getchar(void) __critical; @@ -719,6 +730,7 @@ ao_serial_set_speed(uint8_t speed); void ao_serial_init(void); +#endif /* * ao_gps.c diff --git a/src/ao_adc.c b/src/ao_adc.c index 2b972e6c..50f96848 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -16,6 +16,7 @@ */ #include "ao.h" +#include "ao_pins.h" volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; volatile __data uint8_t ao_adc_head; @@ -52,11 +53,13 @@ ao_adc_isr(void) interrupt 1 a[0] = ADCL; a[1] = ADCH; if (sequence < 5) { +#if HAS_EXTERNAL_TEMP == 0 /* start next channel conversion */ /* v0.2 replaces external temp sensor with internal one */ if (sequence == 1) ADCCON3 = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP; else +#endif ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | (sequence + 1); } else { /* record this conversion series */ @@ -86,7 +89,9 @@ ao_adc_init(void) { ADCCFG = ((1 << 0) | /* acceleration */ (1 << 1) | /* pressure */ -/* (1 << 2) | v0.1 temperature */ +#if HAS_EXTERNAL_TEMP + (1 << 2) | /* v0.1 temperature */ +#endif (1 << 3) | /* battery voltage */ (1 << 4) | /* drogue sense */ (1 << 5)); /* main sense */ diff --git a/src/ao_config.c b/src/ao_config.c index 4349bca8..f8ea27fe 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -38,18 +38,22 @@ __xdata uint8_t ao_config_mutex; */ const uint32_t ao_radio_cal = 1186611; +#if HAS_EEPROM static void _ao_config_put(void) { ao_ee_write_config((uint8_t *) &ao_config, sizeof (ao_config)); } +#endif static void _ao_config_get(void) { if (ao_config_loaded) return; +#if HAS_EEPROM ao_ee_read_config((uint8_t *) &ao_config, sizeof (ao_config)); +#endif if (ao_config.major != AO_CONFIG_MAJOR) { ao_config.major = AO_CONFIG_MAJOR; ao_config.minor = AO_CONFIG_MINOR; @@ -149,6 +153,8 @@ ao_config_radio_channel_set(void) __reentrant ao_config_radio_channel_show(); } +#if HAS_ADC + void ao_config_main_deploy_show(void) __reentrant { @@ -259,6 +265,8 @@ ao_config_apogee_delay_set(void) __reentrant ao_config_apogee_delay_show(); } +#endif /* HAS_ADC */ + void ao_config_radio_cal_show(void) __reentrant { @@ -296,25 +304,31 @@ void ao_config_write(void) __reentrant; __code struct ao_config_var ao_config_vars[] = { +#if HAS_ADC { 'm', ao_config_main_deploy_set, ao_config_main_deploy_show, "m Set height above launch for main deploy (in meters)" }, { 'd', ao_config_apogee_delay_set, ao_config_apogee_delay_show, "d Set apogee igniter delay (in seconds)" }, +#endif /* HAS_ADC */ { 'r', ao_config_radio_channel_set, ao_config_radio_channel_show, "r Set radio channel (freq = 434.550 + channel * .1)" }, { 'c', ao_config_callsign_set, ao_config_callsign_show, "c Set callsign broadcast in each packet (8 char max)" }, +#if HAS_ADC { 'a', ao_config_accel_calibrate_set, ao_config_accel_calibrate_show, "a <+g> <-g> Set accelerometer calibration (0 for auto)" }, +#endif /* HAS_ADC */ { 'f', ao_config_radio_cal_set, ao_config_radio_cal_show, "f Set radio calibration value (cal = rf/(xtal/2^16))" }, { 's', ao_config_show, ao_config_show, "s Show current config values" }, +#if HAS_EEPROM { 'w', ao_config_write, ao_config_write, "w Write current values to eeprom" }, +#endif { '?', ao_config_help, ao_config_help, "? Show available config variables" }, - { 0, ao_config_main_deploy_set, ao_config_main_deploy_show, + { 0, ao_config_help, ao_config_help, NULL }, }; @@ -359,6 +373,7 @@ ao_config_show(void) __reentrant (*ao_config_vars[cmd].show)(); } +#if HAS_EEPROM void ao_config_write(void) __reentrant { @@ -370,6 +385,7 @@ ao_config_write(void) __reentrant } ao_mutex_put(&ao_config_mutex); } +#endif __code struct ao_cmds ao_config_cmds[] = { { 'c', ao_config_set, "c Set config variable (? for help, s to show)" }, diff --git a/src/ao_dbg.c b/src/ao_dbg.c index b218897c..d0633f92 100644 --- a/src/ao_dbg.c +++ b/src/ao_dbg.c @@ -16,19 +16,12 @@ */ #include "ao.h" - -#define DBG_CLOCK (1 << 3) -#define DBG_DATA (1 << 4) -#define DBG_RESET_N (1 << 5) - -#define DBG_CLOCK_PIN (P0_3) -#define DBG_DATA_PIN (P0_4) -#define DBG_RESET_N_PIN (P0_5) +#include "ao_pins.h" static void ao_dbg_send_bits(uint8_t msk, uint8_t val) __reentrant { - P0 = (P0 & ~msk) | (val & msk); + DBG_PORT = (DBG_PORT & ~msk) | (val & msk); _asm nop nop @@ -40,8 +33,8 @@ ao_dbg_send_byte(uint8_t byte) { __xdata uint8_t b, d; - P0 |= DBG_DATA; - P0DIR |= DBG_DATA; + DBG_PORT |= DBG_DATA; + DBG_PORT_DIR |= DBG_DATA; for (b = 0; b < 8; b++) { d = 0; if (byte & 0x80) @@ -50,7 +43,7 @@ ao_dbg_send_byte(uint8_t byte) ao_dbg_send_bits(DBG_CLOCK|DBG_DATA, DBG_CLOCK|d); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA, 0 |d); } - P0DIR &= ~DBG_DATA; + DBG_PORT_DIR &= ~DBG_DATA; } uint8_t @@ -171,20 +164,15 @@ ao_dbg_read_byte(void) static void ao_dbg_set_pins(void) { - /* Disable peripheral use of P0 */ - ADCCFG = 0; - P0SEL = 0; - - - /* make P0_4 tri-state */ - P0INP = DBG_DATA; - P2INP &= ~(P2INP_PDUP0_PULL_DOWN); + /* make DBG_DATA tri-state */ + DBG_PORT_INP |= DBG_DATA; /* Raise RESET_N and CLOCK */ - P0 = DBG_RESET_N | DBG_CLOCK; + DBG_PORT |= DBG_RESET_N | DBG_CLOCK; /* RESET_N and CLOCK are outputs now */ - P0DIR = DBG_RESET_N | DBG_CLOCK; + DBG_PORT_DIR |= DBG_RESET_N | DBG_CLOCK; + DBG_PORT_DIR &= ~DBG_DATA; } static void diff --git a/src/ao_host.h b/src/ao_host.h index 6b42f9f9..fa03a910 100644 --- a/src/ao_host.h +++ b/src/ao_host.h @@ -117,30 +117,6 @@ struct ao_cmds { }; -static int16_t altitude_table[2048] = { -#include "altitude.h" -}; - -int16_t -ao_pres_to_altitude(int16_t pres) __reentrant -{ - pres = pres >> 4; - if (pres < 0) pres = 0; - if (pres > 2047) pres = 2047; - return altitude_table[pres]; -} - -int16_t -ao_altitude_to_pres(int16_t alt) __reentrant -{ - int16_t pres; - - for (pres = 0; pres < 2047; pres++) - if (altitude_table[pres] <= alt) - break; - return pres << 4; -} - struct ao_config { uint16_t main_deploy; int16_t accel_zero_g; diff --git a/src/ao_packet.c b/src/ao_packet.c index 98fdcb90..dcd1647c 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -113,6 +113,11 @@ ao_packet_recv(void) return dma_done; } +#ifndef PACKET_HAS_MASTER +#define PACKET_HAS_MASTER 1 +#endif + +#if PACKET_HAS_MASTER void ao_packet_flush(void) { @@ -122,12 +127,15 @@ ao_packet_flush(void) if (ao_packet_tx_used && ao_packet_master_sleeping) ao_wake_task(&ao_packet_task); } +#endif /* PACKET_HAS_MASTER */ void ao_packet_putchar(char c) __reentrant { while (ao_packet_tx_used == AO_PACKET_MAX && ao_packet_enable) { +#if PACKET_HAS_MASTER ao_packet_flush(); +#endif ao_sleep(&tx_data); } diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index 122c4da0..4c947fbf 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -56,5 +56,5 @@ ao_packet_slave_init(void) { ao_add_stdio(ao_packet_pollchar, ao_packet_putchar, - ao_packet_flush); + NULL); } diff --git a/src/ao_pins.h b/src/ao_pins.h new file mode 100644 index 00000000..84d8a1a1 --- /dev/null +++ b/src/ao_pins.h @@ -0,0 +1,144 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#if defined(TELEMETRUM_V_0_2) + #define HAS_SERIAL_1 1 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define LEDS_AVAILABLE (AO_LED_RED) + #define HAS_EXTERNAL_TEMP 0 +#endif + +#if defined(TELEDONGLE_V_0_2) + #define HAS_SERIAL_1 0 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define LEDS_AVAILABLE (AO_LED_RED) +#endif + +#if defined(TELEMETRUM_V_0_1) + #define HAS_SERIAL_1 1 + #define HAS_ADC 1 + #define HAS_DBG 0 + #define HAS_EEPROM 1 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 1 +#endif + +#if defined(TELEDONGLE_V_0_1) + #define HAS_SERIAL_1 0 + #define HAS_ADC 0 + #define HAS_DBG 0 + #define HAS_EEPROM 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) +#endif + +#if defined(TIDONGLE) + #define HAS_SERIAL_1 0 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define LEDS_AVAILABLE (AO_LED_RED) +#endif + +#if DBG_ON_P1 + + #define DBG_CLOCK (1 << 4) /* mi0 */ + #define DBG_DATA (1 << 5) /* mo0 */ + #define DBG_RESET_N (1 << 3) /* c0 */ + + #define DBG_CLOCK_PIN (P1_4) + #define DBG_DATA_PIN (P1_5) + #define DBG_RESET_N_PIN (P1_3) + + #define DBG_PORT_NUM 1 + #define DBG_PORT P1 + #define DBG_PORT_SEL P1SEL + #define DBG_PORT_INP P1INP + #define DBG_PORT_DIR P1DIR + +#endif /* DBG_ON_P1 */ + +#if DBG_ON_P0 + + #define DBG_CLOCK (1 << 3) + #define DBG_DATA (1 << 4) + #define DBG_RESET_N (1 << 5) + + #define DBG_CLOCK_PIN (P0_3) + #define DBG_DATA_PIN (P0_4) + #define DBG_RESET_N_PIN (P0_5) + + #define DBG_PORT_NUM 0 + #define DBG_PORT P0 + #define DBG_PORT_SEL P0SEL + #define DBG_PORT_INP P0INP + #define DBG_PORT_DIR P0DIR + +#endif /* DBG_ON_P0 */ + +#ifndef HAS_SERIAL_1 +#error Please define HAS_SERIAL_1 +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#ifndef HAS_EEPROM +#error Please define HAS_EEPROM +#endif + +#ifndef HAS_DBG +#error Please define HAS_DBG +#endif + +#ifndef PACKET_HAS_MASTER +#error Please define PACKET_HAS_MASTER +#endif + +#ifndef PACKET_HAS_SLAVE +#error Please define PACKET_HAS_SLAVE +#endif + +#endif /* _AO_PINS_H_ */ diff --git a/src/ao_reboot.c b/src/ao_reboot.c new file mode 100644 index 00000000..82ea32e0 --- /dev/null +++ b/src/ao_reboot.c @@ -0,0 +1,28 @@ +/* + * 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" + +/* Use the watchdog timer to force a complete reboot + */ +void +ao_reboot(void) +{ + WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_32768; + ao_sleep(AO_SEC_TO_TICKS(2)); + ao_panic(AO_PANIC_REBOOT); +} diff --git a/src/ao_stdio.c b/src/ao_stdio.c index 7bc416e1..8add30b8 100644 --- a/src/ao_stdio.c +++ b/src/ao_stdio.c @@ -38,7 +38,8 @@ putchar(char c) void flush(void) { - stdios[ao_cur_stdio].flush(); + if (stdios[ao_cur_stdio].flush) + stdios[ao_cur_stdio].flush(); } __xdata uint8_t ao_stdin_ready; diff --git a/src/ao_teledongle.c b/src/ao_teledongle.c index e4828d80..b07b1746 100644 --- a/src/ao_teledongle.c +++ b/src/ao_teledongle.c @@ -15,8 +15,6 @@ * 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 @@ -35,6 +33,9 @@ main(void) ao_radio_init(); ao_packet_slave_init(); ao_packet_master_init(); +#if HAS_DBG + ao_dbg_init(); +#endif ao_config_init(); ao_start_scheduler(); } diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 89743837..fd0adae8 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -16,6 +16,7 @@ */ #include "ao.h" +#include "ao_pins.h" /* stub so as telemetrum doesn't have monitor mode */ void @@ -31,7 +32,7 @@ main(void) /* Turn on the red LED until the system is stable */ - ao_led_init(AO_LED_RED); + ao_led_init(LEDS_AVAILABLE); ao_led_on(AO_LED_RED); /* A hack -- look at the SPI clock pin, if it's sitting at @@ -59,6 +60,9 @@ main(void) ao_radio_init(); ao_packet_slave_init(); ao_igniter_init(); +#if HAS_DBG + ao_dbg_init(); +#endif ao_config_init(); ao_start_scheduler(); } diff --git a/src/ao_timer.c b/src/ao_timer.c index e81f937d..d1731475 100644 --- a/src/ao_timer.c +++ b/src/ao_timer.c @@ -36,24 +36,30 @@ ao_delay(uint16_t ticks) #define T1_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ #define T1_SAMPLE_TIME 30000 /* 3e6/30000 = 100 */ +#if HAS_ADC volatile __data uint8_t ao_adc_interval = 1; volatile __data uint8_t ao_adc_count; +#endif void ao_timer_isr(void) interrupt 9 { ++ao_tick_count; +#if HAS_ADC if (++ao_adc_count == ao_adc_interval) { ao_adc_count = 0; ao_adc_poll(); } +#endif } +#if HAS_ADC void ao_timer_set_adc_interval(uint8_t interval) __critical { ao_adc_interval = interval; ao_adc_count = 0; } +#endif void ao_timer_init(void) diff --git a/src/teledongle-v0.1/Makefile b/src/teledongle-v0.1/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/teledongle-v0.1/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/teledongle-v0.1/Makefile.defs b/src/teledongle-v0.1/Makefile.defs new file mode 100644 index 00000000..3526b4c5 --- /dev/null +++ b/src/teledongle-v0.1/Makefile.defs @@ -0,0 +1,9 @@ +PROG = teledongle-v0.1.ihx + +SRC = \ + $(TD_SRC) \ + $(DBG_SRC) + +PRODUCT=TeleDongle-v0.1 + +CFLAGS += -DTELEDONGLE_V_0_1 -I. diff --git a/src/teledongle-v0.2/Makefile b/src/teledongle-v0.2/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/teledongle-v0.2/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/teledongle-v0.2/Makefile.defs b/src/teledongle-v0.2/Makefile.defs new file mode 100644 index 00000000..faad4dce --- /dev/null +++ b/src/teledongle-v0.2/Makefile.defs @@ -0,0 +1,9 @@ +PROG = teledongle-v0.2.ihx + +SRC = \ + $(TD_SRC) \ + $(DBG_SRC) + +PRODUCT=TeleDongle-v0.2 + +CFLAGS += -DTELEDONGLE_V_0_2 -I. diff --git a/src/telemetrum-v0.1-sirf/Makefile b/src/telemetrum-v0.1-sirf/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telemetrum-v0.1-sirf/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/telemetrum-v0.1-sirf/Makefile.defs b/src/telemetrum-v0.1-sirf/Makefile.defs new file mode 100644 index 00000000..1157d679 --- /dev/null +++ b/src/telemetrum-v0.1-sirf/Makefile.defs @@ -0,0 +1,11 @@ +PROG = telemetrum-v0.1-sirf.ihx + +SRC = \ + $(TM_BASE_SRC) \ + $(EE_DRIVER_SRC) \ + $(SIRF_DRIVER_SRC) \ + $(DBG_SRC) + +PRODUCT=TeleMetrum-v0.1-SiRF + +CFLAGS += -DTELEMETRUM_V_0_1 -I. diff --git a/src/telemetrum-v0.1-sky/Makefile b/src/telemetrum-v0.1-sky/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telemetrum-v0.1-sky/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/telemetrum-v0.1-sky/Makefile.defs b/src/telemetrum-v0.1-sky/Makefile.defs new file mode 100644 index 00000000..ff7fd1bf --- /dev/null +++ b/src/telemetrum-v0.1-sky/Makefile.defs @@ -0,0 +1,11 @@ +PROG = telemetrum-v0.1-sky.ihx + +SRC = \ + $(TM_BASE_SRC) \ + $(EE_DRIVER_SRC) \ + $(SKY_DRIVER_SRC) \ + $(DBG_SRC) + +PRODUCT=TeleMetrum-v0.1 + +CFLAGS += -DTELEMETRUM_V_0_1 -I. diff --git a/src/telemetrum-v0.2/Makefile b/src/telemetrum-v0.2/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telemetrum-v0.2/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/telemetrum-v0.2/Makefile.defs b/src/telemetrum-v0.2/Makefile.defs new file mode 100644 index 00000000..d5b0a962 --- /dev/null +++ b/src/telemetrum-v0.2/Makefile.defs @@ -0,0 +1,11 @@ +PROG = telemetrum-v0.2.ihx + +SRC = \ + $(TM_BASE_SRC) \ + $(FLASH_DRIVER_SRC) \ + $(SKY_DRIVER_SRC) \ + $(DBG_SRC) + +PRODUCT=TeleMetrum-v0.2 + +CFLAGS += -DTELEMETRUM_V_0_2 -I. diff --git a/src/test/Makefile b/src/test/Makefile new file mode 100644 index 00000000..f6e9b9f5 --- /dev/null +++ b/src/test/Makefile @@ -0,0 +1,24 @@ +vpath % .. + +PROGS=ao_flight_test ao_gps_test ao_gps_test_skytraq ao_convert_test + +CFLAGS=-I.. -I. + +all: $(PROGS) + +clean: + rm -f $(PROGS) + +install: + +ao_flight_test: ao_flight_test.c ao_flight_test.c ao_host.h + cc -g -o $@ $< + +ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h + cc -g -o $@ $< + +ao_gps_test_skytraq: ao_gps_test_skytraq.c ao_gps_skytraq.c ao_gps_print.c ao_host.h + cc -g -o $@ $< + +ao_convert_test: ao_convert_test.c ao_convert.c altitude.h + cc -g -o $@ $< diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/tidongle/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/tidongle/Makefile.defs b/src/tidongle/Makefile.defs new file mode 100644 index 00000000..16762940 --- /dev/null +++ b/src/tidongle/Makefile.defs @@ -0,0 +1,8 @@ +PROG = tidongle.ihx + +SRC = \ + $(TI_SRC) + +PRODUCT=TIDongle + +CFLAGS += -DTIDONGLE -I. -- cgit v1.2.3 From 004c2a9b7a4b44ef71ca60482573e8e9d8c6ce93 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Feb 2010 20:36:08 -0800 Subject: Update .gitignore files --- .gitignore | 7 ++----- debian/.gitignore | 6 ++++++ src/teledongle-v0.1/.gitignore | 2 ++ src/teledongle-v0.2/.gitignore | 2 ++ src/telemetrum-v0.1-sirf/.gitignore | 2 ++ src/telemetrum-v0.1-sky/.gitignore | 2 ++ src/telemetrum-v0.2/.gitignore | 2 ++ src/test/.gitignore | 4 ++++ src/tidongle/.gitignore | 2 ++ 9 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 debian/.gitignore create mode 100644 src/teledongle-v0.1/.gitignore create mode 100644 src/teledongle-v0.2/.gitignore create mode 100644 src/telemetrum-v0.1-sirf/.gitignore create mode 100644 src/telemetrum-v0.1-sky/.gitignore create mode 100644 src/telemetrum-v0.2/.gitignore create mode 100644 src/test/.gitignore create mode 100644 src/tidongle/.gitignore (limited to 'src') diff --git a/.gitignore b/.gitignore index a6f94439..eafee20f 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,8 @@ config.h.in config.h.in~ config.log config.status +build-stamp +configure-stamp configure depcomp install-sh @@ -47,8 +49,3 @@ Makefile.in missing stamp-h1 tags -teledongle -telemetrum-sirf -telemetrum-sky -teleterra -tidongle diff --git a/debian/.gitignore b/debian/.gitignore new file mode 100644 index 00000000..850d7c20 --- /dev/null +++ b/debian/.gitignore @@ -0,0 +1,6 @@ +altos.debhelper.log +altos.postinst.debhelper +altos.postrm.debhelper +altos.substvars +altos +files diff --git a/src/teledongle-v0.1/.gitignore b/src/teledongle-v0.1/.gitignore new file mode 100644 index 00000000..96c802bd --- /dev/null +++ b/src/teledongle-v0.1/.gitignore @@ -0,0 +1,2 @@ +teledongle-v0.1 +ao_product.h diff --git a/src/teledongle-v0.2/.gitignore b/src/teledongle-v0.2/.gitignore new file mode 100644 index 00000000..af79a766 --- /dev/null +++ b/src/teledongle-v0.2/.gitignore @@ -0,0 +1,2 @@ +teledongle-v0.2 +ao_product.h diff --git a/src/telemetrum-v0.1-sirf/.gitignore b/src/telemetrum-v0.1-sirf/.gitignore new file mode 100644 index 00000000..6d584f36 --- /dev/null +++ b/src/telemetrum-v0.1-sirf/.gitignore @@ -0,0 +1,2 @@ +telemetrum-v0.1-sirf +ao_product.h diff --git a/src/telemetrum-v0.1-sky/.gitignore b/src/telemetrum-v0.1-sky/.gitignore new file mode 100644 index 00000000..5a9fafb5 --- /dev/null +++ b/src/telemetrum-v0.1-sky/.gitignore @@ -0,0 +1,2 @@ +telemetrum-v0.1-sky +ao_product.h diff --git a/src/telemetrum-v0.2/.gitignore b/src/telemetrum-v0.2/.gitignore new file mode 100644 index 00000000..76228093 --- /dev/null +++ b/src/telemetrum-v0.2/.gitignore @@ -0,0 +1,2 @@ +telemetrum-v0.2 +ao_product.h diff --git a/src/test/.gitignore b/src/test/.gitignore new file mode 100644 index 00000000..54b00096 --- /dev/null +++ b/src/test/.gitignore @@ -0,0 +1,4 @@ +ao_flight_test +ao_gps_test +ao_gps_test_skytraq +ao_convert_test diff --git a/src/tidongle/.gitignore b/src/tidongle/.gitignore new file mode 100644 index 00000000..3323f640 --- /dev/null +++ b/src/tidongle/.gitignore @@ -0,0 +1,2 @@ +tidongle +ao_product.h -- cgit v1.2.3 From 18eeb79026f7e5c54bf99435537c024427011a36 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Feb 2010 21:05:45 -0800 Subject: Quiet make output. This borrows ideas from the notmuch project to reduce the command line clutter seen when compiling or linking stuff. Signed-off-by: Keith Packard --- src/Makefile.proto | 27 ++++++++++++++++++++------- src/teledongle-v0.1/Makefile.defs | 3 +-- src/teledongle-v0.2/Makefile.defs | 3 +-- src/telemetrum-v0.1-sirf/Makefile.defs | 3 +-- src/telemetrum-v0.1-sky/Makefile.defs | 3 +-- src/telemetrum-v0.2/Makefile.defs | 3 +-- src/tidongle/Makefile.defs | 2 +- 7 files changed, 26 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index 958b7572..c98abca6 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -174,6 +174,10 @@ TD_SRC = \ include Makefile.defs +CFLAGS += $(PRODUCT_DEF) -I. + +NICKLE=nickle + REL=$(SRC:.c=.rel) ao_product.rel ADB=$(REL:.rel=.adb) ASM=$(REL:.rel=.asm) @@ -188,29 +192,38 @@ PMAP=$(PROG:.ihx=.map) PMEM=$(PROG:.ihx=.mem) PAOM=$(PROG:.ihx=) +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + %.rel : %.c $(INC) - $(CC) -c $(CFLAGS) -o$@ $< + $(call quiet,CC,$(PRODUCT_DEF)) $(CFLAGS) -c -o$@ $< -all: $(PROG) +all: ../$(PROG) -$(PROG): $(REL) Makefile Makefile.defs ../Makefile.proto - $(CC) $(LDFLAGS) $(CFLAGS) -o $@ $(REL) +../$(PROG): $(REL) Makefile Makefile.defs ../Makefile.proto + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && mv $(PROG) .. ../altitude.h: make-altitude nickle $< > $@ ao_product.h: ao-make-product.5c - nickle $< -m altusmetrum.org -p $(PRODUCT) -v $(VERSION) > $@ + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -p $(PRODUCT) -v $(VERSION) > $@ ao_product.rel: ao_product.c ao_product.h - $(CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< + $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< distclean: clean clean: rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) rm -f ao_product.h + rm -f ../$(PROG) install: diff --git a/src/teledongle-v0.1/Makefile.defs b/src/teledongle-v0.1/Makefile.defs index 3526b4c5..06559b28 100644 --- a/src/teledongle-v0.1/Makefile.defs +++ b/src/teledongle-v0.1/Makefile.defs @@ -5,5 +5,4 @@ SRC = \ $(DBG_SRC) PRODUCT=TeleDongle-v0.1 - -CFLAGS += -DTELEDONGLE_V_0_1 -I. +PRODUCT_DEF=-DTELEDONGLE_V_0_1 diff --git a/src/teledongle-v0.2/Makefile.defs b/src/teledongle-v0.2/Makefile.defs index faad4dce..23694fda 100644 --- a/src/teledongle-v0.2/Makefile.defs +++ b/src/teledongle-v0.2/Makefile.defs @@ -5,5 +5,4 @@ SRC = \ $(DBG_SRC) PRODUCT=TeleDongle-v0.2 - -CFLAGS += -DTELEDONGLE_V_0_2 -I. +PRODUCT_DEF=-DTELEDONGLE_V_0_2 diff --git a/src/telemetrum-v0.1-sirf/Makefile.defs b/src/telemetrum-v0.1-sirf/Makefile.defs index 1157d679..7306683e 100644 --- a/src/telemetrum-v0.1-sirf/Makefile.defs +++ b/src/telemetrum-v0.1-sirf/Makefile.defs @@ -7,5 +7,4 @@ SRC = \ $(DBG_SRC) PRODUCT=TeleMetrum-v0.1-SiRF - -CFLAGS += -DTELEMETRUM_V_0_1 -I. +PRODUCT_DEF=-DTELEMETRUM_V_0_1 diff --git a/src/telemetrum-v0.1-sky/Makefile.defs b/src/telemetrum-v0.1-sky/Makefile.defs index ff7fd1bf..df475baa 100644 --- a/src/telemetrum-v0.1-sky/Makefile.defs +++ b/src/telemetrum-v0.1-sky/Makefile.defs @@ -7,5 +7,4 @@ SRC = \ $(DBG_SRC) PRODUCT=TeleMetrum-v0.1 - -CFLAGS += -DTELEMETRUM_V_0_1 -I. +PRODUCT_DEF=-DTELEMETRUM_V_0_1 diff --git a/src/telemetrum-v0.2/Makefile.defs b/src/telemetrum-v0.2/Makefile.defs index d5b0a962..eb11e7dc 100644 --- a/src/telemetrum-v0.2/Makefile.defs +++ b/src/telemetrum-v0.2/Makefile.defs @@ -7,5 +7,4 @@ SRC = \ $(DBG_SRC) PRODUCT=TeleMetrum-v0.2 - -CFLAGS += -DTELEMETRUM_V_0_2 -I. +PRODUCT_DEF=-DTELEMETRUM_V_0_2 diff --git a/src/tidongle/Makefile.defs b/src/tidongle/Makefile.defs index 16762940..5b910b9b 100644 --- a/src/tidongle/Makefile.defs +++ b/src/tidongle/Makefile.defs @@ -5,4 +5,4 @@ SRC = \ PRODUCT=TIDongle -CFLAGS += -DTIDONGLE -I. +PRODUCT_DEF=-DTIDONGLE -- cgit v1.2.3 From a5215c2bd9249a285fc834db0c453fb3e7daed87 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Feb 2010 21:20:05 -0800 Subject: Add back stack size checking to altos linking phase This verifies that the stack start specified during the compile will work with the resulting program Signed-off-by: Keith Packard --- src/Makefile.proto | 2 ++ src/check-stack | 7 +++---- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index c98abca6..4f4252ad 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -177,6 +177,7 @@ include Makefile.defs CFLAGS += $(PRODUCT_DEF) -I. NICKLE=nickle +CHECK_STACK=sh ../check-stack REL=$(SRC:.c=.rel) ao_product.rel ADB=$(REL:.rel=.adb) @@ -207,6 +208,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile Makefile.defs ../Makefile.proto $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && mv $(PROG) .. + $(call quiet,CHECK_STACK) ../ao.h $(@F:.ihx=.mem) ../altitude.h: make-altitude nickle $< > $@ diff --git a/src/check-stack b/src/check-stack index 82680b88..1e8044e0 100755 --- a/src/check-stack +++ b/src/check-stack @@ -2,12 +2,11 @@ HEADER=$1 MEM=$2 -HEADER_STACK=`awk '/#define AO_STACK_START/ {print $3}' $HEADER | nickle` -MEM_STACK=`awk '/Stack starts at/ {print $4}' $MEM | nickle` +HEADER_STACK=`awk '/#define AO_STACK_START/ {print strtonum($3)}' $HEADER` +MEM_STACK=`awk '/Stack starts at/ {print strtonum ($4)}' $MEM` if [ "$HEADER_STACK" -lt "$MEM_STACK" ]; then - MIN=0x`nickle -e "$MEM_STACK # 16"` - echo "Set AO_STACK_START to at least $MIN" + echo $MEM_STACK | awk '{ printf ("Set AO_STACK_START to at least 0x%x\n", $1); }' exit 1 else exit 0 -- cgit v1.2.3 From 82fdbfe1229d1ea5e6906ea240d54b3da73d9a69 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Feb 2010 21:35:43 -0800 Subject: Must install .map files for ao-load to work ao-load uses the .map files to rewrite the serial number and other config parameters into the program flash. Signed-off-by: Keith Packard --- src/Makefile.proto | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index 4f4252ad..6cb6e0de 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -207,8 +207,8 @@ quiet ?= $($1) all: ../$(PROG) ../$(PROG): $(REL) Makefile Makefile.defs ../Makefile.proto - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && mv $(PROG) .. - $(call quiet,CHECK_STACK) ../ao.h $(@F:.ihx=.mem) + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && mv $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../ao.h $(PMEM) ../altitude.h: make-altitude nickle $< > $@ -- cgit v1.2.3 From f1956ebadd7bf46b84a05a0c383b6404ca26b344 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Feb 2010 15:10:16 -0800 Subject: Leave .ihx files in the build directory too - easier to debug that way sdcdb wants the .ihx and .cdb files in the same directory, so humor it by copying the .ihx files to the src directory instead of moving them. Signed-off-by: Keith Packard --- src/Makefile.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index 6cb6e0de..106333a6 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -207,7 +207,7 @@ quiet ?= $($1) all: ../$(PROG) ../$(PROG): $(REL) Makefile Makefile.defs ../Makefile.proto - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && mv $(PROG) $(PMAP) .. + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. $(call quiet,CHECK_STACK) ../ao.h $(PMEM) ../altitude.h: make-altitude -- cgit v1.2.3 From 1d6d8d76ec65373ffee70add75d183f5c4168f61 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Feb 2010 15:11:44 -0800 Subject: Eliminate deadlock when writing config from radio link Writing the 'Saved\r\n' string would fill the packet buffer and cause a flush to occur, which would need to wait for the radio link to receive and transmit a packet. The radio link always re-fetches the radio channel number when lighting up the radio, so it need to look in the config space. If the config mutex was held by the config writing process while the radio was trying to get the channel number, then we'd get a deadlock. Signed-off-by: Keith Packard --- src/ao_config.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_config.c b/src/ao_config.c index f8ea27fe..8df994a6 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -377,13 +377,18 @@ ao_config_show(void) __reentrant void ao_config_write(void) __reentrant { + uint8_t saved = 0; ao_mutex_get(&ao_config_mutex); if (ao_config_dirty) { _ao_config_put(); ao_config_dirty = 0; - printf("Saved\n"); + saved = 1; } ao_mutex_put(&ao_config_mutex); + if (saved) + puts("Saved"); + else + puts("Nothing to save"); } #endif -- cgit v1.2.3 From 7aab73a265841aac817ea34235dd1eb819debf76 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Feb 2010 15:14:04 -0800 Subject: Fix up LED colors for each product. Different products assign different color LEDs to the two available LED drivers (P1_0, P1_1). Make the LED color pin assignments per-product (in ao_pins.h), then deal with not always having a green LED. Signed-off-by: Keith Packard --- src/ao.h | 2 -- src/ao_led.c | 2 -- src/ao_packet.c | 4 ++++ src/ao_pins.h | 10 +++++++++- src/ao_teledongle.c | 2 +- 5 files changed, 14 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index b43f5ecd..aefefa46 100644 --- a/src/ao.h +++ b/src/ao.h @@ -263,8 +263,6 @@ ao_beep_init(void); */ #define AO_LED_NONE 0 -#define AO_LED_GREEN 1 -#define AO_LED_RED 2 /* Turn on the specified LEDs */ void diff --git a/src/ao_led.c b/src/ao_led.c index 6c698b4b..5beed58d 100644 --- a/src/ao_led.c +++ b/src/ao_led.c @@ -17,8 +17,6 @@ #include "ao.h" -#define AO_LED_ALL (AO_LED_GREEN|AO_LED_RED) - __pdata uint8_t ao_led_enable; void diff --git a/src/ao_packet.c b/src/ao_packet.c index dcd1647c..d52f2a68 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -67,7 +67,9 @@ ao_packet_recv(void) { uint8_t dma_done; +#ifdef AO_LED_GREEN ao_led_on(AO_LED_GREEN); +#endif ao_radio_get(); ao_dma_set_transfer(ao_radio_dma, &RFDXADDR, @@ -86,7 +88,9 @@ ao_packet_recv(void) ao_radio_abort(); dma_done = ao_radio_dma_done; ao_radio_put(); +#ifdef AO_LED_GREEN ao_led_off(AO_LED_GREEN); +#endif if (dma_done & AO_DMA_DONE) { if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) diff --git a/src/ao_pins.h b/src/ao_pins.h index 84d8a1a1..771d9c7f 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -28,6 +28,7 @@ #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 + #define AO_LED_RED 1 #define LEDS_AVAILABLE (AO_LED_RED) #define HAS_EXTERNAL_TEMP 0 #endif @@ -41,7 +42,9 @@ #define DBG_ON_P0 0 #define PACKET_HAS_MASTER 1 #define PACKET_HAS_SLAVE 0 - #define LEDS_AVAILABLE (AO_LED_RED) + #define AO_LED_RED 1 + #define AO_LED_GREEN 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #endif #if defined(TELEMETRUM_V_0_1) @@ -53,6 +56,8 @@ #define DBG_ON_P0 1 #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define HAS_EXTERNAL_TEMP 1 #endif @@ -66,6 +71,8 @@ #define DBG_ON_P0 1 #define PACKET_HAS_MASTER 1 #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #endif @@ -78,6 +85,7 @@ #define DBG_ON_P0 1 #define PACKET_HAS_MASTER 1 #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 #define LEDS_AVAILABLE (AO_LED_RED) #endif diff --git a/src/ao_teledongle.c b/src/ao_teledongle.c index b07b1746..505dc0cb 100644 --- a/src/ao_teledongle.c +++ b/src/ao_teledongle.c @@ -23,7 +23,7 @@ main(void) ao_clock_init(); /* Turn on the LED until the system is stable */ - ao_led_init(AO_LED_RED|AO_LED_GREEN); + ao_led_init(LEDS_AVAILABLE); ao_led_on(AO_LED_RED); ao_timer_init(); ao_cmd_init(); -- cgit v1.2.3 From b0b99f30c4e00689e9faceb363a5c7284541c6be Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 4 Apr 2010 19:48:50 -0700 Subject: Make ao_radio_idle keep trying to get the radio to idle. Attempting to abort a radio operation could lead to a hang if the user of the radio jumped in and started using it again before the task attempting to abort woke up. This change just keeps smacking the radio until the radio goes idle long enough to detect it. --- src/ao_radio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_radio.c b/src/ao_radio.c index bb19c6a9..0849349e 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -317,8 +317,8 @@ ao_radio_idle(void) { if (RF_MARCSTATE != RF_MARCSTATE_IDLE) { - RFST = RFST_SIDLE; do { + RFST = RFST_SIDLE; ao_yield(); } while (RF_MARCSTATE != RF_MARCSTATE_IDLE); } -- cgit v1.2.3 From 6251e89c6eea655769f77bc18e98e79c99cf3cad Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 4 Apr 2010 19:54:46 -0700 Subject: Don't abort the radio when enabling telemetry monitoring If telemetry monitoring is already on, then there isn't any point, and if it's not on, then presumably there isn't any radio work to abort. Signed-off-by: Keith Packard --- src/ao_monitor.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_monitor.c b/src/ao_monitor.c index 628b6e67..f2f3fc2e 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -80,7 +80,8 @@ ao_set_monitor(uint8_t monitoring) { ao_monitoring = monitoring; ao_wakeup(&ao_monitoring); - ao_radio_abort(); + if (!ao_monitoring) + ao_radio_abort(); } static void -- cgit v1.2.3 From c28646d72005daeadb70b95fd3b0050bd752cc55 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 4 Apr 2010 20:55:30 -0700 Subject: Switch TeleMetrum from v0.2 to v1.0 Signed-off-by: Keith Packard --- src/Makefile | 2 +- src/ao_pins.h | 2 +- src/telemetrum-v0.2/.gitignore | 2 -- src/telemetrum-v0.2/Makefile | 1 - src/telemetrum-v0.2/Makefile.defs | 10 ---------- src/telemetrum-v1.0/.gitignore | 2 ++ src/telemetrum-v1.0/Makefile | 1 + src/telemetrum-v1.0/Makefile.defs | 10 ++++++++++ 8 files changed, 15 insertions(+), 15 deletions(-) delete mode 100644 src/telemetrum-v0.2/.gitignore delete mode 100644 src/telemetrum-v0.2/Makefile delete mode 100644 src/telemetrum-v0.2/Makefile.defs create mode 100644 src/telemetrum-v1.0/.gitignore create mode 100644 src/telemetrum-v1.0/Makefile create mode 100644 src/telemetrum-v1.0/Makefile.defs (limited to 'src') diff --git a/src/Makefile b/src/Makefile index e2699ee6..24f562e1 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,7 +4,7 @@ # CC=sdcc -SUBDIRS=telemetrum-v0.2 teledongle-v0.2 telemetrum-v0.1-sky telemetrum-v0.1-sirf teledongle-v0.1 tidongle test +SUBDIRS=telemetrum-v1.0 teledongle-v0.2 telemetrum-v0.1-sky telemetrum-v0.1-sirf teledongle-v0.1 tidongle test all: all-recursive diff --git a/src/ao_pins.h b/src/ao_pins.h index 771d9c7f..e9a265b0 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -18,7 +18,7 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -#if defined(TELEMETRUM_V_0_2) +#if defined(TELEMETRUM_V_1_0) #define HAS_SERIAL_1 1 #define HAS_ADC 1 #define HAS_EEPROM 1 diff --git a/src/telemetrum-v0.2/.gitignore b/src/telemetrum-v0.2/.gitignore deleted file mode 100644 index 76228093..00000000 --- a/src/telemetrum-v0.2/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -telemetrum-v0.2 -ao_product.h diff --git a/src/telemetrum-v0.2/Makefile b/src/telemetrum-v0.2/Makefile deleted file mode 100644 index d8867b19..00000000 --- a/src/telemetrum-v0.2/Makefile +++ /dev/null @@ -1 +0,0 @@ -include ../Makefile.proto diff --git a/src/telemetrum-v0.2/Makefile.defs b/src/telemetrum-v0.2/Makefile.defs deleted file mode 100644 index eb11e7dc..00000000 --- a/src/telemetrum-v0.2/Makefile.defs +++ /dev/null @@ -1,10 +0,0 @@ -PROG = telemetrum-v0.2.ihx - -SRC = \ - $(TM_BASE_SRC) \ - $(FLASH_DRIVER_SRC) \ - $(SKY_DRIVER_SRC) \ - $(DBG_SRC) - -PRODUCT=TeleMetrum-v0.2 -PRODUCT_DEF=-DTELEMETRUM_V_0_2 diff --git a/src/telemetrum-v1.0/.gitignore b/src/telemetrum-v1.0/.gitignore new file mode 100644 index 00000000..76228093 --- /dev/null +++ b/src/telemetrum-v1.0/.gitignore @@ -0,0 +1,2 @@ +telemetrum-v0.2 +ao_product.h diff --git a/src/telemetrum-v1.0/Makefile b/src/telemetrum-v1.0/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telemetrum-v1.0/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/telemetrum-v1.0/Makefile.defs b/src/telemetrum-v1.0/Makefile.defs new file mode 100644 index 00000000..e3cc5eb2 --- /dev/null +++ b/src/telemetrum-v1.0/Makefile.defs @@ -0,0 +1,10 @@ +PROG = telemetrum-v1.0.ihx + +SRC = \ + $(TM_BASE_SRC) \ + $(FLASH_DRIVER_SRC) \ + $(SKY_DRIVER_SRC) \ + $(DBG_SRC) + +PRODUCT=TeleMetrum-v1.0 +PRODUCT_DEF=-DTELEMETRUM_V_1_0 -- cgit v1.2.3 From 9e10e43eff9de3f034da49c4f88728fb933f5035 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 6 Apr 2010 00:56:57 -0700 Subject: Tasks may move in task structure as a result of ao_exit Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_task.c | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index aefefa46..97cb75ae 100644 --- a/src/ao.h +++ b/src/ao.h @@ -43,7 +43,7 @@ struct ao_task { __xdata void *wchan; /* current wait channel (NULL if running) */ uint16_t alarm; /* abort ao_sleep time */ uint8_t stack_count; /* amount of saved stack */ - uint8_t task_id; /* index in the task array */ + uint8_t task_id; /* unique id */ __code char *name; /* task name */ uint8_t stack[AO_STACK_SIZE]; /* saved stack */ }; diff --git a/src/ao_task.c b/src/ao_task.c index 4a78766e..72c9d7d6 100644 --- a/src/ao_task.c +++ b/src/ao_task.c @@ -28,10 +28,19 @@ void ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant { uint8_t __xdata *stack; + uint8_t task_id; + uint8_t t; if (ao_num_tasks == AO_NUM_TASKS) ao_panic(AO_PANIC_NO_TASK); + for (task_id = 1; task_id != 0; task_id++) { + for (t = 0; t < ao_num_tasks; t++) + if (ao_tasks[t]->task_id == task_id) + break; + if (t == ao_num_tasks) + break; + } ao_tasks[ao_num_tasks++] = task; - task->task_id = ao_num_tasks; + task->task_id = task_id; task->name = name; /* * Construct a stack frame so that it will 'return' -- cgit v1.2.3 From f93c9bf3695862db31f2c3b3bc5a7bb24ef3766c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 8 Apr 2010 17:28:17 -0700 Subject: When changing RESET line, delay 20ms The GPS data sheet suggests a 1uF cap on the reset line to ensure it is held low long enough for the power supply to come up to voltage. TM v1.0 loads a 0.001uF cap there, but in case that isn't large enough, it could be replaced with the larger one. This change makes sure that even with that larger value, the debugging link will be able to reset the target. Signed-off-by: Keith Packard --- src/ao_dbg.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ao_dbg.c b/src/ao_dbg.c index d0633f92..2fc266e3 100644 --- a/src/ao_dbg.c +++ b/src/ao_dbg.c @@ -184,6 +184,12 @@ ao_dbg_long_delay(void) _asm nop _endasm; } +static void +ao_dbg_reset_delay(void) +{ + ao_delay(AO_MS_TO_TICKS(20)); +} + void ao_dbg_debug_mode(void) { @@ -192,7 +198,7 @@ ao_dbg_debug_mode(void) ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); - ao_dbg_long_delay(); + ao_dbg_reset_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); @@ -200,7 +206,7 @@ ao_dbg_debug_mode(void) ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA|DBG_RESET_N); - ao_dbg_long_delay(); + ao_dbg_reset_delay(); } void @@ -211,7 +217,7 @@ ao_dbg_reset(void) ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_long_delay(); + ao_dbg_reset_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); @@ -219,7 +225,7 @@ ao_dbg_reset(void) ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); - ao_dbg_long_delay(); + ao_dbg_reset_delay(); } static void -- cgit v1.2.3 From 9394393c24c0a96b94319f2d0aa78fb498a121c9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 9 Apr 2010 17:51:01 -0700 Subject: Only have the slave return a packet if it received one. When the receive is aborted to switch modes, it's important to not immediately re-acquire the radio and try to send a packet as the aborting thread won't know to kick the receiver again. This prevents the 'C' command from locking up as it tries to stop the packet slave before turning on the transmitter. Signed-off-by: Keith Packard --- src/ao_packet_slave.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index 4c947fbf..e03ebdc3 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -20,12 +20,15 @@ void ao_packet_slave(void) { + uint8_t status; + ao_radio_set_packet(); ao_tx_packet.addr = ao_serial_number; ao_tx_packet.len = AO_PACKET_SYN; while (ao_packet_enable) { - ao_packet_recv(); - ao_packet_send(); + status = ao_packet_recv(); + if (status & AO_DMA_DONE) + ao_packet_send(); } ao_exit(); } -- cgit v1.2.3 From c879b178d83c9a9a521f42a960b10e19b11cee92 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 10 Apr 2010 22:09:57 -0700 Subject: Increase reset switch time to 100ms Signed-off-by: Keith Packard --- src/ao_dbg.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/ao_dbg.c b/src/ao_dbg.c index 2fc266e3..e7fbd7ad 100644 --- a/src/ao_dbg.c +++ b/src/ao_dbg.c @@ -184,11 +184,8 @@ ao_dbg_long_delay(void) _asm nop _endasm; } -static void -ao_dbg_reset_delay(void) -{ - ao_delay(AO_MS_TO_TICKS(20)); -} +#define AO_RESET_LOW_DELAY AO_MS_TO_TICKS(100) +#define AO_RESET_HIGH_DELAY AO_MS_TO_TICKS(100) void ao_dbg_debug_mode(void) @@ -198,7 +195,7 @@ ao_dbg_debug_mode(void) ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); - ao_dbg_reset_delay(); + ao_delay(AO_RESET_LOW_DELAY); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); @@ -206,7 +203,7 @@ ao_dbg_debug_mode(void) ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA|DBG_RESET_N); - ao_dbg_reset_delay(); + ao_delay(AO_RESET_HIGH_DELAY); } void @@ -217,7 +214,7 @@ ao_dbg_reset(void) ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_reset_delay(); + ao_delay(AO_RESET_LOW_DELAY); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); @@ -225,7 +222,7 @@ ao_dbg_reset(void) ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_dbg_long_delay(); ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); - ao_dbg_reset_delay(); + ao_delay(AO_RESET_HIGH_DELAY); } static void -- cgit v1.2.3 From e7dc7fab787df63a4de72c8450e94092eb04d7db Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 22 Apr 2010 14:53:44 -0700 Subject: Add optional 's' command to packet slave to enable/disable slave mode This option has been selected for teledongle so that you can use slave mode and hook two teledongles together over the RF link. Signed-off-by: Keith Packard --- src/ao_packet_slave.c | 26 ++++++++++++++++++++++++-- src/ao_pins.h | 3 ++- 2 files changed, 26 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index e03ebdc3..3c4ffb92 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -36,8 +36,10 @@ ao_packet_slave(void) void ao_packet_slave_start(void) { - ao_packet_enable = 1; - ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); + if (!ao_packet_enable) { + ao_packet_enable = 1; + ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); + } } void @@ -54,10 +56,30 @@ ao_packet_slave_stop(void) } } +#ifdef PACKET_HAS_SLAVE_CMD +void +ao_packet_slave_control(void) +{ + ao_cmd_hex(); + if (ao_cmd_lex_i) + ao_packet_slave_start(); + else + ao_packet_slave_stop(); +} + +__code struct ao_cmds ao_packet_slave_cmds[] = { + { 's', ao_packet_slave_control, "s Remote packet link slave" }, + { 0, ao_packet_slave_control, NULL }, +}; +#endif + void ao_packet_slave_init(void) { ao_add_stdio(ao_packet_pollchar, ao_packet_putchar, NULL); +#ifdef PACKET_HAS_SLAVE_CMD + ao_cmd_register(&ao_packet_slave_cmds[0]); +#endif } diff --git a/src/ao_pins.h b/src/ao_pins.h index e9a265b0..5a0b4318 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -41,7 +41,8 @@ #define DBG_ON_P1 1 #define DBG_ON_P0 0 #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 + #define PACKET_HAS_SLAVE 1 + #define PACKET_HAS_SLAVE_CMD 1 #define AO_LED_RED 1 #define AO_LED_GREEN 2 #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) -- cgit v1.2.3 From aa9ff021d683764a43800eaa18ea0c9be5134939 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 4 May 2010 21:42:54 -0700 Subject: Revert "Add optional 's' command to packet slave to enable/disable slave mode" This reverts commit e7dc7fab787df63a4de72c8450e94092eb04d7db. This patch didn't work, and magically appears to break flashing TM from TD. --- src/ao_packet_slave.c | 26 ++------------------------ src/ao_pins.h | 3 +-- 2 files changed, 3 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index 3c4ffb92..e03ebdc3 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -36,10 +36,8 @@ ao_packet_slave(void) void ao_packet_slave_start(void) { - if (!ao_packet_enable) { - ao_packet_enable = 1; - ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); - } + ao_packet_enable = 1; + ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); } void @@ -56,30 +54,10 @@ ao_packet_slave_stop(void) } } -#ifdef PACKET_HAS_SLAVE_CMD -void -ao_packet_slave_control(void) -{ - ao_cmd_hex(); - if (ao_cmd_lex_i) - ao_packet_slave_start(); - else - ao_packet_slave_stop(); -} - -__code struct ao_cmds ao_packet_slave_cmds[] = { - { 's', ao_packet_slave_control, "s Remote packet link slave" }, - { 0, ao_packet_slave_control, NULL }, -}; -#endif - void ao_packet_slave_init(void) { ao_add_stdio(ao_packet_pollchar, ao_packet_putchar, NULL); -#ifdef PACKET_HAS_SLAVE_CMD - ao_cmd_register(&ao_packet_slave_cmds[0]); -#endif } diff --git a/src/ao_pins.h b/src/ao_pins.h index 5a0b4318..e9a265b0 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -41,8 +41,7 @@ #define DBG_ON_P1 1 #define DBG_ON_P0 0 #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 1 - #define PACKET_HAS_SLAVE_CMD 1 + #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 1 #define AO_LED_GREEN 2 #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) -- cgit v1.2.3 From f7ff3278bb670df59d7425a014cfe8e3718fea3f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 5 May 2010 00:44:42 -0700 Subject: Disable interrupts while reading from stdin With multiple input source support, there is a lag between asking a device if it has data and then waiting for more data to appear. If an interrupt signalling additional input arrives in this interval, we'll go to sleep with input available. This patch uses a big hammer by just disabling interrupts for the whole process. Signed-off-by: Keith Packard --- src/ao_stdio.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/ao_stdio.c b/src/ao_stdio.c index 8add30b8..045dff09 100644 --- a/src/ao_stdio.c +++ b/src/ao_stdio.c @@ -50,6 +50,7 @@ getchar(void) __reentrant char c; int8_t stdio = ao_cur_stdio; + EA = 0; for (;;) { c = stdios[stdio].pollchar(); if (c != AO_READ_AGAIN) @@ -59,6 +60,7 @@ getchar(void) __reentrant if (stdio == ao_cur_stdio) ao_sleep(&ao_stdin_ready); } + EA = 1; ao_cur_stdio = stdio; return c; } -- cgit v1.2.3 From e6bb80975fde20928a830170f0821d59a8c72690 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 5 May 2010 01:31:57 -0700 Subject: Fix all stdio reading functions to be __critical Oh, right SDCC has '__critical' to mark sections of code that need to run with interrupts disabled; no need to use EA = 0 and EA = 1. Signed-off-by: Keith Packard --- src/ao_packet_master.c | 2 +- src/ao_stdio.c | 4 +--- src/ao_usb.c | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index a499ce59..ef86fa28 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -18,7 +18,7 @@ #include "ao.h" static char -ao_packet_getchar(void) +ao_packet_getchar(void) __critical { char c; while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) diff --git a/src/ao_stdio.c b/src/ao_stdio.c index 045dff09..78bbd3c3 100644 --- a/src/ao_stdio.c +++ b/src/ao_stdio.c @@ -45,12 +45,11 @@ flush(void) __xdata uint8_t ao_stdin_ready; char -getchar(void) __reentrant +getchar(void) __reentrant __critical { char c; int8_t stdio = ao_cur_stdio; - EA = 0; for (;;) { c = stdios[stdio].pollchar(); if (c != AO_READ_AGAIN) @@ -60,7 +59,6 @@ getchar(void) __reentrant if (stdio == ao_cur_stdio) ao_sleep(&ao_stdin_ready); } - EA = 1; ao_cur_stdio = stdio; return c; } diff --git a/src/ao_usb.c b/src/ao_usb.c index 527e9b30..e4af8e45 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -395,7 +395,7 @@ ao_usb_pollchar(void) __critical } char -ao_usb_getchar(void) +ao_usb_getchar(void) __critical { char c; -- cgit v1.2.3 From 8b6767e24a88482dbd3d4c4c969a0be08917d22b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 5 May 2010 01:32:46 -0700 Subject: Use ao_delay to sleep for 2 seconds instead of trying ao_sleep ao_sleep doesn't delay for a specified time interval as much as one might want it to. --- src/ao_cmd.c | 2 +- src/ao_reboot.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao_cmd.c b/src/ao_cmd.c index b6d2b886..4a68fba4 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -208,7 +208,7 @@ ao_reboot(void) if (!ao_match_word("eboot")) return; WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; - ao_sleep(AO_SEC_TO_TICKS(2)); + ao_delay(AO_SEC_TO_TICKS(2)); ao_panic(AO_PANIC_REBOOT); } diff --git a/src/ao_reboot.c b/src/ao_reboot.c index 82ea32e0..8c47b893 100644 --- a/src/ao_reboot.c +++ b/src/ao_reboot.c @@ -23,6 +23,6 @@ void ao_reboot(void) { WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_32768; - ao_sleep(AO_SEC_TO_TICKS(2)); + ao_delay(AO_SEC_TO_TICKS(2)); ao_panic(AO_PANIC_REBOOT); } -- cgit v1.2.3 From 823fc0ac27b8df9b4ba1ca0f229b431baf5b46dd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 5 May 2010 12:50:39 -0700 Subject: Don't change dbg clock while changing reset_n. Use 20ms everywhere This changes the reset code to be more conservative about changing things at the same time, and also sets all timings to 20ms to make debugging with the scope easier. Signed-off-by: Keith Packard --- src/ao_dbg.c | 54 +++++++++++++++--------------------------------------- 1 file changed, 15 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/ao_dbg.c b/src/ao_dbg.c index e7fbd7ad..2988aed4 100644 --- a/src/ao_dbg.c +++ b/src/ao_dbg.c @@ -175,54 +175,30 @@ ao_dbg_set_pins(void) DBG_PORT_DIR &= ~DBG_DATA; } -static void -ao_dbg_long_delay(void) -{ - uint8_t n; - - for (n = 0; n < 20; n++) - _asm nop _endasm; -} - -#define AO_RESET_LOW_DELAY AO_MS_TO_TICKS(100) -#define AO_RESET_HIGH_DELAY AO_MS_TO_TICKS(100) +#define ao_reset_delay() ao_delay(AO_MS_TO_TICKS(20)) void ao_dbg_debug_mode(void) { - ao_dbg_set_pins(); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); - ao_delay(AO_RESET_LOW_DELAY); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA|DBG_RESET_N); - ao_delay(AO_RESET_HIGH_DELAY); + ao_dbg_set_pins(); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA|DBG_RESET_N); ao_reset_delay(); } void ao_dbg_reset(void) { - ao_dbg_set_pins(); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_delay(AO_RESET_LOW_DELAY); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); - ao_delay(AO_RESET_HIGH_DELAY); + ao_dbg_set_pins(); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_reset_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA|DBG_RESET_N); ao_reset_delay(); } static void -- cgit v1.2.3 From cde60f16f6ab2cdd5010a0e106ae312d144947cf Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Thu, 6 May 2010 13:58:31 -0600 Subject: Revert "Merge remote branch 'remotes/origin/fix-reset'" This reverts commit 314d27a73c903fef2968dabac3d5313573713460, reversing changes made to fa77db2ffd8a749c93767db5a6311131e00473ae. For whatever reason, this is utterly not doing the right things today! --- src/ao_dbg.c | 54 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/ao_dbg.c b/src/ao_dbg.c index 2988aed4..e7fbd7ad 100644 --- a/src/ao_dbg.c +++ b/src/ao_dbg.c @@ -175,30 +175,54 @@ ao_dbg_set_pins(void) DBG_PORT_DIR &= ~DBG_DATA; } -#define ao_reset_delay() ao_delay(AO_MS_TO_TICKS(20)) +static void +ao_dbg_long_delay(void) +{ + uint8_t n; + + for (n = 0; n < 20; n++) + _asm nop _endasm; +} + +#define AO_RESET_LOW_DELAY AO_MS_TO_TICKS(100) +#define AO_RESET_HIGH_DELAY AO_MS_TO_TICKS(100) void ao_dbg_debug_mode(void) { - ao_dbg_set_pins(); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA|DBG_RESET_N); ao_reset_delay(); + ao_dbg_set_pins(); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); + ao_delay(AO_RESET_LOW_DELAY); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA|DBG_RESET_N); + ao_delay(AO_RESET_HIGH_DELAY); } void ao_dbg_reset(void) { - ao_dbg_set_pins(); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); ao_reset_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA|DBG_RESET_N); ao_reset_delay(); + ao_dbg_set_pins(); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_delay(AO_RESET_LOW_DELAY); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); + ao_delay(AO_RESET_HIGH_DELAY); } static void -- cgit v1.2.3 From 267923e56e22b3635a21f42ef77a3a36158bc273 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 16 Jun 2010 21:49:43 -0700 Subject: Add special code for USB panic's. The USB system may panic if the hardware isn't ready for IN data when the driver thinks it should be. This adds a special panic code to make figuring this out easier. Signed-off-by: Keith Packard --- src/ao.h | 1 + src/ao_usb.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 97cb75ae..a2dfadd0 100644 --- a/src/ao.h +++ b/src/ao.h @@ -110,6 +110,7 @@ ao_start_scheduler(void); #define AO_PANIC_STDIO 7 /* Too many stdio handlers registered */ #define AO_PANIC_REBOOT 8 /* Reboot failed */ #define AO_PANIC_FLASH 9 /* Invalid flash part (or wrong blocksize) */ +#define AO_PANIC_USB 10 /* Trying to send USB packet while busy */ /* Stop the operating system, beeping and blinking the reason */ void diff --git a/src/ao_usb.c b/src/ao_usb.c index e4af8e45..d071fe6f 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -85,7 +85,7 @@ ao_usb_ep0_flush(void) USBINDEX = 0; cs0 = USBCS0; if (cs0 & USBCS0_INPKT_RDY) - ao_panic(0); + ao_panic(AO_PANIC_USB); this_len = ao_usb_ep0_in_len; if (this_len > AO_USB_CONTROL_SIZE) -- cgit v1.2.3 From 52834517c0706b1f16fb81643a42dc1c1997e00a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 21 Jun 2010 15:53:33 -0700 Subject: Abort any in-progress radio operation when changing radio channel In monitor mode, the current receive operation must be aborted so that the radio channel change can take effect without receiving a telemetry packet on the old channel. Aborting any in-progress radio operation will make sure that happens. Signed-off-by: Keith Packard --- src/ao_config.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/ao_config.c b/src/ao_config.c index 8df994a6..cbd639a5 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -151,6 +151,7 @@ ao_config_radio_channel_set(void) __reentrant ao_config_dirty = 1; ao_mutex_put(&ao_config_mutex); ao_config_radio_channel_show(); + ao_radio_abort(); } #if HAS_ADC -- cgit v1.2.3 From a9ec6be0e92dee01f7aac006ef6f7779c1da1b36 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 3 Jul 2010 17:42:36 -0400 Subject: Telemetry code was mis-computing RSSI The RSSI data from the hardware reports in 1/2 dBm increments, and so must be divided to report plain RSSI numbers. Signed-off-by: Keith Packard --- ao-tools/lib/cc-telem.c | 4 ++++ configure.ac | 2 ++ src/ao.h | 2 +- src/ao_monitor.c | 10 +++++++--- 4 files changed, 14 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/ao-tools/lib/cc-telem.c b/ao-tools/lib/cc-telem.c index ccd40ac2..aa52b7c5 100644 --- a/ao-tools/lib/cc-telem.c +++ b/ao-tools/lib/cc-telem.c @@ -101,6 +101,10 @@ cc_telem_parse(const char *input_line, struct cc_telem *telem) telem->flight = 0; cc_parse_int(&telem->rssi, words[5]); + if (version <= 2) { + /* Older telemetry versions mis-computed the rssi value */ + telem->rssi = (telem->rssi + 74) / 2 - 74; + } cc_parse_string(telem->state, sizeof (telem->state), words[9]); cc_parse_int(&telem->tick, words[10]); cc_parse_int(&telem->accel, words[12]); diff --git a/configure.ac b/configure.ac index d6c8682b..fafc6b34 100644 --- a/configure.ac +++ b/configure.ac @@ -77,6 +77,8 @@ PKG_CHECK_MODULES([ALSA], [alsa]) PKG_CHECK_MODULES([PLPLOT], [plplotd]) +PKG_CHECK_MODULES([SNDFILE], [sndfile]) + AC_OUTPUT([ Makefile ao-tools/Makefile diff --git a/src/ao.h b/src/ao.h index a2dfadd0..dfff8a8d 100644 --- a/src/ao.h +++ b/src/ao.h @@ -804,7 +804,7 @@ ao_gps_report_init(void); */ #define AO_MAX_CALLSIGN 8 -#define AO_TELEMETRY_VERSION 2 +#define AO_TELEMETRY_VERSION 3 struct ao_telemetry { uint8_t addr; diff --git a/src/ao_monitor.c b/src/ao_monitor.c index f2f3fc2e..f019d3b4 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -26,6 +26,7 @@ ao_monitor(void) __xdata struct ao_radio_recv recv; __xdata char callsign[AO_MAX_CALLSIGN+1]; uint8_t state; + int16_t rssi; for (;;) { __critical while (!ao_monitoring) @@ -33,6 +34,9 @@ ao_monitor(void) if (!ao_radio_recv(&recv)) continue; state = recv.telemetry.flight_state; + + /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ + rssi = (int16_t) (recv.rssi >> 1) - 74; memcpy(callsign, recv.telemetry.callsign, AO_MAX_CALLSIGN); if (state > ao_flight_invalid) state = ao_flight_invalid; @@ -42,7 +46,7 @@ ao_monitor(void) callsign, recv.telemetry.addr, recv.telemetry.flight, - (int) recv.rssi - 74, recv.status, + rssi, recv.status, ao_state_names[state]); printf("%5u a: %5d p: %5d t: %5d v: %5d d: %5d m: %5d " "fa: %5d ga: %d fv: %7ld fp: %5d gp: %5d a+: %5d a-: %5d ", @@ -64,9 +68,9 @@ ao_monitor(void) putchar(' '); ao_gps_tracking_print(&recv.telemetry.gps_tracking); putchar('\n'); - ao_rssi_set((int) recv.rssi - 74); + ao_rssi_set(rssi); } else { - printf("CRC INVALID RSSI %3d\n", (int) recv.rssi - 74); + printf("CRC INVALID RSSI %3d\n", rssi); } ao_usb_flush(); ao_led_toggle(ao_monitor_led); -- cgit v1.2.3 From 695879dbccfc5ec6b79698653c58814158f91686 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 14 Jul 2010 19:07:02 -0700 Subject: Switch DBG pins to GPIO when using any debug commands. Reboot to restore. If you want to use TeleMetrum as a debug dongle, you need to flip the three pins used to talk to the remote debug port from SPI mode to GPIO mode. This patch doesn't provide any way to get back to SPI mode, so you'll have to reboot the TeleMetrum to write out config parameters or log flight data after using any debug commands. Signed-off-by: Keith Packard --- src/ao_dbg.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/ao_dbg.c b/src/ao_dbg.c index e7fbd7ad..0d9ec8c0 100644 --- a/src/ao_dbg.c +++ b/src/ao_dbg.c @@ -164,6 +164,12 @@ ao_dbg_read_byte(void) static void ao_dbg_set_pins(void) { + /* Make the DBG pins GPIOs. On TeleMetrum, this will + * disable the SPI link, so don't expect SPI to work after + * using the debugger. + */ + DBG_PORT_SEL &= ~(DBG_CLOCK|DBG_DATA|DBG_RESET_N); + /* make DBG_DATA tri-state */ DBG_PORT_INP |= DBG_DATA; -- cgit v1.2.3 From 05111d5be4d37bedaaee6415d6ee27347e6a112c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Jul 2010 12:52:17 -0700 Subject: When the EP0 IN buffer is full, don't panic, just skip sending another If the host doesn't pull the IN packet out of EP0 before sending another SETUP command along, the IN buffer will still be busy when we try to reply to the SETUP command. While I don't quite understand why this would ever happen, there's no need to panic about it, just drop the reply packet on the floor. Signed-off-by: Keith Packard --- src/ao_usb.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_usb.c b/src/ao_usb.c index d071fe6f..f6e0fcf9 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -82,10 +82,11 @@ ao_usb_ep0_flush(void) __xdata uint8_t this_len; __xdata uint8_t cs0; + /* If the IN packet hasn't been picked up, just return */ USBINDEX = 0; cs0 = USBCS0; if (cs0 & USBCS0_INPKT_RDY) - ao_panic(AO_PANIC_USB); + return; this_len = ao_usb_ep0_in_len; if (this_len > AO_USB_CONTROL_SIZE) -- cgit v1.2.3 From f2a006fd98045066bdf429cc142d033e9feb0a8f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Jul 2010 09:31:09 -0700 Subject: Make ao_log_data re-entrant as it is used for both sensor and GPS logs Because ao_log_data is called from two different threads, failing to make it re-entrant would cause the 'log' pointer parameter to get overwritten if another thread asked to log data while the eeprom was busy writing out a block. This would cause the second thread to re-writing data from the first thread's address, but without re-checksumming the data as the checksum is computed before the log mutex is taken. The bug can be seen by log blocks with invalid checksums. Here's what happens with the ao_gps_tracking_report and ao_log threads: ao_gps_tracking_report ao_log Writes a bunch of records *blocks* in the eeprom flush sets ao_log_data 'log' to global 'log' computes checksum for 'log' block *blocks* on ao_log_mutex Wakes up sets ao_log_data 'log' to 'gps_log' writes remaining records 'gps_log' is left with svid = 0 *blocks* on ao_gps_tracking_data writes data, reading from the current ao_log_data 'log' pointer which points at 'gps_log' Making ao_log_data re-entrant fixes this by ensuring that the 'ao_log' thread has its own copy of the ao_log_data 'log' parameter. I made this function take an __xdata restricted pointer so that it could be passed in the dptr register instead of needing to go on the stack. Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_log.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index dfff8a8d..5dd756da 100644 --- a/src/ao.h +++ b/src/ao.h @@ -562,7 +562,7 @@ struct ao_log_record { /* Write a record to the eeprom log */ void -ao_log_data(struct ao_log_record *log); +ao_log_data(__xdata struct ao_log_record *log) __reentrant; /* Flush the log */ void diff --git a/src/ao_log.c b/src/ao_log.c index 44ce90e0..d550d408 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -23,7 +23,7 @@ static __xdata uint8_t ao_log_running; static __xdata uint8_t ao_log_mutex; static uint8_t -ao_log_csum(uint8_t *b) +ao_log_csum(__xdata uint8_t *b) __reentrant { uint8_t sum = 0x5a; uint8_t i; @@ -34,11 +34,11 @@ ao_log_csum(uint8_t *b) } void -ao_log_data(struct ao_log_record *log) +ao_log_data(__xdata struct ao_log_record *log) __reentrant { /* set checksum */ log->csum = 0; - log->csum = ao_log_csum((uint8_t *) log); + log->csum = ao_log_csum((__xdata uint8_t *) log); ao_mutex_get(&ao_log_mutex); { if (ao_log_running) { ao_ee_write(ao_log_current_pos, -- cgit v1.2.3 From 4738cb2fc639adb1d9237e6c903479f0690dd81a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Aug 2010 00:40:59 -0400 Subject: altos: add callsign to packet mode, increase payload to 64 bytes Untested, but it 'should' work. Need to add callsign setting to packet mode users. Signed-off-by: Keith Packard --- src/ao.h | 3 ++- src/ao_packet_master.c | 2 ++ src/ao_packet_slave.c | 4 +++- 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 5dd756da..5f2b8339 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1034,7 +1034,7 @@ struct ao_fifo { * Packet-based command interface */ -#define AO_PACKET_MAX 8 +#define AO_PACKET_MAX 64 #define AO_PACKET_SYN (uint8_t) 0xff struct ao_packet { @@ -1043,6 +1043,7 @@ struct ao_packet { uint8_t seq; uint8_t ack; uint8_t d[AO_PACKET_MAX]; + uint8_t callsign[AO_MAX_CALLSIGN]; }; struct ao_packet_recv { diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index ef86fa28..72bb908a 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -77,12 +77,14 @@ ao_packet_master(void) { uint8_t status; + ao_config_get(); ao_radio_set_packet(); ao_tx_packet.addr = ao_serial_number; ao_tx_packet.len = AO_PACKET_SYN; ao_packet_master_time = ao_time(); ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; while (ao_packet_enable) { + memcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN); ao_packet_send(); if (ao_tx_packet.len) ao_packet_master_busy(); diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index e03ebdc3..9b78767f 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -27,8 +27,10 @@ ao_packet_slave(void) ao_tx_packet.len = AO_PACKET_SYN; while (ao_packet_enable) { status = ao_packet_recv(); - if (status & AO_DMA_DONE) + if (status & AO_DMA_DONE) { + memcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN); ao_packet_send(); + } } ao_exit(); } -- cgit v1.2.3 From 09252ec22d58e946494e4ca2cf367bf3bbe1cc50 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 21 Aug 2010 17:09:41 -0700 Subject: altos: Define USB product ID in per-product Makefile.defs file This allows Win7 to tell which kind of device is connected purely by USB id as it doesn't expose the USB product ID string to user space. Signed-off-by: Keith Packard --- src/Makefile.proto | 2 +- src/ao-make-product.5c | 15 +++++++++++++++ src/ao_product.c | 2 +- src/teledongle-v0.1/Makefile.defs | 1 + src/teledongle-v0.2/Makefile.defs | 1 + src/telemetrum-v0.1-sirf/Makefile.defs | 1 + src/telemetrum-v0.1-sky/Makefile.defs | 1 + src/telemetrum-v1.0/Makefile.defs | 1 + src/tidongle/Makefile.defs | 1 + 9 files changed, 23 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index 106333a6..eedb878a 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -214,7 +214,7 @@ all: ../$(PROG) nickle $< > $@ ao_product.h: ao-make-product.5c - $(call quiet,NICKLE,$<) $< -m altusmetrum.org -p $(PRODUCT) -v $(VERSION) > $@ + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ ao_product.rel: ao_product.c ao_product.h $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< diff --git a/src/ao-make-product.5c b/src/ao-make-product.5c index 933032dd..5f2eb8e8 100644 --- a/src/ao-make-product.5c +++ b/src/ao-make-product.5c @@ -37,11 +37,19 @@ write_int(int a, string description) printf ("#define AO_%s_NUMBER %d\n\n", description, a); } +void +write_hex(int a, string description) +{ + printf ("/* %s */\n", description); + printf ("#define AO_%s_NUMBER 0x%04x\n\n", description, a); +} + string manufacturer = "altusmetrum.org"; string product = "TeleMetrum"; string version = "0.0"; int serial = 1; int user_argind = 0; +int id_product = 0x000a; argdesc argd = { .args = { @@ -57,6 +65,12 @@ argdesc argd = { .name = "product", .expr_name = "prod", .desc = "Product name." }, + { + .var = { .arg_int = &id_product }, + .abbr = 'i', + .name = "id_product", + .expr_name = "id_p", + .desc = "Product ID." }, { .var = { .arg_int = &serial }, .abbr = 's', @@ -82,6 +96,7 @@ main() write_ucs2(product, "iProduct"); write_ucs2(sprintf("%06d", serial), "iSerial"); write_int(serial, "iSerial"); + write_hex(id_product, "idProduct"); write_string(version, "iVersion"); } diff --git a/src/ao_product.c b/src/ao_product.c index b42e62c0..2bd0b59c 100644 --- a/src/ao_product.c +++ b/src/ao_product.c @@ -40,7 +40,7 @@ const uint8_t ao_usb_descriptors [] = 0x00, /* bDeviceProtocol */ AO_USB_CONTROL_SIZE, /* bMaxPacketSize */ LE_WORD(0xFFFE), /* idVendor */ - LE_WORD(0x000A), /* idProduct */ + LE_WORD(AO_idProduct_NUMBER), /* idProduct */ LE_WORD(0x0100), /* bcdDevice */ 0x01, /* iManufacturer */ 0x02, /* iProduct */ diff --git a/src/teledongle-v0.1/Makefile.defs b/src/teledongle-v0.1/Makefile.defs index 06559b28..be7741d8 100644 --- a/src/teledongle-v0.1/Makefile.defs +++ b/src/teledongle-v0.1/Makefile.defs @@ -6,3 +6,4 @@ SRC = \ PRODUCT=TeleDongle-v0.1 PRODUCT_DEF=-DTELEDONGLE_V_0_1 +IDPRODUCT=0x000c diff --git a/src/teledongle-v0.2/Makefile.defs b/src/teledongle-v0.2/Makefile.defs index 23694fda..cbec7805 100644 --- a/src/teledongle-v0.2/Makefile.defs +++ b/src/teledongle-v0.2/Makefile.defs @@ -6,3 +6,4 @@ SRC = \ PRODUCT=TeleDongle-v0.2 PRODUCT_DEF=-DTELEDONGLE_V_0_2 +IDPRODUCT=0x000c diff --git a/src/telemetrum-v0.1-sirf/Makefile.defs b/src/telemetrum-v0.1-sirf/Makefile.defs index 7306683e..2ce6e6ed 100644 --- a/src/telemetrum-v0.1-sirf/Makefile.defs +++ b/src/telemetrum-v0.1-sirf/Makefile.defs @@ -8,3 +8,4 @@ SRC = \ PRODUCT=TeleMetrum-v0.1-SiRF PRODUCT_DEF=-DTELEMETRUM_V_0_1 +IDPRODUCT=0x000b diff --git a/src/telemetrum-v0.1-sky/Makefile.defs b/src/telemetrum-v0.1-sky/Makefile.defs index df475baa..098ac547 100644 --- a/src/telemetrum-v0.1-sky/Makefile.defs +++ b/src/telemetrum-v0.1-sky/Makefile.defs @@ -8,3 +8,4 @@ SRC = \ PRODUCT=TeleMetrum-v0.1 PRODUCT_DEF=-DTELEMETRUM_V_0_1 +IDPRODUCT=0x000b diff --git a/src/telemetrum-v1.0/Makefile.defs b/src/telemetrum-v1.0/Makefile.defs index e3cc5eb2..624ce6e8 100644 --- a/src/telemetrum-v1.0/Makefile.defs +++ b/src/telemetrum-v1.0/Makefile.defs @@ -8,3 +8,4 @@ SRC = \ PRODUCT=TeleMetrum-v1.0 PRODUCT_DEF=-DTELEMETRUM_V_1_0 +IDPRODUCT=0x000b diff --git a/src/tidongle/Makefile.defs b/src/tidongle/Makefile.defs index 5b910b9b..fdd51732 100644 --- a/src/tidongle/Makefile.defs +++ b/src/tidongle/Makefile.defs @@ -6,3 +6,4 @@ SRC = \ PRODUCT=TIDongle PRODUCT_DEF=-DTIDONGLE +IDPRODUCT=0x000a -- cgit v1.2.3 From 56b906f535ac2f86bcab71addbbcd376d74f6a73 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 23 Aug 2010 22:03:36 -0700 Subject: altos: Place rom config variables in fixed location The device serial number and radio calibration values are stored in flash, mostly so that TeleDongle gets them saved. Placing them in well-known locations (starting at 0xa0) makes it possible to find the previous configuration and to re-write it easily, without requiring the .map file. altosui doesn't have the .map file parsing code, so it relies upon this new technique. As a benefit, it reads the old values from the device before reprogramming it. Signed-off-by: Keith Packard --- src/Makefile.proto | 1 + src/ao.h | 12 +++++++++++- src/ao_config.c | 10 ---------- src/ao_product.c | 1 - src/ao_romconfig.c | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 44 insertions(+), 12 deletions(-) create mode 100644 src/ao_romconfig.c (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index eedb878a..8bc8b0e1 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -35,6 +35,7 @@ ALTOS_SRC = \ ao_panic.c \ ao_task.c \ ao_timer.c \ + ao_romconfig.c \ _bp.c # diff --git a/src/ao.h b/src/ao.h index 5f2b8339..9c418db2 100644 --- a/src/ao.h +++ b/src/ao.h @@ -289,6 +289,17 @@ ao_led_for(uint8_t colors, uint16_t ticks) __reentrant; void ao_led_init(uint8_t enable); +/* + * ao_romconfig.c + */ + +#define AO_ROMCONFIG_VERSION 1 + +extern __code __at (0x00a0) uint16_t ao_romconfig_version; +extern __code __at (0x00a2) uint16_t ao_romconfig_check; +extern __code __at (0x00a4) uint16_t ao_serial_number; +extern __code __at (0x00a6) uint32_t ao_radio_cal; + /* * ao_usb.c */ @@ -998,7 +1009,6 @@ ao_rssi_init(uint8_t rssi_led); */ extern const uint8_t ao_usb_descriptors []; -extern const uint16_t ao_serial_number; extern const char ao_version[]; extern const char ao_manufacturer[]; extern const char ao_product[]; diff --git a/src/ao_config.c b/src/ao_config.c index cbd639a5..88b52dc0 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -27,16 +27,6 @@ __xdata uint8_t ao_config_mutex; #define AO_CONFIG_DEFAULT_CALLSIGN "N0CALL" #define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000 #define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 -/* - * For 434.550MHz, the frequency value is: - * - * 434.550e6 / (24e6 / 2**16) = 1186611.2 - * - * This value is stored in a const variable so that - * ao-load can change it during programming for - * devices that have no eeprom for config data. - */ -const uint32_t ao_radio_cal = 1186611; #if HAS_EEPROM static void diff --git a/src/ao_product.c b/src/ao_product.c index 2bd0b59c..f0eb4c07 100644 --- a/src/ao_product.c +++ b/src/ao_product.c @@ -21,7 +21,6 @@ /* Defines which mark this particular AltOS product */ -const uint16_t ao_serial_number = AO_iSerial_NUMBER; const char ao_version[] = AO_iVersion_STRING; const char ao_manufacturer[] = AO_iManufacturer_STRING; const char ao_product[] = AO_iProduct_STRING; diff --git a/src/ao_romconfig.c b/src/ao_romconfig.c new file mode 100644 index 00000000..f3fe61b1 --- /dev/null +++ b/src/ao_romconfig.c @@ -0,0 +1,32 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +__code __at (0x00a0) uint16_t ao_romconfig_version = AO_ROMCONFIG_VERSION; +__code __at (0x00a2) uint16_t ao_romconfig_check = ~AO_ROMCONFIG_VERSION; +__code __at (0x00a4) uint16_t ao_serial_number = 0; +/* + * For 434.550MHz, the frequency value is: + * + * 434.550e6 / (24e6 / 2**16) = 1186611.2 + * + * This value is stored in a const variable so that + * ao-load can change it during programming for + * devices that have no eeprom for config data. + */ +__code __at (0x00a6) uint32_t ao_radio_cal = 1186611; -- cgit v1.2.3 From ba086cc77273efe5397f60dcaccd1e3771441481 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 24 Aug 2010 04:02:27 -0700 Subject: altosui: write USB serial number string while flashing USB serial number is encoded in UCS2 as a part of the string descriptors. Place those right after the other rom config bits so that altosui can find it. altosui is changed to write the serial number there. Signed-off-by: Keith Packard --- ao-tools/altosui/AltosRomconfig.java | 49 +++++++++++++++++++++++++++++++++- ao-tools/altosui/AltosRomconfigUI.java | 21 ++++++++++++++- src/ao.h | 5 ++-- src/ao_product.c | 2 +- 4 files changed, 72 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/ao-tools/altosui/AltosRomconfig.java b/ao-tools/altosui/AltosRomconfig.java index 844da7c4..8c9cb27a 100644 --- a/ao-tools/altosui/AltosRomconfig.java +++ b/ao-tools/altosui/AltosRomconfig.java @@ -47,14 +47,57 @@ public class AltosRomconfig { } } + static void put_string(String value, byte[] bytes, int start) { + for (int i = 0; i < value.length(); i++) + bytes[start + i] = (byte) value.charAt(i); + } + + static final int AO_USB_DESC_STRING = 3; + + static void put_usb_serial(int value, byte[] bytes, int start) { + int offset = start + 0xa; + int string_num = 0; + System.out.printf("Put usb serial %d\n", value); + + while (offset < bytes.length && bytes[offset] != 0) { + if (bytes[offset + 1] == AO_USB_DESC_STRING) { + ++string_num; + if (string_num == 4) + break; + } + offset += ((int) bytes[offset]) & 0xff; + } + System.out.printf("offset %d content %d\n", + offset, bytes[offset]); + if (offset >= bytes.length || bytes[offset] == 0) + return; + int len = ((((int) bytes[offset]) & 0xff) - 2) / 2; + String fmt = String.format("%%0%dd", len); + System.out.printf("existing serial length %d format %s\n", len, fmt); + + String s = String.format(fmt, value); + if (s.length() != len) { + System.out.printf("weird usb length issue %s isn't %d\n", + s, len); + return; + } + for (int i = 0; i < len; i++) { + bytes[offset + 2 + i*2] = (byte) s.charAt(i); + bytes[offset + 2 + i*2+1] = 0; + } + } + public AltosRomconfig(byte[] bytes, int offset) { version = get_int(bytes, offset + 0, 2); check = get_int(bytes, offset + 2, 2); + System.out.printf("version %d check %d\n", version, check); if (check == (~version & 0xffff)) { switch (version) { + case 2: case 1: serial_number = get_int(bytes, offset + 4, 2); radio_calibration = get_int(bytes, offset + 6, 4); + System.out.printf("serial %d cal %d\n", serial_number, radio_calibration); valid = true; break; } @@ -77,6 +120,8 @@ public class AltosRomconfig { throw new IOException("image does not contain existing rom config"); switch (existing.version) { + case 2: + put_usb_serial(serial_number, bytes, offset); case 1: put_int(serial_number, bytes, offset + 4, 2); put_int(radio_calibration, bytes, offset + 6, 4); @@ -86,7 +131,9 @@ public class AltosRomconfig { public void write (AltosHexfile hexfile) throws IOException { write(hexfile.data, 0xa0 - hexfile.address); - new AltosRomconfig(hexfile); + AltosRomconfig check = new AltosRomconfig(hexfile); + if (!check.valid()) + throw new IOException("writing new rom config failed\n"); } public AltosRomconfig(int in_serial_number, int in_radio_calibration) { diff --git a/ao-tools/altosui/AltosRomconfigUI.java b/ao-tools/altosui/AltosRomconfigUI.java index 21c34ef4..bc511865 100644 --- a/ao-tools/altosui/AltosRomconfigUI.java +++ b/ao-tools/altosui/AltosRomconfigUI.java @@ -143,12 +143,31 @@ public class AltosRomconfigUI return Integer.parseInt(serial_value.getText()); } + void set_serial(int serial) { + serial_value.setText(String.format("%d", serial)); + } + int radio_calibration() { return Integer.parseInt(radio_calibration_value.getText()); } + void set_radio_calibration(int calibration) { + radio_calibration_value.setText(String.format("%d", calibration)); + } + + public void set(AltosRomconfig config) { + if (config != null && config.valid()) { + set_serial(config.serial_number); + set_radio_calibration(config.radio_calibration); + } + } + public AltosRomconfig romconfig() { - return new AltosRomconfig(serial(), radio_calibration()); + try { + return new AltosRomconfig(serial(), radio_calibration()); + } catch (NumberFormatException ne) { + return null; + } } public AltosRomconfig showDialog() { diff --git a/src/ao.h b/src/ao.h index 9c418db2..d289ced1 100644 --- a/src/ao.h +++ b/src/ao.h @@ -293,12 +293,13 @@ ao_led_init(uint8_t enable); * ao_romconfig.c */ -#define AO_ROMCONFIG_VERSION 1 +#define AO_ROMCONFIG_VERSION 2 extern __code __at (0x00a0) uint16_t ao_romconfig_version; extern __code __at (0x00a2) uint16_t ao_romconfig_check; extern __code __at (0x00a4) uint16_t ao_serial_number; extern __code __at (0x00a6) uint32_t ao_radio_cal; +extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; /* * ao_usb.c @@ -1008,7 +1009,7 @@ ao_rssi_init(uint8_t rssi_led); * each instance of a product */ -extern const uint8_t ao_usb_descriptors []; +extern __code __at(0x00aa) uint8_t ao_usb_descriptors []; extern const char ao_version[]; extern const char ao_manufacturer[]; extern const char ao_product[]; diff --git a/src/ao_product.c b/src/ao_product.c index f0eb4c07..82d6298f 100644 --- a/src/ao_product.c +++ b/src/ao_product.c @@ -28,7 +28,7 @@ const char ao_product[] = AO_iProduct_STRING; #define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) /* USB descriptors in one giant block of bytes */ -const uint8_t ao_usb_descriptors [] = +__code __at(0x00aa) uint8_t ao_usb_descriptors [] = { /* Device descriptor */ 0x12, -- cgit v1.2.3 From 34055129b4008f6a9833887b12dee39ffa408002 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 26 Aug 2010 15:57:09 -0700 Subject: altos: always rebuild ao_product.c to track git version The git version is built into ao_product.c and saved in eeprom log files, providing useful diagnostics about the firmware revision used for each flight. However, if ao_product.c isn't recompiled, then the updated version won't be included. Force recompilation of this file each time make is run to ensure that the final output contains an updated version number. Signed-off-by: Keith Packard --- src/Makefile.proto | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index 8bc8b0e1..59a3b8a6 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -214,9 +214,11 @@ all: ../$(PROG) ../altitude.h: make-altitude nickle $< > $@ -ao_product.h: ao-make-product.5c +ao_product.h: ao-make-product.5c always $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ +always: + ao_product.rel: ao_product.c ao_product.h $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< -- cgit v1.2.3 From aa6c27df5db6bdae59d00affccb891854a6caa18 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 26 Aug 2010 15:59:09 -0700 Subject: altos: print GPS state flags in GPS 'g' command Having the GPS state information can help with GPS debugging. Signed-off-by: Keith Packard --- src/ao_gps_skytraq.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index ae8c7ef7..c822f7fa 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -422,6 +422,7 @@ gps_dump(void) __reentrant printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second); printf ("Lat/Lon: %ld %ld\n", ao_gps_data.latitude, ao_gps_data.longitude); printf ("Alt: %d\n", ao_gps_data.altitude); + printf ("Flags: 0x%x\n", ao_gps_data.flags); ao_mutex_put(&ao_gps_mutex); } -- cgit v1.2.3 From 68b2b66d7574dfd0bd5e3571b8ffad32ca5d2b73 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 26 Aug 2010 23:37:29 -0700 Subject: altos: mark gps date written only after it gets into eeprom Data logging doesn't start until boost detect occurs. As the GPS date is only logged once, if that happens before logging is written to the flash, then the GPS date will never get saved. Signed-off-by: Keith Packard --- src/ao.h | 3 ++- src/ao_gps_report.c | 4 ++-- src/ao_log.c | 5 ++++- 3 files changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index d289ced1..8db22799 100644 --- a/src/ao.h +++ b/src/ao.h @@ -564,6 +564,7 @@ struct ao_log_record { uint8_t year; uint8_t month; uint8_t day; + uint8_t extra; } gps_date; struct { uint16_t d0; @@ -573,7 +574,7 @@ struct ao_log_record { }; /* Write a record to the eeprom log */ -void +uint8_t ao_log_data(__xdata struct ao_log_record *log) __reentrant; /* Flush the log */ diff --git a/src/ao_gps_report.c b/src/ao_gps_report.c index cceb79ff..7abc93f5 100644 --- a/src/ao_gps_report.c +++ b/src/ao_gps_report.c @@ -51,12 +51,12 @@ ao_gps_report(void) gps_log.u.gps_altitude.unused = 0xffff; ao_log_data(&gps_log); if (!date_reported && (gps_data.flags & AO_GPS_DATE_VALID)) { - date_reported = 1; gps_log.type = AO_LOG_GPS_DATE; gps_log.u.gps_date.year = gps_data.year; gps_log.u.gps_date.month = gps_data.month; gps_log.u.gps_date.day = gps_data.day; - ao_log_data(&gps_log); + gps_log.u.gps_date.extra = 0; + date_reported = ao_log_data(&gps_log); } } } diff --git a/src/ao_log.c b/src/ao_log.c index d550d408..18bdb8c8 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -33,14 +33,16 @@ ao_log_csum(__xdata uint8_t *b) __reentrant return -sum; } -void +uint8_t ao_log_data(__xdata struct ao_log_record *log) __reentrant { + uint8_t wrote = 0; /* set checksum */ log->csum = 0; log->csum = ao_log_csum((__xdata uint8_t *) log); ao_mutex_get(&ao_log_mutex); { if (ao_log_running) { + wrote = 1; ao_ee_write(ao_log_current_pos, (uint8_t *) log, sizeof (struct ao_log_record)); @@ -51,6 +53,7 @@ ao_log_data(__xdata struct ao_log_record *log) __reentrant ao_log_running = 0; } } ao_mutex_put(&ao_log_mutex); + return wrote; } void -- cgit v1.2.3 From 2923cf5057f9cef110dd547d8677ea5b60e00796 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 27 Aug 2010 00:10:29 -0700 Subject: altos: prepare for sdcc 2.9.1 A few minor language changes -- non-standard keywords are now prefixed with __, such as 'at', 'interrupt', 'naked'. Signed-off-by: Keith Packard --- src/ao.h | 16 ++++----- src/ao_adc.c | 2 +- src/ao_cmd.c | 3 +- src/ao_dma.c | 2 +- src/ao_radio.c | 2 +- src/ao_serial.c | 4 +-- src/ao_timer.c | 2 +- src/ao_usb.c | 2 +- src/cc1111.h | 108 ++++++++++++++++++++++++++++---------------------------- 9 files changed, 70 insertions(+), 71 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 8db22799..cd4e4814 100644 --- a/src/ao.h +++ b/src/ao.h @@ -79,7 +79,7 @@ ao_alarm(uint16_t delay); /* Yield the processor to another task */ void -ao_yield(void) _naked; +ao_yield(void) __naked; /* Add a task to the run queue */ void @@ -139,7 +139,7 @@ ao_timer_set_adc_interval(uint8_t interval) __critical; /* Timer interrupt */ void -ao_timer_isr(void) interrupt 9; +ao_timer_isr(void) __interrupt 9; /* Initialize the timer */ void @@ -198,7 +198,7 @@ ao_adc_get(__xdata struct ao_adc *packet); /* The A/D interrupt handler */ void -ao_adc_isr(void) interrupt 1; +ao_adc_isr(void) __interrupt 1; /* Initialize the A/D converter */ void @@ -325,7 +325,7 @@ ao_usb_flush(void); /* USB interrupt handler */ void -ao_usb_isr(void) interrupt 6; +ao_usb_isr(void) __interrupt 6; /* Enable the USB controller */ void @@ -425,7 +425,7 @@ ao_dma_abort(uint8_t id); /* DMA interrupt routine */ void -ao_dma_isr(void) interrupt 8; +ao_dma_isr(void) __interrupt 8; /* * ao_mutex.c @@ -722,10 +722,10 @@ ao_dbg_init(void); #if HAS_SERIAL_1 void -ao_serial_rx1_isr(void) interrupt 3; +ao_serial_rx1_isr(void) __interrupt 3; void -ao_serial_tx1_isr(void) interrupt 14; +ao_serial_tx1_isr(void) __interrupt 14; char ao_serial_getchar(void) __critical; @@ -861,7 +861,7 @@ extern __xdata uint8_t ao_radio_done; extern __xdata uint8_t ao_radio_mutex; void -ao_radio_general_isr(void) interrupt 16; +ao_radio_general_isr(void) __interrupt 16; void ao_radio_get(void); diff --git a/src/ao_adc.c b/src/ao_adc.c index 50f96848..49d2519e 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -41,7 +41,7 @@ ao_adc_get(__xdata struct ao_adc *packet) } void -ao_adc_isr(void) interrupt 1 +ao_adc_isr(void) __interrupt 1 { uint8_t sequence; uint8_t __xdata *a; diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 4a68fba4..a54a2316 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -263,13 +263,12 @@ ao_cmd_register(__code struct ao_cmds *cmds) } void -ao_cmd(void *parameters) +ao_cmd(void) { __xdata char c; __xdata uint8_t cmd, cmds; __code struct ao_cmds * __xdata cs; void (*__xdata func)(void); - (void) parameters; lex_echo = 1; for (;;) { diff --git a/src/ao_dma.c b/src/ao_dma.c index 110138b5..946666ab 100644 --- a/src/ao_dma.c +++ b/src/ao_dma.c @@ -112,7 +112,7 @@ ao_dma_abort(uint8_t id) } void -ao_dma_isr(void) interrupt 8 +ao_dma_isr(void) __interrupt 8 { uint8_t id, mask; diff --git a/src/ao_radio.c b/src/ao_radio.c index 0849349e..f4a9d3b2 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -275,7 +275,7 @@ __xdata uint8_t ao_radio_done; __xdata uint8_t ao_radio_mutex; void -ao_radio_general_isr(void) interrupt 16 +ao_radio_general_isr(void) __interrupt 16 { S1CON &= ~0x03; if (RFIF & RFIF_IM_TIMEOUT) { diff --git a/src/ao_serial.c b/src/ao_serial.c index 3f103766..a48734c2 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -21,7 +21,7 @@ volatile __xdata struct ao_fifo ao_usart1_rx_fifo; volatile __xdata struct ao_fifo ao_usart1_tx_fifo; void -ao_serial_rx1_isr(void) interrupt 3 +ao_serial_rx1_isr(void) __interrupt 3 { if (!ao_fifo_full(ao_usart1_rx_fifo)) ao_fifo_insert(ao_usart1_rx_fifo, U1DBUF); @@ -42,7 +42,7 @@ ao_serial_tx1_start(void) } void -ao_serial_tx1_isr(void) interrupt 14 +ao_serial_tx1_isr(void) __interrupt 14 { UTX1IF = 0; ao_serial_tx1_started = 0; diff --git a/src/ao_timer.c b/src/ao_timer.c index d1731475..c977fbc8 100644 --- a/src/ao_timer.c +++ b/src/ao_timer.c @@ -41,7 +41,7 @@ volatile __data uint8_t ao_adc_interval = 1; volatile __data uint8_t ao_adc_count; #endif -void ao_timer_isr(void) interrupt 9 +void ao_timer_isr(void) __interrupt 9 { ++ao_tick_count; #if HAS_ADC diff --git a/src/ao_usb.c b/src/ao_usb.c index f6e0fcf9..b55130f2 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -43,7 +43,7 @@ ao_usb_set_interrupts(void) * so when we hook that up, fix this */ void -ao_usb_isr(void) interrupt 6 +ao_usb_isr(void) __interrupt 6 { USBIF = 0; ao_usb_iif |= USBIIF; diff --git a/src/cc1111.h b/src/cc1111.h index e8302df2..20ed052a 100644 --- a/src/cc1111.h +++ b/src/cc1111.h @@ -40,16 +40,16 @@ #include #include -sfr at 0xA8 IEN0; /* Interrupt Enable 0 Register */ +sfr __at 0xA8 IEN0; /* Interrupt Enable 0 Register */ -sbit at 0xA8 RFTXRXIE; /* RF TX/RX done interrupt enable */ -sbit at 0xA9 ADCIE; /* ADC interrupt enable */ -sbit at 0xAA URX0IE; /* USART0 RX interrupt enable */ -sbit at 0xAB URX1IE; /* USART1 RX interrupt enable (shared with I2S RX) */ -sbit at 0xAB I2SRXIE; /* I2S RX interrupt enable (shared with USART1 RX) */ -sbit at 0xAC ENCIE; /* AES encryption/decryption interrupt enable */ -sbit at 0xAD STIE; /* Sleep Timer interrupt enable */ -sbit at 0xAF EA; /* Enable All */ +sbit __at 0xA8 RFTXRXIE; /* RF TX/RX done interrupt enable */ +sbit __at 0xA9 ADCIE; /* ADC interrupt enable */ +sbit __at 0xAA URX0IE; /* USART0 RX interrupt enable */ +sbit __at 0xAB URX1IE; /* USART1 RX interrupt enable (shared with I2S RX) */ +sbit __at 0xAB I2SRXIE; /* I2S RX interrupt enable (shared with USART1 RX) */ +sbit __at 0xAC ENCIE; /* AES encryption/decryption interrupt enable */ +sbit __at 0xAD STIE; /* Sleep Timer interrupt enable */ +sbit __at 0xAF EA; /* Enable All */ #define IEN0_EA (1 << 7) #define IEN0_STIE (1 << 5) @@ -60,7 +60,7 @@ sbit at 0xAF EA; /* Enable All */ #define IEN0_ADCIE (1 << 1) #define IEN0_RFTXRXIE (1 << 0) -sfr at 0xB8 IEN1; /* Interrupt Enable 1 Register */ +sfr __at 0xB8 IEN1; /* Interrupt Enable 1 Register */ #define IEN1_P0IE (1 << 5) /* Port 0 interrupt enable */ #define IEN1_T4IE (1 << 4) /* Timer 4 interrupt enable */ @@ -70,7 +70,7 @@ sfr at 0xB8 IEN1; /* Interrupt Enable 1 Register */ #define IEN1_DMAIE (1 << 0) /* DMA transfer interrupt enable */ /* IEN2 */ -sfr at 0x9A IEN2; /* Interrupt Enable 2 Register */ +sfr __at 0x9A IEN2; /* Interrupt Enable 2 Register */ #define IEN2_WDTIE (1 << 5) /* Watchdog timer interrupt enable */ #define IEN2_P1IE (1 << 4) /* Port 1 interrupt enable */ @@ -82,7 +82,7 @@ sfr at 0x9A IEN2; /* Interrupt Enable 2 Register */ #define IEN2_RFIE (1 << 0) /* RF general interrupt enable */ /* CLKCON 0xC6 */ -sfr at 0xC6 CLKCON; /* Clock Control */ +sfr __at 0xC6 CLKCON; /* Clock Control */ #define CLKCON_OSC32K_RC (1 << 7) #define CLKCON_OSC32K_XTAL (0 << 7) @@ -126,20 +126,20 @@ sfr at 0xC6 CLKCON; /* Clock Control */ #define SLEEP_MODE_MASK (3 << 0) /* PCON 0x87 */ -sfr at 0x87 PCON; /* Power Mode Control Register */ +sfr __at 0x87 PCON; /* Power Mode Control Register */ #define PCON_IDLE (1 << 0) /* * TCON */ -sfr at 0x88 TCON; /* CPU Interrupt Flag 1 */ +sfr __at 0x88 TCON; /* CPU Interrupt Flag 1 */ -sbit at 0x8F URX1IF; /* USART1 RX interrupt flag. Automatically cleared */ -sbit at 0x8F I2SRXIF; /* I2S RX interrupt flag. Automatically cleared */ -sbit at 0x8D ADCIF; /* ADC interrupt flag. Automatically cleared */ -sbit at 0x8B URX0IF; /* USART0 RX interrupt flag. Automatically cleared */ -sbit at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically cleared */ +sbit __at 0x8F URX1IF; /* USART1 RX interrupt flag. Automatically cleared */ +sbit __at 0x8F I2SRXIF; /* I2S RX interrupt flag. Automatically cleared */ +sbit __at 0x8D ADCIF; /* ADC interrupt flag. Automatically cleared */ +sbit __at 0x8B URX0IF; /* USART0 RX interrupt flag. Automatically cleared */ +sbit __at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically cleared */ #define TCON_URX1IF (1 << 7) #define TCON_I2SRXIF (1 << 7) @@ -150,10 +150,10 @@ sbit at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically cleare /* * S0CON */ -sfr at 0x98 S0CON; /* CPU Interrupt Flag 2 */ +sfr __at 0x98 S0CON; /* CPU Interrupt Flag 2 */ -sbit at 0x98 ENCIF_0; /* AES interrupt 0. */ -sbit at 0x99 ENCIF_1; /* AES interrupt 1. */ +sbit __at 0x98 ENCIF_0; /* AES interrupt 0. */ +sbit __at 0x99 ENCIF_1; /* AES interrupt 1. */ #define S0CON_ENCIF_1 (1 << 1) #define S0CON_ENCIF_0 (1 << 0) @@ -161,7 +161,7 @@ sbit at 0x99 ENCIF_1; /* AES interrupt 1. */ /* * S1CON */ -sfr at 0x9B S1CON; /* CPU Interrupt Flag 3 */ +sfr __at 0x9B S1CON; /* CPU Interrupt Flag 3 */ #define S1CON_RFIF_1 (1 << 1) #define S1CON_RFIF_0 (1 << 0) @@ -169,15 +169,15 @@ sfr at 0x9B S1CON; /* CPU Interrupt Flag 3 */ /* * IRCON */ -sfr at 0xC0 IRCON; /* CPU Interrupt Flag 4 */ +sfr __at 0xC0 IRCON; /* CPU Interrupt Flag 4 */ -sbit at 0xC0 DMAIF; /* DMA complete interrupt flag */ -sbit at 0xC1 T1IF; /* Timer 1 interrupt flag. Automatically cleared */ -sbit at 0xC2 T2IF; /* Timer 2 interrupt flag. Automatically cleared */ -sbit at 0xC3 T3IF; /* Timer 3 interrupt flag. Automatically cleared */ -sbit at 0xC4 T4IF; /* Timer 4 interrupt flag. Automatically cleared */ -sbit at 0xC5 P0IF; /* Port0 interrupt flag */ -sbit at 0xC7 STIF; /* Sleep Timer interrupt flag */ +sbit __at 0xC0 DMAIF; /* DMA complete interrupt flag */ +sbit __at 0xC1 T1IF; /* Timer 1 interrupt flag. Automatically cleared */ +sbit __at 0xC2 T2IF; /* Timer 2 interrupt flag. Automatically cleared */ +sbit __at 0xC3 T3IF; /* Timer 3 interrupt flag. Automatically cleared */ +sbit __at 0xC4 T4IF; /* Timer 4 interrupt flag. Automatically cleared */ +sbit __at 0xC5 P0IF; /* Port0 interrupt flag */ +sbit __at 0xC7 STIF; /* Sleep Timer interrupt flag */ #define IRCON_DMAIF (1 << 0) /* DMA complete interrupt flag */ #define IRCON_T1IF (1 << 1) /* Timer 1 interrupt flag. Automatically cleared */ @@ -190,15 +190,15 @@ sbit at 0xC7 STIF; /* Sleep Timer interrupt flag */ /* * IRCON2 */ -sfr at 0xE8 IRCON2; /* CPU Interrupt Flag 5 */ +sfr __at 0xE8 IRCON2; /* CPU Interrupt Flag 5 */ -sbit at 0xE8 USBIF; /* USB interrupt flag (shared with Port2) */ -sbit at 0xE8 P2IF; /* Port2 interrupt flag (shared with USB) */ -sbit at 0xE9 UTX0IF; /* USART0 TX interrupt flag */ -sbit at 0xEA UTX1IF; /* USART1 TX interrupt flag (shared with I2S TX) */ -sbit at 0xEA I2STXIF; /* I2S TX interrupt flag (shared with USART1 TX) */ -sbit at 0xEB P1IF; /* Port1 interrupt flag */ -sbit at 0xEC WDTIF; /* Watchdog timer interrupt flag */ +sbit __at 0xE8 USBIF; /* USB interrupt flag (shared with Port2) */ +sbit __at 0xE8 P2IF; /* Port2 interrupt flag (shared with USB) */ +sbit __at 0xE9 UTX0IF; /* USART0 TX interrupt flag */ +sbit __at 0xEA UTX1IF; /* USART1 TX interrupt flag (shared with I2S TX) */ +sbit __at 0xEA I2STXIF; /* I2S TX interrupt flag (shared with USART1 TX) */ +sbit __at 0xEB P1IF; /* Port1 interrupt flag */ +sbit __at 0xEC WDTIF; /* Watchdog timer interrupt flag */ #define IRCON2_USBIF (1 << 0) /* USB interrupt flag (shared with Port2) */ #define IRCON2_P2IF (1 << 0) /* Port2 interrupt flag (shared with USB) */ @@ -225,8 +225,8 @@ sbit at 0xEC WDTIF; /* Watchdog timer interrupt flag */ * Priority = (IP1 << 1) | IP0. Higher priority interrupts served first */ -sfr at 0xB9 IP1; /* Interrupt Priority 1 */ -sfr at 0xA9 IP0; /* Interrupt Priority 0 */ +sfr __at 0xB9 IP1; /* Interrupt Priority 1 */ +sfr __at 0xA9 IP0; /* Interrupt Priority 0 */ #define IP1_IPG5 (1 << 5) #define IP1_IPG4 (1 << 4) @@ -286,13 +286,13 @@ sfr at 0xA9 IP0; /* Interrupt Priority 0 */ */ /* Timer count */ -sfr at 0xCA T3CNT; -sfr at 0xEA T4CNT; +sfr __at 0xCA T3CNT; +sfr __at 0xEA T4CNT; /* Timer control */ -sfr at 0xCB T3CTL; -sfr at 0xEB T4CTL; +sfr __at 0xCB T3CTL; +sfr __at 0xEB T4CTL; #define TxCTL_DIV_1 (0 << 5) #define TxCTL_DIV_2 (1 << 5) @@ -312,10 +312,10 @@ sfr at 0xEB T4CTL; /* Timer 4 channel 0 compare control */ -sfr at 0xCC T3CCTL0; -sfr at 0xCE T3CCTL1; -sfr at 0xEC T4CCTL0; -sfr at 0xEE T4CCTL1; +sfr __at 0xCC T3CCTL0; +sfr __at 0xCE T3CCTL1; +sfr __at 0xEC T4CCTL0; +sfr __at 0xEE T4CCTL1; #define TxCCTLy_IM (1 << 6) #define TxCCTLy_CMP_SET (0 << 3) @@ -328,16 +328,16 @@ sfr at 0xEE T4CCTL1; #define TxCCTLy_CMP_MODE_ENABLE (1 << 2) /* Timer compare value */ -sfr at 0xCD T3CC0; -sfr at 0xCF T3CC1; -sfr at 0xED T4CC0; -sfr at 0xEF T4CC1; +sfr __at 0xCD T3CC0; +sfr __at 0xCF T3CC1; +sfr __at 0xED T4CC0; +sfr __at 0xEF T4CC1; /* * Peripheral control */ -sfr at 0xf1 PERCFG; +sfr __at 0xf1 PERCFG; #define PERCFG_T1CFG_ALT_1 (0 << 6) #define PERCFG_T1CFG_ALT_2 (1 << 6) #define PERCFG_T1CFG_ALT_MASK (1 << 6) -- cgit v1.2.3 From c4a8569f61eddf690d00337543462235ecbfbe54 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Aug 2010 22:41:18 -0700 Subject: altos: flush pending output when terminating packet mode Just in case the last command sent hasn't been transmitted, hang around for up to a second waiting for the data to get across the link. Signed-off-by: Keith Packard --- src/ao_packet_master.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index 72bb908a..5e13a91a 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -121,6 +121,10 @@ ao_packet_forward(void) __reentrant if (c == '\r') c = '\n'; ao_packet_putchar(c); } + + /* Wait for a second if there is any pending data */ + for (c = 0; (ao_packet_tx_used || ao_tx_packet.len) && c < 10; c++) + ao_delay(AO_MS_TO_TICKS(100)); ao_packet_enable = 0; ao_radio_abort(); while (ao_packet_echo_task.wchan || ao_packet_task.wchan) { -- cgit v1.2.3 From 43619c13f749b79c096d1e8fdab3d5cfb5fd85f1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Aug 2010 22:42:23 -0700 Subject: altos: Abort radio harder when terminating packet mode. Make sure the master radio tasks don't get stuck waiting for an incoming packet again by aborting the radio each time we poke the tasks. Signed-off-by: Keith Packard --- src/ao_packet_master.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index 5e13a91a..50f5aeff 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -126,8 +126,8 @@ ao_packet_forward(void) __reentrant for (c = 0; (ao_packet_tx_used || ao_tx_packet.len) && c < 10; c++) ao_delay(AO_MS_TO_TICKS(100)); ao_packet_enable = 0; - ao_radio_abort(); while (ao_packet_echo_task.wchan || ao_packet_task.wchan) { + ao_radio_abort(); ao_wake_task(&ao_packet_echo_task); ao_wake_task(&ao_packet_task); ao_yield(); -- cgit v1.2.3 From 63c832394a829f41b8f77d075786530536360349 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Aug 2010 23:22:27 -0700 Subject: altos: shut down packet mode cleanly Instead of constantly bashing the packet master thread, let it shut itself down in an orderly fashion. It will shut down fairly quickly as all of the activities in that thread are bounded. Otherwise, the master packet thread might leave mutexes locked and all sorts of other horrors. Tested on Linux and Mac OS X and shown to be reliable. Signed-off-by: Keith Packard --- src/ao_packet_master.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index 50f5aeff..641b49f4 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -29,6 +29,8 @@ ao_packet_getchar(void) __critical ao_wake_task(&ao_packet_task); ao_usb_flush(); ao_sleep(&ao_stdin_ready); + if (!ao_packet_enable) + break; } return c; } @@ -127,10 +129,9 @@ ao_packet_forward(void) __reentrant ao_delay(AO_MS_TO_TICKS(100)); ao_packet_enable = 0; while (ao_packet_echo_task.wchan || ao_packet_task.wchan) { - ao_radio_abort(); - ao_wake_task(&ao_packet_echo_task); - ao_wake_task(&ao_packet_task); - ao_yield(); + if (ao_packet_echo_task.wchan) + ao_wake_task(&ao_packet_echo_task); + ao_delay(AO_MS_TO_TICKS(10)); } } -- cgit v1.2.3 From c7ba92317ac55272acbde12416448ebd17b983a6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 30 Aug 2010 04:52:00 -0700 Subject: altos: Windows sends USB Out packets of 0 length. Ack them. This was an untested case as no other operating system sents 0-length out packets (they're not necessary). The correct response is to ACK them by clearing the OUTPKT_RDY bit so that another packet can be sent. Signed-off-by: Keith Packard --- src/ao_usb.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_usb.c b/src/ao_usb.c index b55130f2..b4e3f1fe 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -383,8 +383,11 @@ ao_usb_pollchar(void) __critical if ((USBCSOL & USBCSOL_OUTPKT_RDY) == 0) return AO_READ_AGAIN; ao_usb_out_bytes = (USBCNTH << 8) | USBCNTL; - if (ao_usb_out_bytes == 0) + if (ao_usb_out_bytes == 0) { + USBINDEX = AO_USB_OUT_EP; + USBCSOL &= ~USBCSOL_OUTPKT_RDY; return AO_READ_AGAIN; + } } --ao_usb_out_bytes; c = USBFIFO[AO_USB_OUT_EP << 1]; -- cgit v1.2.3 From 1177e0a684328422be5adc68093d0091a218a824 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 1 Sep 2010 19:53:24 -0700 Subject: altos: Bounds check Skytraq GPS tracking data array Missing GPS serial data could cause the tracking array reset to get skipped, causing the array to be overrun, smashing critical data beyond the array. This was detected using the 'altosui' flash command to program a device from TM. Hitting the USB that hard caused TM to crash with a mutex error (3 beeps) after the ao_gps_task structure was overwritten with zeros. Signed-off-by: Keith Packard --- src/ao.h | 4 +++- src/ao_gps_skytraq.c | 13 +++++++++---- src/ao_gps_test.c | 4 +++- src/ao_gps_test_skytraq.c | 4 +++- 4 files changed, 18 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index cd4e4814..5b174947 100644 --- a/src/ao.h +++ b/src/ao.h @@ -781,9 +781,11 @@ struct ao_gps_sat_data { uint8_t c_n_1; }; +#define AO_MAX_GPS_TRACKING 12 + struct ao_gps_tracking_data { uint8_t channels; - struct ao_gps_sat_data sats[12]; + struct ao_gps_sat_data sats[AO_MAX_GPS_TRACKING]; }; extern __xdata uint8_t ao_gps_mutex; diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index c822f7fa..2d3d464c 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -333,14 +333,19 @@ ao_gps(void) __reentrant ao_gps_skip_field(); /* sats in view */ while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { i = ao_gps_tracking_next.channels; - ao_gps_tracking_next.sats[i].svid = ao_gps_decimal(2); /* SVID */ + c = ao_gps_decimal(2); /* SVID */ + if (i < AO_MAX_GPS_TRACKING) + ao_gps_tracking_next.sats[i].svid = c; ao_gps_lexchar(); ao_gps_skip_field(); /* elevation */ ao_gps_lexchar(); ao_gps_skip_field(); /* azimuth */ - if (!(ao_gps_tracking_next.sats[i].c_n_1 = ao_gps_decimal(2))) /* C/N0 */ - ao_gps_tracking_next.sats[i].svid = 0; - ao_gps_tracking_next.channels = i + 1; + c = ao_gps_decimal(2); /* C/N0 */ + if (i < AO_MAX_GPS_TRACKING) { + if (!(ao_gps_tracking_next.sats[i].c_n_1 = c)) + ao_gps_tracking_next.sats[i].svid = 0; + ao_gps_tracking_next.channels = i + 1; + } } if (ao_gps_char == '*') { uint8_t cksum = ao_gps_cksum ^ '*'; diff --git a/src/ao_gps_test.c b/src/ao_gps_test.c index cdcc6f4c..edb51304 100644 --- a/src/ao_gps_test.c +++ b/src/ao_gps_test.c @@ -62,9 +62,11 @@ struct ao_gps_sat_data { uint8_t c_n_1; }; +#define AO_MAX_GPS_TRACKING 12 + struct ao_gps_tracking_data { uint8_t channels; - struct ao_gps_sat_data sats[12]; + struct ao_gps_sat_data sats[AO_MAX_GPS_TRACKING]; }; void diff --git a/src/ao_gps_test_skytraq.c b/src/ao_gps_test_skytraq.c index 7fa10eaa..4010e09c 100644 --- a/src/ao_gps_test_skytraq.c +++ b/src/ao_gps_test_skytraq.c @@ -63,9 +63,11 @@ struct ao_gps_sat_data { uint8_t c_n_1; }; +#define AO_MAX_GPS_TRACKING 12 + struct ao_gps_tracking_data { uint8_t channels; - struct ao_gps_sat_data sats[12]; + struct ao_gps_sat_data sats[AO_MAX_GPS_TRACKING]; }; void -- cgit v1.2.3 From bc183400ab93d5902c52851319999cc77f27bc81 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 4 Sep 2010 17:35:17 -0700 Subject: altos: add some SDCDB config files --- src/telemetrum-v0.1-sky/.sdcdbrc | 1 + src/telemetrum-v1.0/.sdcdbrc | 1 + 2 files changed, 2 insertions(+) create mode 100644 src/telemetrum-v0.1-sky/.sdcdbrc create mode 100644 src/telemetrum-v1.0/.sdcdbrc (limited to 'src') diff --git a/src/telemetrum-v0.1-sky/.sdcdbrc b/src/telemetrum-v0.1-sky/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telemetrum-v0.1-sky/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telemetrum-v1.0/.sdcdbrc b/src/telemetrum-v1.0/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telemetrum-v1.0/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. -- cgit v1.2.3 From aed59e1c057c13e28fd368dc2592aa4628211097 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 4 Sep 2010 17:59:11 -0700 Subject: Add version numbers to released files. Set version to 0.7.1 Instead of using git revision counts for version numbers, use explicit versions numbers configured in the configure.ac file. Expose published files with version numbers. Signed-off-by: Keith Packard --- ao-tools/altosui/Makefile.am | 8 ++++---- ao-tools/altosui/altos-windows.nsi | 4 ++-- configure.ac | 2 +- src/Makefile | 2 ++ src/Makefile.proto | 6 ++---- src/Version.in | 1 + src/teledongle-v0.1/.gitignore | 2 +- src/teledongle-v0.1/Makefile.defs | 2 +- src/teledongle-v0.2/.gitignore | 2 +- src/teledongle-v0.2/Makefile.defs | 2 +- src/telemetrum-v0.1-sirf/.gitignore | 2 +- src/telemetrum-v0.1-sirf/Makefile.defs | 2 +- src/telemetrum-v0.1-sky/.gitignore | 2 +- src/telemetrum-v0.1-sky/Makefile.defs | 2 +- src/telemetrum-v1.0/.gitignore | 2 +- src/telemetrum-v1.0/Makefile.defs | 2 +- src/tidongle/.gitignore | 2 +- src/tidongle/Makefile.defs | 2 +- 18 files changed, 24 insertions(+), 23 deletions(-) create mode 100644 src/Version.in (limited to 'src') diff --git a/ao-tools/altosui/Makefile.am b/ao-tools/altosui/Makefile.am index 20c8b26d..ed7e2f76 100644 --- a/ao-tools/altosui/Makefile.am +++ b/ao-tools/altosui/Makefile.am @@ -66,8 +66,8 @@ JAVA_ICON=$(top_srcdir)/icon/altus-metrum-16x16.jpg WINDOWS_ICON=$(top_srcdir)/icon/altus-metrum.ico # Firmware -FIRMWARE_TD=$(top_srcdir)/src/teledongle-v0.2.ihx -FIRMWARE_TM=$(top_srcdir)/src/telemetrum-v1.0.ihx +FIRMWARE_TD=$(top_srcdir)/src/teledongle-v0.2-$(VERSION).ihx +FIRMWARE_TM=$(top_srcdir)/src/telemetrum-v1.0-$(VERSION).ihx FIRMWARE=$(FIRMWARE_TM) $(FIRMWARE_TD) # Distribution targets @@ -77,7 +77,7 @@ WINDOWS_DIST=Altos-Windows-$(VERSION_DASH).exe FAT_FILES=$(FATJAR) $(FREETTS_CLASS) -LINUX_FILES=$(FAT_FILES) libaltos.so +LINUX_FILES=$(FAT_FILES) libaltos.so $(FIRMWARE) MACOSX_FILES=$(FAT_FILES) libaltos.dylib MACOSX_EXTRA=$(FIRMWARE) @@ -162,4 +162,4 @@ $(MACOSX_DIST): $(MACOSX_FILES) $(MACOSX_EXTRA) $(WINDOWS_DIST): $(WINDOWS_FILES) altos-windows.nsi -rm -f $@ - makensis -Oaltos-windows.log "-XOutFile $@" altos-windows.nsi \ No newline at end of file + makensis -Oaltos-windows.log "-XOutFile $@" "-DVERSION=$(VERSION)" altos-windows.nsi \ No newline at end of file diff --git a/ao-tools/altosui/altos-windows.nsi b/ao-tools/altosui/altos-windows.nsi index 6f38ac0e..c8539a5c 100644 --- a/ao-tools/altosui/altos-windows.nsi +++ b/ao-tools/altosui/altos-windows.nsi @@ -69,8 +69,8 @@ Section "TeleMetrum and TeleDongle Firmware" SetOutPath $INSTDIR - File "../../src/telemetrum-v1.0/telemetrum-v1.0.ihx" - File "../../src/teledongle-v0.2/teledongle-v0.2.ihx" + File "../../src/telemetrum-v1.0/telemetrum-v1.0-${VERSION}.ihx" + File "../../src/teledongle-v0.2/teledongle-v0.2-${VERSION}.ihx" SectionEnd diff --git a/configure.ac b/configure.ac index 19ae0ac8..d376af3f 100644 --- a/configure.ac +++ b/configure.ac @@ -59,7 +59,6 @@ fi AC_PROG_CC AC_PROG_INSTALL AC_PROG_LN_S -AC_PROG_RANLIB AC_PROG_LIBTOOL PKG_PROG_PKG_CONFIG @@ -126,4 +125,5 @@ ao-tools/ao-view/Makefile ao-tools/libaltos/Makefile ao-tools/altosui/Makefile ao-utils/Makefile +src/Version ]) diff --git a/src/Makefile b/src/Makefile index 24f562e1..95d24425 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,6 +4,8 @@ # CC=sdcc +include Version + SUBDIRS=telemetrum-v1.0 teledongle-v0.2 telemetrum-v0.1-sky telemetrum-v0.1-sirf teledongle-v0.1 tidongle test all: all-recursive diff --git a/src/Makefile.proto b/src/Makefile.proto index 59a3b8a6..b23eb257 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -10,7 +10,7 @@ vpath ao-make-product.5c .. CC=sdcc ifndef VERSION -VERSION=$(shell git describe) +include ../Version endif CFLAGS=--model-small --debug --opt-code-speed @@ -214,11 +214,9 @@ all: ../$(PROG) ../altitude.h: make-altitude nickle $< > $@ -ao_product.h: ao-make-product.5c always +ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ -always: - ao_product.rel: ao_product.c ao_product.h $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< diff --git a/src/Version.in b/src/Version.in new file mode 100644 index 00000000..aff9490b --- /dev/null +++ b/src/Version.in @@ -0,0 +1 @@ +VERSION=@VERSION@ diff --git a/src/teledongle-v0.1/.gitignore b/src/teledongle-v0.1/.gitignore index 96c802bd..9826814b 100644 --- a/src/teledongle-v0.1/.gitignore +++ b/src/teledongle-v0.1/.gitignore @@ -1,2 +1,2 @@ -teledongle-v0.1 +teledongle-v0.1* ao_product.h diff --git a/src/teledongle-v0.1/Makefile.defs b/src/teledongle-v0.1/Makefile.defs index be7741d8..ceb80b7a 100644 --- a/src/teledongle-v0.1/Makefile.defs +++ b/src/teledongle-v0.1/Makefile.defs @@ -1,4 +1,4 @@ -PROG = teledongle-v0.1.ihx +PROG = teledongle-v0.1-$(VERSION).ihx SRC = \ $(TD_SRC) \ diff --git a/src/teledongle-v0.2/.gitignore b/src/teledongle-v0.2/.gitignore index af79a766..f6ea8c6c 100644 --- a/src/teledongle-v0.2/.gitignore +++ b/src/teledongle-v0.2/.gitignore @@ -1,2 +1,2 @@ -teledongle-v0.2 +teledongle-v0.2* ao_product.h diff --git a/src/teledongle-v0.2/Makefile.defs b/src/teledongle-v0.2/Makefile.defs index cbec7805..ea9713b6 100644 --- a/src/teledongle-v0.2/Makefile.defs +++ b/src/teledongle-v0.2/Makefile.defs @@ -1,4 +1,4 @@ -PROG = teledongle-v0.2.ihx +PROG = teledongle-v0.2-$(VERSION).ihx SRC = \ $(TD_SRC) \ diff --git a/src/telemetrum-v0.1-sirf/.gitignore b/src/telemetrum-v0.1-sirf/.gitignore index 6d584f36..7698f5aa 100644 --- a/src/telemetrum-v0.1-sirf/.gitignore +++ b/src/telemetrum-v0.1-sirf/.gitignore @@ -1,2 +1,2 @@ -telemetrum-v0.1-sirf +telemetrum-v0.1-sirf* ao_product.h diff --git a/src/telemetrum-v0.1-sirf/Makefile.defs b/src/telemetrum-v0.1-sirf/Makefile.defs index 2ce6e6ed..a7310fbc 100644 --- a/src/telemetrum-v0.1-sirf/Makefile.defs +++ b/src/telemetrum-v0.1-sirf/Makefile.defs @@ -1,4 +1,4 @@ -PROG = telemetrum-v0.1-sirf.ihx +PROG = telemetrum-v0.1-sirf-$(VERSION).ihx SRC = \ $(TM_BASE_SRC) \ diff --git a/src/telemetrum-v0.1-sky/.gitignore b/src/telemetrum-v0.1-sky/.gitignore index 5a9fafb5..d25d7ad9 100644 --- a/src/telemetrum-v0.1-sky/.gitignore +++ b/src/telemetrum-v0.1-sky/.gitignore @@ -1,2 +1,2 @@ -telemetrum-v0.1-sky +telemetrum-v0.1-sky* ao_product.h diff --git a/src/telemetrum-v0.1-sky/Makefile.defs b/src/telemetrum-v0.1-sky/Makefile.defs index 098ac547..000287ba 100644 --- a/src/telemetrum-v0.1-sky/Makefile.defs +++ b/src/telemetrum-v0.1-sky/Makefile.defs @@ -1,4 +1,4 @@ -PROG = telemetrum-v0.1-sky.ihx +PROG = telemetrum-v0.1-sky-$(VERSION).ihx SRC = \ $(TM_BASE_SRC) \ diff --git a/src/telemetrum-v1.0/.gitignore b/src/telemetrum-v1.0/.gitignore index 76228093..c2212151 100644 --- a/src/telemetrum-v1.0/.gitignore +++ b/src/telemetrum-v1.0/.gitignore @@ -1,2 +1,2 @@ -telemetrum-v0.2 +telemetrum-* ao_product.h diff --git a/src/telemetrum-v1.0/Makefile.defs b/src/telemetrum-v1.0/Makefile.defs index 624ce6e8..010578df 100644 --- a/src/telemetrum-v1.0/Makefile.defs +++ b/src/telemetrum-v1.0/Makefile.defs @@ -1,4 +1,4 @@ -PROG = telemetrum-v1.0.ihx +PROG = telemetrum-v1.0-$(VERSION).ihx SRC = \ $(TM_BASE_SRC) \ diff --git a/src/tidongle/.gitignore b/src/tidongle/.gitignore index 3323f640..3888a0f9 100644 --- a/src/tidongle/.gitignore +++ b/src/tidongle/.gitignore @@ -1,2 +1,2 @@ -tidongle +tidongle* ao_product.h diff --git a/src/tidongle/Makefile.defs b/src/tidongle/Makefile.defs index fdd51732..0e13cb20 100644 --- a/src/tidongle/Makefile.defs +++ b/src/tidongle/Makefile.defs @@ -1,4 +1,4 @@ -PROG = tidongle.ihx +PROG = tidongle-$(VERSION).ihx SRC = \ $(TI_SRC) -- cgit v1.2.3 From 377ee7e90ecd028f984cd1abce96b2efc3b5b977 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 21 Nov 2010 14:03:17 -0800 Subject: altos: Add on/off modes to 'C' command This lets the user turn the radio on/off and then invoke other commands. Signed-off-by: Keith Packard --- src/ao_radio.c | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/ao_radio.c b/src/ao_radio.c index f4a9d3b2..3fb4afd7 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -448,19 +448,32 @@ ao_radio_rdf_abort(void) void ao_radio_test(void) { - ao_set_monitor(0); - ao_packet_slave_stop(); - ao_radio_get(); - printf ("Hit a character to stop..."); flush(); - RFST = RFST_STX; - getchar(); - ao_radio_idle(); - ao_radio_put(); - putchar('\n'); + uint8_t mode = 2; + ao_cmd_white(); + if (ao_cmd_lex_c != '\n') { + ao_cmd_decimal(); + mode = (uint8_t) ao_cmd_lex_u32; + } + mode++; + if (mode & 2) { + ao_set_monitor(0); + ao_packet_slave_stop(); + ao_radio_get(); + RFST = RFST_STX; + } + if (mode == 3) { + printf ("Hit a character to stop..."); flush(); + getchar(); + putchar('\n'); + } + if (mode & 1) { + ao_radio_idle(); + ao_radio_put(); + } } __code struct ao_cmds ao_radio_cmds[] = { - { 'C', ao_radio_test, "C Radio carrier test" }, + { 'C', ao_radio_test, "C <1 start, 0 stop, none both> Radio carrier test" }, { 0, ao_radio_test, NULL }, }; -- cgit v1.2.3 From b27327a05d249eaf969b67d2a8d12fc6a93841f0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 22 Nov 2010 15:56:04 -0800 Subject: altos: assume igniter worked. Many igniters don't go open when fired, so there's no way to know if they worked. Assume they did as a failed igniter is unlikely to do anything when fired again anyways. Signed-off-by: Keith Packard --- src/ao_ignite.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/ao_ignite.c b/src/ao_ignite.c index 4093b6a7..58d340d9 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -113,9 +113,7 @@ ao_igniter(void) ao_igniter_fire(igniter); ao_delay(AO_IGNITER_CHARGE_TIME); - status = ao_igniter_status(igniter); - if (status == ao_igniter_open) - ao_ignition[igniter].fired = 1; + ao_ignition[igniter].fired = 1; } } } -- cgit v1.2.3 From d873dc28f0752aeb58a6263e42bdd5b9095bd392 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 23 Nov 2010 18:56:46 -0800 Subject: altos: remove unused variable from ao_igniter The 'status' variable used to hold a reported status value from the igniter after firing, but we ignore that now. Signed-off-by: Keith Packard --- src/ao_ignite.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/ao_ignite.c b/src/ao_ignite.c index 58d340d9..f2b15dd2 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -101,7 +101,6 @@ void ao_igniter(void) { __xdata enum ao_ignter igniter; - __xdata enum ao_igniter_status status; ao_config_get(); for (;;) { -- cgit v1.2.3 From 54468e5dc567aaac5c5c20e921859b7cec28bb88 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 23 Nov 2010 18:57:49 -0800 Subject: altos: Don't abort radio transmissions with ao_radio_abort We only want to abort pending radio reception to release the radio for other use, or to change the radio channel. Let radio transmission proceed. This fixes a problem with using packet mode to configure the radio channel; if the packet transmission is aborted, the TM ends up wedged. Signed-off-by: Keith Packard --- src/ao_radio.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao_radio.c b/src/ao_radio.c index 3fb4afd7..b2105ff8 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -432,8 +432,11 @@ ao_radio_rdf(int ms) void ao_radio_abort(void) { - ao_dma_abort(ao_radio_dma); - ao_radio_idle(); + /* Only abort if a task is waiting to receive data */ + if (RFST == RFST_SRX) { + ao_dma_abort(ao_radio_dma); + ao_radio_idle(); + } } void -- cgit v1.2.3 From 3b9db8c82d26a6a2e43d4ca40742fc1bdc502380 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 23 Nov 2010 19:02:54 -0800 Subject: altos: Make radio test command careful with the radio mutex. Remember whether the radio test mode is on or off and don't try to do either of them twice to prevent the mutex from being acquired or released twice. Signed-off-by: Keith Packard --- src/ao_radio.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao_radio.c b/src/ao_radio.c index b2105ff8..67d5f6ba 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -452,26 +452,29 @@ void ao_radio_test(void) { uint8_t mode = 2; + static __xdata radio_on; ao_cmd_white(); if (ao_cmd_lex_c != '\n') { ao_cmd_decimal(); mode = (uint8_t) ao_cmd_lex_u32; } mode++; - if (mode & 2) { + if ((mode & 2) && !radio_on) { ao_set_monitor(0); ao_packet_slave_stop(); ao_radio_get(); RFST = RFST_STX; + radio_on = 1; } if (mode == 3) { printf ("Hit a character to stop..."); flush(); getchar(); putchar('\n'); } - if (mode & 1) { + if ((mode & 1) && radio_on) { ao_radio_idle(); ao_radio_put(); + radio_on = 0; } } -- cgit v1.2.3 From 4893ed50bc14772986ac02f9b39928f1882da923 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 24 Nov 2010 23:54:08 -0800 Subject: Revert "altos: Don't abort radio transmissions with ao_radio_abort" This reverts commit 54468e5dc567aaac5c5c20e921859b7cec28bb88. With this patch in place, TD could not be placed in 'packet' mode. --- src/ao_radio.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/ao_radio.c b/src/ao_radio.c index 67d5f6ba..cafa7010 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -432,11 +432,8 @@ ao_radio_rdf(int ms) void ao_radio_abort(void) { - /* Only abort if a task is waiting to receive data */ - if (RFST == RFST_SRX) { - ao_dma_abort(ao_radio_dma); - ao_radio_idle(); - } + ao_dma_abort(ao_radio_dma); + ao_radio_idle(); } void -- cgit v1.2.3 From 07213dc34fa20470a4b36a327a83d75b0f010ebb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 26 Nov 2010 16:14:15 -0800 Subject: altos: clean up radio abort paths. Share radio code. Instead of aborting the DMA and radio operation and expecting that to be handled reasonably by the radio receiving task, rewrite things so that the abort function just wakes the receiving task while that terminates the DMA and cleans up the radio. This eliminates all kinds of nasty bugs dealing with radio abort smashing the radio registers at the wrong time, or interrupting a radio transmission. Signed-off-by: Keith Packard --- src/ao.h | 31 ++++++++-------- src/ao_config.c | 2 +- src/ao_dma.c | 4 +-- src/ao_monitor.c | 6 ++-- src/ao_packet.c | 98 ++++++++++++++++++++++---------------------------- src/ao_packet_master.c | 5 +-- src/ao_packet_slave.c | 7 ++-- src/ao_radio.c | 68 +++++++++++++++++++++-------------- src/ao_telemetry.c | 2 +- 9 files changed, 109 insertions(+), 114 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 5b174947..58659af5 100644 --- a/src/ao.h +++ b/src/ao.h @@ -391,14 +391,10 @@ ao_cmd_init(void); * ao_dma.c */ -/* Allocate a DMA channel. the 'done' parameter will be set - * when the dma is finished or aborted and will be used to - * wakeup any waiters +/* Allocate a DMA channel. the 'done' parameter will be set when the + * dma is finished and will be used to wakeup any waiters */ -#define AO_DMA_DONE 1 -#define AO_DMA_ABORTED 2 - uint8_t ao_dma_alloc(__xdata uint8_t * done); @@ -838,6 +834,15 @@ struct ao_telemetry { struct ao_gps_tracking_data gps_tracking; }; +/* + * ao_radio_recv tacks on rssi and status bytes + */ +struct ao_telemetry_recv { + struct ao_telemetry telemetry; + int8_t rssi; + uint8_t status; +}; + /* Set delay between telemetry reports (0 to disable) */ #define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(1000) @@ -880,22 +885,16 @@ void ao_radio_set_rdf(void); void -ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant; - -struct ao_radio_recv { - struct ao_telemetry telemetry; - int8_t rssi; - uint8_t status; -}; +ao_radio_send(__xdata void *data, uint8_t size) __reentrant; uint8_t -ao_radio_recv(__xdata struct ao_radio_recv *recv) __reentrant; +ao_radio_recv(__xdata void *data, uint8_t size) __reentrant; void -ao_radio_rdf(int ms); +ao_radio_recv_abort(void); void -ao_radio_abort(void); +ao_radio_rdf(int ms); void ao_radio_rdf_abort(void); diff --git a/src/ao_config.c b/src/ao_config.c index 88b52dc0..fd33e2cc 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -141,7 +141,7 @@ ao_config_radio_channel_set(void) __reentrant ao_config_dirty = 1; ao_mutex_put(&ao_config_mutex); ao_config_radio_channel_show(); - ao_radio_abort(); + ao_radio_recv_abort(); } #if HAS_ADC diff --git a/src/ao_dma.c b/src/ao_dma.c index 946666ab..6052964a 100644 --- a/src/ao_dma.c +++ b/src/ao_dma.c @@ -107,8 +107,6 @@ ao_dma_abort(uint8_t id) uint8_t mask = (1 << id); DMAARM = 0x80 | mask; DMAIRQ &= ~mask; - *(ao_dma_done[id]) |= AO_DMA_ABORTED; - ao_wakeup(ao_dma_done[id]); } void @@ -124,7 +122,7 @@ ao_dma_isr(void) __interrupt 8 DMAIF = 0; /* Clear the completed ID */ DMAIRQ = ~mask; - *(ao_dma_done[id]) |= AO_DMA_DONE; + *(ao_dma_done[id]) = 1; ao_wakeup(ao_dma_done[id]); break; } diff --git a/src/ao_monitor.c b/src/ao_monitor.c index f019d3b4..1e7f5102 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -23,7 +23,7 @@ __pdata uint8_t ao_monitor_led; void ao_monitor(void) { - __xdata struct ao_radio_recv recv; + __xdata struct ao_telemetry_recv recv; __xdata char callsign[AO_MAX_CALLSIGN+1]; uint8_t state; int16_t rssi; @@ -31,7 +31,7 @@ ao_monitor(void) for (;;) { __critical while (!ao_monitoring) ao_sleep(&ao_monitoring); - if (!ao_radio_recv(&recv)) + if (!ao_radio_recv(&recv, sizeof (recv))) continue; state = recv.telemetry.flight_state; @@ -85,7 +85,7 @@ ao_set_monitor(uint8_t monitoring) ao_monitoring = monitoring; ao_wakeup(&ao_monitoring); if (!ao_monitoring) - ao_radio_abort(); + ao_radio_recv_abort(); } static void diff --git a/src/ao_packet.c b/src/ao_packet.c index d52f2a68..9896149c 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -33,8 +33,6 @@ void ao_packet_send(void) { ao_led_on(AO_LED_RED); - ao_radio_get(); - /* If any tx data is pending then copy it into the tx packet */ if (ao_packet_tx_used && ao_tx_packet.len == 0) { memcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); @@ -43,22 +41,7 @@ ao_packet_send(void) ao_packet_tx_used = 0; ao_wakeup(&tx_data); } - ao_radio_done = 0; - ao_dma_set_transfer(ao_radio_dma, - &ao_tx_packet, - &RFDXADDR, - sizeof (struct ao_packet), - 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; - __critical while (!ao_radio_done) - ao_sleep(&ao_radio_done); - ao_radio_put(); + ao_radio_send(&ao_tx_packet, sizeof (ao_tx_packet)); ao_led_off(AO_LED_RED); } @@ -70,51 +53,56 @@ ao_packet_recv(void) #ifdef AO_LED_GREEN ao_led_on(AO_LED_GREEN); #endif - ao_radio_get(); - ao_dma_set_transfer(ao_radio_dma, - &RFDXADDR, - &ao_rx_packet, - sizeof (struct ao_packet_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; - __critical while (!ao_radio_dma_done) - if (ao_sleep(&ao_radio_dma_done) != 0) - ao_radio_abort(); - dma_done = ao_radio_dma_done; - ao_radio_put(); + dma_done = ao_radio_recv(&ao_rx_packet, sizeof (struct ao_packet_recv)); #ifdef AO_LED_GREEN ao_led_off(AO_LED_GREEN); #endif - if (dma_done & AO_DMA_DONE) { - if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) - return AO_DMA_ABORTED; - if (ao_rx_packet.packet.len == AO_PACKET_SYN) { + /* Check to see if we got a valid packet */ + if (!dma_done) + return 0; + if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) + return 0; + + /* SYN packets carry no data */ + if (ao_rx_packet.packet.len == AO_PACKET_SYN) { + rx_seq = ao_rx_packet.packet.seq; + ao_tx_packet.seq = ao_rx_packet.packet.ack; + ao_tx_packet.ack = rx_seq; + } else if (ao_rx_packet.packet.len) { + + /* Check for incoming data at the next sequence and + * for an empty data buffer + */ + if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) && + ao_packet_rx_used == ao_packet_rx_len) { + + /* Copy data to the receive data buffer and set up the + * offsets + */ + memcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); + ao_packet_rx_used = 0; + ao_packet_rx_len = ao_rx_packet.packet.len; + + /* Mark the sequence that we've received to + * let the sender know when we return a packet + */ rx_seq = ao_rx_packet.packet.seq; - ao_tx_packet.seq = ao_rx_packet.packet.ack; ao_tx_packet.ack = rx_seq; - } else if (ao_rx_packet.packet.len) { - if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) && ao_packet_rx_used == ao_packet_rx_len) { - memcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); - ao_packet_rx_used = 0; - ao_packet_rx_len = ao_rx_packet.packet.len; - rx_seq = ao_rx_packet.packet.seq; - ao_tx_packet.ack = rx_seq; - ao_wakeup(&ao_stdin_ready); - } - } - if (ao_rx_packet.packet.ack == ao_tx_packet.seq) { - ao_tx_packet.len = 0; - ao_wakeup(&ao_tx_packet); + + /* Poke anyone looking for received data */ + ao_wakeup(&ao_stdin_ready); } } - return dma_done; + + /* If the other side has seen the latest data we queued, + * wake up any task waiting to send data and let them go again + */ + if (ao_rx_packet.packet.ack == ao_tx_packet.seq) { + ao_tx_packet.len = 0; + ao_wakeup(&ao_tx_packet); + } + return 1; } #ifndef PACKET_HAS_MASTER diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index 641b49f4..3b23ad92 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -77,8 +77,6 @@ ao_packet_master_check_busy(void) void ao_packet_master(void) { - uint8_t status; - ao_config_get(); ao_radio_set_packet(); ao_tx_packet.addr = ao_serial_number; @@ -92,8 +90,7 @@ ao_packet_master(void) ao_packet_master_busy(); ao_packet_master_check_busy(); ao_alarm(ao_packet_master_delay); - status = ao_packet_recv(); - if (status & AO_DMA_DONE) { + if (ao_packet_recv()) { /* if we can transmit data, do so */ if (ao_packet_tx_used && ao_tx_packet.len == 0) continue; diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index 9b78767f..3040d781 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -20,14 +20,11 @@ void ao_packet_slave(void) { - uint8_t status; - ao_radio_set_packet(); ao_tx_packet.addr = ao_serial_number; ao_tx_packet.len = AO_PACKET_SYN; while (ao_packet_enable) { - status = ao_packet_recv(); - if (status & AO_DMA_DONE) { + if (ao_packet_recv()) { memcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN); ao_packet_send(); } @@ -47,7 +44,7 @@ ao_packet_slave_stop(void) { if (ao_packet_enable) { ao_packet_enable = 0; - ao_radio_abort(); + ao_radio_recv_abort(); while (ao_packet_task.wchan) { ao_wake_task(&ao_packet_task); ao_yield(); diff --git a/src/ao_radio.c b/src/ao_radio.c index cafa7010..362b73aa 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -272,6 +272,7 @@ static __code uint8_t packet_setup[] = { __xdata uint8_t ao_radio_dma; __xdata uint8_t ao_radio_dma_done; __xdata uint8_t ao_radio_done; +__xdata uint8_t ao_radio_abort; __xdata uint8_t ao_radio_mutex; void @@ -279,7 +280,7 @@ ao_radio_general_isr(void) __interrupt 16 { S1CON &= ~0x03; if (RFIF & RFIF_IM_TIMEOUT) { - ao_dma_abort(ao_radio_dma); + ao_radio_recv_abort(); RFIF &= ~ RFIF_IM_TIMEOUT; } else if (RFIF & RFIF_IM_DONE) { ao_radio_done = 1; @@ -338,14 +339,14 @@ ao_radio_get(void) void -ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant +ao_radio_send(__xdata void *packet, uint8_t size) __reentrant { ao_radio_get(); ao_radio_done = 0; ao_dma_set_transfer(ao_radio_dma, - telemetry, + packet, &RFDXADDR, - sizeof (struct ao_telemetry), + size, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | DMA_CFG0_TRIGGER_RADIO, @@ -360,13 +361,14 @@ ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant } uint8_t -ao_radio_recv(__xdata struct ao_radio_recv *radio) __reentrant +ao_radio_recv(__xdata void *packet, uint8_t size) __reentrant { + ao_radio_abort = 0; ao_radio_get(); ao_dma_set_transfer(ao_radio_dma, &RFDXADDR, - radio, - sizeof (struct ao_radio_recv), + packet, + size, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | DMA_CFG0_TRIGGER_RADIO, @@ -375,13 +377,32 @@ ao_radio_recv(__xdata struct ao_radio_recv *radio) __reentrant DMA_CFG1_PRIORITY_HIGH); ao_dma_start(ao_radio_dma); RFST = RFST_SRX; - __critical while (!ao_radio_dma_done) - ao_sleep(&ao_radio_dma_done); + __critical while (!ao_radio_dma_done && !ao_radio_abort) + ao_sleep(&ao_radio_dma_done); + + /* If recv was aborted, clean up by stopping the DMA engine + * and idling the radio + */ + if (!ao_radio_dma_done) { + ao_dma_abort(ao_radio_dma); + ao_radio_idle(); + } ao_radio_put(); - return (ao_radio_dma_done & AO_DMA_DONE); + return ao_radio_dma_done; +} + +/* + * Wake up a task waiting to receive a radio packet + * and tell them to abort the transfer + */ + +void +ao_radio_recv_abort(void) +{ + ao_radio_abort = 1; + ao_wakeup(&ao_radio_dma_done); } -__xdata ao_radio_rdf_running; __xdata ao_radio_rdf_value = 0x55; void @@ -390,8 +411,9 @@ ao_radio_rdf(int ms) uint8_t i; uint8_t pkt_len; + ao_radio_abort = 0; ao_radio_get(); - ao_radio_rdf_running = 1; + ao_radio_done = 0; for (i = 0; i < sizeof (rdf_setup); i += 2) RF[rdf_setup[i]] = rdf_setup[i+1]; @@ -419,28 +441,22 @@ ao_radio_rdf(int ms) DMA_CFG1_PRIORITY_HIGH); ao_dma_start(ao_radio_dma); RFST = RFST_STX; - - __critical while (!ao_radio_dma_done) - ao_sleep(&ao_radio_dma_done); - ao_radio_rdf_running = 0; - ao_radio_idle(); + __critical while (!ao_radio_done && !ao_radio_abort) + ao_sleep(&ao_radio_done); + if (!ao_radio_done) { + ao_dma_abort(ao_radio_dma); + ao_radio_idle(); + } for (i = 0; i < sizeof (telemetry_setup); i += 2) RF[telemetry_setup[i]] = telemetry_setup[i+1]; ao_radio_put(); } -void -ao_radio_abort(void) -{ - ao_dma_abort(ao_radio_dma); - ao_radio_idle(); -} - void ao_radio_rdf_abort(void) { - if (ao_radio_rdf_running) - ao_radio_abort(); + ao_radio_abort = 1; + ao_wakeup(&ao_radio_done); } diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 88ac142c..277c3ce0 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -52,7 +52,7 @@ ao_telemetry(void) memcpy(&telemetry.gps, &ao_gps_data, sizeof (struct ao_gps_data)); memcpy(&telemetry.gps_tracking, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data)); ao_mutex_put(&ao_gps_mutex); - ao_radio_send(&telemetry); + ao_radio_send(&telemetry, sizeof (telemetry)); ao_delay(ao_telemetry_interval); if (ao_rdf && (int16_t) (ao_time() - ao_rdf_time) >= 0) -- cgit v1.2.3 From 484b44e81b655f1ecb48256095382a56d2839bae Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 26 Nov 2010 17:39:40 -0800 Subject: altos: eliminate ao_wake_task Waking up a task waiting on some random object is a bad idea. Fix the waiters to look for suitable signalling. Signed-off-by: Keith Packard --- src/ao.h | 4 ---- src/ao_packet.c | 2 +- src/ao_packet_master.c | 16 +++++++--------- src/ao_packet_slave.c | 7 ++++--- src/ao_radio.c | 7 ++++++- src/ao_task.c | 9 +-------- 6 files changed, 19 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 58659af5..9682e42f 100644 --- a/src/ao.h +++ b/src/ao.h @@ -69,10 +69,6 @@ ao_sleep(__xdata void *wchan); void ao_wakeup(__xdata void *wchan); -/* Wake up a specific task */ -void -ao_wake_task(__xdata struct ao_task *task); - /* set an alarm to go off in 'delay' ticks */ void ao_alarm(uint16_t delay); diff --git a/src/ao_packet.c b/src/ao_packet.c index 9896149c..f627e02b 100644 --- a/src/ao_packet.c +++ b/src/ao_packet.c @@ -117,7 +117,7 @@ ao_packet_flush(void) * then poke the master to send all queued data */ if (ao_packet_tx_used && ao_packet_master_sleeping) - ao_wake_task(&ao_packet_task); + ao_wakeup(&ao_packet_master_sleeping); } #endif /* PACKET_HAS_MASTER */ diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index 3b23ad92..0808bc80 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -21,16 +21,13 @@ static char ao_packet_getchar(void) __critical { char c; - while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) - { + while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) { if (!ao_packet_enable) break; if (ao_packet_master_sleeping) - ao_wake_task(&ao_packet_task); + ao_wakeup(&ao_packet_master_sleeping); ao_usb_flush(); ao_sleep(&ao_stdin_ready); - if (!ao_packet_enable) - break; } return c; } @@ -41,7 +38,7 @@ ao_packet_echo(void) __reentrant uint8_t c; while (ao_packet_enable) { c = ao_packet_getchar(); - if (ao_packet_enable) + if (c != AO_READ_AGAIN) ao_usb_putchar(c); } ao_exit(); @@ -97,7 +94,8 @@ ao_packet_master(void) if (ao_rx_packet.packet.len) ao_packet_master_busy(); ao_packet_master_sleeping = 1; - ao_delay(ao_packet_master_delay); + ao_alarm(ao_packet_master_delay); + ao_sleep(&ao_packet_master_sleeping); ao_packet_master_sleeping = 0; } } @@ -126,8 +124,8 @@ ao_packet_forward(void) __reentrant ao_delay(AO_MS_TO_TICKS(100)); ao_packet_enable = 0; while (ao_packet_echo_task.wchan || ao_packet_task.wchan) { - if (ao_packet_echo_task.wchan) - ao_wake_task(&ao_packet_echo_task); + ao_radio_recv_abort(); + ao_wakeup(&ao_stdin_ready); ao_delay(AO_MS_TO_TICKS(10)); } } diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index 3040d781..39d04bbb 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -44,12 +44,13 @@ ao_packet_slave_stop(void) { if (ao_packet_enable) { ao_packet_enable = 0; - ao_radio_recv_abort(); while (ao_packet_task.wchan) { - ao_wake_task(&ao_packet_task); - ao_yield(); + ao_radio_recv_abort(); + ao_delay(AO_MS_TO_TICKS(10)); } + ao_radio_get(); ao_radio_set_telemetry(); + ao_radio_put(); } } diff --git a/src/ao_radio.c b/src/ao_radio.c index 362b73aa..7b7c5161 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -377,8 +377,13 @@ ao_radio_recv(__xdata void *packet, uint8_t size) __reentrant DMA_CFG1_PRIORITY_HIGH); ao_dma_start(ao_radio_dma); RFST = RFST_SRX; + + /* Wait for DMA to be done, for the radio receive process to + * get aborted or for a receive timeout to fire + */ __critical while (!ao_radio_dma_done && !ao_radio_abort) - ao_sleep(&ao_radio_dma_done); + if (ao_sleep(&ao_radio_dma_done)) + break; /* If recv was aborted, clean up by stopping the DMA engine * and idling the radio diff --git a/src/ao_task.c b/src/ao_task.c index 72c9d7d6..35f34b49 100644 --- a/src/ao_task.c +++ b/src/ao_task.c @@ -204,12 +204,11 @@ ao_sleep(__xdata void *wchan) ao_cur_task->wchan = wchan; } ao_yield(); + ao_cur_task->alarm = 0; if (ao_cur_task->wchan) { ao_cur_task->wchan = NULL; - ao_cur_task->alarm = 0; return 1; } - ao_cur_task->alarm = 0; return 0; } @@ -233,12 +232,6 @@ ao_alarm(uint16_t delay) ao_cur_task->alarm = 1; } -void -ao_wake_task(__xdata struct ao_task *task) -{ - task->wchan = NULL; -} - void ao_exit(void) __critical { -- cgit v1.2.3 From 9f7296b3feab872bf51fc369ade69cc1e7cf7a3f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 22 Dec 2010 21:06:22 -0800 Subject: altos: Split out SPI driver. For TM with the companion connector, the SPI bus will be shared among multiple devices. Split out the existing SPI code into a common driver, with the SPI bus protected by a mutex. Signed-off-by: Keith Packard --- src/Makefile.proto | 6 ++ src/ao.h | 13 +++ src/ao_ee.c | 133 ++-------------------------- src/ao_flash.c | 137 ++-------------------------- src/ao_pins.h | 22 +++++ src/ao_spi.c | 157 +++++++++++++++++++++++++++++++++ src/ao_telemetrum.c | 1 + src/telemetrum-v0.1-sirf/Makefile.defs | 1 + src/telemetrum-v0.1-sky/Makefile.defs | 1 + src/telemetrum-v1.0/Makefile.defs | 1 + 10 files changed, 217 insertions(+), 255 deletions(-) create mode 100644 src/ao_spi.c (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index b23eb257..c79638ac 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -71,6 +71,12 @@ TELE_DRIVER_SRC = \ ao_convert.c \ ao_serial.c +# +# Spi bus driver +# +SPI_DRIVER_SRC = \ + ao_spi.c + # # Debug dongle driver (only on TI) # diff --git a/src/ao.h b/src/ao.h index 9682e42f..69f4665b 100644 --- a/src/ao.h +++ b/src/ao.h @@ -736,6 +736,19 @@ void ao_serial_init(void); #endif +/* + * ao_spi.c + */ + +void +ao_spi_send(void __xdata *block, uint16_t len) __reentrant; + +void +ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; + +void +ao_spi_init(void); + /* * ao_gps.c */ diff --git a/src/ao_ee.c b/src/ao_ee.c index 26cfb7fd..36c8a100 100644 --- a/src/ao_ee.c +++ b/src/ao_ee.c @@ -25,15 +25,8 @@ #define EE_CS P1_2 #define EE_CS_INDEX 2 -__xdata uint8_t ao_ee_dma_in_done; -__xdata uint8_t ao_ee_dma_out_done; __xdata uint8_t ao_ee_mutex; -uint8_t ao_ee_dma_out_id; -uint8_t ao_ee_dma_in_id; - -static __xdata uint8_t ao_ee_const = 0xff; - #define ao_ee_delay() do { \ _asm nop _endasm; \ _asm nop _endasm; \ @@ -54,82 +47,6 @@ void ao_ee_cs_high(void) ao_ee_delay(); } -/* Send bytes over SPI. - * - * This sets up two DMA engines, one writing the data and another reading - * bytes coming back. We use the bytes coming back to tell when the transfer - * is complete, as the transmit register is double buffered and hence signals - * completion one byte before the transfer is actually complete - */ -static void -ao_ee_send(void __xdata *block, uint16_t len) -{ - ao_dma_set_transfer(ao_ee_dma_in_id, - &U0DBUFXADDR, - &ao_ee_const, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_URX0, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_set_transfer(ao_ee_dma_out_id, - block, - &U0DBUFXADDR, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_UTX0, - DMA_CFG1_SRCINC_1 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_start(ao_ee_dma_in_id); - ao_dma_start(ao_ee_dma_out_id); - ao_dma_trigger(ao_ee_dma_out_id); - __critical while (!ao_ee_dma_in_done) - ao_sleep(&ao_ee_dma_in_done); -} - -/* Receive bytes over SPI. - * - * This sets up tow DMA engines, one reading the data and another - * writing constant values to the SPI transmitter as that is what - * clocks the data coming in. - */ -static void -ao_ee_recv(void __xdata *block, uint16_t len) -{ - ao_dma_set_transfer(ao_ee_dma_in_id, - &U0DBUFXADDR, - block, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_URX0, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_1 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_set_transfer(ao_ee_dma_out_id, - &ao_ee_const, - &U0DBUFXADDR, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_UTX0, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_start(ao_ee_dma_in_id); - ao_dma_start(ao_ee_dma_out_id); - ao_dma_trigger(ao_ee_dma_out_id); - __critical while (!ao_ee_dma_in_done) - ao_sleep(&ao_ee_dma_in_done); -} #define EE_BLOCK 256 @@ -143,7 +60,7 @@ ao_ee_write_enable(void) { ao_ee_cs_low(); ao_ee_instruction.instruction = EE_WREN; - ao_ee_send(&ao_ee_instruction, 1); + ao_spi_send(&ao_ee_instruction, 1); ao_ee_cs_high(); } @@ -152,8 +69,8 @@ ao_ee_rdsr(void) { ao_ee_cs_low(); ao_ee_instruction.instruction = EE_RDSR; - ao_ee_send(&ao_ee_instruction, 1); - ao_ee_recv(&ao_ee_instruction, 1); + ao_spi_send(&ao_ee_instruction, 1); + ao_spi_recv(&ao_ee_instruction, 1); ao_ee_cs_high(); return ao_ee_instruction.instruction; } @@ -164,7 +81,7 @@ ao_ee_wrsr(uint8_t status) ao_ee_cs_low(); ao_ee_instruction.instruction = EE_WRSR; ao_ee_instruction.address[0] = status; - ao_ee_send(&ao_ee_instruction, 2); + ao_spi_send(&ao_ee_instruction, 2); ao_ee_cs_high(); } @@ -191,8 +108,8 @@ ao_ee_write_block(void) ao_ee_instruction.address[0] = ao_ee_block >> 8; ao_ee_instruction.address[1] = ao_ee_block; ao_ee_instruction.address[2] = 0; - ao_ee_send(&ao_ee_instruction, 4); - ao_ee_send(ao_ee_data, EE_BLOCK); + ao_spi_send(&ao_ee_instruction, 4); + ao_spi_send(ao_ee_data, EE_BLOCK); ao_ee_cs_high(); for (;;) { uint8_t status = ao_ee_rdsr(); @@ -210,8 +127,8 @@ ao_ee_read_block(void) ao_ee_instruction.address[0] = ao_ee_block >> 8; ao_ee_instruction.address[1] = ao_ee_block; ao_ee_instruction.address[2] = 0; - ao_ee_send(&ao_ee_instruction, 4); - ao_ee_recv(ao_ee_data, EE_BLOCK); + ao_spi_send(&ao_ee_instruction, 4); + ao_spi_recv(ao_ee_data, EE_BLOCK); ao_ee_cs_high(); } @@ -423,39 +340,5 @@ ao_ee_init(void) P1DIR |= (1 << EE_CS_INDEX); P1SEL &= ~(1 << EE_CS_INDEX); - /* Set up the USART pin assignment */ - PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2; - - /* Ensure that USART0 takes precidence over USART1 for pins that - * they share - */ - P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | P2SEL_PRI3P1_USART0; - - /* Make the SPI pins be controlled by the USART peripheral */ - P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3)); - - /* Set up OUT DMA */ - ao_ee_dma_out_id = ao_dma_alloc(&ao_ee_dma_out_done); - - /* Set up IN DMA */ - ao_ee_dma_in_id = ao_dma_alloc(&ao_ee_dma_in_done); - - /* Set up the USART. - * - * SPI master mode - */ - U0CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_MASTER); - - /* Set the baud rate and signal parameters - * - * The cc1111 is limited to a 24/8 MHz SPI clock, - * while the 25LC1024 is limited to 20MHz. So, - * use the 3MHz clock (BAUD_E 17, BAUD_M 0) - */ - U0BAUD = 0; - U0GCR = (UxGCR_CPOL_NEGATIVE | - UxGCR_CPHA_FIRST_EDGE | - UxGCR_ORDER_MSB | - (17 << UxGCR_BAUD_E_SHIFT)); ao_cmd_register(&ao_ee_cmds[0]); } diff --git a/src/ao_flash.c b/src/ao_flash.c index 638e51e0..4f3618ee 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -18,22 +18,11 @@ #include "ao.h" #include "at45db161d.h" -/* - * Using SPI on USART 0, with P1_1 as the chip select - */ - #define FLASH_CS P1_1 #define FLASH_CS_INDEX 1 -__xdata uint8_t ao_flash_dma_in_done; -__xdata uint8_t ao_flash_dma_out_done; __xdata uint8_t ao_flash_mutex; -uint8_t ao_flash_dma_out_id; -uint8_t ao_flash_dma_in_id; - -static __xdata uint8_t ao_flash_const = 0xff; - #define ao_flash_delay() do { \ _asm nop _endasm; \ _asm nop _endasm; \ @@ -54,83 +43,6 @@ void ao_flash_cs_high(void) ao_flash_delay(); } -/* Send bytes over SPI. - * - * This sets up two DMA engines, one writing the data and another reading - * bytes coming back. We use the bytes coming back to tell when the transfer - * is complete, as the transmit register is double buffered and hence signals - * completion one byte before the transfer is actually complete - */ -static void -ao_flash_send(void __xdata *block, uint16_t len) -{ - ao_dma_set_transfer(ao_flash_dma_in_id, - &U0DBUFXADDR, - &ao_flash_const, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_URX0, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_set_transfer(ao_flash_dma_out_id, - block, - &U0DBUFXADDR, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_UTX0, - DMA_CFG1_SRCINC_1 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_start(ao_flash_dma_in_id); - ao_dma_start(ao_flash_dma_out_id); - ao_dma_trigger(ao_flash_dma_out_id); - __critical while (!ao_flash_dma_in_done) - ao_sleep(&ao_flash_dma_in_done); -} - -/* Receive bytes over SPI. - * - * This sets up tow DMA engines, one reading the data and another - * writing constant values to the SPI transmitter as that is what - * clocks the data coming in. - */ -static void -ao_flash_recv(void __xdata *block, uint16_t len) -{ - ao_dma_set_transfer(ao_flash_dma_in_id, - &U0DBUFXADDR, - block, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_URX0, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_1 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_set_transfer(ao_flash_dma_out_id, - &ao_flash_const, - &U0DBUFXADDR, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_UTX0, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_start(ao_flash_dma_in_id); - ao_dma_start(ao_flash_dma_out_id); - ao_dma_trigger(ao_flash_dma_out_id); - __critical while (!ao_flash_dma_in_done) - ao_sleep(&ao_flash_dma_in_done); -} - struct ao_flash_instruction { uint8_t instruction; uint8_t address[3]; @@ -144,7 +56,7 @@ ao_flash_set_pagesize_512(void) ao_flash_instruction.address[0] = FLASH_SET_512_BYTE_0; ao_flash_instruction.address[1] = FLASH_SET_512_BYTE_1; ao_flash_instruction.address[2] = FLASH_SET_512_BYTE_2; - ao_flash_send(&ao_flash_instruction, 4); + ao_spi_send(&ao_flash_instruction, 4); ao_flash_cs_high(); } @@ -154,8 +66,8 @@ ao_flash_read_status(void) { ao_flash_cs_low(); ao_flash_instruction.instruction = FLASH_READ_STATUS; - ao_flash_send(&ao_flash_instruction, 1); - ao_flash_recv(&ao_flash_instruction, 1); + ao_spi_send(&ao_flash_instruction, 1); + ao_spi_recv(&ao_flash_instruction, 1); ao_flash_cs_high(); return ao_flash_instruction.instruction; } @@ -268,8 +180,8 @@ ao_flash_write_block(void) ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift); ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); ao_flash_instruction.address[2] = 0; - ao_flash_send(&ao_flash_instruction, 4); - ao_flash_send(ao_flash_data, FLASH_BLOCK_SIZE); + ao_spi_send(&ao_flash_instruction, 4); + ao_spi_send(ao_flash_data, FLASH_BLOCK_SIZE); ao_flash_cs_high(); ao_flash_write_pending = 1; } @@ -286,8 +198,8 @@ ao_flash_read_block(void) ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift); ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); ao_flash_instruction.address[2] = 0; - ao_flash_send(&ao_flash_instruction, 4); - ao_flash_recv(ao_flash_data, FLASH_BLOCK_SIZE); + ao_spi_send(&ao_flash_instruction, 4); + ao_spi_recv(ao_flash_data, FLASH_BLOCK_SIZE); ao_flash_cs_high(); } @@ -543,40 +455,5 @@ ao_ee_init(void) FLASH_CS = 1; P1DIR |= (1 << FLASH_CS_INDEX); P1SEL &= ~(1 << FLASH_CS_INDEX); - - /* Set up the USART pin assignment */ - PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2; - - /* Ensure that USART0 takes precidence over USART1 for pins that - * they share - */ - P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | P2SEL_PRI3P1_USART0; - - /* Make the SPI pins be controlled by the USART peripheral */ - P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3)); - - /* Set up OUT DMA */ - ao_flash_dma_out_id = ao_dma_alloc(&ao_flash_dma_out_done); - - /* Set up IN DMA */ - ao_flash_dma_in_id = ao_dma_alloc(&ao_flash_dma_in_done); - - /* Set up the USART. - * - * SPI master mode - */ - U0CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_MASTER); - - /* Set the baud rate and signal parameters - * - * The cc1111 is limited to a 24/8 MHz SPI clock, - * while the at45db161d.h is limited to 20MHz. So, - * use the 3MHz clock (BAUD_E 17, BAUD_M 0) - */ - U0BAUD = 0; - U0GCR = (UxGCR_CPOL_NEGATIVE | - UxGCR_CPHA_FIRST_EDGE | - UxGCR_ORDER_MSB | - (17 << UxGCR_BAUD_E_SHIFT)); ao_cmd_register(&ao_flash_cmds[0]); } diff --git a/src/ao_pins.h b/src/ao_pins.h index e9a265b0..edbb4908 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -31,6 +31,8 @@ #define AO_LED_RED 1 #define LEDS_AVAILABLE (AO_LED_RED) #define HAS_EXTERNAL_TEMP 0 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 #endif #if defined(TELEDONGLE_V_0_2) @@ -45,6 +47,8 @@ #define AO_LED_RED 1 #define AO_LED_GREEN 2 #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 #endif #if defined(TELEMETRUM_V_0_1) @@ -60,6 +64,8 @@ #define AO_LED_GREEN 1 #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define HAS_EXTERNAL_TEMP 1 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 #endif #if defined(TELEDONGLE_V_0_1) @@ -74,6 +80,8 @@ #define AO_LED_RED 2 #define AO_LED_GREEN 1 #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 0 + #define SPI_CS_ON_P0 1 #endif #if defined(TIDONGLE) @@ -87,6 +95,8 @@ #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 2 #define LEDS_AVAILABLE (AO_LED_RED) + #define SPI_CS_ON_P1 0 + #define SPI_CS_ON_P0 1 #endif #if DBG_ON_P1 @@ -125,6 +135,18 @@ #endif /* DBG_ON_P0 */ +#if SPI_CS_ON_P1 + #define SPI_CS_PORT P1 + #define SPI_CS_SEL P1SEL + #define SPI_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P0 + #define SPI_CS_PORT P0 + #define SPI_CS_SEL P0SEL + #define SPI_CS_DIR P0DIR +#endif + #ifndef HAS_SERIAL_1 #error Please define HAS_SERIAL_1 #endif diff --git a/src/ao_spi.c b/src/ao_spi.c new file mode 100644 index 00000000..bd52a0d4 --- /dev/null +++ b/src/ao_spi.c @@ -0,0 +1,157 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +__xdata uint8_t ao_spi_mutex; +__xdata uint8_t ao_spi_dma_in_done; +__xdata uint8_t ao_spi_dma_out_done; + +uint8_t ao_spi_dma_out_id; +uint8_t ao_spi_dma_in_id; + +static __xdata uint8_t ao_spi_const = 0xff; + +/* Send bytes over SPI. + * + * This sets up two DMA engines, one writing the data and another reading + * bytes coming back. We use the bytes coming back to tell when the transfer + * is complete, as the transmit register is double buffered and hence signals + * completion one byte before the transfer is actually complete + */ +void +ao_spi_send(void __xdata *block, uint16_t len) __reentrant +{ + ao_mutex_get(&ao_spi_mutex); + ao_dma_set_transfer(ao_spi_dma_in_id, + &U0DBUFXADDR, + &ao_spi_const, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_URX0, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_set_transfer(ao_spi_dma_out_id, + block, + &U0DBUFXADDR, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_UTX0, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_start(ao_spi_dma_in_id); + ao_dma_start(ao_spi_dma_out_id); + ao_dma_trigger(ao_spi_dma_out_id); + __critical while (!ao_spi_dma_in_done) + ao_sleep(&ao_spi_dma_in_done); + ao_mutex_put(&ao_spi_mutex); +} + +/* Receive bytes over SPI. + * + * This sets up tow DMA engines, one reading the data and another + * writing constant values to the SPI transmitter as that is what + * clocks the data coming in. + */ +void +ao_spi_recv(void __xdata *block, uint16_t len) __reentrant +{ + ao_mutex_get(&ao_spi_mutex); + ao_dma_set_transfer(ao_spi_dma_in_id, + &U0DBUFXADDR, + block, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_URX0, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_1 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_set_transfer(ao_spi_dma_out_id, + &ao_spi_const, + &U0DBUFXADDR, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_UTX0, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_start(ao_spi_dma_in_id); + ao_dma_start(ao_spi_dma_out_id); + ao_dma_trigger(ao_spi_dma_out_id); + __critical while (!ao_spi_dma_in_done) + ao_sleep(&ao_spi_dma_in_done); + ao_mutex_put(&ao_spi_mutex); +} + +/* + * Initialize USART0 for SPI using config alt 2 + * + * MO P1_5 + * MI P1_4 + * CLK P1_3 + * + * Chip select is the responsibility of the caller + */ + +void +ao_spi_init(void) +{ + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2; + + /* Ensure that USART0 takes precidence over USART1 for pins that + * they share + */ + P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | P2SEL_PRI3P1_USART0; + + /* Make the SPI pins be controlled by the USART peripheral */ + P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3)); + + /* Set up OUT DMA */ + ao_spi_dma_out_id = ao_dma_alloc(&ao_spi_dma_out_done); + + /* Set up IN DMA */ + ao_spi_dma_in_id = ao_dma_alloc(&ao_spi_dma_in_done); + + /* Set up the USART. + * + * SPI master mode + */ + U0CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_MASTER); + + /* Set the baud rate and signal parameters + * + * The cc1111 is limited to a 24/8 MHz SPI clock. + * Every peripheral I've ever seen goes faster than that, + * so set the clock to 3MHz (BAUD_E 17, BAUD_M 0) + */ + U0BAUD = 0; + U0GCR = (UxGCR_CPOL_NEGATIVE | + UxGCR_CPHA_FIRST_EDGE | + UxGCR_ORDER_MSB | + (17 << UxGCR_BAUD_E_SHIFT)); +} diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index fd0adae8..1209c820 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -48,6 +48,7 @@ main(void) ao_adc_init(); ao_beep_init(); ao_cmd_init(); + ao_spi_init(); ao_ee_init(); ao_flight_init(); ao_log_init(); diff --git a/src/telemetrum-v0.1-sirf/Makefile.defs b/src/telemetrum-v0.1-sirf/Makefile.defs index a7310fbc..ac8dcdb9 100644 --- a/src/telemetrum-v0.1-sirf/Makefile.defs +++ b/src/telemetrum-v0.1-sirf/Makefile.defs @@ -2,6 +2,7 @@ PROG = telemetrum-v0.1-sirf-$(VERSION).ihx SRC = \ $(TM_BASE_SRC) \ + $(SPI_DRIVER_SRC) \ $(EE_DRIVER_SRC) \ $(SIRF_DRIVER_SRC) \ $(DBG_SRC) diff --git a/src/telemetrum-v0.1-sky/Makefile.defs b/src/telemetrum-v0.1-sky/Makefile.defs index 000287ba..e032d1eb 100644 --- a/src/telemetrum-v0.1-sky/Makefile.defs +++ b/src/telemetrum-v0.1-sky/Makefile.defs @@ -2,6 +2,7 @@ PROG = telemetrum-v0.1-sky-$(VERSION).ihx SRC = \ $(TM_BASE_SRC) \ + $(SPI_DRIVER_SRC) \ $(EE_DRIVER_SRC) \ $(SKY_DRIVER_SRC) \ $(DBG_SRC) diff --git a/src/telemetrum-v1.0/Makefile.defs b/src/telemetrum-v1.0/Makefile.defs index 010578df..a60a501a 100644 --- a/src/telemetrum-v1.0/Makefile.defs +++ b/src/telemetrum-v1.0/Makefile.defs @@ -2,6 +2,7 @@ PROG = telemetrum-v1.0-$(VERSION).ihx SRC = \ $(TM_BASE_SRC) \ + $(SPI_DRIVER_SRC) \ $(FLASH_DRIVER_SRC) \ $(SKY_DRIVER_SRC) \ $(DBG_SRC) -- cgit v1.2.3 From 5688af4e4d7ca8e559d758257e79b7979f1cc924 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 22 Dec 2010 21:13:56 -0800 Subject: altos: Add telemetrum-v1.1 directory This just clones the v1.0 build; changes will be added on top of this. Signed-off-by: Keith Packard --- src/Makefile | 2 +- src/ao_pins.h | 15 +++++++++++++++ src/telemetrum-v1.1/.gitignore | 2 ++ src/telemetrum-v1.1/.sdcdbrc | 1 + src/telemetrum-v1.1/Makefile | 1 + src/telemetrum-v1.1/Makefile.defs | 12 ++++++++++++ 6 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 src/telemetrum-v1.1/.gitignore create mode 100644 src/telemetrum-v1.1/.sdcdbrc create mode 100644 src/telemetrum-v1.1/Makefile create mode 100644 src/telemetrum-v1.1/Makefile.defs (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 95d24425..a6615321 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,7 +6,7 @@ CC=sdcc include Version -SUBDIRS=telemetrum-v1.0 teledongle-v0.2 telemetrum-v0.1-sky telemetrum-v0.1-sirf teledongle-v0.1 tidongle test +SUBDIRS=telemetrum-v1.1 telemetrum-v1.0 teledongle-v0.2 telemetrum-v0.1-sky telemetrum-v0.1-sirf teledongle-v0.1 tidongle test all: all-recursive diff --git a/src/ao_pins.h b/src/ao_pins.h index edbb4908..b5089b85 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -28,6 +28,21 @@ #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 + #define AO_LED_RED 1 + #define LEDS_AVAILABLE (AO_LED_RED) + #define HAS_EXTERNAL_TEMP 0 +#endif + +#if defined(TELEMETRUM_V_1_1) + #define HAS_SERIAL_1 1 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + #define AO_LED_RED 1 #define LEDS_AVAILABLE (AO_LED_RED) #define HAS_EXTERNAL_TEMP 0 diff --git a/src/telemetrum-v1.1/.gitignore b/src/telemetrum-v1.1/.gitignore new file mode 100644 index 00000000..c2212151 --- /dev/null +++ b/src/telemetrum-v1.1/.gitignore @@ -0,0 +1,2 @@ +telemetrum-* +ao_product.h diff --git a/src/telemetrum-v1.1/.sdcdbrc b/src/telemetrum-v1.1/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telemetrum-v1.1/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telemetrum-v1.1/Makefile b/src/telemetrum-v1.1/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telemetrum-v1.1/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/telemetrum-v1.1/Makefile.defs b/src/telemetrum-v1.1/Makefile.defs new file mode 100644 index 00000000..a230203a --- /dev/null +++ b/src/telemetrum-v1.1/Makefile.defs @@ -0,0 +1,12 @@ +PROG = telemetrum-v1.1-$(VERSION).ihx + +SRC = \ + $(TM_BASE_SRC) \ + $(SPI_DRIVER_SRC) \ + $(FLASH_DRIVER_SRC) \ + $(SKY_DRIVER_SRC) \ + $(DBG_SRC) + +PRODUCT=TeleMetrum-v1.1 +PRODUCT_DEF=-DTELEMETRUM_V_1_1 +IDPRODUCT=0x000b -- cgit v1.2.3 From f3f1b1488bdc92fa9277dc549ba9f3210a8d4c8c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Jan 2011 11:28:35 -0800 Subject: altos: packet and usb i/o routines use 'char', not 'uint8_t' Just fixing the type of a local variable holding a character passed from the packet link to usb. Signed-off-by: Keith Packard --- src/ao_packet_master.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index 0808bc80..5f79885c 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -35,7 +35,7 @@ ao_packet_getchar(void) __critical static void ao_packet_echo(void) __reentrant { - uint8_t c; + char c; while (ao_packet_enable) { c = ao_packet_getchar(); if (c != AO_READ_AGAIN) -- cgit v1.2.3 From ddcc94da4326f9ce954bd31a46b36165c58e6c18 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Jan 2011 12:51:39 -0800 Subject: altos: Simplify storage API This removes the config-specific APIs and exposes global variables for the available storage space, block size and config storage location. Signed-off-by: Keith Packard --- src/ao.h | 44 +++++++--------- src/ao_config.c | 7 ++- src/ao_ee.c | 95 +++++++++++++++------------------- src/ao_flash.c | 146 ++++++++++++++++++---------------------------------- src/ao_log.c | 25 +++++---- src/ao_telemetrum.c | 2 +- src/at45db161d.h | 7 --- 7 files changed, 133 insertions(+), 193 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 69f4665b..67337de7 100644 --- a/src/ao.h +++ b/src/ao.h @@ -430,42 +430,38 @@ void ao_mutex_put(__xdata uint8_t *ao_mutex) __reentrant; /* - * ao_ee.c + * Storage interface, provided by one of the eeprom or flash + * drivers */ -/* - * We reserve the last block on the device for - * configuration space. Writes and reads in this - * area return errors. - */ +/* Total bytes of available storage */ +extern __xdata uint32_t ao_storage_total; -#define AO_EE_BLOCK_SIZE ((uint16_t) (256)) -#define AO_EE_DEVICE_SIZE ((uint32_t) 128 * (uint32_t) 1024) -#define AO_EE_DATA_SIZE (AO_EE_DEVICE_SIZE - (uint32_t) AO_EE_BLOCK_SIZE) -#define AO_EE_CONFIG_BLOCK ((uint16_t) (AO_EE_DATA_SIZE / AO_EE_BLOCK_SIZE)) +/* Block size - device is erased in these units. At least 256 bytes */ +extern __xdata uint32_t ao_storage_block; -void -ao_ee_flush(void) __reentrant; +/* Byte offset of config block. Will be ao_storage_block bytes long */ +extern __xdata uint32_t ao_storage_config; -/* Write to the eeprom */ -uint8_t -ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant; +/* Initialize above values. Can only be called once the OS is running */ +void +ao_storage_setup(void); -/* Read from the eeprom */ -uint8_t -ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant; +/* Flush any pending write data */ +void +ao_storage_flush(void) __reentrant; -/* Write the config block (at the end of the eeprom) */ +/* Write data. Returns 0 on failure, 1 on success */ uint8_t -ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant; +ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; -/* Read the config block (at the end of the eeprom) */ +/* Read data. Returns 0 on failure, 1 on success */ uint8_t -ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant; +ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; -/* Initialize the EEPROM code */ +/* Initialize the storage code */ void -ao_ee_init(void); +ao_storage_init(void); /* * ao_log.c diff --git a/src/ao_config.c b/src/ao_config.c index fd33e2cc..2153b841 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -32,7 +32,9 @@ __xdata uint8_t ao_config_mutex; static void _ao_config_put(void) { - ao_ee_write_config((uint8_t *) &ao_config, sizeof (ao_config)); + ao_storage_setup(); + ao_storage_write(ao_storage_config, &ao_config, sizeof (ao_config)); + ao_storage_flush(); } #endif @@ -42,7 +44,8 @@ _ao_config_get(void) if (ao_config_loaded) return; #if HAS_EEPROM - ao_ee_read_config((uint8_t *) &ao_config, sizeof (ao_config)); + ao_storage_setup(); + ao_storage_read(ao_storage_config, &ao_config, sizeof (ao_config)); #endif if (ao_config.major != AO_CONFIG_MAJOR) { ao_config.major = AO_CONFIG_MAJOR; diff --git a/src/ao_ee.c b/src/ao_ee.c index 36c8a100..6fe88252 100644 --- a/src/ao_ee.c +++ b/src/ao_ee.c @@ -18,6 +18,18 @@ #include "ao.h" #include "25lc1024.h" +#define EE_BLOCK_SIZE ((uint16_t) (256)) +#define EE_DEVICE_SIZE ((uint32_t) 128 * (uint32_t) 1024) + +/* Total bytes of available storage */ +__xdata uint32_t ao_storage_total; + +/* Block size - device is erased in these units. At least 256 bytes */ +__xdata uint32_t ao_storage_block; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +__xdata uint32_t ao_storage_config; + /* * Using SPI on USART 0, with P1_2 as the chip select */ @@ -25,7 +37,7 @@ #define EE_CS P1_2 #define EE_CS_INDEX 2 -__xdata uint8_t ao_ee_mutex; +static __xdata uint8_t ao_ee_mutex; #define ao_ee_delay() do { \ _asm nop _endasm; \ @@ -33,23 +45,20 @@ __xdata uint8_t ao_ee_mutex; _asm nop _endasm; \ } while(0) -void ao_ee_cs_low(void) +static void ao_ee_cs_low(void) { ao_ee_delay(); EE_CS = 0; ao_ee_delay(); } -void ao_ee_cs_high(void) +static void ao_ee_cs_high(void) { ao_ee_delay(); EE_CS = 1; ao_ee_delay(); } - -#define EE_BLOCK 256 - struct ao_ee_instruction { uint8_t instruction; uint8_t address[3]; @@ -87,7 +96,7 @@ ao_ee_wrsr(uint8_t status) #define EE_BLOCK_NONE 0xffff -static __xdata uint8_t ao_ee_data[EE_BLOCK]; +static __xdata uint8_t ao_ee_data[EE_BLOCK_SIZE]; static __pdata uint16_t ao_ee_block = EE_BLOCK_NONE; static __pdata uint8_t ao_ee_block_dirty; @@ -109,7 +118,7 @@ ao_ee_write_block(void) ao_ee_instruction.address[1] = ao_ee_block; ao_ee_instruction.address[2] = 0; ao_spi_send(&ao_ee_instruction, 4); - ao_spi_send(ao_ee_data, EE_BLOCK); + ao_spi_send(ao_ee_data, EE_BLOCK_SIZE); ao_ee_cs_high(); for (;;) { uint8_t status = ao_ee_rdsr(); @@ -128,7 +137,7 @@ ao_ee_read_block(void) ao_ee_instruction.address[1] = ao_ee_block; ao_ee_instruction.address[2] = 0; ao_spi_send(&ao_ee_instruction, 4); - ao_spi_recv(ao_ee_data, EE_BLOCK); + ao_spi_recv(ao_ee_data, EE_BLOCK_SIZE); ao_ee_cs_high(); } @@ -152,13 +161,13 @@ ao_ee_fill(uint16_t block) } uint8_t -ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant +ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant { uint16_t block; uint16_t this_len; uint8_t this_off; - if (pos >= AO_EE_DATA_SIZE || pos + len > AO_EE_DATA_SIZE) + if (pos >= ao_storage_total || pos + len > ao_storage_total) return 0; while (len) { @@ -166,7 +175,7 @@ ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant * a single block */ this_off = pos; - this_len = 256 - (uint16_t) this_off; + this_len = EE_BLOCK_SIZE - (uint16_t) this_off; block = (uint16_t) (pos >> 8); if (this_len > len) this_len = len; @@ -175,7 +184,7 @@ ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant /* Transfer the data */ ao_mutex_get(&ao_ee_mutex); { - if (this_len != 256) + if (this_len != EE_BLOCK_SIZE) ao_ee_fill(block); else { ao_ee_flush_internal(); @@ -194,13 +203,13 @@ ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant } uint8_t -ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant +ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant { uint16_t block; uint16_t this_len; uint8_t this_off; - if (pos >= AO_EE_DATA_SIZE || pos + len > AO_EE_DATA_SIZE) + if (pos >= ao_storage_total || pos + len > ao_storage_total) return 0; while (len) { @@ -208,7 +217,7 @@ ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant * a single block */ this_off = pos; - this_len = 256 - (uint16_t) this_off; + this_len = EE_BLOCK_SIZE - (uint16_t) this_off; block = (uint16_t) (pos >> 8); if (this_len > len) this_len = len; @@ -230,47 +239,17 @@ ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant } void -ao_ee_flush(void) __reentrant -{ - ao_mutex_get(&ao_ee_mutex); { - ao_ee_flush_internal(); - } ao_mutex_put(&ao_ee_mutex); -} - -/* - * Read/write the config block, which is in - * the last block of the ao_eeprom - */ -uint8_t -ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant +ao_storage_flush(void) __reentrant { - if (len > AO_EE_BLOCK_SIZE) - return 0; ao_mutex_get(&ao_ee_mutex); { - ao_ee_fill(AO_EE_CONFIG_BLOCK); - memcpy(ao_ee_data, buf, len); - ao_ee_block_dirty = 1; ao_ee_flush_internal(); } ao_mutex_put(&ao_ee_mutex); - return 1; -} - -uint8_t -ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant -{ - if (len > AO_EE_BLOCK_SIZE) - return 0; - ao_mutex_get(&ao_ee_mutex); { - ao_ee_fill(AO_EE_CONFIG_BLOCK); - memcpy(buf, ao_ee_data, len); - } ao_mutex_put(&ao_ee_mutex); - return 1; } static void ee_dump(void) __reentrant { - uint8_t b; + static __xdata uint8_t b; uint16_t block; uint8_t i; @@ -286,7 +265,7 @@ ee_dump(void) __reentrant ao_cmd_put16((uint16_t) i); } putchar(' '); - ao_ee_read(((uint32_t) block << 8) | i, &b, 1); + ao_storage_read(((uint32_t) block << 8) | i, &b, 1); ao_cmd_put8(b); ++i; } while (i != 0); @@ -299,7 +278,7 @@ ee_store(void) __reentrant uint16_t block; uint8_t i; uint16_t len; - uint8_t b; + static __xdata uint8_t b; uint32_t addr; ao_cmd_hex(); @@ -316,10 +295,10 @@ ee_store(void) __reentrant if (ao_cmd_status != ao_cmd_success) return; b = ao_cmd_lex_i; - ao_ee_write(addr, &b, 1); + ao_storage_write(addr, &b, 1); addr++; } - ao_ee_flush(); + ao_storage_flush(); } __code struct ao_cmds ao_ee_cmds[] = { @@ -328,12 +307,22 @@ __code struct ao_cmds ao_ee_cmds[] = { { 0, ee_store, NULL }, }; +void +ao_storage_setup(void) +{ + if (ao_storage_total == 0) { + ao_storage_total = EE_DEVICE_SIZE; + ao_storage_block = EE_BLOCK_SIZE; + ao_storage_config = EE_DEVICE_SIZE - EE_BLOCK_SIZE; + } +} + /* * To initialize the chip, set up the CS line and * the SPI interface */ void -ao_ee_init(void) +ao_storage_init(void) { /* set up CS */ EE_CS = 1; diff --git a/src/ao_flash.c b/src/ao_flash.c index 4f3618ee..3a06bae1 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -18,9 +18,20 @@ #include "ao.h" #include "at45db161d.h" +/* Total bytes of available storage */ +__xdata uint32_t ao_storage_total; + +/* Block size - device is erased in these units. At least 256 bytes */ +__xdata uint32_t ao_storage_block; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +__xdata uint32_t ao_storage_config; + #define FLASH_CS P1_1 #define FLASH_CS_INDEX 1 +#define FLASH_BLOCK_SIZE_MAX 512 + __xdata uint8_t ao_flash_mutex; #define ao_flash_delay() do { \ @@ -79,12 +90,12 @@ static __pdata uint16_t ao_flash_block = FLASH_BLOCK_NONE; static __pdata uint8_t ao_flash_block_dirty; static __pdata uint8_t ao_flash_write_pending; static __pdata uint8_t ao_flash_setup_done; -static __data uint32_t ao_flash_device_size; static __data uint8_t ao_flash_block_shift; static __data uint16_t ao_flash_block_size; +static __data uint16_t ao_flash_block_mask; -static void -ao_flash_setup(void) +void +ao_storage_setup(void) { uint8_t status; @@ -114,43 +125,47 @@ ao_flash_setup(void) /* AT45DB321D */ case 0x34: ao_flash_block_shift = 9; - ao_flash_device_size = ((uint32_t) 4 * (uint32_t) 1024 * (uint32_t) 1024); + ao_storage_total = ((uint32_t) 4 * (uint32_t) 1024 * (uint32_t) 1024); break; /* AT45DB161D */ case 0x2c: ao_flash_block_shift = 9; - ao_flash_device_size = ((uint32_t) 2 * (uint32_t) 1024 * (uint32_t) 1024); + ao_storage_total = ((uint32_t) 2 * (uint32_t) 1024 * (uint32_t) 1024); break; /* AT45DB081D */ case 0x24: ao_flash_block_shift = 8; - ao_flash_device_size = ((uint32_t) 1024 * (uint32_t) 1024); + ao_storage_total = ((uint32_t) 1024 * (uint32_t) 1024); break; /* AT45DB041D */ case 0x1c: ao_flash_block_shift = 8; - ao_flash_device_size = ((uint32_t) 512 * (uint32_t) 1024); + ao_storage_total = ((uint32_t) 512 * (uint32_t) 1024); break; /* AT45DB021D */ case 0x14: ao_flash_block_shift = 8; - ao_flash_device_size = ((uint32_t) 256 * (uint32_t) 1024); + ao_storage_total = ((uint32_t) 256 * (uint32_t) 1024); break; /* AT45DB011D */ case 0x0c: ao_flash_block_shift = 8; - ao_flash_device_size = ((uint32_t) 128 * (uint32_t) 1024); + ao_storage_total = ((uint32_t) 128 * (uint32_t) 1024); break; default: ao_panic(AO_PANIC_FLASH); } ao_flash_block_size = 1 << ao_flash_block_shift; + + ao_storage_block = ao_flash_block_size; + ao_storage_config = ao_storage_total - ao_storage_block; + ao_flash_setup_done = 1; ao_mutex_put(&ao_flash_mutex); } @@ -181,7 +196,7 @@ ao_flash_write_block(void) ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); ao_flash_instruction.address[2] = 0; ao_spi_send(&ao_flash_instruction, 4); - ao_spi_send(ao_flash_data, FLASH_BLOCK_SIZE); + ao_spi_send(ao_flash_data, ao_storage_block); ao_flash_cs_high(); ao_flash_write_pending = 1; } @@ -199,7 +214,7 @@ ao_flash_read_block(void) ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); ao_flash_instruction.address[2] = 0; ao_spi_send(&ao_flash_instruction, 4); - ao_spi_recv(ao_flash_data, FLASH_BLOCK_SIZE); + ao_spi_recv(ao_flash_data, ao_flash_block_size); ao_flash_cs_high(); } @@ -223,29 +238,29 @@ ao_flash_fill(uint16_t block) } uint8_t -ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant +ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant { uint16_t block; uint16_t this_len; uint16_t this_off; - ao_flash_setup(); - if (pos >= FLASH_DATA_SIZE || pos + len > FLASH_DATA_SIZE) + ao_storage_setup(); + if (pos >= ao_storage_total || pos + len > ao_storage_total) return 0; while (len) { /* Compute portion of transfer within * a single block */ - this_off = (uint16_t) pos & FLASH_BLOCK_MASK; - this_len = FLASH_BLOCK_SIZE - this_off; - block = (uint16_t) (pos >> FLASH_BLOCK_SHIFT); + this_off = (uint16_t) pos & ao_flash_block_mask; + this_len = ao_flash_block_size - this_off; + block = (uint16_t) (pos >> ao_flash_block_shift); if (this_len > len) this_len = len; /* Transfer the data */ ao_mutex_get(&ao_flash_mutex); { - if (this_len != FLASH_BLOCK_SIZE) + if (this_len != ao_flash_block_size) ao_flash_fill(block); else { ao_flash_flush_internal(); @@ -264,14 +279,14 @@ ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant } uint8_t -ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant +ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant { uint16_t block; uint16_t this_len; uint16_t this_off; - ao_flash_setup(); - if (pos >= FLASH_DATA_SIZE || pos + len > FLASH_DATA_SIZE) + ao_storage_setup(); + if (pos >= ao_storage_total || pos + len > ao_storage_total) return 0; while (len) { @@ -279,9 +294,9 @@ ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant /* Compute portion of transfer within * a single block */ - this_off = (uint16_t) pos & FLASH_BLOCK_MASK; - this_len = FLASH_BLOCK_SIZE - this_off; - block = (uint16_t) (pos >> FLASH_BLOCK_SHIFT); + this_off = (uint16_t) pos & ao_flash_block_mask; + this_len = ao_flash_block_size - this_off; + block = (uint16_t) (pos >> ao_flash_block_shift); if (this_len > len) this_len = len; @@ -300,50 +315,17 @@ ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant } void -ao_ee_flush(void) __reentrant -{ - ao_mutex_get(&ao_flash_mutex); { - ao_flash_flush_internal(); - } ao_mutex_put(&ao_flash_mutex); -} - -/* - * Read/write the config block, which is in - * the last block of the flash - */ - -uint8_t -ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant +ao_storage_flush(void) __reentrant { - ao_flash_setup(); - if (len > FLASH_BLOCK_SIZE) - return 0; ao_mutex_get(&ao_flash_mutex); { - ao_flash_fill(FLASH_CONFIG_BLOCK); - memcpy(ao_flash_data, buf, len); - ao_flash_block_dirty = 1; ao_flash_flush_internal(); } ao_mutex_put(&ao_flash_mutex); - return 1; -} - -uint8_t -ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant -{ - ao_flash_setup(); - if (len > FLASH_BLOCK_SIZE) - return 0; - ao_mutex_get(&ao_flash_mutex); { - ao_flash_fill(FLASH_CONFIG_BLOCK); - memcpy(buf, ao_flash_data, len); - } ao_mutex_put(&ao_flash_mutex); - return 1; } static void flash_dump(void) __reentrant { - uint8_t b; + static __xdata uint8_t b; uint16_t block; uint8_t i; @@ -359,7 +341,7 @@ flash_dump(void) __reentrant ao_cmd_put16((uint16_t) i); } putchar(' '); - ao_ee_read(((uint32_t) block << 8) | i, &b, 1); + ao_storage_read(((uint32_t) block << 8) | i, &b, 1); ao_cmd_put8(b); ++i; } while (i != 0); @@ -372,7 +354,7 @@ flash_store(void) __reentrant uint16_t block; uint8_t i; uint16_t len; - uint8_t b; + static __xdata uint8_t b; uint32_t addr; ao_cmd_hex(); @@ -389,33 +371,10 @@ flash_store(void) __reentrant if (ao_cmd_status != ao_cmd_success) return; b = ao_cmd_lex_i; - ao_ee_write(addr, &b, 1); + ao_storage_write(addr, &b, 1); addr++; } - ao_ee_flush(); -} - -void -ao_ee_dump_config(void) __reentrant -{ - uint16_t i; - printf("Configuration block %d\n", FLASH_CONFIG_BLOCK); - ao_mutex_get(&ao_flash_mutex); { - ao_flash_flush_internal(); - ao_flash_block = FLASH_BLOCK_NONE; - ao_flash_fill(FLASH_CONFIG_BLOCK); - i = 0; - do { - if ((i & 7) == 0) { - if (i) - putchar('\n'); - ao_cmd_put16((uint16_t) i); - } - putchar(' '); - ao_cmd_put8(ao_flash_data[i]); - ++i; - } while (i < sizeof (ao_config)); - } ao_mutex_put(&ao_flash_mutex); + ao_storage_flush(); } static void @@ -423,18 +382,15 @@ flash_status(void) __reentrant { uint8_t status; - ao_flash_setup(); + ao_storage_setup(); ao_mutex_get(&ao_flash_mutex); { status = ao_flash_read_status(); printf ("Flash status: 0x%02x\n", status); - printf ("Flash block shift: %d\n", FLASH_BLOCK_SHIFT); - printf ("Flash block size: %d\n", FLASH_BLOCK_SIZE); - printf ("Flash block mask: %d\n", FLASH_BLOCK_MASK); - printf ("Flash device size: %ld\n", FLASH_DEVICE_SIZE); - printf ("Flash data size: %ld\n", FLASH_DATA_SIZE); - printf ("Flash config block: %d\n", FLASH_CONFIG_BLOCK); + printf ("Flash block shift: %d\n", ao_flash_block_shift); + printf ("Flash block size: %d\n", ao_flash_block_size); + printf ("Flash block mask: %d\n", ao_flash_block_mask); + printf ("Flash device size: %ld\n", ao_storage_total); } ao_mutex_put(&ao_flash_mutex); - ao_ee_dump_config(); } __code struct ao_cmds ao_flash_cmds[] = { @@ -449,7 +405,7 @@ __code struct ao_cmds ao_flash_cmds[] = { * the SPI interface */ void -ao_ee_init(void) +ao_storage_init(void) { /* set up CS */ FLASH_CS = 1; diff --git a/src/ao_log.c b/src/ao_log.c index 18bdb8c8..30acc50a 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -18,6 +18,7 @@ #include "ao.h" static __pdata uint32_t ao_log_current_pos; +static __pdata uint32_t ao_log_end_pos; static __pdata uint32_t ao_log_start_pos; static __xdata uint8_t ao_log_running; static __xdata uint8_t ao_log_mutex; @@ -41,16 +42,14 @@ ao_log_data(__xdata struct ao_log_record *log) __reentrant log->csum = 0; log->csum = ao_log_csum((__xdata uint8_t *) log); ao_mutex_get(&ao_log_mutex); { + if (ao_log_current_pos >= ao_log_end_pos) + ao_log_running = 0; if (ao_log_running) { wrote = 1; - ao_ee_write(ao_log_current_pos, - (uint8_t *) log, - sizeof (struct ao_log_record)); + ao_storage_write(ao_log_current_pos, + log, + sizeof (struct ao_log_record)); ao_log_current_pos += sizeof (struct ao_log_record); - if (ao_log_current_pos >= AO_EE_DATA_SIZE) - ao_log_current_pos = 0; - if (ao_log_current_pos == ao_log_start_pos) - ao_log_running = 0; } } ao_mutex_put(&ao_log_mutex); return wrote; @@ -59,7 +58,7 @@ ao_log_data(__xdata struct ao_log_record *log) __reentrant void ao_log_flush(void) { - ao_ee_flush(); + ao_storage_flush(); } __xdata struct ao_log_record log; @@ -76,7 +75,7 @@ ao_log_dump_check_data(void) static void ao_log_scan(void) { - if (!ao_ee_read(0, (uint8_t *) &log, sizeof (struct ao_log_record))) + if (!ao_storage_read(0, &log, sizeof (struct ao_log_record))) ao_panic(AO_PANIC_LOG); if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) { ao_flight_number = log.u.flight.flight + 1; @@ -97,6 +96,12 @@ typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; void ao_log(void) { + ao_storage_setup(); + + /* For now, use all of the available space */ + ao_log_current_pos = 0; + ao_log_end_pos = ao_storage_config; + ao_log_scan(); while (!ao_log_running) @@ -179,8 +184,6 @@ ao_log_init(void) ao_log_running = 0; /* For now, just log the flight starting at the begining of eeprom */ - ao_log_start_pos = 0; - ao_log_current_pos = ao_log_start_pos; ao_log_state = ao_flight_invalid; /* Create a task to log events to eeprom */ diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 1209c820..ed43c447 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -49,7 +49,7 @@ main(void) ao_beep_init(); ao_cmd_init(); ao_spi_init(); - ao_ee_init(); + ao_storage_init(); ao_flight_init(); ao_log_init(); ao_report_init(); diff --git a/src/at45db161d.h b/src/at45db161d.h index 8b72e647..96042459 100644 --- a/src/at45db161d.h +++ b/src/at45db161d.h @@ -26,13 +26,6 @@ * area return errors. */ -#define FLASH_BLOCK_SIZE_MAX 512 -#define FLASH_BLOCK_SHIFT (ao_flash_block_shift) -#define FLASH_BLOCK_SIZE (ao_flash_block_size) -#define FLASH_BLOCK_MASK (FLASH_BLOCK_SIZE - 1) -#define FLASH_DEVICE_SIZE (ao_flash_device_size) -#define FLASH_DATA_SIZE (FLASH_DEVICE_SIZE - (uint32_t) FLASH_BLOCK_SIZE) -#define FLASH_CONFIG_BLOCK ((uint16_t) (FLASH_DATA_SIZE / FLASH_BLOCK_SIZE)) #define FLASH_READ 0x03 #define FLASH_WRITE 0x82 -- cgit v1.2.3 From e4ba9bf4291bf17c777c8c3ef7c71e4a30b9947a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Jan 2011 17:34:58 -0800 Subject: altos: Require manual flight erasing. This supports flash chips that require larger erase blocks. Signed-off-by: Keith Packard --- src/ao.h | 11 +++ src/ao_config.c | 20 +++-- src/ao_ee.c | 12 +++ src/ao_flash.c | 12 +++ src/ao_log.c | 231 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 5 files changed, 265 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 67337de7..f23e4134 100644 --- a/src/ao.h +++ b/src/ao.h @@ -443,6 +443,8 @@ extern __xdata uint32_t ao_storage_block; /* Byte offset of config block. Will be ao_storage_block bytes long */ extern __xdata uint32_t ao_storage_config; +#define AO_STORAGE_ERASE_LOG (ao_storage_config + AO_CONFIG_MAX_SIZE) + /* Initialize above values. Can only be called once the OS is running */ void ao_storage_setup(void); @@ -459,6 +461,10 @@ ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; uint8_t ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; +/* Erase a block of storage. This always clears ao_storage_block bytes */ +uint8_t +ao_storage_erase(uint32_t pos); + /* Initialize the storage code */ void ao_storage_init(void); @@ -993,9 +999,14 @@ struct ao_config { extern __xdata struct ao_config ao_config; +#define AO_CONFIG_MAX_SIZE 128 + void ao_config_get(void); +void +ao_config_put(void); + void ao_config_init(void); diff --git a/src/ao_config.c b/src/ao_config.c index 2153b841..2673e472 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -36,6 +36,14 @@ _ao_config_put(void) ao_storage_write(ao_storage_config, &ao_config, sizeof (ao_config)); ao_storage_flush(); } + +void +ao_config_put(void) +{ + ao_mutex_get(&ao_config_mutex); + _ao_config_put(); + ao_mutex_put(&ao_config_mutex); +} #endif static void @@ -288,13 +296,13 @@ struct ao_config_var { const char *help; }; -void +static void ao_config_help(void) __reentrant; -void +static void ao_config_show(void) __reentrant; -void +static void ao_config_write(void) __reentrant; __code struct ao_config_var ao_config_vars[] = { @@ -348,7 +356,7 @@ ao_config_set(void) ao_cmd_status = ao_cmd_syntax_error; } -void +static void ao_config_help(void) __reentrant { uint8_t cmd; @@ -356,7 +364,7 @@ ao_config_help(void) __reentrant puts (ao_config_vars[cmd].help); } -void +static void ao_config_show(void) __reentrant { uint8_t cmd; @@ -368,7 +376,7 @@ ao_config_show(void) __reentrant } #if HAS_EEPROM -void +static void ao_config_write(void) __reentrant { uint8_t saved = 0; diff --git a/src/ao_ee.c b/src/ao_ee.c index 6fe88252..575a7b30 100644 --- a/src/ao_ee.c +++ b/src/ao_ee.c @@ -246,6 +246,18 @@ ao_storage_flush(void) __reentrant } ao_mutex_put(&ao_ee_mutex); } +uint8_t +ao_storage_erase(uint32_t pos) __reentrant +{ + ao_mutex_get(&ao_ee_mutex); { + uint16_t block = (uint16_t) (pos >> 8); + ao_ee_fill(block); + memset(ao_ee_data, 0xff, EE_BLOCK_SIZE); + ao_ee_block_dirty = 1; + } ao_mutex_put(&ao_ee_mutex); + return 1; +} + static void ee_dump(void) __reentrant { diff --git a/src/ao_flash.c b/src/ao_flash.c index 3a06bae1..bc8b56ad 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -322,6 +322,18 @@ ao_storage_flush(void) __reentrant } ao_mutex_put(&ao_flash_mutex); } +uint8_t +ao_storage_erase(uint32_t pos) __reentrant +{ + ao_mutex_get(&ao_flash_mutex); { + uint16_t block = (uint16_t) (pos >> ao_flash_block_shift); + ao_flash_fill(block); + memset(ao_flash_data, 0xff, ao_flash_block_size); + ao_flash_block_dirty = 1; + } ao_mutex_put(&ao_flash_mutex); + return 1; +} + static void flash_dump(void) __reentrant { diff --git a/src/ao_log.c b/src/ao_log.c index 30acc50a..132512e6 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -61,6 +61,8 @@ ao_log_flush(void) ao_storage_flush(); } +static void ao_log_scan(void); + __xdata struct ao_log_record log; __xdata uint16_t ao_flight_number; @@ -72,21 +74,6 @@ ao_log_dump_check_data(void) return 1; } -static void -ao_log_scan(void) -{ - if (!ao_storage_read(0, &log, sizeof (struct ao_log_record))) - ao_panic(AO_PANIC_LOG); - if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) { - ao_flight_number = log.u.flight.flight + 1; - if (ao_flight_number == 0) - ao_flight_number = 1; - } else { - ao_flight_number = 1; - } - ao_wakeup(&ao_flight_number); -} - __xdata uint8_t ao_log_adc_pos; __xdata enum flight_state ao_log_state; @@ -161,6 +148,160 @@ ao_log(void) } } +/* + * When erasing a flight log, make sure the config block + * has an up-to-date version of the current flight number + */ + +struct ao_log_erase { + uint8_t unused; + uint16_t flight; +}; + +static __xdata struct ao_log_erase erase; + +#define LOG_MAX_ERASE 16 + +static uint32_t +ao_log_erase_pos(uint8_t i) +{ + return i * sizeof (struct ao_log_erase) + AO_STORAGE_ERASE_LOG; +} + +static void +ao_log_write_erase(uint8_t pos) +{ + erase.unused = 0x00; + erase.flight = ao_flight_number; + ao_storage_write(ao_log_erase_pos(pos), &erase, sizeof (erase)); +} + +static void +ao_log_read_erase(uint8_t pos) +{ + ao_storage_read(ao_log_erase_pos(pos), &erase, sizeof (erase)); +} + + +static void +ao_log_erase_mark(void) +{ + uint8_t i; + + for (i = 0; i < LOG_MAX_ERASE; i++) { + ao_log_read_erase(i); + if (erase.unused == 0 && erase.flight == ao_flight_number) + return; + if (erase.unused == 0xff) { + ao_log_write_erase(i); + return; + } + } + ao_config_put(); +} + +static void +ao_log_erase(uint8_t pos) +{ + ao_config_get(); + (void) pos; +// ao_log_current_pos = pos * ao_config.flight_log_max; +// ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; +// if (ao_log_end_pos > ao_storage_config) +// return; + + ao_log_current_pos = 0; + ao_log_end_pos = ao_storage_config; + + while (ao_log_current_pos < ao_log_end_pos) { + ao_storage_erase(ao_log_current_pos); + ao_log_current_pos += ao_storage_block; + } +} + +static uint16_t +ao_log_flight(uint8_t slot) +{ + (void) slot; + if (!ao_storage_read(0, + &log, + sizeof (struct ao_log_record))) + ao_panic(AO_PANIC_LOG); + + if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) + return log.u.flight.flight; + return 0; +} + +static void +ao_log_scan(void) +{ + uint8_t log_slot; + uint8_t log_avail = 0; + uint16_t log_flight; + + ao_config_get(); + + ao_flight_number = 0; + + /* Scan the log space looking for an empty one, and find the biggest flight number */ + log_slot = 0; + { + log_flight = ao_log_flight(log_slot); + if (log_flight) { + if (++log_flight == 0) + log_flight = 1; + if (ao_flight_number == 0 || + (int16_t) (log_flight - ao_flight_number) > 0) { + ao_flight_number = log_flight; + } + } else + log_avail |= 1 << log_slot; + } + + /* Now look through the log of flight numbers from erase operations and + * see if the last one is bigger than what we found above + */ + for (log_slot = LOG_MAX_ERASE; log_slot-- > 0;) { + ao_log_read_erase(log_slot); + if (erase.unused == 0) { + if (ao_flight_number == 0 || + (int16_t) (erase.flight - ao_flight_number) > 0) + ao_flight_number = erase.flight; + break; + } + } + if (ao_flight_number == 0) + ao_flight_number = 1; + + /* With a flight number in hand, find a place to write a new log, + * use the target flight number to index the available log slots so + * that we write logs to each spot about the same number of times. + */ + + /* If there are no log slots available, then + * do not log the next flight + */ + if (!log_avail) { + ao_log_current_pos = 0; + ao_log_end_pos = 0; + } else { + log_slot = ao_flight_number % log_slot; + while (!((log_avail & (1 << log_slot)))) { + if ((1 << log_slot) > log_avail) + log_slot = 0; + else + log_slot++; + } +// ao_log_current_pos = log_slot * ao_config.flight_log_max; +// ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; + ao_log_current_pos = 0; + ao_log_end_pos = ao_storage_config; + } + + ao_wakeup(&ao_flight_number); +} + void ao_log_start(void) { @@ -178,6 +319,64 @@ ao_log_stop(void) static __xdata struct ao_task ao_log_task; +void +ao_log_list(void) __reentrant +{ + uint8_t slot; + uint16_t flight; + + slot = 0; + { + flight = ao_log_flight(slot); + if (flight) + printf ("Flight %d\n", flight); + } +} + +void +ao_log_delete(void) __reentrant +{ + uint8_t slot; + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + slot = 0; + /* Look for the flight log matching the requested flight */ + { + if (ao_log_flight(slot) == ao_cmd_lex_i) { + ao_log_current_pos = 0; + ao_log_end_pos = ao_storage_config; + while (ao_log_current_pos < ao_log_end_pos) { + /* + * Check to see if we've reached the end of + * the used memory to avoid re-erasing the same + * memory over and over again + */ + if (ao_storage_read(ao_log_current_pos, + &log, + sizeof (struct ao_log_record))) { + for (slot = 0; slot < sizeof (struct ao_log_record); slot++) + if (((uint8_t *) &log)[slot] != 0xff) + break; + if (slot == sizeof (struct ao_log_record)) + break; + } + ao_storage_erase(ao_log_current_pos); + ao_log_current_pos += ao_storage_block; + } + puts("Erased\n"); + return; + } + } + printf("No such flight: %d\n", ao_cmd_lex_i); +} + +__code struct ao_cmds ao_log_cmds[] = { + { 'l', ao_log_list, "l List stored flight logs" }, + { 'd', ao_log_delete, "d Delete stored flight" }, + { 0, ao_log_delete, NULL }, +}; + void ao_log_init(void) { @@ -186,6 +385,8 @@ ao_log_init(void) /* For now, just log the flight starting at the begining of eeprom */ ao_log_state = ao_flight_invalid; + ao_cmd_register(&ao_log_cmds[0]); + /* Create a task to log events to eeprom */ ao_add_task(&ao_log_task, ao_log, "log"); } -- cgit v1.2.3 From 569a1dac55b70c30f01afa7bcb74442ecdd85d85 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Jan 2011 22:37:38 -0800 Subject: altos: Move common storage code to ao_storage.c. Add M25P80 driver This reworks the storage API so that you erase blocks and then store data to them so that the M25P80 driver will work. Signed-off-by: Keith Packard --- src/Makefile.proto | 10 + src/ao.h | 45 +++-- src/ao_config.c | 2 + src/ao_ee.c | 157 ++++------------ src/ao_flash.c | 166 ++++------------- src/ao_log.c | 7 +- src/ao_m25.c | 380 ++++++++++++++++++++++++++++++++++++++ src/ao_pins.h | 2 + src/ao_storage.c | 164 ++++++++++++++++ src/at45db161d.h | 1 + src/telemetrum-v1.1/Makefile.defs | 2 +- 11 files changed, 662 insertions(+), 274 deletions(-) create mode 100644 src/ao_m25.c create mode 100644 src/ao_storage.c (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index c79638ac..709cbca7 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -94,14 +94,24 @@ TM_DRIVER_SRC = \ # # 25LC1024 driver source EE_DRIVER_SRC = \ + ao_storage.c \ ao_ee.c # # AT45DB161D driver source FLASH_DRIVER_SRC = \ + ao_storage.c \ ao_flash.c +# +# Numonyx M25P80 driver source +# + +M25_DRIVER_SRC = \ + ao_storage.c \ + ao_m25.c + # # SiRF driver source # diff --git a/src/ao.h b/src/ao.h index f23e4134..e1306c79 100644 --- a/src/ao.h +++ b/src/ao.h @@ -443,16 +443,15 @@ extern __xdata uint32_t ao_storage_block; /* Byte offset of config block. Will be ao_storage_block bytes long */ extern __xdata uint32_t ao_storage_config; +/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ +extern __xdata uint16_t ao_storage_unit; + #define AO_STORAGE_ERASE_LOG (ao_storage_config + AO_CONFIG_MAX_SIZE) /* Initialize above values. Can only be called once the OS is running */ void ao_storage_setup(void); -/* Flush any pending write data */ -void -ao_storage_flush(void) __reentrant; - /* Write data. Returns 0 on failure, 1 on success */ uint8_t ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; @@ -463,12 +462,36 @@ ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; /* Erase a block of storage. This always clears ao_storage_block bytes */ uint8_t -ao_storage_erase(uint32_t pos); +ao_storage_erase(uint32_t pos) __reentrant; + +/* Flush any pending writes to stable storage */ +void +ao_storage_flush(void) __reentrant; /* Initialize the storage code */ void ao_storage_init(void); +/* + * Low-level functions wrapped by ao_storage.c + */ + +/* Read data within a storage unit */ +uint8_t +ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Write data within a storage unit */ +uint8_t +ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Initialize low-level device bits */ +void +ao_storage_device_init(void); + +/* Print out information about flash chips */ +void +ao_storage_device_info(void) __reentrant; + /* * ao_log.c */ @@ -581,14 +604,6 @@ ao_log_flush(void); */ extern __xdata uint16_t ao_flight_number; -/* Retrieve first log record for the current flight */ -uint8_t -ao_log_dump_first(void); - -/* return next log record for the current flight */ -uint8_t -ao_log_dump_next(void); - /* Logging thread main routine */ void ao_log(void); @@ -605,6 +620,10 @@ ao_log_stop(void); void ao_log_init(void); +/* Write out the current flight number to the erase log */ +void +ao_log_write_erase(uint8_t pos); + /* * ao_flight.c */ diff --git a/src/ao_config.c b/src/ao_config.c index 2673e472..38b72798 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -33,7 +33,9 @@ static void _ao_config_put(void) { ao_storage_setup(); + ao_storage_erase(ao_storage_config); ao_storage_write(ao_storage_config, &ao_config, sizeof (ao_config)); + ao_log_write_erase(0); ao_storage_flush(); } diff --git a/src/ao_ee.c b/src/ao_ee.c index 575a7b30..7de05b7b 100644 --- a/src/ao_ee.c +++ b/src/ao_ee.c @@ -30,6 +30,9 @@ __xdata uint32_t ao_storage_block; /* Byte offset of config block. Will be ao_storage_block bytes long */ __xdata uint32_t ao_storage_config; +/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ +__xdata uint16_t ao_storage_unit; + /* * Using SPI on USART 0, with P1_2 as the chip select */ @@ -161,80 +164,34 @@ ao_ee_fill(uint16_t block) } uint8_t -ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant { - uint16_t block; - uint16_t this_len; - uint8_t this_off; - - if (pos >= ao_storage_total || pos + len > ao_storage_total) - return 0; - while (len) { - - /* Compute portion of transfer within - * a single block - */ - this_off = pos; - this_len = EE_BLOCK_SIZE - (uint16_t) this_off; - block = (uint16_t) (pos >> 8); - if (this_len > len) - this_len = len; - if (this_len & 0xff00) - ao_panic(AO_PANIC_EE); - - /* Transfer the data */ - ao_mutex_get(&ao_ee_mutex); { - if (this_len != EE_BLOCK_SIZE) - ao_ee_fill(block); - else { - ao_ee_flush_internal(); - ao_ee_block = block; - } - memcpy(ao_ee_data + this_off, buf, this_len); - ao_ee_block_dirty = 1; - } ao_mutex_put(&ao_ee_mutex); - - /* See how much is left */ - buf += this_len; - len -= this_len; - pos += this_len; - } + uint16_t block = (uint16_t) (pos >> 8); + + /* Transfer the data */ + ao_mutex_get(&ao_ee_mutex); { + if (len != EE_BLOCK_SIZE) + ao_ee_fill(block); + else { + ao_ee_flush_internal(); + ao_ee_block = block; + } + memcpy(ao_ee_data + (uint16_t) (pos & 0xff), buf, len); + ao_ee_block_dirty = 1; + } ao_mutex_put(&ao_ee_mutex); return 1; } uint8_t -ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant { - uint16_t block; - uint16_t this_len; - uint8_t this_off; - - if (pos >= ao_storage_total || pos + len > ao_storage_total) - return 0; - while (len) { - - /* Compute portion of transfer within - * a single block - */ - this_off = pos; - this_len = EE_BLOCK_SIZE - (uint16_t) this_off; - block = (uint16_t) (pos >> 8); - if (this_len > len) - this_len = len; - if (this_len & 0xff00) - ao_panic(AO_PANIC_EE); - - /* Transfer the data */ - ao_mutex_get(&ao_ee_mutex); { - ao_ee_fill(block); - memcpy(buf, ao_ee_data + this_off, this_len); - } ao_mutex_put(&ao_ee_mutex); + uint16_t block = (uint16_t) (pos >> 8); - /* See how much is left */ - buf += this_len; - len -= this_len; - pos += this_len; - } + /* Transfer the data */ + ao_mutex_get(&ao_ee_mutex); { + ao_ee_fill(block); + memcpy(buf, ao_ee_data + (uint16_t) (pos & 0xff), len); + } ao_mutex_put(&ao_ee_mutex); return 1; } @@ -258,67 +215,11 @@ ao_storage_erase(uint32_t pos) __reentrant return 1; } -static void -ee_dump(void) __reentrant -{ - static __xdata uint8_t b; - uint16_t block; - 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_storage_read(((uint32_t) block << 8) | i, &b, 1); - ao_cmd_put8(b); - ++i; - } while (i != 0); - putchar('\n'); -} - static void ee_store(void) __reentrant { - uint16_t block; - uint8_t i; - uint16_t len; - static __xdata uint8_t b; - 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_storage_write(addr, &b, 1); - addr++; - } - ao_storage_flush(); } -__code struct ao_cmds ao_ee_cmds[] = { - { 'e', ee_dump, "e Dump a block of EEPROM data" }, - { 'w', ee_store, "w ... Write data to EEPROM" }, - { 0, ee_store, NULL }, -}; - void ao_storage_setup(void) { @@ -326,20 +227,24 @@ ao_storage_setup(void) ao_storage_total = EE_DEVICE_SIZE; ao_storage_block = EE_BLOCK_SIZE; ao_storage_config = EE_DEVICE_SIZE - EE_BLOCK_SIZE; + ao_storage_unit = EE_BLOCK_SIZE; } } +void +ao_storage_device_info(void) __reentrant +{ +} + /* * To initialize the chip, set up the CS line and * the SPI interface */ void -ao_storage_init(void) +ao_storage_device_init(void) { /* set up CS */ EE_CS = 1; P1DIR |= (1 << EE_CS_INDEX); P1SEL &= ~(1 << EE_CS_INDEX); - - ao_cmd_register(&ao_ee_cmds[0]); } diff --git a/src/ao_flash.c b/src/ao_flash.c index bc8b56ad..1201a0e5 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -27,6 +27,9 @@ __xdata uint32_t ao_storage_block; /* Byte offset of config block. Will be ao_storage_block bytes long */ __xdata uint32_t ao_storage_config; +/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ +__xdata uint16_t ao_storage_unit; + #define FLASH_CS P1_1 #define FLASH_CS_INDEX 1 @@ -162,9 +165,11 @@ ao_storage_setup(void) ao_panic(AO_PANIC_FLASH); } ao_flash_block_size = 1 << ao_flash_block_shift; + ao_flash_block_mask = ao_flash_block_size - 1; ao_storage_block = ao_flash_block_size; ao_storage_config = ao_storage_total - ao_storage_block; + ao_storage_unit = ao_flash_block_size; ao_flash_setup_done = 1; ao_mutex_put(&ao_flash_mutex); @@ -238,79 +243,38 @@ ao_flash_fill(uint16_t block) } uint8_t -ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant { - uint16_t block; - uint16_t this_len; - uint16_t this_off; + uint16_t block = (uint16_t) (pos >> ao_flash_block_shift); - ao_storage_setup(); - if (pos >= ao_storage_total || pos + len > ao_storage_total) - return 0; - while (len) { - - /* Compute portion of transfer within - * a single block - */ - this_off = (uint16_t) pos & ao_flash_block_mask; - this_len = ao_flash_block_size - this_off; - block = (uint16_t) (pos >> ao_flash_block_shift); - if (this_len > len) - this_len = len; - - /* Transfer the data */ - ao_mutex_get(&ao_flash_mutex); { - if (this_len != ao_flash_block_size) - ao_flash_fill(block); - else { - ao_flash_flush_internal(); - ao_flash_block = block; - } - memcpy(ao_flash_data + this_off, buf, this_len); - ao_flash_block_dirty = 1; - } ao_mutex_put(&ao_flash_mutex); - - /* See how much is left */ - buf += this_len; - len -= this_len; - pos += this_len; - } + /* Transfer the data */ + ao_mutex_get(&ao_flash_mutex); { + if (len != ao_flash_block_size) + ao_flash_fill(block); + else { + ao_flash_flush_internal(); + ao_flash_block = block; + } + memcpy(ao_flash_data + (uint16_t) (pos & ao_flash_block_mask), + buf, + len); + ao_flash_block_dirty = 1; + } ao_mutex_put(&ao_flash_mutex); return 1; } uint8_t -ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant { - uint16_t block; - uint16_t this_len; - uint16_t this_off; + uint16_t block = (uint16_t) (pos >> ao_flash_block_shift); - ao_storage_setup(); - if (pos >= ao_storage_total || pos + len > ao_storage_total) - return 0; - while (len) { - - - /* Compute portion of transfer within - * a single block - */ - this_off = (uint16_t) pos & ao_flash_block_mask; - this_len = ao_flash_block_size - this_off; - block = (uint16_t) (pos >> ao_flash_block_shift); - if (this_len > len) - this_len = len; - - /* Transfer the data */ - ao_mutex_get(&ao_flash_mutex); { - ao_flash_fill(block); - memcpy(buf, ao_flash_data + this_off, this_len); - } ao_mutex_put(&ao_flash_mutex); - - /* See how much is left */ - buf += this_len; - len -= this_len; - pos += this_len; - } + /* Transfer the data */ + ao_mutex_get(&ao_flash_mutex); { + ao_flash_fill(block); + memcpy(buf, + ao_flash_data + (uint16_t) (pos & ao_flash_block_mask), + len); + } ao_mutex_put(&ao_flash_mutex); return 1; } @@ -325,8 +289,9 @@ ao_storage_flush(void) __reentrant uint8_t ao_storage_erase(uint32_t pos) __reentrant { + uint16_t block = (uint16_t) (pos >> ao_flash_block_shift); + ao_mutex_get(&ao_flash_mutex); { - uint16_t block = (uint16_t) (pos >> ao_flash_block_shift); ao_flash_fill(block); memset(ao_flash_data, 0xff, ao_flash_block_size); ao_flash_block_dirty = 1; @@ -334,63 +299,8 @@ ao_storage_erase(uint32_t pos) __reentrant return 1; } -static void -flash_dump(void) __reentrant -{ - static __xdata uint8_t b; - uint16_t block; - 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_storage_read(((uint32_t) block << 8) | i, &b, 1); - ao_cmd_put8(b); - ++i; - } while (i != 0); - putchar('\n'); -} - -static void -flash_store(void) __reentrant -{ - uint16_t block; - uint8_t i; - uint16_t len; - static __xdata uint8_t b; - 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_storage_write(addr, &b, 1); - addr++; - } - ao_storage_flush(); -} - -static void -flash_status(void) __reentrant +void +ao_storage_device_info(void) __reentrant { uint8_t status; @@ -405,23 +315,15 @@ flash_status(void) __reentrant } ao_mutex_put(&ao_flash_mutex); } -__code struct ao_cmds ao_flash_cmds[] = { - { 'e', flash_dump, "e Dump a block of flash data" }, - { 'w', flash_store, "w ... Write data to flash" }, - { 'f', flash_status, "f Show flash status register" }, - { 0, flash_store, NULL }, -}; - /* * To initialize the chip, set up the CS line and * the SPI interface */ void -ao_storage_init(void) +ao_storage_device_init(void) { /* set up CS */ FLASH_CS = 1; P1DIR |= (1 << FLASH_CS_INDEX); P1SEL &= ~(1 << FLASH_CS_INDEX); - ao_cmd_register(&ao_flash_cmds[0]); } diff --git a/src/ao_log.c b/src/ao_log.c index 132512e6..9ca033e1 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -168,7 +168,7 @@ ao_log_erase_pos(uint8_t i) return i * sizeof (struct ao_log_erase) + AO_STORAGE_ERASE_LOG; } -static void +void ao_log_write_erase(uint8_t pos) { erase.unused = 0x00; @@ -364,13 +364,16 @@ ao_log_delete(void) __reentrant ao_storage_erase(ao_log_current_pos); ao_log_current_pos += ao_storage_block; } - puts("Erased\n"); + puts("Erased"); return; } } + ao_log_erase_mark(); printf("No such flight: %d\n", ao_cmd_lex_i); } + + __code struct ao_cmds ao_log_cmds[] = { { 'l', ao_log_list, "l List stored flight logs" }, { 'd', ao_log_delete, "d Delete stored flight" }, diff --git a/src/ao_m25.c b/src/ao_m25.c new file mode 100644 index 00000000..afd5df76 --- /dev/null +++ b/src/ao_m25.c @@ -0,0 +1,380 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +/* Total bytes of available storage */ +__xdata uint32_t ao_storage_total; + +/* Block size - device is erased in these units. At least 256 bytes */ +__xdata uint32_t ao_storage_block; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +__xdata uint32_t ao_storage_config; + +/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ +__xdata uint16_t ao_storage_unit; + +/* + * Each flash chip is arranged in 64kB sectors; the + * chip cannot erase in units smaller than that. + * + * Writing happens in units of 256 byte pages and + * can only change bits from 1 to 0. So, you can rewrite + * the same contents, or append to an existing page easily enough + */ + +#define M25_WREN 0x06 /* Write Enable */ +#define M25_WRDI 0x04 /* Write Disable */ +#define M25_RDID 0x9f /* Read Identification */ +#define M25_RDSR 0x05 /* Read Status Register */ +#define M25_WRSR 0x01 /* Write Status Register */ +#define M25_READ 0x03 /* Read Data Bytes */ +#define M25_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */ +#define M25_PP 0x02 /* Page Program */ +#define M25_SE 0xd8 /* Sector Erase */ +#define M25_BE 0xc7 /* Bulk Erase */ +#define M25_DP 0xb9 /* Deep Power-down */ + +/* RDID response */ +#define M25_MANUF_OFFSET 0 +#define M25_MEMORY_TYPE_OFFSET 1 +#define M25_CAPACITY_OFFSET 2 +#define M25_UID_OFFSET 3 +#define M25_CFI_OFFSET 4 +#define M25_RDID_LEN 4 /* that's all we need */ + +#define M25_CAPACITY_128KB 0x11 +#define M25_CAPACITY_256KB 0x12 +#define M25_CAPACITY_512KB 0x13 +#define M25_CAPACITY_1MB 0x14 +#define M25_CAPACITY_2MB 0x15 + +/* + * Status register bits + */ + +#define M25_STATUS_SRWD (1 << 7) /* Status register write disable */ +#define M25_STATUS_BP_MASK (7 << 2) /* Block protect bits */ +#define M25_STATUS_BP_SHIFT (2) +#define M25_STATUS_WEL (1 << 1) /* Write enable latch */ +#define M25_STATUS_WIP (1 << 0) /* Write in progress */ + +/* + * On teleterra, the m25 chip select pins are + * wired on P0_0 through P0_3. + */ + +#if M25_MAX_CHIPS > 1 +static uint8_t ao_m25_size[M25_MAX_CHIPS]; /* number of sectors in each chip */ +static uint8_t ao_m25_pin[M25_MAX_CHIPS]; /* chip select pin for each chip */ +static uint8_t ao_m25_numchips; /* number of chips detected */ +#endif +static uint8_t ao_m25_total; /* total sectors available */ +static uint8_t ao_m25_wip; /* write in progress */ + +static __xdata uint8_t ao_m25_mutex; + +/* + * This little array is abused to send and receive data. A particular + * caution -- the read and write addresses are written into the last + * three bytes of the array by ao_m25_set_page_address and then the + * first byte is used by ao_m25_wait_wip and ao_m25_write_enable, neither + * of which touch those last three bytes. + */ + +static __xdata uint8_t ao_m25_instruction[4]; + +#define M25_SELECT(cs) (SPI_CS_PORT &= ~(cs)) +#define M25_DESELECT(cs) (SPI_CS_PORT |= (cs)) + +#define M25_BLOCK_SHIFT 16 +#define M25_BLOCK 65536L +#define M25_POS_TO_SECTOR(pos) ((uint8_t) ((pos) >> M25_BLOCK_SHIFT)) +#define M25_SECTOR_TO_POS(sector) (((uint32_t) (sector)) << M25_BLOCK_SHIFT) + +/* + * Block until the specified chip is done writing + */ +static void +ao_m25_wait_wip(uint8_t cs) +{ + if (ao_m25_wip & cs) { + M25_SELECT(cs); + ao_m25_instruction[0] = M25_RDSR; + ao_spi_send(ao_m25_instruction, 1); + do { + ao_spi_recv(ao_m25_instruction, 1); + } while (ao_m25_instruction[0] & M25_STATUS_WIP); + M25_DESELECT(cs); + ao_m25_wip &= ~cs; + } +} + +/* + * Set the write enable latch so that page program and sector + * erase commands will work. Also mark the chip as busy writing + * so that future operations will block until the WIP bit goes off + */ +static void +ao_m25_write_enable(uint8_t cs) +{ + M25_SELECT(cs); + ao_m25_instruction[0] = M25_WREN; + ao_spi_send(&ao_m25_instruction, 1); + M25_DESELECT(cs); + ao_m25_wip |= cs; +} + + +/* + * Returns the number of 64kB sectors + */ +static uint8_t +ao_m25_read_capacity(uint8_t cs) +{ + uint8_t capacity; + M25_SELECT(cs); + ao_m25_instruction[0] = M25_RDID; + ao_spi_send(ao_m25_instruction, 1); + ao_spi_recv(ao_m25_instruction, M25_RDID_LEN); + M25_DESELECT(cs); + + /* Check to see if the chip is present */ + if (ao_m25_instruction[0] == 0xff) + return 0; + capacity = ao_m25_instruction[M25_CAPACITY_OFFSET]; + + /* Sanity check capacity number */ + if (capacity < 0x11 || 0x1f < capacity) + return 0; + return 1 << (capacity - 0x10); +} + +static uint8_t +ao_m25_set_address(uint32_t pos) +{ + uint8_t chip; +#if M25_MAX_CHIPS > 1 + uint8_t size; + + for (chip = 0; chip < ao_m25_numchips; chip++) { + size = ao_m25_size[chip]; + if (M25_POS_TO_SECTOR(pos) < size) + break; + pos -= M25_SECTOR_TO_POS(size); + } + if (chip == ao_m25_numchips) + return 0xff; + + chip = ao_m25_pin[chip]; +#else + chip = M25_CS_MASK; +#endif + ao_m25_wait_wip(chip); + + ao_m25_instruction[1] = pos >> 16; + ao_m25_instruction[2] = pos >> 8; + ao_m25_instruction[3] = pos; + return chip; +} + +/* + * Scan the possible chip select lines + * to see which flash chips are connected + */ +static uint8_t +ao_m25_scan(void) +{ +#if M25_MAX_CHIPS > 1 + uint8_t pin, size; +#endif + + if (ao_m25_total) + return 1; + +#if M25_MAX_CHIPS > 1 + ao_m25_numchips = 0; + for (pin = 1; pin != 0; pin <<= 1) { + if (M25_CS_MASK & pin) { + size = ao_m25_read_capacity(pin); + if (size != 0) { + ao_m25_size[ao_m25_numchips] = size; + ao_m25_pin[ao_m25_numchips] = pin; + ao_m25_total += size; + ao_m25_numchips++; + } + } + } +#else + ao_m25_total = ao_m25_read_capacity(M25_CS_MASK); +#endif + if (!ao_m25_total) + return 0; + ao_storage_total = M25_SECTOR_TO_POS(ao_m25_total); + ao_storage_block = M25_BLOCK; + ao_storage_config = ao_storage_total - M25_BLOCK; + ao_storage_unit = 256; + return 1; +} + +/* + * Erase the specified sector + */ +uint8_t +ao_storage_erase(uint32_t pos) __reentrant +{ + uint8_t cs; + + if (pos >= ao_storage_total || pos + ao_storage_block > ao_storage_total) + return 0; + + ao_mutex_get(&ao_m25_mutex); + ao_m25_scan(); + + cs = ao_m25_set_address(pos); + + ao_m25_wait_wip(cs); + ao_m25_write_enable(cs); + + ao_m25_instruction[0] = M25_SE; + M25_SELECT(cs); + ao_spi_send(ao_m25_instruction, 4); + M25_DESELECT(cs); + ao_m25_wip |= cs; + + ao_mutex_put(&ao_m25_mutex); + return 1; +} + +/* + * Write to flash + */ +uint8_t +ao_storage_device_write(uint32_t pos, __xdata void *d, uint16_t len) __reentrant +{ + uint8_t cs; + + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + + ao_mutex_get(&ao_m25_mutex); + ao_m25_scan(); + + cs = ao_m25_set_address(pos); + ao_m25_write_enable(cs); + + ao_m25_instruction[0] = M25_PP; + M25_SELECT(cs); + ao_spi_send(ao_m25_instruction, 4); + ao_spi_send(d, len); + M25_DESELECT(cs); + + ao_mutex_put(&ao_m25_mutex); + return 1; +} + +/* + * Read from flash + */ +uint8_t +ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant +{ + uint8_t cs; + + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + ao_mutex_get(&ao_m25_mutex); + ao_m25_scan(); + + cs = ao_m25_set_address(pos); + + /* No need to use the FAST_READ as we're running at only 8MHz */ + ao_m25_instruction[0] = M25_READ; + M25_SELECT(cs); + ao_spi_send(ao_m25_instruction, 4); + ao_spi_recv(d, len); + M25_DESELECT(cs); + + ao_mutex_put(&ao_m25_mutex); + return 1; +} + +void +ao_storage_flush(void) __reentrant +{ +} + +void +ao_storage_setup(void) +{ + ao_mutex_get(&ao_m25_mutex); + ao_m25_scan(); + ao_mutex_put(&ao_m25_mutex); +} + +void +ao_storage_device_info(void) __reentrant +{ + uint8_t cs; +#if M25_MAX_CHIPS > 1 + uint8_t chip; +#endif + + ao_mutex_get(&ao_m25_mutex); + ao_m25_scan(); + ao_mutex_put(&ao_m25_mutex); + +#if M25_MAX_CHIPS > 1 + printf ("Detected chips %d size %d\n", ao_m25_numchips, ao_m25_total); + for (chip = 0; chip < ao_m25_numchips; chip++) + printf ("Flash chip %d select %02x size %d\n", + chip, ao_m25_pin[chip], ao_m25_size[chip]); +#else + printf ("Detected chips 1 size %d\n", ao_m25_total); +#endif + + printf ("Available chips:\n"); + for (cs = 1; cs != 0; cs <<= 1) { + if ((M25_CS_MASK & cs) == 0) + continue; + + ao_mutex_get(&ao_m25_mutex); + M25_SELECT(cs); + ao_m25_instruction[0] = M25_RDID; + ao_spi_send(ao_m25_instruction, 1); + ao_spi_recv(ao_m25_instruction, M25_RDID_LEN); + M25_DESELECT(cs); + + printf ("Select %02x manf %02x type %02x cap %02x uid %02x\n", + cs, + ao_m25_instruction[M25_MANUF_OFFSET], + ao_m25_instruction[M25_MEMORY_TYPE_OFFSET], + ao_m25_instruction[M25_CAPACITY_OFFSET], + ao_m25_instruction[M25_UID_OFFSET]); + ao_mutex_put(&ao_m25_mutex); + } +} + +void +ao_storage_device_init(void) +{ + /* Set up chip select wires */ + SPI_CS_PORT |= M25_CS_MASK; /* raise all CS pins */ + SPI_CS_DIR |= M25_CS_MASK; /* set CS pins as outputs */ + SPI_CS_SEL &= ~M25_CS_MASK; /* set CS pins as GPIO */ +} diff --git a/src/ao_pins.h b/src/ao_pins.h index b5089b85..9446964e 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -48,6 +48,8 @@ #define HAS_EXTERNAL_TEMP 0 #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ + #define M25_MAX_CHIPS 1 #endif #if defined(TELEDONGLE_V_0_2) diff --git a/src/ao_storage.c b/src/ao_storage.c new file mode 100644 index 00000000..25a7c8b9 --- /dev/null +++ b/src/ao_storage.c @@ -0,0 +1,164 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +uint8_t +ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +{ + uint16_t this_len; + uint16_t this_off; + + ao_storage_setup(); + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + while (len) { + + /* Compute portion of transfer within + * a single block + */ + this_off = (uint16_t) pos & (ao_storage_unit - 1); + this_len = ao_storage_unit - this_off; + if (this_len > len) + this_len = len; + + if (!ao_storage_device_read(pos, buf, this_len)) + return 0; + + /* See how much is left */ + buf += this_len; + len -= this_len; + pos += this_len; + } + return 1; +} + +uint8_t +ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +{ + uint16_t this_len; + uint16_t this_off; + + ao_storage_setup(); + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + while (len) { + + /* Compute portion of transfer within + * a single block + */ + this_off = (uint16_t) pos & (ao_storage_unit - 1); + this_len = ao_storage_unit - this_off; + if (this_len > len) + this_len = len; + + if (!ao_storage_device_write(pos, buf, this_len)) + return 0; + + /* See how much is left */ + buf += this_len; + len -= this_len; + pos += this_len; + } + return 1; +} + +static __xdata uint8_t storage_data[8]; + +static void +ao_storage_dump(void) __reentrant +{ + uint8_t i, j; + + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + for (i = 0; ; i += 8) { + if (ao_storage_read(((uint32_t) (ao_cmd_lex_i) << 8) + i, + storage_data, + 8)) { + ao_cmd_put16((uint16_t) i); + for (j = 0; j < 7; j++) { + putchar(' '); + ao_cmd_put8(storage_data[j]); + } + putchar ('\n'); + } + if (i == 248) + break; + } +} + +static void +ao_storage_store(void) __reentrant +{ + uint16_t block; + uint8_t i; + uint16_t len; + static __xdata uint8_t b; + 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_storage_write(addr, &b, 1); + addr++; + } +} + +void +ao_storage_zap(void) __reentrant +{ + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_storage_erase((uint32_t) ao_cmd_lex_i << 8); +} + +void +ao_storage_info(void) __reentrant +{ + printf("Storage size: %ld\n", ao_storage_total); + printf("Storage erase unit: %ld\n", ao_storage_block); + ao_storage_device_info(); +} + +__code struct ao_cmds ao_storage_cmds[] = { + { 'f', ao_storage_info, "f Show storage info" }, + { 'e', ao_storage_dump, "e Dump a block of flash data" }, + { 'w', ao_storage_store,"w ... Write data to flash" }, + { 'z', ao_storage_zap, "z Erase flash containing " }, + { 0, ao_storage_zap, NULL }, +}; + +void +ao_storage_init(void) +{ + ao_storage_device_init(); + ao_cmd_register(&ao_storage_cmds[0]); +} diff --git a/src/at45db161d.h b/src/at45db161d.h index 96042459..9ee6f1b6 100644 --- a/src/at45db161d.h +++ b/src/at45db161d.h @@ -29,6 +29,7 @@ #define FLASH_READ 0x03 #define FLASH_WRITE 0x82 +#define FLASH_PAGE_ERASE 0x81 #define FLASH_READ_STATUS 0xd7 #define FLASH_SET_CONFIG 0x3d diff --git a/src/telemetrum-v1.1/Makefile.defs b/src/telemetrum-v1.1/Makefile.defs index a230203a..f38226c6 100644 --- a/src/telemetrum-v1.1/Makefile.defs +++ b/src/telemetrum-v1.1/Makefile.defs @@ -3,7 +3,7 @@ PROG = telemetrum-v1.1-$(VERSION).ihx SRC = \ $(TM_BASE_SRC) \ $(SPI_DRIVER_SRC) \ - $(FLASH_DRIVER_SRC) \ + $(M25_DRIVER_SRC) \ $(SKY_DRIVER_SRC) \ $(DBG_SRC) -- cgit v1.2.3 From e991f52276248fa08d96fbecc458bc478e98d299 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Jan 2011 23:35:31 -0800 Subject: altos: Rip out 'optimization' in ao_log_scan Remove premature optimization to avoid re-scanning the flight logs for the best empty entry. Signed-off-by: Keith Packard --- src/ao_log.c | 29 +++++++++-------------------- 1 file changed, 9 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/ao_log.c b/src/ao_log.c index 9ca033e1..00bb46d3 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -234,9 +234,10 @@ ao_log_flight(uint8_t slot) } static void -ao_log_scan(void) +ao_log_scan(void) __reentrant { uint8_t log_slot; + uint8_t log_slots; uint8_t log_avail = 0; uint16_t log_flight; @@ -244,7 +245,7 @@ ao_log_scan(void) ao_flight_number = 0; - /* Scan the log space looking for an empty one, and find the biggest flight number */ + /* Scan the log space looking for the biggest flight number */ log_slot = 0; { log_flight = ao_log_flight(log_slot); @@ -256,8 +257,9 @@ ao_log_scan(void) ao_flight_number = log_flight; } } else - log_avail |= 1 << log_slot; + log_avail = 1; } + log_slots = log_slot + 1; /* Now look through the log of flight numbers from erase operations and * see if the last one is bigger than what we found above @@ -279,25 +281,12 @@ ao_log_scan(void) * that we write logs to each spot about the same number of times. */ - /* If there are no log slots available, then - * do not log the next flight - */ - if (!log_avail) { - ao_log_current_pos = 0; - ao_log_end_pos = 0; - } else { - log_slot = ao_flight_number % log_slot; - while (!((log_avail & (1 << log_slot)))) { - if ((1 << log_slot) > log_avail) - log_slot = 0; - else - log_slot++; - } -// ao_log_current_pos = log_slot * ao_config.flight_log_max; -// ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; + /* Find a log slot for the next flight, if available */ + if (log_avail) { ao_log_current_pos = 0; ao_log_end_pos = ao_storage_config; - } + } else + ao_log_current_pos = ao_log_end_pos = 0; ao_wakeup(&ao_flight_number); } -- cgit v1.2.3 From 408a3e04362d626778640dd0ce7d356d3863de53 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Jan 2011 23:38:13 -0800 Subject: altos: Mark end of available flight list with 'done' to make the UI code easier to write Signed-off-by: Keith Packard --- src/ao_log.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/ao_log.c b/src/ao_log.c index 00bb46d3..21d0bc34 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -320,6 +320,7 @@ ao_log_list(void) __reentrant if (flight) printf ("Flight %d\n", flight); } + printf ("done\n"); } void -- cgit v1.2.3 From a9b210bc33cd95e7108ab51925fdf0d5e8deaf7e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 7 Jan 2011 10:05:11 -0800 Subject: altos: Add configuration parameter for maximum flight log size This parameter will permit available storage to be split into multiple separate flight logs. Signed-off-by: Keith Packard --- src/ao.h | 3 ++- src/ao_config.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index e1306c79..a5890d47 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1002,7 +1002,7 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 3 +#define AO_CONFIG_MINOR 4 struct ao_config { uint8_t major; @@ -1014,6 +1014,7 @@ struct ao_config { uint8_t apogee_delay; /* minor version 1 */ int16_t accel_minus_g; /* minor version 2 */ uint32_t radio_cal; /* minor version 3 */ + uint32_t flight_log_max; /* minor version 4 */ }; extern __xdata struct ao_config ao_config; diff --git a/src/ao_config.c b/src/ao_config.c index 38b72798..ebfb0386 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -27,6 +27,7 @@ __xdata uint8_t ao_config_mutex; #define AO_CONFIG_DEFAULT_CALLSIGN "N0CALL" #define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000 #define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 +#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 256 * (uint32_t) 1024) #if HAS_EEPROM static void @@ -83,6 +84,9 @@ _ao_config_get(void) /* Fixups for minor version 3 */ if (ao_config.minor < 3) ao_config.radio_cal = ao_radio_cal; + /* Fixups for minor version 4 */ + if (ao_config.minor < 4) + ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -291,6 +295,30 @@ ao_config_radio_cal_set(void) __reentrant ao_config_radio_cal_show(); } +#if HAS_EEPROM +void +ao_config_log_show(void) __reentrant +{ + printf("Max flight log: %d kB\n", (int16_t) (ao_config.flight_log_max >> 10)); +} + +void +ao_config_log_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_mutex_get(&ao_config_mutex); + _ao_config_get(); + if (ao_storage_block > 1024 && (ao_cmd_lex_u32 & ((ao_storage_block >> 10) - 1))) + printf("Flight log size must be multiple of %ld\n", ao_storage_block >> 10); + ao_config.flight_log_max = ao_cmd_lex_u32 << 10; + ao_config_dirty = 1; + ao_mutex_put(&ao_config_mutex); + ao_config_log_show(); +} +#endif /* HAS_EEPROM */ + struct ao_config_var { char cmd; void (*set)(void) __reentrant; @@ -324,6 +352,10 @@ __code struct ao_config_var ao_config_vars[] = { #endif /* HAS_ADC */ { 'f', ao_config_radio_cal_set, ao_config_radio_cal_show, "f Set radio calibration value (cal = rf/(xtal/2^16))" }, +#if HAS_EEPROM + { 'l', ao_config_log_set, ao_config_log_show, + "l Set flight log size in kB" }, +#endif { 's', ao_config_show, ao_config_show, "s Show current config values" }, #if HAS_EEPROM -- cgit v1.2.3 From 2722703bd848b07a02d3ce0c83a502eca52a9f1d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 7 Jan 2011 14:58:39 -0800 Subject: altos: support storage of multiple flights. This adds the logging support for dealing with multiple flights Signed-off-by: Keith Packard --- src/ao.h | 4 ++ src/ao_config.c | 20 ++++++---- src/ao_log.c | 120 +++++++++++++++++++++++++++++++------------------------ src/ao_storage.c | 24 ++++++++++- 4 files changed, 105 insertions(+), 63 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index a5890d47..ad02a829 100644 --- a/src/ao.h +++ b/src/ao.h @@ -624,6 +624,10 @@ ao_log_init(void); void ao_log_write_erase(uint8_t pos); +/* Returns true if there are any logs stored in eeprom */ +uint8_t +ao_log_present(void); + /* * ao_flight.c */ diff --git a/src/ao_config.c b/src/ao_config.c index ebfb0386..a3e0a64f 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -27,7 +27,7 @@ __xdata uint8_t ao_config_mutex; #define AO_CONFIG_DEFAULT_CALLSIGN "N0CALL" #define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000 #define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 -#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 256 * (uint32_t) 1024) +#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 192 * (uint32_t) 1024) #if HAS_EEPROM static void @@ -308,14 +308,18 @@ ao_config_log_set(void) __reentrant ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); - if (ao_storage_block > 1024 && (ao_cmd_lex_u32 & ((ao_storage_block >> 10) - 1))) + if (ao_log_present()) + printf("Storage must be empty before changing log size\n"); + else if (ao_storage_block > 1024 && (ao_cmd_lex_u32 & ((ao_storage_block >> 10) - 1))) printf("Flight log size must be multiple of %ld\n", ao_storage_block >> 10); - ao_config.flight_log_max = ao_cmd_lex_u32 << 10; - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); - ao_config_log_show(); + else { + ao_mutex_get(&ao_config_mutex); + _ao_config_get(); + ao_config.flight_log_max = ao_cmd_lex_u32 << 10; + ao_config_dirty = 1; + ao_mutex_put(&ao_config_mutex); + ao_config_log_show(); + } } #endif /* HAS_EEPROM */ diff --git a/src/ao_log.c b/src/ao_log.c index 21d0bc34..47f24f01 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -85,10 +85,6 @@ ao_log(void) { ao_storage_setup(); - /* For now, use all of the available space */ - ao_log_current_pos = 0; - ao_log_end_pos = ao_storage_config; - ao_log_scan(); while (!ao_log_running) @@ -200,66 +196,64 @@ ao_log_erase_mark(void) ao_config_put(); } -static void -ao_log_erase(uint8_t pos) +static uint8_t +ao_log_slots() { - ao_config_get(); - (void) pos; -// ao_log_current_pos = pos * ao_config.flight_log_max; -// ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; -// if (ao_log_end_pos > ao_storage_config) -// return; - - ao_log_current_pos = 0; - ao_log_end_pos = ao_storage_config; - - while (ao_log_current_pos < ao_log_end_pos) { - ao_storage_erase(ao_log_current_pos); - ao_log_current_pos += ao_storage_block; - } + return (uint8_t) (ao_storage_config / ao_config.flight_log_max); +} + +static uint32_t +ao_log_pos(uint8_t slot) +{ + return ((slot) * ao_config.flight_log_max); } static uint16_t ao_log_flight(uint8_t slot) { - (void) slot; - if (!ao_storage_read(0, + if (!ao_storage_read(ao_log_pos(slot), &log, sizeof (struct ao_log_record))) - ao_panic(AO_PANIC_LOG); + return 0; if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) return log.u.flight.flight; return 0; } -static void -ao_log_scan(void) __reentrant +static uint16_t +ao_log_max_flight(void) { uint8_t log_slot; uint8_t log_slots; - uint8_t log_avail = 0; uint16_t log_flight; - - ao_config_get(); - - ao_flight_number = 0; + uint16_t max_flight = 0; /* Scan the log space looking for the biggest flight number */ - log_slot = 0; - { + log_slots = ao_log_slots(); + for (log_slot = 0; log_slot < log_slots; log_slot++) { log_flight = ao_log_flight(log_slot); - if (log_flight) { - if (++log_flight == 0) - log_flight = 1; - if (ao_flight_number == 0 || - (int16_t) (log_flight - ao_flight_number) > 0) { - ao_flight_number = log_flight; - } - } else - log_avail = 1; + if (!log_flight) + continue; + if (max_flight == 0 || (int16_t) (log_flight - max_flight) > 0) + max_flight = log_flight; } - log_slots = log_slot + 1; + return max_flight; +} + +static void +ao_log_scan(void) __reentrant +{ + uint8_t log_slot; + uint8_t log_slots; + uint8_t log_want; + + ao_config_get(); + + ao_flight_number = ao_log_max_flight(); + if (ao_flight_number) + if (++ao_flight_number == 0) + ao_flight_number = 1; /* Now look through the log of flight numbers from erase operations and * see if the last one is bigger than what we found above @@ -282,11 +276,19 @@ ao_log_scan(void) __reentrant */ /* Find a log slot for the next flight, if available */ - if (log_avail) { - ao_log_current_pos = 0; - ao_log_end_pos = ao_storage_config; - } else - ao_log_current_pos = ao_log_end_pos = 0; + ao_log_current_pos = ao_log_end_pos = 0; + log_slots = ao_log_slots(); + log_want = (ao_flight_number - 1) % log_slots; + log_slot = log_want; + do { + if (ao_log_flight(log_slot) == 0) { + ao_log_current_pos = ao_log_pos(log_slot); + ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; + break; + } + if (++log_slot >= log_slots) + log_slot = 0; + } while (log_slot != log_want); ao_wakeup(&ao_flight_number); } @@ -306,19 +308,28 @@ ao_log_stop(void) ao_log_flush(); } +uint8_t +ao_log_present(void) +{ + return ao_log_max_flight() != 0; +} + static __xdata struct ao_task ao_log_task; void ao_log_list(void) __reentrant { uint8_t slot; + uint8_t slots; uint16_t flight; - slot = 0; + slots = ao_log_slots(); + for (slot = 0; slot < slots; slot++) { flight = ao_log_flight(slot); if (flight) - printf ("Flight %d\n", flight); + printf ("flight %d start %ld end %ld\n", + flight, ao_log_pos(slot), ao_log_pos(slot+1)); } printf ("done\n"); } @@ -327,15 +338,18 @@ void ao_log_delete(void) __reentrant { uint8_t slot; + uint8_t slots; + ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - slot = 0; + + slots = ao_log_slots(); /* Look for the flight log matching the requested flight */ - { + for (slot = 0; slot < slots; slot++) { if (ao_log_flight(slot) == ao_cmd_lex_i) { - ao_log_current_pos = 0; - ao_log_end_pos = ao_storage_config; + ao_log_current_pos = ao_log_pos(slot); + ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; while (ao_log_current_pos < ao_log_end_pos) { /* * Check to see if we've reached the end of diff --git a/src/ao_storage.c b/src/ao_storage.c index 25a7c8b9..c4beedd2 100644 --- a/src/ao_storage.c +++ b/src/ao_storage.c @@ -103,6 +103,10 @@ ao_storage_dump(void) __reentrant } } +#if 0 + +/* not enough space for this today + */ static void ao_storage_store(void) __reentrant { @@ -130,6 +134,7 @@ ao_storage_store(void) __reentrant addr++; } } +#endif void ao_storage_zap(void) __reentrant @@ -140,6 +145,18 @@ ao_storage_zap(void) __reentrant ao_storage_erase((uint32_t) ao_cmd_lex_i << 8); } +void +ao_storage_zapall(void) __reentrant +{ + uint32_t pos; + + ao_cmd_white(); + if (!ao_match_word("DoIt")) + return; + for (pos = 0; pos < ao_storage_config; pos += ao_storage_block) + ao_storage_erase(pos); +} + void ao_storage_info(void) __reentrant { @@ -151,8 +168,11 @@ ao_storage_info(void) __reentrant __code struct ao_cmds ao_storage_cmds[] = { { 'f', ao_storage_info, "f Show storage info" }, { 'e', ao_storage_dump, "e Dump a block of flash data" }, - { 'w', ao_storage_store,"w ... Write data to flash" }, - { 'z', ao_storage_zap, "z Erase flash containing " }, +#if 0 + { 'w', ao_storage_store, "w ... Write data to flash" }, + #endif + { 'z', ao_storage_zap, "z Erase flash containing " }, + { 'Z', ao_storage_zapall,"Z Erase all logs. is doit with D&I" }, { 0, ao_storage_zap, NULL }, }; -- cgit v1.2.3 From d8c9684239b67a69a4a3d24202a6df0d73c4f7f5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 7 Jan 2011 17:54:54 -0800 Subject: altos: Speed up at45 and 25lc erase speeds No need to read the block to be erased before erasing it. Signed-off-by: Keith Packard --- src/ao_ee.c | 9 +++++---- src/ao_flash.c | 5 ++--- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/ao_ee.c b/src/ao_ee.c index 7de05b7b..e3b41103 100644 --- a/src/ao_ee.c +++ b/src/ao_ee.c @@ -19,6 +19,7 @@ #include "25lc1024.h" #define EE_BLOCK_SIZE ((uint16_t) (256)) +#define EE_BLOCK_SHIFT 8 #define EE_DEVICE_SIZE ((uint32_t) 128 * (uint32_t) 1024) /* Total bytes of available storage */ @@ -166,7 +167,7 @@ ao_ee_fill(uint16_t block) uint8_t ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant { - uint16_t block = (uint16_t) (pos >> 8); + uint16_t block = (uint16_t) (pos >> EE_BLOCK_SHIFT); /* Transfer the data */ ao_mutex_get(&ao_ee_mutex); { @@ -185,7 +186,7 @@ ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentra uint8_t ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant { - uint16_t block = (uint16_t) (pos >> 8); + uint16_t block = (uint16_t) (pos >> EE_BLOCK_SHIFT); /* Transfer the data */ ao_mutex_get(&ao_ee_mutex); { @@ -207,8 +208,8 @@ uint8_t ao_storage_erase(uint32_t pos) __reentrant { ao_mutex_get(&ao_ee_mutex); { - uint16_t block = (uint16_t) (pos >> 8); - ao_ee_fill(block); + ao_ee_flush_internal(); + ao_ee_block = (uint16_t) (pos >> EE_BLOCK_SHIFT); memset(ao_ee_data, 0xff, EE_BLOCK_SIZE); ao_ee_block_dirty = 1; } ao_mutex_put(&ao_ee_mutex); diff --git a/src/ao_flash.c b/src/ao_flash.c index 1201a0e5..3a264ceb 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -289,10 +289,9 @@ ao_storage_flush(void) __reentrant uint8_t ao_storage_erase(uint32_t pos) __reentrant { - uint16_t block = (uint16_t) (pos >> ao_flash_block_shift); - ao_mutex_get(&ao_flash_mutex); { - ao_flash_fill(block); + ao_flash_flush_internal(); + ao_flash_block = (uint16_t) (pos >> ao_flash_block_shift); memset(ao_flash_data, 0xff, ao_flash_block_size); ao_flash_block_dirty = 1; } ao_mutex_put(&ao_flash_mutex); -- cgit v1.2.3 From 1cc08af4f4a1ff61fc0deca3bdd95e8a5ca8ec5c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 7 Jan 2011 17:55:54 -0800 Subject: altos: white space fix Signed-off-by: Keith Packard --- src/ao_storage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_storage.c b/src/ao_storage.c index c4beedd2..c51bec4a 100644 --- a/src/ao_storage.c +++ b/src/ao_storage.c @@ -170,7 +170,7 @@ __code struct ao_cmds ao_storage_cmds[] = { { 'e', ao_storage_dump, "e Dump a block of flash data" }, #if 0 { 'w', ao_storage_store, "w ... Write data to flash" }, - #endif +#endif { 'z', ao_storage_zap, "z Erase flash containing " }, { 'Z', ao_storage_zapall,"Z Erase all logs. is doit with D&I" }, { 0, ao_storage_zap, NULL }, -- cgit v1.2.3 From edd22ee49adf60c35f2fe6ba97c111b7ad4131c2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 7 Jan 2011 17:56:06 -0800 Subject: altos: report flight log offsets in hex block numbers instead of bytes makes them compatible with the 'e' command. Signed-off-by: Keith Packard --- src/ao_log.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao_log.c b/src/ao_log.c index 47f24f01..f319834a 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -328,8 +328,10 @@ ao_log_list(void) __reentrant { flight = ao_log_flight(slot); if (flight) - printf ("flight %d start %ld end %ld\n", - flight, ao_log_pos(slot), ao_log_pos(slot+1)); + printf ("flight %d start %x end %x\n", + flight, + (uint16_t) (ao_log_pos(slot) >> 8), + (uint16_t) (ao_log_pos(slot+1) >> 8)); } printf ("done\n"); } -- cgit v1.2.3 From 73620c41017c1774d6190dfd4be5b742eb64f8d3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 7 Jan 2011 20:13:28 -0800 Subject: altos: ensure erase mark is written when erasing flights It was getting called only when *failing* to erase a flight (oops), secondly, it wasn't getting written because ao_storage_flush wasn't getting called. Signed-off-by: Keith Packard --- src/ao_log.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_log.c b/src/ao_log.c index f319834a..55b9dfff 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -170,6 +170,7 @@ ao_log_write_erase(uint8_t pos) erase.unused = 0x00; erase.flight = ao_flight_number; ao_storage_write(ao_log_erase_pos(pos), &erase, sizeof (erase)); + ao_storage_flush(); } static void @@ -350,6 +351,7 @@ ao_log_delete(void) __reentrant /* Look for the flight log matching the requested flight */ for (slot = 0; slot < slots; slot++) { if (ao_log_flight(slot) == ao_cmd_lex_i) { + ao_log_erase_mark(); ao_log_current_pos = ao_log_pos(slot); ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; while (ao_log_current_pos < ao_log_end_pos) { @@ -374,7 +376,6 @@ ao_log_delete(void) __reentrant return; } } - ao_log_erase_mark(); printf("No such flight: %d\n", ao_cmd_lex_i); } -- cgit v1.2.3 From bbddcae2a15b6d430e84956ddf26955aa9173cc0 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 7 Jan 2011 20:18:25 -0800 Subject: altos: Optimize Morse code generation This reduces the size of data and code needed to report the flight states Signed-off-by: Keith Packard --- src/ao_report.c | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/ao_report.c b/src/ao_report.c index 3b469de6..511b4f16 100644 --- a/src/ao_report.c +++ b/src/ao_report.c @@ -17,17 +17,24 @@ #include "ao.h" -static const char * __xdata flight_reports[] = { - "...", /* startup, 'S' */ - "..", /* idle 'I' */ - ".--.", /* pad 'P' */ - "-...", /* boost 'B' */ - "..-.", /* fast 'F' */ - "-.-.", /* coast 'C' */ - "-..", /* drogue 'D' */ - "--", /* main 'M' */ - ".-..", /* landed 'L' */ - ".-.-.-", /* invalid */ +#define BIT(i,x) ((x) ? (1 << (i)) : 0) +#define MORSE1(a) (1 | BIT(3,a)) +#define MORSE2(a,b) (2 | BIT(3,a) | BIT(4,b)) +#define MORSE3(a,b,c) (3 | BIT(3,a) | BIT(4,b) | BIT(5,c)) +#define MORSE4(a,b,c,d) (4 | BIT(3,a) | BIT(4,b) | BIT(5,c) | BIT(6,d)) +#define MORSE5(a,b,c,d,e) (5 | BIT(3,a) | BIT(4,b) | BIT(5,c) | BIT(6,d) | BIT(7,e)) + +static const uint8_t flight_reports[] = { + MORSE3(0,0,0), /* startup, 'S' */ + MORSE2(0,0), /* idle 'I' */ + MORSE4(0,1,1,0), /* pad 'P' */ + MORSE4(1,0,0,0), /* boost 'B' */ + MORSE4(0,0,1,0), /* fast 'F' */ + MORSE4(1,0,1,0), /* coast 'C' */ + MORSE3(1,0,0), /* drogue 'D' */ + MORSE2(1,1), /* main 'M' */ + MORSE4(0,1,0,0), /* landed 'L' */ + MORSE4(1,0,0,1), /* invalid 'X' */ }; #if 1 @@ -42,17 +49,18 @@ static __xdata enum ao_flight_state ao_report_state; static void ao_report_beep(void) __reentrant { - char *r = flight_reports[ao_flight_state]; - char c; + uint8_t r = flight_reports[ao_flight_state]; + uint8_t l = r & 7; if (!r) return; - while (c = *r++) { - if (c == '.') - signal(AO_MS_TO_TICKS(200)); - else + while (l--) { + if (r & 8) signal(AO_MS_TO_TICKS(600)); + else + signal(AO_MS_TO_TICKS(200)); pause(AO_MS_TO_TICKS(200)); + r >>= 1; } pause(AO_MS_TO_TICKS(400)); } -- cgit v1.2.3 From 00891b40754962ef6530b237ef52017bb58112d5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 7 Jan 2011 20:25:09 -0800 Subject: altos: Check requested log max size against available space Make sure the amount of memory requested for a single log isn't more than is available on the device. Signed-off-by: Keith Packard --- src/ao_config.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ao_config.c b/src/ao_config.c index a3e0a64f..e97b7eb1 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -305,17 +305,22 @@ ao_config_log_show(void) __reentrant void ao_config_log_set(void) __reentrant { + uint16_t block = (uint16_t) (ao_storage_block >> 10); + uint16_t config = (uint16_t) (ao_storage_config >> 10); + ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; if (ao_log_present()) printf("Storage must be empty before changing log size\n"); - else if (ao_storage_block > 1024 && (ao_cmd_lex_u32 & ((ao_storage_block >> 10) - 1))) - printf("Flight log size must be multiple of %ld\n", ao_storage_block >> 10); + else if (block > 1024 && (ao_cmd_lex_i & (block - 1))) + printf("Flight log size must be multiple of %d kB\n", block); + else if (ao_cmd_lex_i > config) + printf("Flight log max %d kB\n", config); else { ao_mutex_get(&ao_config_mutex); _ao_config_get(); - ao_config.flight_log_max = ao_cmd_lex_u32 << 10; + ao_config.flight_log_max = (uint32_t) ao_cmd_lex_i << 10; ao_config_dirty = 1; ao_mutex_put(&ao_config_mutex); ao_config_log_show(); -- cgit v1.2.3 From 52ac83fedbfd380d14d4df2e79992bbdfba3552a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 7 Jan 2011 20:26:39 -0800 Subject: altos: Check for full log and complain Reports special tone along with the continuity checks. Reports flight 0 in telemetry. Signed-off-by: Keith Packard --- src/ao.h | 4 ++++ src/ao_log.c | 6 ++++++ src/ao_report.c | 10 ++++++++++ src/ao_telemetry.c | 2 +- 4 files changed, 21 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index ad02a829..37a39a79 100644 --- a/src/ao.h +++ b/src/ao.h @@ -628,6 +628,10 @@ ao_log_write_erase(uint8_t pos); uint8_t ao_log_present(void); +/* Returns true if there is no more storage space available */ +uint8_t +ao_log_full(void); + /* * ao_flight.c */ diff --git a/src/ao_log.c b/src/ao_log.c index 55b9dfff..ba019992 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -315,6 +315,12 @@ ao_log_present(void) return ao_log_max_flight() != 0; } +uint8_t +ao_log_full(void) +{ + return ao_log_current_pos == ao_log_end_pos; +} + static __xdata struct ao_task ao_log_task; void diff --git a/src/ao_report.c b/src/ao_report.c index 511b4f16..cc8b512b 100644 --- a/src/ao_report.c +++ b/src/ao_report.c @@ -128,6 +128,16 @@ ao_report_continuity(void) __reentrant ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(20)); } } + if (ao_log_full()) { + pause(AO_MS_TO_TICKS(100)); + c = 2; + while (c--) { + ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(100)); + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(100)); + ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(100)); + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(100)); + } + } c = 50; while (c-- && ao_flight_state == ao_flight_pad) pause(AO_MS_TO_TICKS(100)); diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 277c3ce0..22ab1d67 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -34,7 +34,7 @@ ao_telemetry(void) ao_sleep(&ao_flight_number); memcpy(telemetry.callsign, ao_config.callsign, AO_MAX_CALLSIGN); telemetry.addr = ao_serial_number; - telemetry.flight = ao_flight_number; + telemetry.flight = ao_log_full() ? 0 : ao_flight_number; telemetry.accel_plus_g = ao_config.accel_plus_g; telemetry.accel_minus_g = ao_config.accel_minus_g; ao_rdf_time = ao_time(); -- cgit v1.2.3 From 57de960b8148bf485607898c3d66af6994d76481 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 7 Jan 2011 20:52:33 -0800 Subject: altos: Remove unused accel_vel_mach and accel_vel_boost variables Presumably left-over debugging code. Signed-off-by: Keith Packard --- src/ao_flight.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index 980c16be..5567d87f 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -84,9 +84,6 @@ __xdata uint8_t ao_flight_force_idle; #define ACCEL_VEL_MACH VEL_MPS_TO_COUNT(200) #define ACCEL_VEL_BOOST VEL_MPS_TO_COUNT(5) -int32_t accel_vel_mach; -int32_t accel_vel_boost; - /* * Barometer calibration * @@ -214,8 +211,6 @@ ao_flight(void) ao_config_get(); ao_main_pres = ao_altitude_to_pres(ao_pres_to_altitude(ao_ground_pres) + ao_config.main_deploy); ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; - accel_vel_mach = ACCEL_VEL_MACH; - accel_vel_boost = ACCEL_VEL_BOOST; ao_flight_vel = 0; ao_min_vel = 0; ao_old_vel = ao_flight_vel; -- cgit v1.2.3 From c437b14b7fc7afdfc7b809a04d7fa29d5e742307 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 7 Jan 2011 21:00:10 -0800 Subject: altos: Remove redundant initialization of ao_interval variables These are all initialized in the ao_flight_drogue state transition. Signed-off-by: Keith Packard --- src/ao_flight.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index 5567d87f..7fe85cb1 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -463,11 +463,5 @@ void ao_flight_init(void) { ao_flight_state = ao_flight_startup; - ao_interval_min_accel = 0; - ao_interval_max_accel = 0x7fff; - ao_interval_min_pres = 0; - ao_interval_max_pres = 0x7fff; - ao_interval_end = AO_INTERVAL_TICKS; - ao_add_task(&flight_task, ao_flight, "flight"); } -- cgit v1.2.3 From 7ad419d81c90ef6a16656970466313767fef830f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Jan 2011 21:26:41 -0800 Subject: altos: oops -- 'e' command was only showing 7 of the 8 bytes per line Just a silly off-by-one error when printing out the data received from flash. Signed-off-by: Keith Packard --- src/ao_storage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_storage.c b/src/ao_storage.c index c51bec4a..709259ee 100644 --- a/src/ao_storage.c +++ b/src/ao_storage.c @@ -92,7 +92,7 @@ ao_storage_dump(void) __reentrant storage_data, 8)) { ao_cmd_put16((uint16_t) i); - for (j = 0; j < 7; j++) { + for (j = 0; j < 8; j++) { putchar(' '); ao_cmd_put8(storage_data[j]); } -- cgit v1.2.3 From d794ef9e0fbe4d13259db1bbd69f01717c14400b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 12 Jan 2011 12:41:26 -0800 Subject: altos: check for valid flight number in ao_log_delete Zero is not a valid flight number, and ao_log_flight uses that to indicate 'no flight in this slot'. Check the user-provided input for zero before looking through the slots. Signed-off-by: Keith Packard --- src/ao_log.c | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/ao_log.c b/src/ao_log.c index ba019992..8666482b 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -355,31 +355,33 @@ ao_log_delete(void) __reentrant slots = ao_log_slots(); /* Look for the flight log matching the requested flight */ - for (slot = 0; slot < slots; slot++) { - if (ao_log_flight(slot) == ao_cmd_lex_i) { - ao_log_erase_mark(); - ao_log_current_pos = ao_log_pos(slot); - ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; - while (ao_log_current_pos < ao_log_end_pos) { - /* - * Check to see if we've reached the end of - * the used memory to avoid re-erasing the same - * memory over and over again - */ - if (ao_storage_read(ao_log_current_pos, - &log, - sizeof (struct ao_log_record))) { - for (slot = 0; slot < sizeof (struct ao_log_record); slot++) - if (((uint8_t *) &log)[slot] != 0xff) + if (ao_cmd_lex_i) { + for (slot = 0; slot < slots; slot++) { + if (ao_log_flight(slot) == ao_cmd_lex_i) { + ao_log_erase_mark(); + ao_log_current_pos = ao_log_pos(slot); + ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; + while (ao_log_current_pos < ao_log_end_pos) { + /* + * Check to see if we've reached the end of + * the used memory to avoid re-erasing the same + * memory over and over again + */ + if (ao_storage_read(ao_log_current_pos, + &log, + sizeof (struct ao_log_record))) { + for (slot = 0; slot < sizeof (struct ao_log_record); slot++) + if (((uint8_t *) &log)[slot] != 0xff) + break; + if (slot == sizeof (struct ao_log_record)) break; - if (slot == sizeof (struct ao_log_record)) - break; + } + ao_storage_erase(ao_log_current_pos); + ao_log_current_pos += ao_storage_block; } - ao_storage_erase(ao_log_current_pos); - ao_log_current_pos += ao_storage_block; + puts("Erased"); + return; } - puts("Erased"); - return; } } printf("No such flight: %d\n", ao_cmd_lex_i); -- cgit v1.2.3 From 47ee4597e55749e8f66f61a585ea32776979bf80 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Jan 2011 16:25:10 -0800 Subject: altos: TELEMETRY PROTOCOL CHANGE. Switch to 16-bit serial numbers. What a terrible mistake! The flight computer serial numbers were recorded in only 8 bits, so serial numbers > 255 would get truncated. There's really no fix other than bumping the field to 16 bits and reflashing every TM and TD on the planet. Very unfortunate. Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_monitor.c | 4 ++-- src/ao_telemetry.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 37a39a79..5721c344 100644 --- a/src/ao.h +++ b/src/ao.h @@ -856,7 +856,7 @@ ao_gps_report_init(void); #define AO_TELEMETRY_VERSION 3 struct ao_telemetry { - uint8_t addr; + uint16_t serial; uint16_t flight; uint8_t flight_state; int16_t flight_accel; diff --git a/src/ao_monitor.c b/src/ao_monitor.c index 1e7f5102..4ba3da6d 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -41,10 +41,10 @@ ao_monitor(void) if (state > ao_flight_invalid) state = ao_flight_invalid; if (recv.status & PKT_APPEND_STATUS_1_CRC_OK) { - printf("VERSION %d CALL %s SERIAL %3d FLIGHT %5u RSSI %4d STATUS %02x STATE %7s ", + printf("VERSION %d CALL %s SERIAL %d FLIGHT %5u RSSI %4d STATUS %02x STATE %7s ", AO_TELEMETRY_VERSION, callsign, - recv.telemetry.addr, + recv.telemetry.serial, recv.telemetry.flight, rssi, recv.status, ao_state_names[state]); diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 22ab1d67..7aad929f 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -33,7 +33,7 @@ ao_telemetry(void) while (!ao_flight_number) ao_sleep(&ao_flight_number); memcpy(telemetry.callsign, ao_config.callsign, AO_MAX_CALLSIGN); - telemetry.addr = ao_serial_number; + telemetry.serial = ao_serial_number; telemetry.flight = ao_log_full() ? 0 : ao_flight_number; telemetry.accel_plus_g = ao_config.accel_plus_g; telemetry.accel_minus_g = ao_config.accel_minus_g; -- cgit v1.2.3 From 7a35b2d7048669a96256d4ea0086299f8a0cb1df Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Jan 2011 22:42:38 -0800 Subject: altos: Flush log when full When the log storage is full, make sure any pending writes are flushed out so that the last bit isn't lost. Signed-off-by: Keith Packard --- src/ao_log.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao_log.c b/src/ao_log.c index 8666482b..fa072550 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -42,8 +42,8 @@ ao_log_data(__xdata struct ao_log_record *log) __reentrant log->csum = 0; log->csum = ao_log_csum((__xdata uint8_t *) log); ao_mutex_get(&ao_log_mutex); { - if (ao_log_current_pos >= ao_log_end_pos) - ao_log_running = 0; + if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_stop(); if (ao_log_running) { wrote = 1; ao_storage_write(ao_log_current_pos, -- cgit v1.2.3 From 8a775b8f9ecefa143050653d74dfd218b32b9bb5 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 16 Jan 2011 10:54:45 +1000 Subject: altos: Restructure skytraq NMEA parsing code to save some space Splitting this into several smaller functions appears to make SDCC generate better code. --- src/ao_gps_skytraq.c | 401 +++++++++++++++++++++++++++------------------------ 1 file changed, 212 insertions(+), 189 deletions(-) (limited to 'src') diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index 2d3d464c..a2d5f1db 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -180,6 +180,215 @@ ao_gps_parse_flag(char no_c, char yes_c) __reentrant return ret; } +static void +ao_nmea_gga() +{ + uint8_t i; + + /* Now read the data into the gps data record + * + * $GPGGA,025149.000,4528.1723,N,12244.2480,W,1,05,2.0,103.5,M,-19.5,M,,0000*66 + * + * Essential fix data + * + * 025149.000 time (02:51:49.000 GMT) + * 4528.1723,N Latitude 45°28.1723' N + * 12244.2480,W Longitude 122°44.2480' W + * 1 Fix quality: + * 0 = invalid + * 1 = GPS fix (SPS) + * 2 = DGPS fix + * 3 = PPS fix + * 4 = Real Time Kinematic + * 5 = Float RTK + * 6 = estimated (dead reckoning) + * 7 = Manual input mode + * 8 = Simulation mode + * 05 Number of satellites (5) + * 2.0 Horizontal dilution + * 103.5,M Altitude, 103.5M above msl + * -19.5,M Height of geoid above WGS84 ellipsoid + * ? time in seconds since last DGPS update + * 0000 DGPS station ID + * *66 checksum + */ + + ao_gps_next_tick = ao_time(); + ao_gps_next.flags = AO_GPS_RUNNING | ao_gps_date_flags; + ao_gps_next.hour = ao_gps_decimal(2); + ao_gps_next.minute = ao_gps_decimal(2); + ao_gps_next.second = ao_gps_decimal(2); + ao_gps_skip_field(); /* skip seconds fraction */ + + ao_gps_next.latitude = ao_gps_parse_pos(2); + if (ao_gps_parse_flag('N', 'S')) + ao_gps_next.latitude = -ao_gps_next.latitude; + ao_gps_next.longitude = ao_gps_parse_pos(3); + if (ao_gps_parse_flag('E', 'W')) + ao_gps_next.longitude = -ao_gps_next.longitude; + + i = ao_gps_decimal(0xff); + if (i == 1) + ao_gps_next.flags |= AO_GPS_VALID; + + i = ao_gps_decimal(0xff) << AO_GPS_NUM_SAT_SHIFT; + if (i > AO_GPS_NUM_SAT_MASK) + i = AO_GPS_NUM_SAT_MASK; + ao_gps_next.flags |= i; + + ao_gps_lexchar(); + ao_gps_next.hdop = ao_gps_decimal(0xff); + if (ao_gps_next.hdop <= 50) { + ao_gps_next.hdop = (uint8_t) 5 * ao_gps_next.hdop; + if (ao_gps_char == '.') + ao_gps_next.hdop = (ao_gps_next.hdop + + ((uint8_t) ao_gps_decimal(1) >> 1)); + } else + ao_gps_next.hdop = 255; + ao_gps_skip_field(); + + ao_gps_next.altitude = ao_gps_decimal(0xff); + ao_gps_skip_field(); /* skip any fractional portion */ + + /* Skip remaining fields */ + while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { + ao_gps_lexchar(); + ao_gps_skip_field(); + } + if (ao_gps_char == '*') { + uint8_t cksum = ao_gps_cksum ^ '*'; + if (cksum != ao_gps_hex(2)) + ao_gps_error = 1; + } else + ao_gps_error = 1; + if (!ao_gps_error) { + ao_mutex_get(&ao_gps_mutex); + ao_gps_tick = ao_gps_next_tick; + memcpy(&ao_gps_data, &ao_gps_next, sizeof (struct ao_gps_data)); + ao_mutex_put(&ao_gps_mutex); + ao_wakeup(&ao_gps_data); + } +} + +static void +ao_nmea_gsv(void) +{ + char c; + uint8_t i; + uint8_t done; + /* Now read the data into the GPS tracking data record + * + * $GPGSV,3,1,12,05,54,069,45,12,44,061,44,21,07,184,46,22,78,289,47*72 + * + * Satellites in view data + * + * 3 Total number of GSV messages + * 1 Sequence number of current GSV message + * 12 Total sats in view (0-12) + * 05 SVID + * 54 Elevation + * 069 Azimuth + * 45 C/N0 in dB + * ... other SVIDs + * 72 checksum + */ + c = ao_gps_decimal(1); /* total messages */ + i = ao_gps_decimal(1); /* message sequence */ + if (i == 1) { + ao_gps_tracking_next.channels = 0; + } + done = (uint8_t) c == i; + ao_gps_lexchar(); + ao_gps_skip_field(); /* sats in view */ + while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { + i = ao_gps_tracking_next.channels; + c = ao_gps_decimal(2); /* SVID */ + if (i < AO_MAX_GPS_TRACKING) + ao_gps_tracking_next.sats[i].svid = c; + ao_gps_lexchar(); + ao_gps_skip_field(); /* elevation */ + ao_gps_lexchar(); + ao_gps_skip_field(); /* azimuth */ + c = ao_gps_decimal(2); /* C/N0 */ + if (i < AO_MAX_GPS_TRACKING) { + if (!(ao_gps_tracking_next.sats[i].c_n_1 = c)) + ao_gps_tracking_next.sats[i].svid = 0; + ao_gps_tracking_next.channels = i + 1; + } + } + if (ao_gps_char == '*') { + uint8_t cksum = ao_gps_cksum ^ '*'; + if (cksum != ao_gps_hex(2)) + ao_gps_error = 1; + } + else + ao_gps_error = 1; + if (ao_gps_error) + ao_gps_tracking_next.channels = 0; + else if (done) { + ao_mutex_get(&ao_gps_mutex); + memcpy(&ao_gps_tracking_data, &ao_gps_tracking_next, + sizeof(ao_gps_tracking_data)); + ao_mutex_put(&ao_gps_mutex); + ao_wakeup(&ao_gps_tracking_data); + } +} + +static void +ao_nmea_rmc(void) +{ + char a, c; + uint8_t i; + /* Parse the RMC record to read out the current date */ + + /* $GPRMC,111636.932,A,2447.0949,N,12100.5223,E,000.0,000.0,030407,,,A*61 + * + * Recommended Minimum Specific GNSS Data + * + * 111636.932 UTC time 11:16:36.932 + * A Data Valid (V = receiver warning) + * 2447.0949 Latitude + * N North/south indicator + * 12100.5223 Longitude + * E East/west indicator + * 000.0 Speed over ground + * 000.0 Course over ground + * 030407 UTC date (ddmmyy format) + * A Mode indicator: + * N = data not valid + * A = autonomous mode + * D = differential mode + * E = estimated (dead reckoning) mode + * M = manual input mode + * S = simulator mode + * 61 checksum + */ + ao_gps_skip_field(); + for (i = 0; i < 8; i++) { + ao_gps_lexchar(); + ao_gps_skip_field(); + } + a = ao_gps_decimal(2); + c = ao_gps_decimal(2); + i = ao_gps_decimal(2); + /* Skip remaining fields */ + while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { + ao_gps_lexchar(); + ao_gps_skip_field(); + } + if (ao_gps_char == '*') { + uint8_t cksum = ao_gps_cksum ^ '*'; + if (cksum != ao_gps_hex(2)) + ao_gps_error = 1; + } else + ao_gps_error = 1; + if (!ao_gps_error) { + ao_gps_next.year = i; + ao_gps_next.month = c; + ao_gps_next.day = a; + ao_gps_date_flags = AO_GPS_DATE_VALID; + } +} void ao_gps(void) __reentrant @@ -222,197 +431,11 @@ ao_gps(void) __reentrant continue; if (a == (uint8_t) 'G' && c == (uint8_t) 'G' && i == (uint8_t) 'A') { - /* Now read the data into the gps data record - * - * $GPGGA,025149.000,4528.1723,N,12244.2480,W,1,05,2.0,103.5,M,-19.5,M,,0000*66 - * - * Essential fix data - * - * 025149.000 time (02:51:49.000 GMT) - * 4528.1723,N Latitude 45°28.1723' N - * 12244.2480,W Longitude 122°44.2480' W - * 1 Fix quality: - * 0 = invalid - * 1 = GPS fix (SPS) - * 2 = DGPS fix - * 3 = PPS fix - * 4 = Real Time Kinematic - * 5 = Float RTK - * 6 = estimated (dead reckoning) - * 7 = Manual input mode - * 8 = Simulation mode - * 05 Number of satellites (5) - * 2.0 Horizontal dilution - * 103.5,M Altitude, 103.5M above msl - * -19.5,M Height of geoid above WGS84 ellipsoid - * ? time in seconds since last DGPS update - * 0000 DGPS station ID - * *66 checksum - */ - - ao_gps_next_tick = ao_time(); - ao_gps_next.flags = AO_GPS_RUNNING | ao_gps_date_flags; - ao_gps_next.hour = ao_gps_decimal(2); - ao_gps_next.minute = ao_gps_decimal(2); - ao_gps_next.second = ao_gps_decimal(2); - ao_gps_skip_field(); /* skip seconds fraction */ - - ao_gps_next.latitude = ao_gps_parse_pos(2); - if (ao_gps_parse_flag('N', 'S')) - ao_gps_next.latitude = -ao_gps_next.latitude; - ao_gps_next.longitude = ao_gps_parse_pos(3); - if (ao_gps_parse_flag('E', 'W')) - ao_gps_next.longitude = -ao_gps_next.longitude; - - i = ao_gps_decimal(0xff); - if (i == 1) - ao_gps_next.flags |= AO_GPS_VALID; - - i = ao_gps_decimal(0xff) << AO_GPS_NUM_SAT_SHIFT; - if (i > AO_GPS_NUM_SAT_MASK) - i = AO_GPS_NUM_SAT_MASK; - ao_gps_next.flags |= i; - - ao_gps_lexchar(); - ao_gps_next.hdop = ao_gps_decimal(0xff); - if (ao_gps_next.hdop <= 50) { - ao_gps_next.hdop = (uint8_t) 5 * ao_gps_next.hdop; - if (ao_gps_char == '.') - ao_gps_next.hdop = (ao_gps_next.hdop + - ((uint8_t) ao_gps_decimal(1) >> 1)); - } else - ao_gps_next.hdop = 255; - ao_gps_skip_field(); - - ao_gps_next.altitude = ao_gps_decimal(0xff); - ao_gps_skip_field(); /* skip any fractional portion */ - - /* Skip remaining fields */ - while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { - ao_gps_lexchar(); - ao_gps_skip_field(); - } - if (ao_gps_char == '*') { - uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex(2)) - ao_gps_error = 1; - } else - ao_gps_error = 1; - if (!ao_gps_error) { - ao_mutex_get(&ao_gps_mutex); - ao_gps_tick = ao_gps_next_tick; - memcpy(&ao_gps_data, &ao_gps_next, sizeof (struct ao_gps_data)); - ao_mutex_put(&ao_gps_mutex); - ao_wakeup(&ao_gps_data); - } + ao_nmea_gga(); } else if (a == (uint8_t) 'G' && c == (uint8_t) 'S' && i == (uint8_t) 'V') { - uint8_t done; - /* Now read the data into the GPS tracking data record - * - * $GPGSV,3,1,12,05,54,069,45,12,44,061,44,21,07,184,46,22,78,289,47*72 - * - * Satellites in view data - * - * 3 Total number of GSV messages - * 1 Sequence number of current GSV message - * 12 Total sats in view (0-12) - * 05 SVID - * 54 Elevation - * 069 Azimuth - * 45 C/N0 in dB - * ... other SVIDs - * 72 checksum - */ - c = ao_gps_decimal(1); /* total messages */ - i = ao_gps_decimal(1); /* message sequence */ - if (i == 1) { - ao_gps_tracking_next.channels = 0; - } - done = (uint8_t) c == i; - ao_gps_lexchar(); - ao_gps_skip_field(); /* sats in view */ - while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { - i = ao_gps_tracking_next.channels; - c = ao_gps_decimal(2); /* SVID */ - if (i < AO_MAX_GPS_TRACKING) - ao_gps_tracking_next.sats[i].svid = c; - ao_gps_lexchar(); - ao_gps_skip_field(); /* elevation */ - ao_gps_lexchar(); - ao_gps_skip_field(); /* azimuth */ - c = ao_gps_decimal(2); /* C/N0 */ - if (i < AO_MAX_GPS_TRACKING) { - if (!(ao_gps_tracking_next.sats[i].c_n_1 = c)) - ao_gps_tracking_next.sats[i].svid = 0; - ao_gps_tracking_next.channels = i + 1; - } - } - if (ao_gps_char == '*') { - uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex(2)) - ao_gps_error = 1; - } - else - ao_gps_error = 1; - if (ao_gps_error) - ao_gps_tracking_next.channels = 0; - else if (done) { - ao_mutex_get(&ao_gps_mutex); - memcpy(&ao_gps_tracking_data, &ao_gps_tracking_next, - sizeof(ao_gps_tracking_data)); - ao_mutex_put(&ao_gps_mutex); - ao_wakeup(&ao_gps_tracking_data); - } + ao_nmea_gsv(); } else if (a == (uint8_t) 'R' && c == (uint8_t) 'M' && i == (uint8_t) 'C') { - /* Parse the RMC record to read out the current date */ - - /* $GPRMC,111636.932,A,2447.0949,N,12100.5223,E,000.0,000.0,030407,,,A*61 - * - * Recommended Minimum Specific GNSS Data - * - * 111636.932 UTC time 11:16:36.932 - * A Data Valid (V = receiver warning) - * 2447.0949 Latitude - * N North/south indicator - * 12100.5223 Longitude - * E East/west indicator - * 000.0 Speed over ground - * 000.0 Course over ground - * 030407 UTC date (ddmmyy format) - * A Mode indicator: - * N = data not valid - * A = autonomous mode - * D = differential mode - * E = estimated (dead reckoning) mode - * M = manual input mode - * S = simulator mode - * 61 checksum - */ - ao_gps_skip_field(); - for (i = 0; i < 8; i++) { - ao_gps_lexchar(); - ao_gps_skip_field(); - } - a = ao_gps_decimal(2); - c = ao_gps_decimal(2); - i = ao_gps_decimal(2); - /* Skip remaining fields */ - while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { - ao_gps_lexchar(); - ao_gps_skip_field(); - } - if (ao_gps_char == '*') { - uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex(2)) - ao_gps_error = 1; - } else - ao_gps_error = 1; - if (!ao_gps_error) { - ao_gps_next.year = i; - ao_gps_next.month = c; - ao_gps_next.day = a; - ao_gps_date_flags = AO_GPS_DATE_VALID; - } + ao_nmea_rmc(); } } } -- cgit v1.2.3 From 118fe84c9ff1cc9d1653e67a2315e22e19d60a14 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Jan 2011 11:26:31 -0800 Subject: altos: average 512 accel/baro samples at startup instead of 1000 This lets us use a simple shift instead of a divide, saving a huge amount of code space. Signed-off-by: Keith Packard --- src/ao_flight.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index 7fe85cb1..9f651ae2 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -196,17 +196,17 @@ ao_flight(void) /* startup state: * - * Collect 1000 samples of acceleration and pressure + * Collect 512 samples of acceleration and pressure * data and average them to find the resting values */ - if (nsamples < 1000) { + if (nsamples < 512) { ao_raw_accel_sum += ao_raw_accel; ao_raw_pres_sum += ao_raw_pres; ++nsamples; continue; } - ao_ground_accel = (ao_raw_accel_sum / nsamples); - ao_ground_pres = (ao_raw_pres_sum / nsamples); + ao_ground_accel = ao_raw_accel_sum >> 9; + ao_ground_pres = ao_raw_pres_sum >> 9; ao_min_pres = ao_ground_pres; ao_config_get(); ao_main_pres = ao_altitude_to_pres(ao_pres_to_altitude(ao_ground_pres) + ao_config.main_deploy); -- cgit v1.2.3 From 58838c0b96a91da0bd0cd77c3ff312b589c08136 Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sat, 15 Jan 2011 23:21:26 +1300 Subject: altos: Added check for an accel value above 1.5g When detecting flight or idle mode, this should indicate that accel cal values are out of whack. Signed-off-by: Mike Beattie --- src/ao_flight.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index 9f651ae2..5a9a8d80 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -221,6 +221,7 @@ ao_flight(void) if (ao_config.accel_plus_g != 0 && ao_config.accel_minus_g != 0 && ao_flight_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP && + ao_flight_accel > ao_config.accel_plus_g - ACCEL_NOSE_UP && !ao_flight_force_idle) { /* Disable the USB controller in flight mode -- cgit v1.2.3 From add2802a8a33336180fe6856241a7f4a8200e89c Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Sun, 16 Jan 2011 00:10:30 +1300 Subject: altos: Added check for out of bounds accel Chose invalid flight mode instead of idle to give user feedback. Signed-off-by: Mike Beattie --- src/ao_flight.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index 5a9a8d80..01dbb11b 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -237,9 +237,18 @@ ao_flight(void) ao_flight_state = ao_flight_pad; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } else { - ao_flight_state = ao_flight_idle; + if (ao_flight_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || + ao_flight_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) + { + /* Detected an accel value outside -1.5g to 1.5g + * -> invalid mode + */ + ao_flight_state = ao_flight_invalid; + } else { + ao_flight_state = ao_flight_idle; + } - /* Turn on packet system in idle mode + /* Turn on packet system in idle or invalid mode */ ao_packet_slave_start(); ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); -- cgit v1.2.3 From ab31b1c737d8fd32af482e5b06699f1b832a25a1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Jan 2011 00:56:22 -0800 Subject: altos: Add DATA_TO_XDATA to linux test harness The flight test harness needs to expose every function used by the flight code in some form, and this macro is about to become used. Signed-off-by: Keith Packard --- src/ao_flight_test.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 2bf7f2b2..e0cfa47a 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -154,6 +154,8 @@ struct ao_config { struct ao_config ao_config = { 250, 15937, 16467 }; +#define DATA_TO_XDATA(x) (x) + #include "ao_flight.c" void -- cgit v1.2.3 From afd3d3cdb8c2291c1c7cda7908392d68cd04f87f Mon Sep 17 00:00:00 2001 From: Mike Beattie Date: Mon, 17 Jan 2011 15:03:40 +1300 Subject: Rework invalid accel cal detection code Slightly reduces code space. Uncalibrated accelerometer now enters invalid state as well. Signed-off-by: Mike Beattie --- src/ao_flight.c | 63 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index 01dbb11b..e99692a3 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -216,45 +216,56 @@ ao_flight(void) ao_old_vel = ao_flight_vel; ao_old_vel_tick = ao_flight_tick; - /* Go to pad state if the nose is pointing up */ + /* Check to see what mode we should go to. + * - Invalid mode if accel cal appears to be out + * - pad mode if we're upright, + * - idle mode otherwise + */ ao_config_get(); - if (ao_config.accel_plus_g != 0 && - ao_config.accel_minus_g != 0 && - ao_flight_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP && - ao_flight_accel > ao_config.accel_plus_g - ACCEL_NOSE_UP && - !ao_flight_force_idle) + if (ao_config.accel_plus_g == 0 || + ao_config.accel_minus_g == 0 || + ao_flight_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || + ao_flight_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) { + /* Detected an accel value outside -1.5g to 1.5g + * (or uncalibrated values), so we go into invalid mode + */ + ao_flight_state = ao_flight_invalid; + /* Allow packet mode in invalid flight state, + * Still need to be able to fix the problem! + */ + ao_packet_slave_start(); + + } else if (ao_flight_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP && + !ao_flight_force_idle) + { + /* Set pad mode - we can fly! */ + ao_flight_state = ao_flight_pad; + /* Disable the USB controller in flight mode * to save power */ ao_usb_disable(); - /* Turn on telemetry system - */ + /* Turn on telemetry system */ ao_rdf_set(1); ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); - ao_flight_state = ao_flight_pad; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); } else { - if (ao_flight_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || - ao_flight_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) - { - /* Detected an accel value outside -1.5g to 1.5g - * -> invalid mode - */ - ao_flight_state = ao_flight_invalid; - } else { - ao_flight_state = ao_flight_idle; - } - - /* Turn on packet system in idle or invalid mode - */ + /* Set idle mode */ + ao_flight_state = ao_flight_idle; + + /* Turn on packet system in idle mode */ ao_packet_slave_start(); - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); } - /* signal successful initialization by turning off the LED */ - ao_led_off(AO_LED_RED); + /* wakeup threads due to state change */ + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + break; case ao_flight_pad: -- cgit v1.2.3 From 1b8d7313504240ed04e0747e9b0f6e9a83d323e2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 16 Jan 2011 15:57:15 -0800 Subject: altos: Auto-calibrate linux-based flight testing code Use the provided ground acceleration average to set the two accelerometer calibration values so that the flight code will detect pad/idle mode correctly. Signed-off-by: Keith Packard --- src/ao_flight_test.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index e0cfa47a..108d2c19 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -238,6 +238,8 @@ ao_sleep(void *wchan) switch (type) { case 'F': ao_flight_ground_accel = a; + ao_config.accel_plus_g = a; + ao_config.accel_minus_g = a + 530; ao_flight_started = 1; break; case 'S': -- cgit v1.2.3 From 69290588980bb15732a99eca5c911a3b6e9a37b9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Jan 2011 12:12:02 -0800 Subject: altos: Ensure flight code gets first crack at new ADC data Instead of having everyone wait on the raw ADC ring, have the flight code wait on that and have everyone else wait for the flight code to finish looking at the data and move its pointer forwards. Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_adc.c | 10 ++-------- src/ao_config.c | 6 +++--- src/ao_flight.c | 3 ++- src/ao_flight_test.c | 2 +- src/ao_ignite.c | 1 - src/ao_log.c | 4 ++-- src/ao_test.c | 2 +- 8 files changed, 12 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 5721c344..abac22a3 100644 --- a/src/ao.h +++ b/src/ao.h @@ -649,7 +649,7 @@ enum ao_flight_state { ao_flight_invalid = 9 }; -extern __xdata struct ao_adc ao_flight_data; +extern __data uint8_t ao_flight_adc; extern __pdata enum ao_flight_state ao_flight_state; extern __pdata uint16_t ao_flight_tick; extern __pdata int16_t ao_flight_accel; diff --git a/src/ao_adc.c b/src/ao_adc.c index 49d2519e..f577b458 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -27,16 +27,10 @@ ao_adc_poll(void) ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 0; } -void -ao_adc_sleep(void) -{ - ao_sleep(&ao_adc_ring); -} - void ao_adc_get(__xdata struct ao_adc *packet) { - uint8_t i = ao_adc_ring_prev(ao_adc_head); + uint8_t i = ao_adc_ring_prev(ao_flight_adc); memcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); } @@ -65,7 +59,7 @@ ao_adc_isr(void) __interrupt 1 /* record this conversion series */ ao_adc_ring[ao_adc_head].tick = ao_time(); ao_adc_head = ao_adc_ring_next(ao_adc_head); - ao_wakeup(ao_adc_ring); + ao_wakeup(DATA_TO_XDATA(&ao_adc_head)); } } diff --git a/src/ao_config.c b/src/ao_config.c index e97b7eb1..bbee3b44 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -209,10 +209,10 @@ ao_config_accel_calibrate_auto(char *orientation) __reentrant puts("Calibrating..."); flush(); i = ACCEL_CALIBRATE_SAMPLES; accel_total = 0; - cal_adc_ring = ao_adc_head; + cal_adc_ring = ao_flight_adc; while (i) { - ao_sleep(&ao_adc_ring); - while (i && cal_adc_ring != ao_adc_head) { + ao_sleep(DATA_TO_XDATA(&ao_flight_adc)); + while (i && cal_adc_ring != ao_flight_adc) { accel_total += (int32_t) ao_adc_ring[cal_adc_ring].accel; cal_adc_ring = ao_adc_ring_next(cal_adc_ring); i--; diff --git a/src/ao_flight.c b/src/ao_flight.c index e99692a3..9eb9a014 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -146,7 +146,8 @@ ao_flight(void) ao_raw_pres = 0; ao_flight_tick = 0; for (;;) { - ao_sleep(&ao_adc_ring); + ao_wakeup(DATA_TO_XDATA(&ao_flight_adc)); + ao_sleep(DATA_TO_XDATA(&ao_adc_head)); while (ao_flight_adc != ao_adc_head) { __pdata uint8_t ticks; __pdata int16_t ao_vel_change; diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 108d2c19..5c619518 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -180,7 +180,7 @@ void ao_sleep(void *wchan) { ao_dump_state(); - if (wchan == &ao_adc_ring) { + if (wchan == &ao_adc_head) { char type; uint16_t tick; uint16_t a, b; diff --git a/src/ao_ignite.c b/src/ao_ignite.c index f2b15dd2..603fcd25 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -52,7 +52,6 @@ ao_igniter_status(enum ao_igniter igniter) __xdata uint8_t request, firing, fired; __critical { - ao_adc_sleep(); ao_adc_get(&adc); request = ao_ignition[igniter].request; fired = ao_ignition[igniter].fired; diff --git a/src/ao_log.c b/src/ao_log.c index fa072550..099c5f6f 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -99,10 +99,10 @@ ao_log(void) /* Write the whole contents of the ring to the log * when starting up. */ - ao_log_adc_pos = ao_adc_ring_next(ao_adc_head); + ao_log_adc_pos = ao_adc_ring_next(ao_flight_adc); for (;;) { /* Write samples to EEPROM */ - while (ao_log_adc_pos != ao_adc_head) { + while (ao_log_adc_pos != ao_flight_adc) { log.type = AO_LOG_SENSOR; log.tick = ao_adc_ring[ao_log_adc_pos].tick; log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel; diff --git a/src/ao_test.c b/src/ao_test.c index b9f7d338..14c2eb75 100644 --- a/src/ao_test.c +++ b/src/ao_test.c @@ -53,7 +53,7 @@ blink_1(void) static __xdata struct ao_adc adc; for (;;) { - ao_sleep(&ao_adc_ring); + ao_sleep(&ao_adc_head); ao_adc_get(&adc); if (adc.accel < 15900) ao_led_on(AO_LED_RED); -- cgit v1.2.3 From 2681a17500913cbaf3966f09380bb1d6b59e3863 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Jan 2011 12:18:32 -0800 Subject: altos: Sample the accelerometer reference voltage on v1.1 boards This places the 5v reference samples in an array parallel to the basic ADC values. It doesn't do anything with the values, just stores them. Signed-off-by: Keith Packard --- src/ao.h | 8 ++++++++ src/ao_adc.c | 28 ++++++++++++++++++++++------ src/ao_pins.h | 3 +++ 3 files changed, 33 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index abac22a3..cef20e61 100644 --- a/src/ao.h +++ b/src/ao.h @@ -163,6 +163,11 @@ struct ao_adc { #endif #if HAS_ADC + +#ifndef HAS_ACCEL_REF +#error Please define HAS_ACCEL_REF +#endif + /* * ao_adc.c */ @@ -178,6 +183,9 @@ struct ao_adc { */ extern volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; extern volatile __data uint8_t ao_adc_head; +#if HAS_ACCEL_REF +extern volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; +#endif /* Trigger a conversion sequence (called from the timer interrupt) */ void diff --git a/src/ao_adc.c b/src/ao_adc.c index f577b458..3adf9b2e 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -19,12 +19,19 @@ #include "ao_pins.h" volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; +#if HAS_ACCEL_REF +volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; +#endif volatile __data uint8_t ao_adc_head; void ao_adc_poll(void) { +#if HAS_ACCEL_REF + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 2; +#else ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 0; +#endif } void @@ -41,20 +48,29 @@ ao_adc_isr(void) __interrupt 1 uint8_t __xdata *a; sequence = (ADCCON2 & ADCCON2_SCH_MASK) >> ADCCON2_SCH_SHIFT; - if (sequence == ADCCON3_ECH_TEMP) - sequence = 2; - a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].accel + sequence); +#if HAS_ACCEL_REF + if (sequence == 2) { + a = (uint8_t __xdata *) (&ao_accel_ref[ao_adc_head]); + sequence = 0; + } else +#endif + { + if (sequence == ADCCON3_ECH_TEMP) + sequence = 2; + a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].accel + sequence); + sequence++; + } a[0] = ADCL; a[1] = ADCH; - if (sequence < 5) { + if (sequence < 6) { #if HAS_EXTERNAL_TEMP == 0 /* start next channel conversion */ /* v0.2 replaces external temp sensor with internal one */ - if (sequence == 1) + if (sequence == 2) ADCCON3 = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP; else #endif - ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | (sequence + 1); + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | sequence; } else { /* record this conversion series */ ao_adc_ring[ao_adc_head].tick = ao_time(); diff --git a/src/ao_pins.h b/src/ao_pins.h index 9446964e..2c5b9db5 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -31,6 +31,7 @@ #define AO_LED_RED 1 #define LEDS_AVAILABLE (AO_LED_RED) #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL_REF 0 #endif #if defined(TELEMETRUM_V_1_1) @@ -46,6 +47,7 @@ #define AO_LED_RED 1 #define LEDS_AVAILABLE (AO_LED_RED) #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL_REF 1 #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ @@ -81,6 +83,7 @@ #define AO_LED_GREEN 1 #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define HAS_EXTERNAL_TEMP 1 + #define HAS_ACCEL_REF 0 #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 #endif -- cgit v1.2.3 From 2887fe7affc0706dbeb2f04df9a00a9b799903ed Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Jan 2011 12:25:57 -0800 Subject: altos: Optimize fetching of ADC data in flight code This stores the address of the desired sample in a local variable and then fetches through that. Saves quite a few instructions. Signed-off-by: Keith Packard --- src/ao_flight.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index 9eb9a014..637acd52 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -151,12 +151,14 @@ ao_flight(void) while (ao_flight_adc != ao_adc_head) { __pdata uint8_t ticks; __pdata int16_t ao_vel_change; + __xdata struct ao_adc *ao_adc; ao_flight_prev_tick = ao_flight_tick; /* Capture a sample */ - ao_raw_accel = ao_adc_ring[ao_flight_adc].accel; - ao_raw_pres = ao_adc_ring[ao_flight_adc].pres; - ao_flight_tick = ao_adc_ring[ao_flight_adc].tick; + ao_adc = &ao_adc_ring[ao_flight_adc]; + ao_flight_tick = ao_adc->tick; + ao_raw_accel = ao_adc->accel; + ao_raw_pres = ao_adc->pres; ao_flight_accel -= ao_flight_accel >> 4; ao_flight_accel += ao_raw_accel >> 4; -- cgit v1.2.3 From 4b71c4f4ed6cae23a7f4a2e7ae697da9ec614898 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Jan 2011 12:26:53 -0800 Subject: altos: Use 5V reference data to correct accelerometer measurements. When the 3.3V and 5V values shift relative to each other (usually due to changes in power consumption), the measured acceleration will appear to shift. This patch converts the 3.3V referenced acceleration value into a 5V referenced acceleration, eliminating this error. Signed-off-by: Keith Packard --- src/ao_flight.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index 637acd52..81aecad3 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -158,6 +158,90 @@ ao_flight(void) ao_adc = &ao_adc_ring[ao_flight_adc]; ao_flight_tick = ao_adc->tick; ao_raw_accel = ao_adc->accel; +#if HAS_ACCEL_REF + /* + * Ok, the math here is a bit tricky. + * + * ao_raw_accel: ADC output for acceleration + * ao_accel_ref: ADC output for the 5V reference. + * ao_cook_accel: Corrected acceleration value + * Vcc: 3.3V supply to the CC1111 + * Vac: 5V supply to the accelerometer + * accel: input voltage to accelerometer ADC pin + * ref: input voltage to 5V reference ADC pin + * + * + * Measured acceleration is ratiometric to Vcc: + * + * ao_raw_accel accel + * ------------ = ----- + * 32767 Vcc + * + * Measured 5v reference is also ratiometric to Vcc: + * + * ao_accel_ref ref + * ------------ = ----- + * 32767 Vcc + * + * + * ao_accel_ref = 32767 * (ref / Vcc) + * + * Acceleration is measured ratiometric to the 5V supply, + * so what we want is: + * + * ao_cook_accel accel + * ------------- = ----- + * 32767 ref + * + * + * accel Vcc + * = ----- * --- + * Vcc ref + * + * ao_raw_accel 32767 + * = ------------ * ------------ + * 32737 ao_accel_ref + * + * Multiply through by 32767: + * + * ao_raw_accel * 32767 + * ao_cook_accel = -------------------- + * ao_accel_ref + * + * Now, the tricky part. Getting this to compile efficiently + * and keeping all of the values in-range. + * + * First off, we need to use a shift of 16 instead of * 32767 as SDCC + * does the obvious optimizations for byte-granularity shifts: + * + * ao_cook_accel = (ao_raw_accel << 16) / ao_accel_ref + * + * Next, lets check our input ranges: + * + * 0 <= ao_raw_accel <= 0x7fff (singled ended ADC conversion) + * 0x7000 <= ao_accel_ref <= 0x7fff (the 5V ref value is close to 0x7fff) + * + * Plugging in our input ranges, we get an output range of 0 - 0x12490, + * which is 17 bits. That won't work. If we take the accel ref and shift + * by a bit, we'll change its range: + * + * 0xe000 <= ao_accel_ref<<1 <= 0xfffe + * + * ao_cook_accel = (ao_raw_accel << 16) / (ao_accel_ref << 1) + * + * Now the output range is 0 - 0x9248, which nicely fits in 16 bits. It + * is, however, one bit too large for our signed computations. So, we + * take the result and shift that by a bit: + * + * ao_cook_accel = ((ao_raw_accel << 16) / (ao_accel_ref << 1)) >> 1 + * + * This finally creates an output range of 0 - 0x4924. As the ADC only + * provides 11 bits of data, we haven't actually lost any precision, + * just dropped a bit of noise off the low end. + */ + ao_raw_accel = (uint16_t) ((((uint32_t) ao_raw_accel << 16) / (ao_accel_ref[ao_flight_adc] << 1))) >> 1; + ao_adc->accel = ao_raw_accel; +#endif ao_raw_pres = ao_adc->pres; ao_flight_accel -= ao_flight_accel >> 4; -- cgit v1.2.3 From 97f4f2e0d28eec1cf19d2d25140e42f6ac277700 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 19 Jan 2011 11:21:52 -0800 Subject: altos: Program default flight log max value for new boards New boards have no config space values at all, and so they need each value to be set. Yes, this should be fixed so that there aren't two copies of these assignments. Signed-off-by: Keith Packard --- src/ao_config.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/ao_config.c b/src/ao_config.c index bbee3b44..cd56b473 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -70,6 +70,7 @@ _ao_config_get(void) sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; ao_config.radio_cal = ao_radio_cal; + ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { -- cgit v1.2.3 From d3bc27fabb6159ce58b14d0f7929b0f46f67c378 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 Feb 2011 09:54:01 -0800 Subject: altos/test: Add dependencies in the Makefile for ao_flight_test Yes, it would be nice to automate dependency generation here, but I can't be bothered. Signed-off-by: Keith Packard --- src/test/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/test/Makefile b/src/test/Makefile index f6e9b9f5..cd9cafc8 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -11,7 +11,7 @@ clean: install: -ao_flight_test: ao_flight_test.c ao_flight_test.c ao_host.h +ao_flight_test: ao_flight_test.c ao_flight_test.c ao_host.h ao_flight.c altitude.h cc -g -o $@ $< ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h -- cgit v1.2.3 From 8b09cc1825645a57c256f38a2f9586ddecf6bda5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 Feb 2011 10:02:46 -0800 Subject: altos/test: auto-configure acceleration parameters from the log file The flight test code had static accelerometer configuration values, making it impossible to use data from different boards without recompiling. As the eeprom and telem log files both contain the necessary data, parse that instead. Signed-off-by: Keith Packard --- src/ao_flight_test.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 5c619518..8ce94895 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -152,7 +152,7 @@ struct ao_config { #define ao_config_get() -struct ao_config ao_config = { 250, 15937, 16467 }; +struct ao_config ao_config; #define DATA_TO_XDATA(x) (x) @@ -220,6 +220,11 @@ ao_sleep(void *wchan) tick = strtoul(words[1], NULL, 16); a = strtoul(words[2], NULL, 16); b = strtoul(words[3], NULL, 16); + } else if (nword >= 6 && strcmp(words[0], "Accel")) { + ao_config.accel_plus_g = atoi(words[3]); + ao_config.accel_minus_g = atoi(words[5]); + } else if (nword >= 4 && strcmp(words[0], "Main")) { + ao_config.main_deploy = atoi(words[2]); } else if (nword >= 36 && strcmp(words[0], "CALL") == 0) { tick = atoi(words[10]); if (!ao_flight_started) { @@ -238,8 +243,12 @@ ao_sleep(void *wchan) switch (type) { case 'F': ao_flight_ground_accel = a; - ao_config.accel_plus_g = a; - ao_config.accel_minus_g = a + 530; + if (ao_config.accel_plus_g == 0) { + ao_config.accel_plus_g = a; + ao_config.accel_minus_g = a + 530; + } + if (ao_config.main_deploy == 0) + ao_config.main_deploy = 250; ao_flight_started = 1; break; case 'S': -- cgit v1.2.3 From fe5123fa801f5dafed8b052da607899d1ef20500 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Wed, 2 Feb 2011 19:12:57 +1000 Subject: ao_radio: generalise setup of packet size --- src/ao.h | 10 +++++----- src/ao_radio.c | 58 ++++++++-------------------------------------------------- 2 files changed, 13 insertions(+), 55 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index cef20e61..c2d7d22b 100644 --- a/src/ao.h +++ b/src/ao.h @@ -922,13 +922,13 @@ ao_radio_get(void); #define ao_radio_put() ao_mutex_put(&ao_radio_mutex) void -ao_radio_set_telemetry(void); +ao_radio_set_fixed_pkt(size_t size); -void -ao_radio_set_packet(void); +#define ao_radio_set_telemetry() \ + ao_radio_set_fixed_pkt(sizeof (struct ao_telemetry)) -void -ao_radio_set_rdf(void); +#define ao_radio_set_packet() \ + ao_radio_set_fixed_pkt(sizeof (struct ao_packet)) void ao_radio_send(__xdata void *data, uint8_t size) __reentrant; diff --git a/src/ao_radio.c b/src/ao_radio.c index 7b7c5161..d156f543 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -217,7 +217,7 @@ static __code uint8_t rdf_setup[] = { RF_PKTCTRL0_LENGTH_CONFIG_FIXED), }; -static __code uint8_t telemetry_setup[] = { +static __code uint8_t fixed_pkt_setup[] = { RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | (DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)), @@ -232,34 +232,8 @@ static __code uint8_t telemetry_setup[] = { RF_DEVIATN_OFF, ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), - /* 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), -}; - -static __code uint8_t packet_setup[] = { - 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_DEVIATN_OFF, ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | - (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), - - /* max packet length */ - RF_PKTLEN_OFF, sizeof (struct ao_packet), + /* max packet length -- now set inline */ + // RF_PKTLEN_OFF, sizeof (struct ao_telemetry), RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| PKTCTRL1_APPEND_STATUS| PKTCTRL1_ADR_CHK_NONE), @@ -290,27 +264,12 @@ ao_radio_general_isr(void) __interrupt 16 } void -ao_radio_set_telemetry(void) +ao_radio_set_fixed_pkt(size_t size) { uint8_t i; - for (i = 0; i < sizeof (telemetry_setup); i += 2) - RF[telemetry_setup[i]] = telemetry_setup[i+1]; -} - -void -ao_radio_set_packet(void) -{ - uint8_t i; - for (i = 0; i < sizeof (packet_setup); i += 2) - RF[packet_setup[i]] = packet_setup[i+1]; -} - -void -ao_radio_set_rdf(void) -{ - uint8_t i; - for (i = 0; i < sizeof (rdf_setup); i += 2) - RF[rdf_setup[i]] = rdf_setup[i+1]; + for (i = 0; i < sizeof (fixed_pkt_setup); i += 2) + RF[fixed_pkt_setup[i]] = fixed_pkt_setup[i+1]; + RF[RF_PKTLEN_OFF] = size; } void @@ -452,8 +411,7 @@ ao_radio_rdf(int ms) ao_dma_abort(ao_radio_dma); ao_radio_idle(); } - for (i = 0; i < sizeof (telemetry_setup); i += 2) - RF[telemetry_setup[i]] = telemetry_setup[i+1]; + ao_radio_set_telemetry(); ao_radio_put(); } -- cgit v1.2.3 From aad7103dcf44e69a5a30e008836cce5542ea33e2 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sat, 19 Feb 2011 04:17:17 +1000 Subject: src/ao_gps_skytraq: simplify parsing code Added macros to make correctly constructing skytraq commands easier. Simplified code path for NMEA processing marginally. --- src/ao_gps_skytraq.c | 146 ++++++++++++++++++++++++++++----------------------- src/ao_host.h | 1 + 2 files changed, 82 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index a2d5f1db..4d4ca592 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -19,7 +19,7 @@ #include "ao.h" #endif -#define AO_GPS_LEADER 2 +#define AO_GPS_LEADER 2 static const char ao_gps_header[] = "GP"; @@ -37,24 +37,32 @@ static __xdata struct ao_gps_data ao_gps_next; static __xdata uint8_t ao_gps_date_flags; static __xdata struct ao_gps_tracking_data ao_gps_tracking_next; -static const char ao_gps_config[] = { - 0xa0, 0xa1, 0x00, 0x09, /* length 9 bytes */ - 0x08, /* configure nmea */ - 1, /* gga interval */ - 1, /* gsa interval */ - 1, /* gsv interval */ - 1, /* gll interval */ - 1, /* rmc interval */ - 1, /* vtg interval */ - 1, /* zda interval */ - 0, /* attributes (0 = update to sram, 1 = update flash too) */ - 0x09, 0x0d, 0x0a, - - 0xa0, 0xa1, 0x00, 0x03, /* length: 3 bytes */ - 0x3c, /* configure navigation mode */ - 0x00, /* 0 = car, 1 = pedestrian */ - 0x00, /* 0 = update to sram, 1 = update sram + flash */ - 0x3c, 0x0d, 0x0a, +#define STQ_S 0xa0, 0xa1 +#define STQ_E 0x0d, 0x0a +#define SKYTRAQ_MSG_2(id,a,b) \ + STQ_S, 0, 3, id, a,b, (id^a^b), STQ_E +#define SKYTRAQ_MSG_3(id,a,b,c) \ + STQ_S, 0, 4, id, a,b,c, (id^a^b^c), STQ_E +#define SKYTRAQ_MSG_8(id,a,b,c,d,e,f,g,h) \ + STQ_S, 0, 9, id, a,b,c,d,e,f,g,h, (id^a^b^c^d^e^f^g^h), STQ_E +#define SKYTRAQ_MSG_14(id,a,b,c,d,e,f,g,h,i,j,k,l,m,n) \ + STQ_S, 0,15, id, a,b,c,d,e,f,g,h,i,j,k,l,m,n, \ + (id^a^b^c^d^e^f^g^h^i^j^k^l^m^n), STQ_E + +static const uint8_t ao_gps_config[] = { + SKYTRAQ_MSG_8(0x08, 1, 1, 1, 1, 1, 1, 1, 0), /* configure nmea */ + /* gga interval */ + /* gsa interval */ + /* gsv interval */ + /* gll interval */ + /* rmc interval */ + /* vtg interval */ + /* zda interval */ + /* attributes (0 = update to sram, 1 = update flash too) */ + + SKYTRAQ_MSG_2(0x3c, 0x00, 0x00), /* configure navigation mode */ + /* 0 = car, 1 = pedestrian */ + /* 0 = update to sram, 1 = update sram + flash */ }; static void @@ -67,13 +75,6 @@ ao_gps_lexchar(void) ao_gps_cksum ^= ao_gps_char; } -void -ao_gps_skip(void) -{ - while (ao_gps_char >= '0') - ao_gps_lexchar(); -} - void ao_gps_skip_field(void) { @@ -390,53 +391,68 @@ ao_nmea_rmc(void) } } +#define ao_skytraq_sendstruct(s) ao_skytraq_sendbytes((s), (s)+sizeof(s)) + +static void +ao_skytraq_sendbytes(const uint8_t *b, const uint8_t *e) +{ + while (b != e) { + if (*b == 0xa0) + ao_delay(AO_MS_TO_TICKS(500)); + ao_serial_putchar(*b++); + } +} + +static void +ao_gps_nmea_parse(void) +{ + uint8_t a, b, c; + + ao_gps_cksum = 0; + ao_gps_error = 0; + + for (a = 0; a < AO_GPS_LEADER; a++) { + ao_gps_lexchar(); + if (ao_gps_char != ao_gps_header[a]) + return; + } + + ao_gps_lexchar(); + a = ao_gps_char; + ao_gps_lexchar(); + b = ao_gps_char; + ao_gps_lexchar(); + c = ao_gps_char; + ao_gps_lexchar(); + + if (ao_gps_char != ',') + return; + + if (a == (uint8_t) 'G' && b == (uint8_t) 'G' && c == (uint8_t) 'A') { + ao_nmea_gga(); + } else if (a == (uint8_t) 'G' && b == (uint8_t) 'S' && c == (uint8_t) 'V') { + ao_nmea_gsv(); + } else if (a == (uint8_t) 'R' && b == (uint8_t) 'M' && c == (uint8_t) 'C') { + ao_nmea_rmc(); + } +} + void ao_gps(void) __reentrant { - char a, c; - uint8_t i; - ao_serial_set_speed(AO_SERIAL_SPEED_9600); - for (i = 0; i < sizeof (ao_gps_config); i++) - ao_serial_putchar(ao_gps_config[i]); - for (;;) { - /* Locate the begining of the next record */ - for (;;) { - c = ao_serial_getchar(); - if (c == '$') - break; - } - ao_gps_cksum = 0; - ao_gps_error = 0; + /* give skytraq time to boot in case of cold start */ + ao_delay(AO_MS_TO_TICKS(2000)); - /* Skip anything other than GP */ - for (i = 0; i < AO_GPS_LEADER; i++) { - ao_gps_lexchar(); - if (ao_gps_char != ao_gps_header[i]) - break; - } - if (i != AO_GPS_LEADER) - continue; + ao_skytraq_sendstruct(ao_gps_config); - /* pull the record identifier characters off the link */ - ao_gps_lexchar(); - a = ao_gps_char; - ao_gps_lexchar(); - c = ao_gps_char; - ao_gps_lexchar(); - i = ao_gps_char; - ao_gps_lexchar(); - if (ao_gps_char != ',') - continue; - - if (a == (uint8_t) 'G' && c == (uint8_t) 'G' && i == (uint8_t) 'A') { - ao_nmea_gga(); - } else if (a == (uint8_t) 'G' && c == (uint8_t) 'S' && i == (uint8_t) 'V') { - ao_nmea_gsv(); - } else if (a == (uint8_t) 'R' && c == (uint8_t) 'M' && i == (uint8_t) 'C') { - ao_nmea_rmc(); + for (;;) { + /* Locate the begining of the next record */ + if (ao_serial_getchar() == '$') { + ao_gps_nmea_parse(); } + } } diff --git a/src/ao_host.h b/src/ao_host.h index fa03a910..a96b7629 100644 --- a/src/ao_host.h +++ b/src/ao_host.h @@ -69,6 +69,7 @@ uint8_t ao_adc_head; #define ao_cmd_register(c) #define ao_usb_disable() #define ao_telemetry_set_interval(x) +#define ao_delay(x) enum ao_igniter { ao_igniter_drogue = 0, -- cgit v1.2.3 From b080e933a65d268aaaec8cfd5f617a13d5babc43 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sat, 19 Feb 2011 05:49:15 +1000 Subject: src/ao_gps_skytraq.c: Update logging rate to 10Hz Send commands to skytraq to update baud rate to 57,600 bps, and set NMEA output rate to 10Hz. --- src/ao_gps_skytraq.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'src') diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index 4d4ca592..88509a3d 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -49,6 +49,13 @@ static __xdata struct ao_gps_tracking_data ao_gps_tracking_next; STQ_S, 0,15, id, a,b,c,d,e,f,g,h,i,j,k,l,m,n, \ (id^a^b^c^d^e^f^g^h^i^j^k^l^m^n), STQ_E +static const uint8_t ao_gps_config_serial[] = { + SKYTRAQ_MSG_3(0x05, 0, 4, 0), /* set serial port */ + /* 0 = com1 */ + /* 0 = 4800, 1 = 9600, 2 = 19200, 3 = 38400, + * 4 = 57600, 5 = 115200 */ +}; + static const uint8_t ao_gps_config[] = { SKYTRAQ_MSG_8(0x08, 1, 1, 1, 1, 1, 1, 1, 0), /* configure nmea */ /* gga interval */ @@ -63,6 +70,10 @@ static const uint8_t ao_gps_config[] = { SKYTRAQ_MSG_2(0x3c, 0x00, 0x00), /* configure navigation mode */ /* 0 = car, 1 = pedestrian */ /* 0 = update to sram, 1 = update sram + flash */ + + SKYTRAQ_MSG_2(0x0e, 10, 0), /* config nav interval */ + /* interval */ + /* 0 = update to sram, 1 = update sram */ }; static void @@ -444,6 +455,9 @@ ao_gps(void) __reentrant /* give skytraq time to boot in case of cold start */ ao_delay(AO_MS_TO_TICKS(2000)); + ao_skytraq_sendstruct(ao_gps_config_serial); + ao_delay(AO_MS_TO_TICKS(1000)); + ao_serial_set_speed(AO_SERIAL_SPEED_57600); ao_skytraq_sendstruct(ao_gps_config); -- cgit v1.2.3 From 2cfe205de4242398e69c9e7c613af0d2a7094686 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 Mar 2011 00:01:01 -0800 Subject: Revert "src/ao_gps_skytraq.c: Update logging rate to 10Hz" This reverts commit b080e933a65d268aaaec8cfd5f617a13d5babc43. 10Hz data isn't any better than 1Hz data; it still doesn't like going upwards rapidly. --- src/ao_gps_skytraq.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'src') diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index 88509a3d..4d4ca592 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -49,13 +49,6 @@ static __xdata struct ao_gps_tracking_data ao_gps_tracking_next; STQ_S, 0,15, id, a,b,c,d,e,f,g,h,i,j,k,l,m,n, \ (id^a^b^c^d^e^f^g^h^i^j^k^l^m^n), STQ_E -static const uint8_t ao_gps_config_serial[] = { - SKYTRAQ_MSG_3(0x05, 0, 4, 0), /* set serial port */ - /* 0 = com1 */ - /* 0 = 4800, 1 = 9600, 2 = 19200, 3 = 38400, - * 4 = 57600, 5 = 115200 */ -}; - static const uint8_t ao_gps_config[] = { SKYTRAQ_MSG_8(0x08, 1, 1, 1, 1, 1, 1, 1, 0), /* configure nmea */ /* gga interval */ @@ -70,10 +63,6 @@ static const uint8_t ao_gps_config[] = { SKYTRAQ_MSG_2(0x3c, 0x00, 0x00), /* configure navigation mode */ /* 0 = car, 1 = pedestrian */ /* 0 = update to sram, 1 = update sram + flash */ - - SKYTRAQ_MSG_2(0x0e, 10, 0), /* config nav interval */ - /* interval */ - /* 0 = update to sram, 1 = update sram */ }; static void @@ -455,9 +444,6 @@ ao_gps(void) __reentrant /* give skytraq time to boot in case of cold start */ ao_delay(AO_MS_TO_TICKS(2000)); - ao_skytraq_sendstruct(ao_gps_config_serial); - ao_delay(AO_MS_TO_TICKS(1000)); - ao_serial_set_speed(AO_SERIAL_SPEED_57600); ao_skytraq_sendstruct(ao_gps_config); -- cgit v1.2.3 From 8cdf4fb051c22b35c251d90bc288551f7c2898bf Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sun, 27 Feb 2011 11:11:12 +1000 Subject: src/ao_cmd: Shave off bytes from doc strings Switch to using { func, "X args\0Desc" } to specify command, saving a char field by looking at help[0] instead, and reduce help length by doing alignment with printf instead of hardcoded spaces. --- src/ao.h | 1 - src/ao_adc.c | 4 ++-- src/ao_cmd.c | 22 ++++++++++++---------- src/ao_config.c | 4 ++-- src/ao_dbg.c | 14 +++++++------- src/ao_flight_test.c | 1 - src/ao_gps_skytraq.c | 4 ++-- src/ao_host.h | 1 - src/ao_ignite.c | 6 +++--- src/ao_log.c | 6 +++--- src/ao_monitor.c | 4 ++-- src/ao_packet_master.c | 4 ++-- src/ao_radio.c | 4 ++-- src/ao_serial.c | 4 ++-- src/ao_storage.c | 12 +++++------- 15 files changed, 44 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index c2d7d22b..791064e8 100644 --- a/src/ao.h +++ b/src/ao.h @@ -380,7 +380,6 @@ uint8_t ao_match_word(__code char *word); struct ao_cmds { - char cmd; void (*func)(void); const char *help; }; diff --git a/src/ao_adc.c b/src/ao_adc.c index 3adf9b2e..9990a1fd 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -90,8 +90,8 @@ ao_adc_dump(void) __reentrant } __code struct ao_cmds ao_adc_cmds[] = { - { 'a', ao_adc_dump, "a Display current ADC values" }, - { 0, ao_adc_dump, NULL }, + { ao_adc_dump, "a\0Display current ADC values" }, + { 0, NULL }, }; void diff --git a/src/ao_cmd.c b/src/ao_cmd.c index a54a2316..6007773c 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -237,8 +237,10 @@ help(void) puts(help_txt); for (cmds = 0; cmds < ao_ncmds; cmds++) { cs = ao_cmds[cmds]; - for (cmd = 0; cs[cmd].cmd != '\0'; cmd++) - puts(cs[cmd].help); + for (cmd = 0; cs[cmd].func; cmd++) + printf("%-45s %s\n", + cs[cmd].help, + cs[cmd].help+1+strlen(cs[cmd].help)); } } @@ -282,8 +284,8 @@ ao_cmd(void) func = (void (*)(void)) NULL; for (cmds = 0; cmds < ao_ncmds; cmds++) { cs = ao_cmds[cmds]; - for (cmd = 0; cs[cmd].cmd != '\0'; cmd++) - if (cs[cmd].cmd == c) { + for (cmd = 0; cs[cmd].func; cmd++) + if (cs[cmd].help[0] == c) { func = cs[cmd].func; break; } @@ -301,12 +303,12 @@ ao_cmd(void) __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" }, - { 'E', echo, "E <0 off, 1 on> Set command echo mode" }, - { 'r', ao_reboot, "r eboot Reboot" }, - { 'v', version, "v Show version" }, - { 0, help, NULL }, + { help, "?\0Print this message" }, + { ao_task_info, "T\0Show task states" }, + { echo, "E <0 off, 1 on>\0Set command echo mode" }, + { ao_reboot, "r eboot\0Reboot" }, + { version, "v\0Show version" }, + { 0, NULL }, }; void diff --git a/src/ao_config.c b/src/ao_config.c index cd56b473..c6d36247 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -439,8 +439,8 @@ ao_config_write(void) __reentrant #endif __code struct ao_cmds ao_config_cmds[] = { - { 'c', ao_config_set, "c Set config variable (? for help, s to show)" }, - { '\0', ao_config_set, NULL }, + { ao_config_set, "c \0Set config variable (? for help, s to show)" }, + { 0, NULL }, }; void diff --git a/src/ao_dbg.c b/src/ao_dbg.c index 0d9ec8c0..49371560 100644 --- a/src/ao_dbg.c +++ b/src/ao_dbg.c @@ -348,13 +348,13 @@ debug_output(void) } __code struct ao_cmds ao_dbg_cmds[7] = { - { 'D', debug_enable, "D Enable debug mode" }, - { 'G', debug_get, "G Get data from debug port" }, - { 'I', debug_input, "I Input bytes to target at " }, - { 'O', debug_output, "O Output bytes to target at " }, - { 'P', debug_put, "P ... Put data to debug port" }, - { 'R', debug_reset, "R Reset target" }, - { 0, debug_reset, 0 }, + { debug_enable, "D\0Enable debug mode" }, + { debug_get, "G \0Get data from debug port" }, + { debug_input, "I \0Input bytes to target at " }, + { debug_output, "O \0Output bytes to target at " }, + { debug_put, "P ...\0Put data to debug port" }, + { debug_reset, "R\0Reset target" }, + { 0, NULL }, }; void diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 8ce94895..0c2006d5 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -114,7 +114,6 @@ const char const * const ao_state_names[] = { }; struct ao_cmds { - char cmd; void (*func)(void); const char *help; }; diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index 4d4ca592..d286a30a 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -471,8 +471,8 @@ gps_dump(void) __reentrant } __code struct ao_cmds ao_gps_cmds[] = { - { 'g', gps_dump, "g Display current GPS values" }, - { 0, gps_dump, NULL }, + { gps_dump, "g\0Display current GPS values" }, + { 0, NULL }, }; void diff --git a/src/ao_host.h b/src/ao_host.h index a96b7629..65c25fe5 100644 --- a/src/ao_host.h +++ b/src/ao_host.h @@ -112,7 +112,6 @@ const char const * const ao_state_names[] = { }; struct ao_cmds { - char cmd; void (*func)(void); const char *help; }; diff --git a/src/ao_ignite.c b/src/ao_ignite.c index 603fcd25..798ba9b4 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -154,9 +154,9 @@ ao_ignite_test(void) } __code struct ao_cmds ao_ignite_cmds[] = { - { 'i', ao_ignite_manual, "i {main|drogue} Fire igniter. is doit with D&I" }, - { 't', ao_ignite_test, "t Test igniter continuity" }, - { 0, ao_ignite_manual, NULL }, + { ao_ignite_manual, "i {main|drogue}\0Fire igniter. is doit with D&I" }, + { ao_ignite_test, "t\0Test igniter continuity" }, + { 0, NULL }, }; __xdata struct ao_task ao_igniter_task; diff --git a/src/ao_log.c b/src/ao_log.c index 099c5f6f..1b10961d 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -390,9 +390,9 @@ ao_log_delete(void) __reentrant __code struct ao_cmds ao_log_cmds[] = { - { 'l', ao_log_list, "l List stored flight logs" }, - { 'd', ao_log_delete, "d Delete stored flight" }, - { 0, ao_log_delete, NULL }, + { ao_log_list, "l\0List stored flight logs" }, + { ao_log_delete, "d \0Delete stored flight" }, + { 0, NULL }, }; void diff --git a/src/ao_monitor.c b/src/ao_monitor.c index 4ba3da6d..9c4be6fb 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -96,8 +96,8 @@ set_monitor(void) } __code struct ao_cmds ao_monitor_cmds[] = { - { 'm', set_monitor, "m <0 off, 1 on> Enable/disable radio monitoring" }, - { 0, set_monitor, NULL }, + { set_monitor, "m <0 off, 1 on>\0Enable/disable radio monitoring" }, + { 0, NULL }, }; void diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index 5f79885c..5c4ab0dd 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -133,8 +133,8 @@ ao_packet_forward(void) __reentrant __code struct ao_cmds ao_packet_master_cmds[] = { - { 'p', ao_packet_forward, "p Remote packet link." }, - { 0, ao_packet_forward, NULL }, + { ao_packet_forward, "p\0Remote packet link." }, + { 0, NULL }, }; void diff --git a/src/ao_radio.c b/src/ao_radio.c index d156f543..d7c00213 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -455,8 +455,8 @@ ao_radio_test(void) } __code struct ao_cmds ao_radio_cmds[] = { - { 'C', ao_radio_test, "C <1 start, 0 stop, none both> Radio carrier test" }, - { 0, ao_radio_test, NULL }, + { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" }, + { 0, NULL }, }; void diff --git a/src/ao_serial.c b/src/ao_serial.c index a48734c2..dd383fca 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -93,8 +93,8 @@ monitor_serial(void) } __code struct ao_cmds ao_serial_cmds[] = { - { 'M', monitor_serial, "M Monitor serial data" }, - { 0, monitor_serial, NULL }, + { monitor_serial, "M \0Monitor serial data" }, + { 0, NULL }, }; static const struct { diff --git a/src/ao_storage.c b/src/ao_storage.c index 709259ee..9f0f75fb 100644 --- a/src/ao_storage.c +++ b/src/ao_storage.c @@ -166,14 +166,12 @@ ao_storage_info(void) __reentrant } __code struct ao_cmds ao_storage_cmds[] = { - { 'f', ao_storage_info, "f Show storage info" }, - { 'e', ao_storage_dump, "e Dump a block of flash data" }, -#if 0 - { 'w', ao_storage_store, "w ... Write data to flash" }, +#ifdef HAS_STORAGE_DBG + { ao_storage_store, "w ...\0Write data to flash" }, #endif - { 'z', ao_storage_zap, "z Erase flash containing " }, - { 'Z', ao_storage_zapall,"Z Erase all logs. is doit with D&I" }, - { 0, ao_storage_zap, NULL }, + { ao_storage_zap, "z \0Erase flash containing " }, + { ao_storage_zapall,"Z \0Erase all logs. is doit with D&I" }, + { 0, NULL }, }; void -- cgit v1.2.3 From 6e340c87d3198647cf075ed520a82703b0d59beb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 Mar 2011 00:26:17 -0800 Subject: altos: Oops. Lost a couple of commands when merging the doc patch I didn't merge this carefully enough and managed to lose the 'f' and 'e' commands, which are kinda useful. Signed-off-by: Keith Packard --- src/ao_storage.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/ao_storage.c b/src/ao_storage.c index 9f0f75fb..69183514 100644 --- a/src/ao_storage.c +++ b/src/ao_storage.c @@ -166,6 +166,8 @@ ao_storage_info(void) __reentrant } __code struct ao_cmds ao_storage_cmds[] = { + { ao_storage_info, "f\0Show storage info" }, + { ao_storage_dump, "e \0Dump a block of flash data" }, #ifdef HAS_STORAGE_DBG { ao_storage_store, "w ...\0Write data to flash" }, #endif -- cgit v1.2.3 From fdd15a254c6fab5ba2d02320ba0ceb3e6a56354c Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sat, 26 Feb 2011 11:48:30 +1000 Subject: ao_intflash: Use internal flash for storage Makes any free pages at end of CC1111's internal flash available via the ao_storage API. --- src/ao_intflash.c | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 src/ao_intflash.c (limited to 'src') diff --git a/src/ao_intflash.c b/src/ao_intflash.c new file mode 100644 index 00000000..ad5e5aac --- /dev/null +++ b/src/ao_intflash.c @@ -0,0 +1,204 @@ +/* + * Copyright © 2011 Anthony Towns + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "cc1111.h" + +#define FCTL_BUSY (1 << 7) +#define FCTL_SWBSY (1 << 6) +#define FCTL_CONTRD_ENABLE (1 << 4) +#define FCTL_WRITE (1 << 1) +#define FCTL_ERASE (1 << 0) + +#define ENDOFCODE (0x51f0 + 1500) +#define NUM_PAGES ((0x8000-ENDOFCODE)/1024) +#define SIZE (1024*NUM_PAGES) +#define LOCN (0x8000 - SIZE) + +#if NUM_PAGES < 1 +#error "Too few pages" +#endif + +#if LOCN % 1024 != 0 +#error "Pages aren't aligned properly" +#endif + +__xdata __at(LOCN) uint8_t ao_intflash[SIZE]; + +/* Total bytes of available storage */ +__xdata uint32_t ao_storage_total = sizeof(ao_intflash); + +/* Block size - device is erased in these units. */ +__xdata uint32_t ao_storage_block = 1024; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +__xdata uint32_t ao_storage_config = sizeof(ao_intflash); + +/* Storage unit size - device reads and writes must be within blocks of this size. */ +__xdata uint16_t ao_storage_unit = 1024; + +__xdata static uint8_t ao_intflash_dma_done; +static uint8_t ao_intflash_dma; + +/* + * The internal flash chip is arranged in 1kB sectors; the + * chip cannot erase in units smaller than that. + * + * Writing happens in units of 2 bytes and + * can only change bits from 1 to 0. So, you can rewrite + * the same contents, or append to an existing page easily enough + */ + +/* + * Erase the specified sector + */ +uint8_t +ao_storage_erase(uint32_t pos) __reentrant +{ + uint16_t addr; + + if (pos >= ao_storage_total || pos + ao_storage_block > ao_storage_total) + return 0; + + addr = ((uint16_t)(ao_intflash + pos) >> 1); + + while (FCTL & FCTL_BUSY) + ; + + FWT = 0x1F; // 21000 * f / 16e9 ; f = system freq = 24MHz + FADDRH = addr >> 8; + FADDRL = addr & ~0xFF00; + + _asm + .even + orl _FCTL, #FCTL_ERASE; ; FCTL |= FCTL_ERASE + nop; ; Required, see datasheet. + _endasm; + + while (FCTL & FCTL_BUSY) + ; + + return 1; +} + +/* + * Write to flash + */ + +static void +word_aligned_write(uint32_t pos, __xdata void *d, uint16_t len) __reentrant +{ + uint16_t addr; + + addr = ((uint16_t)(ao_intflash + pos) >> 1); + + ao_dma_set_transfer(ao_intflash_dma, d, &X_FWDATA, + DMA_LEN_HIGH_VLEN_LEN | len, + DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_FLASH, + DMA_CFG1_SRCINC_1 | DMA_CFG1_DESTINC_0 | + DMA_CFG1_IRQMASK | DMA_CFG1_PRIORITY_HIGH); + + while (FCTL & FCTL_BUSY) + ; + + FWT = 0x1F; // 21000 * f / 16e9 ; f = system freq = 24MHz + + FADDRH = addr >> 8; + FADDRL = addr & ~0xFF00; + + ao_dma_start(ao_intflash_dma); + + _asm + .even + orl _FCTL, #FCTL_WRITE; ; FCTL |= FCTL_WRITE + _endasm; + + __critical while (!ao_intflash_dma_done) + ao_sleep(&ao_intflash_dma_done); + + while (FCTL & (FCTL_BUSY | FCTL_SWBSY)) + ; +} + +uint8_t +ao_storage_device_write(uint32_t pos, __xdata void *v, uint16_t len) __reentrant +{ + static __xdata uint8_t b[2]; + __xdata uint8_t *d = v; + uint8_t oddlen; + + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + if (len == 0) + return 1; + + if (pos & 1) { + b[0] = ~0; + b[1] = d[0]; + word_aligned_write(pos-1, b, 2); + pos++; + len--; + d++; + } + oddlen = len & 1; + len &= ~1; + if (len > 0) { + word_aligned_write(pos, d, len); + } + if (oddlen) { + b[0] = d[len]; + b[1] = ~0; + word_aligned_write(pos+len, b, 2); + } + + return 1; +} + +/* + * Read from flash + */ +uint8_t +ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant +{ + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + memcpy(d, ao_intflash+pos, len); + return 1; +} + +void +ao_storage_flush(void) __reentrant +{ +} + +void +ao_storage_setup(void) +{ +} + +void +ao_storage_device_info(void) __reentrant +{ + printf ("Using internal flash, starting at 0x%04x\n", LOCN); +} + +void +ao_storage_device_init(void) +{ + ao_intflash_dma = ao_dma_alloc(&ao_intflash_dma_done); +} -- cgit v1.2.3 From 02611efea0c485d78fad08c696c1f56e868d36b8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Mar 2011 20:56:25 -0800 Subject: altos: Make serial, usb, beeper and accelerometer optional components Not all boards will have these, so fix places that use them to deal with that. Signed-off-by: Keith Packard --- src/Makefile.proto | 23 +++++++++-- src/ao.h | 14 ++++++- src/ao_flight.c | 114 +++++++++++++++++++++++++++++++++++++++++---------- src/ao_flight_test.c | 9 ++++ src/ao_log.c | 2 + src/ao_panic.c | 8 ++++ src/ao_pins.h | 18 ++++++++ src/ao_product.c | 4 +- src/ao_report.c | 34 ++++++++------- src/ao_telemetry.c | 6 +++ 10 files changed, 189 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index 709cbca7..30cd5798 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -42,11 +42,15 @@ ALTOS_SRC = \ # Shared AltOS drivers # ALTOS_DRIVER_SRC = \ - ao_beep.c \ ao_config.c \ ao_led.c \ ao_radio.c \ - ao_stdio.c \ + ao_stdio.c + +BEEP_DRIVER_SRC = \ + ao_beep.c + +USB_DRIVER_SRC = \ ao_usb.c TELE_COMMON_SRC = \ @@ -68,7 +72,12 @@ TELE_RECEIVER_SRC =\ # TELE_DRIVER_SRC = \ - ao_convert.c \ + ao_convert.c + +# +# Serial port driver +# +SERIAL_DRIVER_SRC = \ ao_serial.c # @@ -89,7 +98,9 @@ DBG_SRC = \ TM_DRIVER_SRC = \ ao_adc.c \ ao_gps_report.c \ - ao_ignite.c + ao_ignite.c \ + $(BEEP_DRIVER_SRC) \ + $(USB_DRIVER_SRC) # # 25LC1024 driver source @@ -142,6 +153,7 @@ TM_BASE_SRC = \ $(ALTOS_SRC) \ $(ALTOS_DRIVER_SRC) \ $(TELE_DRIVER_SRC) \ + $(SERIAL_DRIVER_SRC) \ $(TELE_COMMON_SRC) \ $(TM_DRIVER_SRC) \ $(TM_TASK_SRC) \ @@ -158,6 +170,7 @@ TI_SRC = \ $(ALTOS_DRIVER_SRC) \ $(TELE_RECEIVER_SRC) \ $(TELE_COMMON_SRC) \ + $(USB_DRIVER_SRC) \ $(TI_MAIN_SRC) \ $(DBG_SRC) @@ -172,6 +185,7 @@ TT_SRC = \ $(TELE_RECEIVER_SRC) \ $(TELE_DRIVER_SRC) \ $(TELE_COMMON_SRC) \ + $(USB_DRIVER_SRC) \ $(TT_MAIN_SRC) @@ -187,6 +201,7 @@ TD_SRC = \ $(ALTOS_DRIVER_SRC) \ $(TELE_RECEIVER_SRC) \ $(TELE_COMMON_SRC) \ + $(USB_DRIVER_SRC) \ $(TD_MAIN_SRC) include Makefile.defs diff --git a/src/ao.h b/src/ao.h index 791064e8..5bbe5158 100644 --- a/src/ao.h +++ b/src/ao.h @@ -164,9 +164,13 @@ struct ao_adc { #if HAS_ADC +#if HAS_ACCEL #ifndef HAS_ACCEL_REF #error Please define HAS_ACCEL_REF #endif +#else +#define HAS_ACCEL_REF 0 +#endif /* * ao_adc.c @@ -303,7 +307,14 @@ extern __code __at (0x00a0) uint16_t ao_romconfig_version; extern __code __at (0x00a2) uint16_t ao_romconfig_check; extern __code __at (0x00a4) uint16_t ao_serial_number; extern __code __at (0x00a6) uint32_t ao_radio_cal; + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + +#if HAS_USB extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; +#endif /* * ao_usb.c @@ -327,9 +338,11 @@ ao_usb_pollchar(void); void ao_usb_flush(void); +#if HAS_USB /* USB interrupt handler */ void ao_usb_isr(void) __interrupt 6; +#endif /* Enable the USB controller */ void @@ -1062,7 +1075,6 @@ ao_rssi_init(uint8_t rssi_led); * each instance of a product */ -extern __code __at(0x00aa) uint8_t ao_usb_descriptors []; extern const char ao_version[]; extern const char ao_manufacturer[]; extern const char ao_product[]; diff --git a/src/ao_flight.c b/src/ao_flight.c index 81aecad3..843865e8 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -19,39 +19,57 @@ #include "ao.h" #endif +#ifndef HAS_ACCEL +#error Please define HAS_ACCEL +#endif + +#ifndef HAS_GPS +#error Please define HAS_GPS +#endif + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + /* Main flight thread. */ __pdata enum ao_flight_state ao_flight_state; /* current flight state */ __pdata uint16_t ao_flight_tick; /* time of last data */ __pdata uint16_t ao_flight_prev_tick; /* time of previous data */ -__pdata int16_t ao_flight_accel; /* filtered acceleration */ __pdata int16_t ao_flight_pres; /* filtered pressure */ __pdata int16_t ao_ground_pres; /* startup pressure */ -__pdata int16_t ao_ground_accel; /* startup acceleration */ __pdata int16_t ao_min_pres; /* minimum recorded pressure */ __pdata uint16_t ao_launch_tick; /* time of launch detect */ __pdata int16_t ao_main_pres; /* pressure to eject main */ +#if HAS_ACCEL +__pdata int16_t ao_flight_accel; /* filtered acceleration */ +__pdata int16_t ao_ground_accel; /* startup acceleration */ +#endif /* * track min/max data over a long interval to detect * resting */ __pdata uint16_t ao_interval_end; -__pdata int16_t ao_interval_cur_min_accel; -__pdata int16_t ao_interval_cur_max_accel; __pdata int16_t ao_interval_cur_min_pres; __pdata int16_t ao_interval_cur_max_pres; -__pdata int16_t ao_interval_min_accel; -__pdata int16_t ao_interval_max_accel; __pdata int16_t ao_interval_min_pres; __pdata int16_t ao_interval_max_pres; +#if HAS_ACCEL +__pdata int16_t ao_interval_cur_min_accel; +__pdata int16_t ao_interval_cur_max_accel; +__pdata int16_t ao_interval_min_accel; +__pdata int16_t ao_interval_max_accel; +#endif __data uint8_t ao_flight_adc; -__pdata int16_t ao_raw_accel, ao_raw_accel_prev, ao_raw_pres; -__pdata int16_t ao_accel_2g; - +__pdata int16_t ao_raw_pres; __xdata uint8_t ao_flight_force_idle; +#if HAS_ACCEL +__pdata int16_t ao_raw_accel, ao_raw_accel_prev; +__pdata int16_t ao_accel_2g; + /* Accelerometer calibration * * We're sampling the accelerometer through a resistor divider which @@ -84,6 +102,8 @@ __xdata uint8_t ao_flight_force_idle; #define ACCEL_VEL_MACH VEL_MPS_TO_COUNT(200) #define ACCEL_VEL_BOOST VEL_MPS_TO_COUNT(5) +#endif + /* * Barometer calibration * @@ -117,6 +137,7 @@ __xdata uint8_t ao_flight_force_idle; #define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) +#if HAS_ACCEL /* This value is scaled in a weird way. It's a running total of accelerometer * readings minus the ground accelerometer reading. That means it measures * velocity, and quite accurately too. As it gets updated 100 times a second, @@ -126,7 +147,10 @@ __pdata int32_t ao_flight_vel; __pdata int32_t ao_min_vel; __pdata int32_t ao_old_vel; __pdata int16_t ao_old_vel_tick; -__xdata int32_t ao_raw_accel_sum, ao_raw_pres_sum; +__xdata int32_t ao_raw_accel_sum; +#endif + +__xdata int32_t ao_raw_pres_sum; /* Landing is detected by getting constant readings from both pressure and accelerometer * for a fairly long time (AO_INTERVAL_TICKS) @@ -141,22 +165,31 @@ ao_flight(void) __pdata static uint16_t nsamples = 0; ao_flight_adc = ao_adc_head; + ao_raw_pres = 0; +#if HAS_ACCEL ao_raw_accel_prev = 0; ao_raw_accel = 0; - ao_raw_pres = 0; +#endif ao_flight_tick = 0; for (;;) { ao_wakeup(DATA_TO_XDATA(&ao_flight_adc)); ao_sleep(DATA_TO_XDATA(&ao_adc_head)); while (ao_flight_adc != ao_adc_head) { +#if HAS_ACCEL __pdata uint8_t ticks; __pdata int16_t ao_vel_change; +#endif __xdata struct ao_adc *ao_adc; ao_flight_prev_tick = ao_flight_tick; /* Capture a sample */ ao_adc = &ao_adc_ring[ao_flight_adc]; ao_flight_tick = ao_adc->tick; + ao_raw_pres = ao_adc->pres; + ao_flight_pres -= ao_flight_pres >> 4; + ao_flight_pres += ao_raw_pres >> 4; + +#if HAS_ACCEL ao_raw_accel = ao_adc->accel; #if HAS_ACCEL_REF /* @@ -242,12 +275,9 @@ ao_flight(void) ao_raw_accel = (uint16_t) ((((uint32_t) ao_raw_accel << 16) / (ao_accel_ref[ao_flight_adc] << 1))) >> 1; ao_adc->accel = ao_raw_accel; #endif - ao_raw_pres = ao_adc->pres; ao_flight_accel -= ao_flight_accel >> 4; ao_flight_accel += ao_raw_accel >> 4; - ao_flight_pres -= ao_flight_pres >> 4; - ao_flight_pres += ao_raw_pres >> 4; /* Update velocity * * The accelerometer is mounted so that @@ -264,12 +294,14 @@ ao_flight(void) ao_flight_vel += (int32_t) ao_vel_change; else ao_flight_vel += (int32_t) ao_vel_change * (int32_t) ticks; +#endif ao_flight_adc = ao_adc_ring_next(ao_flight_adc); } if (ao_flight_pres < ao_min_pres) ao_min_pres = ao_flight_pres; +#if HAS_ACCEL if (ao_flight_vel >= 0) { if (ao_flight_vel < ao_min_vel) ao_min_vel = ao_flight_vel; @@ -277,6 +309,7 @@ ao_flight(void) if (-ao_flight_vel < ao_min_vel) ao_min_vel = -ao_flight_vel; } +#endif switch (ao_flight_state) { case ao_flight_startup: @@ -287,21 +320,27 @@ ao_flight(void) * data and average them to find the resting values */ if (nsamples < 512) { +#if HAS_ACCEL ao_raw_accel_sum += ao_raw_accel; +#endif ao_raw_pres_sum += ao_raw_pres; ++nsamples; continue; } +#if HAS_ACCEL ao_ground_accel = ao_raw_accel_sum >> 9; +#endif ao_ground_pres = ao_raw_pres_sum >> 9; ao_min_pres = ao_ground_pres; ao_config_get(); ao_main_pres = ao_altitude_to_pres(ao_pres_to_altitude(ao_ground_pres) + ao_config.main_deploy); +#if HAS_ACCEL ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; ao_flight_vel = 0; ao_min_vel = 0; ao_old_vel = ao_flight_vel; ao_old_vel_tick = ao_flight_tick; +#endif /* Check to see what mode we should go to. * - Invalid mode if accel cal appears to be out @@ -309,6 +348,7 @@ ao_flight(void) * - idle mode otherwise */ ao_config_get(); +#if HAS_ACCEL if (ao_config.accel_plus_g == 0 || ao_config.accel_minus_g == 0 || ao_flight_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || @@ -323,17 +363,23 @@ ao_flight(void) */ ao_packet_slave_start(); - } else if (ao_flight_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP && - !ao_flight_force_idle) + } else +#endif + if (!ao_flight_force_idle +#if HAS_ACCEL + && ao_flight_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP +#endif + ) { /* Set pad mode - we can fly! */ ao_flight_state = ao_flight_pad; +#if HAS_USB /* Disable the USB controller in flight mode * to save power */ ao_usb_disable(); - +#endif /* Turn on telemetry system */ ao_rdf_set(1); ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); @@ -356,6 +402,7 @@ ao_flight(void) break; case ao_flight_pad: +#if HAS_ACCEL /* Trim velocity * * Once a second, remove any velocity from @@ -366,6 +413,7 @@ ao_flight(void) ao_flight_vel -= ao_old_vel; ao_old_vel = ao_flight_vel; } +#endif /* pad to boost: * * accelerometer: > 2g AND velocity > 5m/s @@ -376,11 +424,18 @@ ao_flight(void) * the barometer, but we use both to make sure this * transition is detected */ - if ((ao_flight_accel < ao_ground_accel - ACCEL_BOOST && - ao_flight_vel > ACCEL_VEL_BOOST) || + if ( +#if HAS_ACCEL + (ao_flight_accel < ao_ground_accel - ACCEL_BOOST && + ao_flight_vel > ACCEL_VEL_BOOST) || +#endif ao_flight_pres < ao_ground_pres - BARO_LAUNCH) { +#if HAS_ACCEL ao_flight_state = ao_flight_boost; +#else + ao_flight_state = ao_flight_coast; +#endif ao_launch_tick = ao_flight_tick; /* start logging data */ @@ -392,14 +447,17 @@ ao_flight(void) /* disable RDF beacon */ ao_rdf_set(0); +#if HAS_GPS /* Record current GPS position by waking up GPS log tasks */ ao_wakeup(&ao_gps_data); ao_wakeup(&ao_gps_tracking_data); +#endif ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); break; } break; +#if HAS_ACCEL case ao_flight_boost: /* boost to fast: @@ -448,6 +506,7 @@ ao_flight(void) ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } break; +#endif case ao_flight_coast: /* apogee detect: coast to drogue deploy: @@ -478,8 +537,10 @@ ao_flight(void) /* Set the 'last' limits to max range to prevent * early resting detection */ +#if HAS_ACCEL ao_interval_min_accel = 0; ao_interval_max_accel = 0x7fff; +#endif ao_interval_min_pres = 0; ao_interval_max_pres = 0x7fff; @@ -487,7 +548,9 @@ ao_flight(void) ao_interval_end = ao_flight_tick + AO_INTERVAL_TICKS; ao_interval_cur_min_pres = ao_interval_cur_max_pres = ao_flight_pres; +#if HAS_ACCEL ao_interval_cur_min_accel = ao_interval_cur_max_accel = ao_flight_accel; +#endif /* and enter drogue state */ ao_flight_state = ao_flight_drogue; @@ -530,21 +593,28 @@ ao_flight(void) ao_interval_cur_min_pres = ao_flight_pres; if (ao_flight_pres > ao_interval_cur_max_pres) ao_interval_cur_max_pres = ao_flight_pres; +#if HAS_ACCEL if (ao_flight_accel < ao_interval_cur_min_accel) ao_interval_cur_min_accel = ao_flight_accel; if (ao_flight_accel > ao_interval_cur_max_accel) ao_interval_cur_max_accel = ao_flight_accel; +#endif if ((int16_t) (ao_flight_tick - ao_interval_end) >= 0) { ao_interval_max_pres = ao_interval_cur_max_pres; ao_interval_min_pres = ao_interval_cur_min_pres; + ao_interval_cur_min_pres = ao_interval_cur_max_pres = ao_flight_pres; +#if HAS_ACCEL ao_interval_max_accel = ao_interval_cur_max_accel; ao_interval_min_accel = ao_interval_cur_min_accel; - ao_interval_end = ao_flight_tick + AO_INTERVAL_TICKS; - ao_interval_cur_min_pres = ao_interval_cur_max_pres = ao_flight_pres; ao_interval_cur_min_accel = ao_interval_cur_max_accel = ao_flight_accel; +#endif + ao_interval_end = ao_flight_tick + AO_INTERVAL_TICKS; - if ((uint16_t) (ao_interval_max_accel - ao_interval_min_accel) < (uint16_t) ACCEL_INT_LAND && + if ( +#if HAS_ACCEL + (uint16_t) (ao_interval_max_accel - ao_interval_min_accel) < (uint16_t) ACCEL_INT_LAND && +#endif ao_flight_pres > ao_ground_pres - BARO_LAND && (uint16_t) (ao_interval_max_pres - ao_interval_min_pres) < (uint16_t) BARO_INT_LAND) { diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 0c2006d5..e75bc8df 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -155,6 +155,15 @@ struct ao_config ao_config; #define DATA_TO_XDATA(x) (x) +#define HAS_FLIGHT 1 +#define HAS_ADC 1 +#define HAS_USB 1 +#define HAS_GPS 1 +#ifndef HAS_ACCEL +#define HAS_ACCEL 1 +#endif +#define HAS_ACCEL_REF 0 + #include "ao_flight.c" void diff --git a/src/ao_log.c b/src/ao_log.c index 1b10961d..817d3e6f 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -92,7 +92,9 @@ ao_log(void) log.type = AO_LOG_FLIGHT; log.tick = ao_flight_tick; +#if HAS_ACCEL log.u.flight.ground_accel = ao_ground_accel; +#endif log.u.flight.flight = ao_flight_number; ao_log_data(&log); diff --git a/src/ao_panic.c b/src/ao_panic.c index e996371e..fdada201 100644 --- a/src/ao_panic.c +++ b/src/ao_panic.c @@ -17,6 +17,14 @@ #include "ao.h" +#ifndef HAS_BEEP +#error Please define HAS_BEEP +#endif + +#if !HAS_BEEP +#define ao_beep(x) +#endif + static void ao_panic_delay(uint8_t n) { diff --git a/src/ao_pins.h b/src/ao_pins.h index 2c5b9db5..59604588 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -19,6 +19,9 @@ #define _AO_PINS_H_ #if defined(TELEMETRUM_V_1_0) + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 #define HAS_SERIAL_1 1 #define HAS_ADC 1 #define HAS_EEPROM 1 @@ -32,9 +35,13 @@ #define LEDS_AVAILABLE (AO_LED_RED) #define HAS_EXTERNAL_TEMP 0 #define HAS_ACCEL_REF 0 + #define HAS_ACCEL 1 #endif #if defined(TELEMETRUM_V_1_1) + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 #define HAS_SERIAL_1 1 #define HAS_ADC 1 #define HAS_EEPROM 1 @@ -52,9 +59,12 @@ #define SPI_CS_ON_P0 0 #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ #define M25_MAX_CHIPS 1 + #define HAS_ACCEL 1 #endif #if defined(TELEDONGLE_V_0_2) + #define HAS_USB 1 + #define HAS_BEEP 0 #define HAS_SERIAL_1 0 #define HAS_ADC 0 #define HAS_DBG 1 @@ -71,6 +81,9 @@ #endif #if defined(TELEMETRUM_V_0_1) + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 #define HAS_SERIAL_1 1 #define HAS_ADC 1 #define HAS_DBG 0 @@ -86,9 +99,12 @@ #define HAS_ACCEL_REF 0 #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 + #define HAS_ACCEL 1 #endif #if defined(TELEDONGLE_V_0_1) + #define HAS_USB 1 + #define HAS_BEEP 0 #define HAS_SERIAL_1 0 #define HAS_ADC 0 #define HAS_DBG 0 @@ -105,6 +121,8 @@ #endif #if defined(TIDONGLE) + #define HAS_USB 1 + #define HAS_BEEP 0 #define HAS_SERIAL_1 0 #define HAS_ADC 0 #define HAS_DBG 1 diff --git a/src/ao_product.c b/src/ao_product.c index 82d6298f..54ba2a14 100644 --- a/src/ao_product.c +++ b/src/ao_product.c @@ -16,7 +16,6 @@ */ #include "ao.h" -#include "ao_usb.h" #include PRODUCT_DEFS /* Defines which mark this particular AltOS product */ @@ -27,6 +26,8 @@ const char ao_product[] = AO_iProduct_STRING; #define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) +#if HAS_USB +#include "ao_usb.h" /* USB descriptors in one giant block of bytes */ __code __at(0x00aa) uint8_t ao_usb_descriptors [] = { @@ -151,3 +152,4 @@ __code __at(0x00aa) uint8_t ao_usb_descriptors [] = /* Terminating zero */ 0 }; +#endif diff --git a/src/ao_report.c b/src/ao_report.c index cc8b512b..c9ee7cae 100644 --- a/src/ao_report.c +++ b/src/ao_report.c @@ -37,10 +37,14 @@ static const uint8_t flight_reports[] = { MORSE4(1,0,0,1), /* invalid 'X' */ }; -#if 1 -#define signal(time) ao_beep_for(AO_BEEP_MID, time) +#if HAS_BEEP +#define low(time) ao_beep_for(AO_BEEP_LOW, time) +#define mid(time) ao_beep_for(AO_BEEP_MID, time) +#define high(time) ao_beep_for(AO_BEEP_HIGH, time) #else -#define signal(time) ao_led_for(AO_LED_RED, time) +#define low(time) ao_led_for(AO_LED_RED, time) +#define mid(time) ao_led_for(AO_LED_RED|AO_LED_GREEN, time) +#define high(time) ao_led_for(AO_LED_GREEN, time) #endif #define pause(time) ao_delay(time) @@ -56,9 +60,9 @@ ao_report_beep(void) __reentrant return; while (l--) { if (r & 8) - signal(AO_MS_TO_TICKS(600)); + mid(AO_MS_TO_TICKS(600)); else - signal(AO_MS_TO_TICKS(200)); + mid(AO_MS_TO_TICKS(200)); pause(AO_MS_TO_TICKS(200)); r >>= 1; } @@ -69,12 +73,12 @@ static void ao_report_digit(uint8_t digit) __reentrant { if (!digit) { - signal(AO_MS_TO_TICKS(500)); + mid(AO_MS_TO_TICKS(500)); pause(AO_MS_TO_TICKS(200)); } else { while (digit--) { - signal(AO_MS_TO_TICKS(200)); - pause(AO_MS_TO_TICKS(200)); + mid(AO_MS_TO_TICKS(200)); + mid(AO_MS_TO_TICKS(200)); } } pause(AO_MS_TO_TICKS(300)); @@ -118,24 +122,24 @@ ao_report_continuity(void) __reentrant (ao_report_igniter_ready(ao_igniter_main) << 1)); if (c) { while (c--) { - ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(25)); + high(AO_MS_TO_TICKS(25)); pause(AO_MS_TO_TICKS(100)); } } else { c = 10; while (c--) { - ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(20)); - ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(20)); + high(AO_MS_TO_TICKS(20)); + low(AO_MS_TO_TICKS(20)); } } if (ao_log_full()) { pause(AO_MS_TO_TICKS(100)); c = 2; while (c--) { - ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(100)); - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(100)); - ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(100)); - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(100)); + low(AO_MS_TO_TICKS(100)); + mid(AO_MS_TO_TICKS(100)); + high(AO_MS_TO_TICKS(100)); + mid(AO_MS_TO_TICKS(100)); } } c = 50; diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 7aad929f..dd79f3fc 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -42,16 +42,22 @@ ao_telemetry(void) while (ao_telemetry_interval == 0) ao_sleep(&ao_telemetry_interval); telemetry.flight_state = ao_flight_state; +#if HAS_ACCEL telemetry.flight_accel = ao_flight_accel; telemetry.ground_accel = ao_ground_accel; telemetry.flight_vel = ao_flight_vel; +#endif telemetry.flight_pres = ao_flight_pres; telemetry.ground_pres = ao_ground_pres; +#if HAS_ADC ao_adc_get(&telemetry.adc); +#endif +#if HAS_GPS ao_mutex_get(&ao_gps_mutex); memcpy(&telemetry.gps, &ao_gps_data, sizeof (struct ao_gps_data)); memcpy(&telemetry.gps_tracking, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data)); ao_mutex_put(&ao_gps_mutex); +#endif ao_radio_send(&telemetry, sizeof (telemetry)); ao_delay(ao_telemetry_interval); if (ao_rdf && -- cgit v1.2.3 From e339ffd8bd8b9e3f4758017ba355028000cb612e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Mar 2011 21:57:52 -0800 Subject: altos/test: Use ao_convert.c instead of hand-coded pres → alt func MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix up ao_convert.c so that it can be used within the flight test code instead of having a (broken) copy of the code there. Signed-off-by: Keith Packard --- src/ao_convert.c | 2 +- src/ao_flight_test.c | 25 +------------------------ 2 files changed, 2 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/ao_convert.c b/src/ao_convert.c index cec4c29f..0969f107 100644 --- a/src/ao_convert.c +++ b/src/ao_convert.c @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#ifndef AO_CONVERT_TEST +#if !defined(AO_CONVERT_TEST) && !defined(AO_FLIGHT_TEST) #include "ao.h" #endif diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index e75bc8df..70888d34 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -118,30 +118,7 @@ struct ao_cmds { const char *help; }; - -static int16_t altitude_table[2048] = { -#include "altitude.h" -}; - -int16_t -ao_pres_to_altitude(int16_t pres) __reentrant -{ - pres = pres >> 4; - if (pres < 0) pres = 0; - if (pres > 2047) pres = 2047; - return altitude_table[pres]; -} - -int16_t -ao_altitude_to_pres(int16_t alt) __reentrant -{ - int16_t pres; - - for (pres = 0; pres < 2047; pres++) - if (altitude_table[pres] <= alt) - break; - return pres << 4; -} +#include "ao_convert.c" struct ao_config { uint16_t main_deploy; -- cgit v1.2.3 From 1e56ed44e562f808addfd76bfb352f981db94094 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Mar 2011 21:59:08 -0800 Subject: altos/test: Add baro-only flight test program This builds the flight code in baro-only mode for testing. Signed-off-by: Keith Packard --- src/ao_flight_test.c | 10 +++++++++- src/test/Makefile | 7 +++++-- 2 files changed, 14 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 70888d34..a635803f 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -72,6 +72,7 @@ uint8_t ao_adc_head; #define ao_telemetry_set_interval(x) #define ao_rdf_set(rdf) #define ao_packet_slave_start() +#define ao_packet_slave_stop() enum ao_igniter { ao_igniter_drogue = 0, @@ -138,8 +139,8 @@ struct ao_config ao_config; #define HAS_GPS 1 #ifndef HAS_ACCEL #define HAS_ACCEL 1 -#endif #define HAS_ACCEL_REF 0 +#endif #include "ao_flight.c" @@ -268,12 +269,19 @@ ao_dump_state(void) { if (ao_flight_state == ao_flight_startup) return; +#if HAS_ACCEL printf ("\t\t\t\t\t%s accel %g vel %g alt %d main %d\n", ao_state_names[ao_flight_state], (ao_ground_accel - ao_flight_accel) / COUNTS_PER_G * GRAVITY, (double) ao_flight_vel / 100 / COUNTS_PER_G * GRAVITY, ao_pres_to_altitude(ao_flight_pres) - ao_pres_to_altitude(ao_ground_pres), ao_pres_to_altitude(ao_main_pres) - ao_pres_to_altitude(ao_ground_pres)); +#else + printf ("\t\t\t\t\t%s alt %d main %d\n", + ao_state_names[ao_flight_state], + ao_pres_to_altitude(ao_flight_pres) - ao_pres_to_altitude(ao_ground_pres), + ao_pres_to_altitude(ao_main_pres) - ao_pres_to_altitude(ao_ground_pres)); +#endif if (ao_flight_state == ao_flight_landed) exit(0); } diff --git a/src/test/Makefile b/src/test/Makefile index cd9cafc8..853713fa 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,6 +1,6 @@ vpath % .. -PROGS=ao_flight_test ao_gps_test ao_gps_test_skytraq ao_convert_test +PROGS=ao_flight_test ao_flight_test_baro ao_gps_test ao_gps_test_skytraq ao_convert_test CFLAGS=-I.. -I. @@ -11,9 +11,12 @@ clean: install: -ao_flight_test: ao_flight_test.c ao_flight_test.c ao_host.h ao_flight.c altitude.h +ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c altitude.h cc -g -o $@ $< +ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c altitude.h + cc -g -o $@ -DHAS_ACCEL=0 ../ao_flight_test.c + ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h cc -g -o $@ $< -- cgit v1.2.3 From 2d41358c80f2eb8b6e98d699149bb941a6671475 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Mar 2011 21:00:52 -0800 Subject: altos: Start with packet slave running. Turn off in pad mode. Instead of turning slave mode on in idle mode, start with it running and disable it in pad mode instead. This means packet mode is available in startup mode too. Signed-off-by: Keith Packard --- src/ao_flight.c | 11 ++++------- src/ao_packet_slave.c | 4 ++++ src/ao_pins.h | 6 ++++++ 3 files changed, 14 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index 843865e8..8e370c4f 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -358,10 +358,6 @@ ao_flight(void) * (or uncalibrated values), so we go into invalid mode */ ao_flight_state = ao_flight_invalid; - /* Allow packet mode in invalid flight state, - * Still need to be able to fix the problem! - */ - ao_packet_slave_start(); } else #endif @@ -380,6 +376,10 @@ ao_flight(void) */ ao_usb_disable(); #endif + + /* Disable packet mode in pad state */ + ao_packet_slave_stop(); + /* Turn on telemetry system */ ao_rdf_set(1); ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); @@ -390,9 +390,6 @@ ao_flight(void) /* Set idle mode */ ao_flight_state = ao_flight_idle; - /* Turn on packet system in idle mode */ - ao_packet_slave_start(); - /* signal successful initialization by turning off the LED */ ao_led_off(AO_LED_RED); } diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index 39d04bbb..eb456dab 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -26,6 +26,9 @@ ao_packet_slave(void) while (ao_packet_enable) { if (ao_packet_recv()) { memcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN); +#if HAS_FLIGHT + ao_flight_force_idle = TRUE; +#endif ao_packet_send(); } } @@ -60,4 +63,5 @@ ao_packet_slave_init(void) ao_add_stdio(ao_packet_pollchar, ao_packet_putchar, NULL); + ao_packet_slave_start(); } diff --git a/src/ao_pins.h b/src/ao_pins.h index 59604588..a486b9ba 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -19,6 +19,7 @@ #define _AO_PINS_H_ #if defined(TELEMETRUM_V_1_0) + #define HAS_FLIGHT 1 #define HAS_USB 1 #define HAS_BEEP 1 #define HAS_GPS 1 @@ -39,6 +40,7 @@ #endif #if defined(TELEMETRUM_V_1_1) + #define HAS_FLIGHT 1 #define HAS_USB 1 #define HAS_BEEP 1 #define HAS_GPS 1 @@ -63,6 +65,7 @@ #endif #if defined(TELEDONGLE_V_0_2) + #define HAS_FLIGHT 0 #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 0 @@ -81,6 +84,7 @@ #endif #if defined(TELEMETRUM_V_0_1) + #define HAS_FLIGHT 1 #define HAS_USB 1 #define HAS_BEEP 1 #define HAS_GPS 1 @@ -103,6 +107,7 @@ #endif #if defined(TELEDONGLE_V_0_1) + #define HAS_FLIGHT 0 #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 0 @@ -121,6 +126,7 @@ #endif #if defined(TIDONGLE) + #define HAS_FLIGHT 0 #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 0 -- cgit v1.2.3 From 0e4c55d78852415e79f7318471f4d00c89703b78 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Mar 2011 21:03:57 -0800 Subject: altos: Add TeleMini v1.0 This adds initial code for the telemini board, a two channel flight computer with digital telemetry and a barometric sensor. Signed-off-by: Keith Packard --- src/Makefile | 7 +++++- src/Makefile.proto | 27 ++++++++++++++++++++++ src/ao_pins.h | 19 +++++++++++++++ src/ao_telemini.c | 51 +++++++++++++++++++++++++++++++++++++++++ src/telemini-v0.1/.gitignore | 2 ++ src/telemini-v0.1/.sdcdbrc | 1 + src/telemini-v0.1/Makefile | 1 + src/telemini-v0.1/Makefile.defs | 8 +++++++ 8 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 src/ao_telemini.c create mode 100644 src/telemini-v0.1/.gitignore create mode 100644 src/telemini-v0.1/.sdcdbrc create mode 100644 src/telemini-v0.1/Makefile create mode 100644 src/telemini-v0.1/Makefile.defs (limited to 'src') diff --git a/src/Makefile b/src/Makefile index a6615321..42383f88 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,7 +6,12 @@ CC=sdcc include Version -SUBDIRS=telemetrum-v1.1 telemetrum-v1.0 teledongle-v0.2 telemetrum-v0.1-sky telemetrum-v0.1-sirf teledongle-v0.1 tidongle test +SUBDIRS=\ + telemetrum-v1.1 telemetrum-v1.0 \ + teledongle-v0.2 teledongle-v0.1 \ + telemini-v0.1 \ + telemetrum-v0.1-sky telemetrum-v0.1-sirf \ + tidongle test all: all-recursive diff --git a/src/Makefile.proto b/src/Makefile.proto index 30cd5798..625ca459 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -159,6 +159,33 @@ TM_BASE_SRC = \ $(TM_TASK_SRC) \ $(TM_MAIN_SRC) +# +# Sources for TeleMini +TMINI_DRIVER_SRC = \ + ao_adc.c \ + ao_ignite.c \ + ao_config.c \ + ao_storage.c \ + ao_intflash.c + +TMINI_TASK_SRC = \ + ao_flight.c \ + ao_log.c \ + ao_report.c \ + ao_telemetry.c + +TMINI_MAIN_SRC = \ + ao_telemini.c + +TMINI_BASE_SRC = \ + $(ALTOS_SRC) \ + $(ALTOS_DRIVER_SRC) \ + $(TELE_DRIVER_SRC) \ + $(TELE_COMMON_SRC) \ + $(TMINI_DRIVER_SRC) \ + $(TMINI_TASK_SRC) \ + $(TMINI_MAIN_SRC) + TI_MAIN_SRC = \ ao_tidongle.c diff --git a/src/ao_pins.h b/src/ao_pins.h index a486b9ba..8e07be86 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -83,6 +83,25 @@ #define SPI_CS_ON_P0 0 #endif +#if defined(TELEMINI_V_0_1) + #define HAS_FLIGHT 1 + #define HAS_USB 0 + #define HAS_BEEP 0 + #define HAS_GPS 0 + #define HAS_SERIAL_1 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define HAS_DBG 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define AO_LED_GREEN 1 + #define AO_LED_RED 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL 0 +#endif + #if defined(TELEMETRUM_V_0_1) #define HAS_FLIGHT 1 #define HAS_USB 1 diff --git a/src/ao_telemini.c b/src/ao_telemini.c new file mode 100644 index 00000000..97bc2cf4 --- /dev/null +++ b/src/ao_telemini.c @@ -0,0 +1,51 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +/* stub so as telemini doesn't have monitor mode */ +void +ao_set_monitor(uint8_t monitoring) +{ + (void) monitoring; +} + +void +main(void) +{ + ao_clock_init(); + + + /* Turn on the red LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + + ao_timer_init(); + ao_adc_init(); + ao_cmd_init(); + ao_storage_init(); + ao_flight_init(); + ao_log_init(); + ao_report_init(); + ao_telemetry_init(); + ao_radio_init(); + ao_packet_slave_init(); + ao_igniter_init(); + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/telemini-v0.1/.gitignore b/src/telemini-v0.1/.gitignore new file mode 100644 index 00000000..82868aac --- /dev/null +++ b/src/telemini-v0.1/.gitignore @@ -0,0 +1,2 @@ +telemini-* +ao_product.h diff --git a/src/telemini-v0.1/.sdcdbrc b/src/telemini-v0.1/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telemini-v0.1/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telemini-v0.1/Makefile b/src/telemini-v0.1/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telemini-v0.1/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/telemini-v0.1/Makefile.defs b/src/telemini-v0.1/Makefile.defs new file mode 100644 index 00000000..8a3e1ef9 --- /dev/null +++ b/src/telemini-v0.1/Makefile.defs @@ -0,0 +1,8 @@ +PROG = telemini-v0.1-$(VERSION).ihx + +SRC = \ + $(TMINI_BASE_SRC) + +PRODUCT=TeleMini-v0.1 +PRODUCT_DEF=-DTELEMINI_V_0_1 +IDPRODUCT=0x000a -- cgit v1.2.3 From fc5d014721a7e5a7b22f07eb4ab0bb3c764473fe Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Sat, 26 Feb 2011 16:06:48 +1000 Subject: ao_intflash: Avoid overwriting code Require firmware to specify the end of its codespace in its Makefile, and use this to determine where the start of available flash is. Should give compile time errors if either there's no room left for storage, or if there's not enough room for code. --- src/Makefile.proto | 6 ++++-- src/ao_intflash.c | 2 +- src/telemini-v0.1/Makefile.defs | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index 625ca459..ee3b4d6c 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -13,9 +13,11 @@ ifndef VERSION include ../Version endif -CFLAGS=--model-small --debug --opt-code-speed +CFLAGS=--model-small --debug --opt-code-speed -DCODESIZE=$(CODESIZE) -LDFLAGS=--out-fmt-ihx --code-loc 0x0000 --code-size 0x8000 \ +CODESIZE ?= 0x8000 + +LDFLAGS=--out-fmt-ihx --code-loc 0x0000 --code-size $(CODESIZE) \ --xram-loc 0xf000 --xram-size 0xda2 --iram-size 0xff INC = \ diff --git a/src/ao_intflash.c b/src/ao_intflash.c index ad5e5aac..450d94a3 100644 --- a/src/ao_intflash.c +++ b/src/ao_intflash.c @@ -24,7 +24,7 @@ #define FCTL_WRITE (1 << 1) #define FCTL_ERASE (1 << 0) -#define ENDOFCODE (0x51f0 + 1500) +#define ENDOFCODE (CODESIZE) #define NUM_PAGES ((0x8000-ENDOFCODE)/1024) #define SIZE (1024*NUM_PAGES) #define LOCN (0x8000 - SIZE) diff --git a/src/telemini-v0.1/Makefile.defs b/src/telemini-v0.1/Makefile.defs index 8a3e1ef9..94ac1268 100644 --- a/src/telemini-v0.1/Makefile.defs +++ b/src/telemini-v0.1/Makefile.defs @@ -6,3 +6,4 @@ SRC = \ PRODUCT=TeleMini-v0.1 PRODUCT_DEF=-DTELEMINI_V_0_1 IDPRODUCT=0x000a +CODESIZE=0x6700 -- cgit v1.2.3 From f8afc2641c779fc312a42a6358187d8716ebe61a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 Mar 2011 23:52:11 -0800 Subject: altos: Switch LED usage for TeleMini around We're using the LEDs instead of tones, so make red mean 'low tone', green mean 'middle tone' and both mean 'high tone'. Signed-off-by: Keith Packard --- src/ao_report.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ao_report.c b/src/ao_report.c index c9ee7cae..4646fb09 100644 --- a/src/ao_report.c +++ b/src/ao_report.c @@ -42,9 +42,9 @@ static const uint8_t flight_reports[] = { #define mid(time) ao_beep_for(AO_BEEP_MID, time) #define high(time) ao_beep_for(AO_BEEP_HIGH, time) #else -#define low(time) ao_led_for(AO_LED_RED, time) -#define mid(time) ao_led_for(AO_LED_RED|AO_LED_GREEN, time) -#define high(time) ao_led_for(AO_LED_GREEN, time) +#define low(time) ao_led_for(AO_LED_GREEN, time) +#define mid(time) ao_led_for(AO_LED_RED, time) +#define high(time) ao_led_for(AO_LED_GREEN|AO_LED_RED, time) #endif #define pause(time) ao_delay(time) -- cgit v1.2.3 From ddd7485f05d0cad8f5b3e1ee9b9a4d2812ea1837 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 Mar 2011 08:03:11 -0800 Subject: altos: Switch pins around for TeleMini TeleMini has fewer sensors and uses P0 for igniters instead of P2. Signed-off-by: Keith Packard --- src/ao_adc.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/ao_ignite.c | 10 ++++++++++ src/ao_pins.h | 22 ++++++++++++++++++++++ 3 files changed, 86 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_adc.c b/src/ao_adc.c index 9990a1fd..ce935716 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -48,6 +48,8 @@ ao_adc_isr(void) __interrupt 1 uint8_t __xdata *a; sequence = (ADCCON2 & ADCCON2_SCH_MASK) >> ADCCON2_SCH_SHIFT; +#if IGNITE_ON_P2 + /* TeleMetrum readings */ #if HAS_ACCEL_REF if (sequence == 2) { a = (uint8_t __xdata *) (&ao_accel_ref[ao_adc_head]); @@ -71,7 +73,47 @@ ao_adc_isr(void) __interrupt 1 else #endif ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | sequence; - } else { + } +#endif + +#if IGNITE_ON_P0 + /* TeleMini readings */ + a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].pres); + switch (sequence) { + case 0: + /* pressure */ + a += 0; + sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 1; + break; + case 1: + /* drogue sense */ + a += 6; + sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 2; + break; + case 2: + /* main sense */ + a += 8; + sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 3; + break; + case 3: + /* battery */ + a += 4; + sequence = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP; + break; + case ADCCON3_ECH_TEMP: + a += 2; + sequence = 0; + break; + } + a[0] = ADCL; + a[1] = ADCH; + if (sequence) { + /* Start next conversion */ + ADCCON3 = sequence; + } +#endif + + else { /* record this conversion series */ ao_adc_ring[ao_adc_head].tick = ao_time(); ao_adc_head = ao_adc_ring_next(ao_adc_head); @@ -97,6 +139,8 @@ __code struct ao_cmds ao_adc_cmds[] = { void ao_adc_init(void) { +#if IGNITE_ON_P2 + /* TeleMetrum configuration */ ADCCFG = ((1 << 0) | /* acceleration */ (1 << 1) | /* pressure */ #if HAS_EXTERNAL_TEMP @@ -105,6 +149,15 @@ ao_adc_init(void) (1 << 3) | /* battery voltage */ (1 << 4) | /* drogue sense */ (1 << 5)); /* main sense */ +#endif + +#if IGNITE_ON_P0 + /* TeleMini configuration */ + ADCCFG = ((1 << 0) | /* pressure */ + (1 << 1) | /* drogue sense */ + (1 << 2) | /* main sense */ + (1 << 3)); /* battery voltage */ +#endif /* enable interrupts */ ADCIF = 0; diff --git a/src/ao_ignite.c b/src/ao_ignite.c index 798ba9b4..7874ee01 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -17,11 +17,21 @@ #include "ao.h" +#if IGNITE_ON_P2 #define AO_IGNITER_DROGUE P2_3 #define AO_IGNITER_MAIN P2_4 #define AO_IGNITER_DIR P2DIR #define AO_IGNITER_DROGUE_BIT (1 << 3) #define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +#if IGNITE_ON_P0 +#define AO_IGNITER_DROGUE P0_5 +#define AO_IGNITER_MAIN P0_4 +#define AO_IGNITER_DIR P0DIR +#define AO_IGNITER_DROGUE_BIT (1 << 5) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif /* test these values with real igniters */ #define AO_IGNITER_OPEN 1000 diff --git a/src/ao_pins.h b/src/ao_pins.h index 8e07be86..0de39970 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -29,6 +29,8 @@ #define HAS_DBG 1 #define DBG_ON_P1 1 #define DBG_ON_P0 0 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 @@ -50,6 +52,8 @@ #define HAS_DBG 1 #define DBG_ON_P1 1 #define DBG_ON_P0 0 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 @@ -74,6 +78,8 @@ #define HAS_EEPROM 0 #define DBG_ON_P1 1 #define DBG_ON_P0 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 #define PACKET_HAS_MASTER 1 #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 1 @@ -92,6 +98,8 @@ #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_DBG 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 1 #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 @@ -113,6 +121,8 @@ #define HAS_EEPROM 1 #define DBG_ON_P1 0 #define DBG_ON_P0 1 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 #define AO_LED_RED 2 @@ -135,6 +145,8 @@ #define HAS_EEPROM 0 #define DBG_ON_P1 0 #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 #define PACKET_HAS_MASTER 1 #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 2 @@ -154,6 +166,8 @@ #define HAS_EEPROM 0 #define DBG_ON_P1 0 #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 #define PACKET_HAS_MASTER 1 #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 2 @@ -210,6 +224,14 @@ #define SPI_CS_DIR P0DIR #endif +#ifndef IGNITE_ON_P2 +#error Please define IGNITE_ON_P2 +#endif + +#ifndef IGNITE_ON_P0 +#error Please define IGNITE_ON_P0 +#endif + #ifndef HAS_SERIAL_1 #error Please define HAS_SERIAL_1 #endif -- cgit v1.2.3 From 1d8579f973bfe1047ee91f03555e74abdc483e69 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 Mar 2011 16:31:43 -0800 Subject: altos: oops -- altitude reporting wasn't pausing between signals need to actually alternate the LED/tone with some space so you can count. Signed-off-by: Keith Packard --- src/ao_report.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_report.c b/src/ao_report.c index 4646fb09..3223390f 100644 --- a/src/ao_report.c +++ b/src/ao_report.c @@ -78,7 +78,7 @@ ao_report_digit(uint8_t digit) __reentrant } else { while (digit--) { mid(AO_MS_TO_TICKS(200)); - mid(AO_MS_TO_TICKS(200)); + pause(AO_MS_TO_TICKS(200)); } } pause(AO_MS_TO_TICKS(300)); -- cgit v1.2.3 From 82707a05af0eb2d54f46b58805c95cdf4e5a3703 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 16 Mar 2011 20:36:50 -0700 Subject: altos: Internal flash ops block when running from flash The docs say that if you are executing from flash, then the CPU will stall after a flash write or erase command is started until the operation is complete. Take advantage of that to simplify the flash code. Signed-off-by: Keith Packard --- src/ao_intflash.c | 151 ++++++++++++++++++++++++++++-------------------------- src/cc1111.h | 20 ++++++++ 2 files changed, 98 insertions(+), 73 deletions(-) (limited to 'src') diff --git a/src/ao_intflash.c b/src/ao_intflash.c index 450d94a3..88d1f7f6 100644 --- a/src/ao_intflash.c +++ b/src/ao_intflash.c @@ -18,38 +18,45 @@ #include "ao.h" #include "cc1111.h" -#define FCTL_BUSY (1 << 7) -#define FCTL_SWBSY (1 << 6) -#define FCTL_CONTRD_ENABLE (1 << 4) -#define FCTL_WRITE (1 << 1) -#define FCTL_ERASE (1 << 0) - #define ENDOFCODE (CODESIZE) -#define NUM_PAGES ((0x8000-ENDOFCODE)/1024) -#define SIZE (1024*NUM_PAGES) -#define LOCN (0x8000 - SIZE) +#define AO_INTFLASH_BLOCK 1024 +#define AO_INTFLASH_BLOCKS ((0x8000 - ENDOFCODE)/AO_INTFLASH_BLOCK) +#define AO_INTFLASH_SIZE (AO_INTFLASH_BLOCK * AO_INTFLASH_BLOCKS) +#define AO_INTFLASH_LOCATION (0x8000 - AO_INTFLASH_SIZE) + +/* + * 21000 * 24e6 + * FWT = ------------ + * 16e9 + * + * = 31.5 + * + * Round up and use 32 + */ -#if NUM_PAGES < 1 +#define FLASH_TIMING 0x20 + +#if AO_INTFLASH_BLOCKS < 2 #error "Too few pages" #endif -#if LOCN % 1024 != 0 +#if AO_INFTLASH_LOCATION % 1024 != 0 #error "Pages aren't aligned properly" #endif -__xdata __at(LOCN) uint8_t ao_intflash[SIZE]; +__xdata __at(AO_INTFLASH_LOCATION) uint8_t ao_intflash[AO_INTFLASH_SIZE]; /* Total bytes of available storage */ __xdata uint32_t ao_storage_total = sizeof(ao_intflash); /* Block size - device is erased in these units. */ -__xdata uint32_t ao_storage_block = 1024; +__xdata uint32_t ao_storage_block = AO_INTFLASH_BLOCK; /* Byte offset of config block. Will be ao_storage_block bytes long */ -__xdata uint32_t ao_storage_config = sizeof(ao_intflash); +__xdata uint32_t ao_storage_config = sizeof(ao_intflash) - AO_INTFLASH_BLOCK; /* Storage unit size - device reads and writes must be within blocks of this size. */ -__xdata uint16_t ao_storage_unit = 1024; +__xdata uint16_t ao_storage_unit = AO_INTFLASH_BLOCK; __xdata static uint8_t ao_intflash_dma_done; static uint8_t ao_intflash_dma; @@ -76,21 +83,16 @@ ao_storage_erase(uint32_t pos) __reentrant addr = ((uint16_t)(ao_intflash + pos) >> 1); - while (FCTL & FCTL_BUSY) - ; - - FWT = 0x1F; // 21000 * f / 16e9 ; f = system freq = 24MHz FADDRH = addr >> 8; - FADDRL = addr & ~0xFF00; - - _asm - .even - orl _FCTL, #FCTL_ERASE; ; FCTL |= FCTL_ERASE - nop; ; Required, see datasheet. - _endasm; - - while (FCTL & FCTL_BUSY) - ; + FADDRL = addr; + + __critical { + _asm + .even + orl _FCTL, #FCTL_ERASE; ; FCTL |= FCTL_ERASE + nop ; Required, see datasheet. + _endasm; + } return 1; } @@ -100,45 +102,54 @@ ao_storage_erase(uint32_t pos) __reentrant */ static void -word_aligned_write(uint32_t pos, __xdata void *d, uint16_t len) __reentrant +ao_intflash_write_aligned(uint16_t pos, __xdata void *d, uint16_t len) __reentrant { - uint16_t addr; - - addr = ((uint16_t)(ao_intflash + pos) >> 1); - - ao_dma_set_transfer(ao_intflash_dma, d, &X_FWDATA, - DMA_LEN_HIGH_VLEN_LEN | len, - DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_FLASH, - DMA_CFG1_SRCINC_1 | DMA_CFG1_DESTINC_0 | - DMA_CFG1_IRQMASK | DMA_CFG1_PRIORITY_HIGH); - - while (FCTL & FCTL_BUSY) - ; - - FWT = 0x1F; // 21000 * f / 16e9 ; f = system freq = 24MHz - - FADDRH = addr >> 8; - FADDRL = addr & ~0xFF00; + pos = ((uint16_t) ao_intflash + pos) >> 1; + + ao_dma_set_transfer(ao_intflash_dma, + d, + &FWDATAXADDR, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_FLASH, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_HIGH); + + FADDRH = pos >> 8; + FADDRL = pos; ao_dma_start(ao_intflash_dma); - _asm - .even - orl _FCTL, #FCTL_WRITE; ; FCTL |= FCTL_WRITE - _endasm; + __critical { + _asm + .even + orl _FCTL, #FCTL_WRITE; ; FCTL |= FCTL_WRITE + nop + _endasm; + } +} - __critical while (!ao_intflash_dma_done) - ao_sleep(&ao_intflash_dma_done); +static void +ao_intflash_write_byte(uint16_t pos, uint8_t byte) __reentrant +{ + static __xdata uint8_t b[2]; - while (FCTL & (FCTL_BUSY | FCTL_SWBSY)) - ; + if (pos & 1) { + b[0] = 0xff; + b[1] = byte; + } else { + b[0] = byte; + b[1] = 0xff; + } + ao_intflash_write_aligned(pos, b, 2); } uint8_t -ao_storage_device_write(uint32_t pos, __xdata void *v, uint16_t len) __reentrant +ao_storage_device_write(uint32_t pos32, __xdata void *v, uint16_t len) __reentrant { - static __xdata uint8_t b[2]; + uint16_t pos = pos32; __xdata uint8_t *d = v; uint8_t oddlen; @@ -148,23 +159,15 @@ ao_storage_device_write(uint32_t pos, __xdata void *v, uint16_t len) __reentrant return 1; if (pos & 1) { - b[0] = ~0; - b[1] = d[0]; - word_aligned_write(pos-1, b, 2); - pos++; + ao_intflash_write_byte(pos++, *d++); len--; - d++; } oddlen = len & 1; - len &= ~1; - if (len > 0) { - word_aligned_write(pos, d, len); - } - if (oddlen) { - b[0] = d[len]; - b[1] = ~0; - word_aligned_write(pos+len, b, 2); - } + len -= oddlen; + if (len) + ao_intflash_write_aligned(pos, d, len); + if (oddlen) + ao_intflash_write_byte(pos + len, d[len]); return 1; } @@ -194,11 +197,13 @@ ao_storage_setup(void) void ao_storage_device_info(void) __reentrant { - printf ("Using internal flash, starting at 0x%04x\n", LOCN); + printf ("Using internal flash, starting at 0x%04x\n", AO_INTFLASH_LOCATION); } void ao_storage_device_init(void) { ao_intflash_dma = ao_dma_alloc(&ao_intflash_dma_done); + + FWT = FLASH_TIMING; } diff --git a/src/cc1111.h b/src/cc1111.h index 20ed052a..effb1a68 100644 --- a/src/cc1111.h +++ b/src/cc1111.h @@ -884,6 +884,26 @@ __xdata __at (0xDFF9) volatile uint8_t U1DBUFXADDR; sfr at 0xc2 U0BAUD; sfr at 0xfa U1BAUD; +/* Flash controller */ + +sfr at 0xAE FCTL; +#define FCTL_BUSY (1 << 7) +#define FCTL_SWBSY (1 << 6) +#define FCTL_CONTRD_ENABLE (1 << 4) +#define FCTL_WRITE (1 << 1) +#define FCTL_ERASE (1 << 0) + +/* Flash write data. Write two bytes here */ +sfr at 0xAF FWDATA; +__xdata __at (0xDFAF) volatile uint8_t FWDATAXADDR; + +/* Flash write/erase address */ +sfr at 0xAD FADDRH; +sfr at 0xAC FADDRL; + +/* Flash timing */ +sfr at 0xAB FWT; + /* Radio */ sfr at 0xD9 RFD; -- cgit v1.2.3 From 8b546b474b7b6c5b4169b4c1ca09c6f17ebb3ae5 Mon Sep 17 00:00:00 2001 From: Anthony Towns Date: Fri, 11 Mar 2011 21:41:01 +1000 Subject: ignore new flight test file --- src/test/.gitignore | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/test/.gitignore b/src/test/.gitignore index 54b00096..0a43de8a 100644 --- a/src/test/.gitignore +++ b/src/test/.gitignore @@ -1,4 +1,5 @@ ao_flight_test +ao_flight_test_baro ao_gps_test ao_gps_test_skytraq ao_convert_test -- cgit v1.2.3 From c826fab31f8aea25a942b6bb8435d4b04c1bef10 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 17 Mar 2011 16:00:10 -0700 Subject: altos: Add tiny logging for TeleMini/TeleNano This splits the logging code into management of the log space within storage and separate code to actually write suitable log entries. A new log writing module, ao_log_tiny, is added which writes only altimeter data at a fairly low data rate for devices using on-chip storage. Signed-off-by: Keith Packard --- src/Makefile.proto | 2 + src/ao.h | 102 ++++++++++++++++++++------------- src/ao_log.c | 162 ++++++----------------------------------------------- src/ao_log_big.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++ src/ao_log_tiny.c | 82 +++++++++++++++++++++++++++ 5 files changed, 309 insertions(+), 184 deletions(-) create mode 100644 src/ao_log_big.c create mode 100644 src/ao_log_tiny.c (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index ee3b4d6c..30e626ad 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -142,6 +142,7 @@ SKY_DRIVER_SRC = \ TM_TASK_SRC = \ ao_flight.c \ ao_log.c \ + ao_log_big.c \ ao_report.c \ ao_telemetry.c @@ -173,6 +174,7 @@ TMINI_DRIVER_SRC = \ TMINI_TASK_SRC = \ ao_flight.c \ ao_log.c \ + ao_log_tiny.c \ ao_report.c \ ao_telemetry.c diff --git a/src/ao.h b/src/ao.h index 5bbe5158..fd8c6034 100644 --- a/src/ao.h +++ b/src/ao.h @@ -516,6 +516,70 @@ ao_storage_device_info(void) __reentrant; * ao_log.c */ +/* We record flight numbers in the first record of + * the log. Tasks may wait for this to be initialized + * by sleeping on this variable. + */ +extern __xdata uint16_t ao_flight_number; + +extern __pdata uint32_t ao_log_current_pos; +extern __pdata uint32_t ao_log_end_pos; +extern __pdata uint32_t ao_log_start_pos; +extern __xdata uint8_t ao_log_running; +extern __xdata enum flight_state ao_log_state; + +/* required functions from the underlying log system */ + +/* Return the flight number from the given log slot, 0 if none */ +uint16_t +ao_log_flight(uint8_t slot); + +/* Flush the log */ +void +ao_log_flush(void); + +/* Logging thread main routine */ +void +ao_log(void); + +/* functions provided in ao_log.c */ + +/* Figure out the current flight number */ +void +ao_log_scan(void) __reentrant; + +/* Return the position of the start of the given log slot */ +uint32_t +ao_log_pos(uint8_t slot); + +/* Start logging to eeprom */ +void +ao_log_start(void); + +/* Stop logging */ +void +ao_log_stop(void); + +/* Initialize the logging system */ +void +ao_log_init(void); + +/* Write out the current flight number to the erase log */ +void +ao_log_write_erase(uint8_t pos); + +/* Returns true if there are any logs stored in eeprom */ +uint8_t +ao_log_present(void); + +/* Returns true if there is no more storage space available */ +uint8_t +ao_log_full(void); + +/* + * ao_log_big.c + */ + /* * The data log is recorded in the eeprom as a sequence * of data packets. @@ -614,44 +678,6 @@ struct ao_log_record { uint8_t ao_log_data(__xdata struct ao_log_record *log) __reentrant; -/* Flush the log */ -void -ao_log_flush(void); - -/* We record flight numbers in the first record of - * the log. Tasks may wait for this to be initialized - * by sleeping on this variable. - */ -extern __xdata uint16_t ao_flight_number; - -/* Logging thread main routine */ -void -ao_log(void); - -/* Start logging to eeprom */ -void -ao_log_start(void); - -/* Stop logging */ -void -ao_log_stop(void); - -/* Initialize the logging system */ -void -ao_log_init(void); - -/* Write out the current flight number to the erase log */ -void -ao_log_write_erase(uint8_t pos); - -/* Returns true if there are any logs stored in eeprom */ -uint8_t -ao_log_present(void); - -/* Returns true if there is no more storage space available */ -uint8_t -ao_log_full(void); - /* * ao_flight.c */ diff --git a/src/ao_log.c b/src/ao_log.c index 817d3e6f..433e9c3a 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -17,43 +17,12 @@ #include "ao.h" -static __pdata uint32_t ao_log_current_pos; -static __pdata uint32_t ao_log_end_pos; -static __pdata uint32_t ao_log_start_pos; -static __xdata uint8_t ao_log_running; -static __xdata uint8_t ao_log_mutex; - -static uint8_t -ao_log_csum(__xdata uint8_t *b) __reentrant -{ - uint8_t sum = 0x5a; - uint8_t i; - - for (i = 0; i < sizeof (struct ao_log_record); i++) - sum += *b++; - return -sum; -} - -uint8_t -ao_log_data(__xdata struct ao_log_record *log) __reentrant -{ - uint8_t wrote = 0; - /* set checksum */ - log->csum = 0; - log->csum = ao_log_csum((__xdata uint8_t *) log); - ao_mutex_get(&ao_log_mutex); { - if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) - ao_log_stop(); - if (ao_log_running) { - wrote = 1; - ao_storage_write(ao_log_current_pos, - log, - sizeof (struct ao_log_record)); - ao_log_current_pos += sizeof (struct ao_log_record); - } - } ao_mutex_put(&ao_log_mutex); - return wrote; -} +__pdata uint32_t ao_log_current_pos; +__pdata uint32_t ao_log_end_pos; +__pdata uint32_t ao_log_start_pos; +__xdata uint8_t ao_log_running; +__xdata enum flight_state ao_log_state; +__xdata uint16_t ao_flight_number; void ao_log_flush(void) @@ -61,91 +30,6 @@ ao_log_flush(void) ao_storage_flush(); } -static void ao_log_scan(void); - -__xdata struct ao_log_record log; -__xdata uint16_t ao_flight_number; - -static uint8_t -ao_log_dump_check_data(void) -{ - if (ao_log_csum((uint8_t *) &log) != 0) - return 0; - return 1; -} - -__xdata uint8_t ao_log_adc_pos; -__xdata enum flight_state ao_log_state; - -/* a hack to make sure that ao_log_records fill the eeprom block in even units */ -typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; - -void -ao_log(void) -{ - ao_storage_setup(); - - ao_log_scan(); - - while (!ao_log_running) - ao_sleep(&ao_log_running); - - log.type = AO_LOG_FLIGHT; - log.tick = ao_flight_tick; -#if HAS_ACCEL - log.u.flight.ground_accel = ao_ground_accel; -#endif - log.u.flight.flight = ao_flight_number; - ao_log_data(&log); - - /* Write the whole contents of the ring to the log - * when starting up. - */ - ao_log_adc_pos = ao_adc_ring_next(ao_flight_adc); - for (;;) { - /* Write samples to EEPROM */ - while (ao_log_adc_pos != ao_flight_adc) { - log.type = AO_LOG_SENSOR; - log.tick = ao_adc_ring[ao_log_adc_pos].tick; - log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel; - log.u.sensor.pres = ao_adc_ring[ao_log_adc_pos].pres; - ao_log_data(&log); - if ((ao_log_adc_pos & 0x1f) == 0) { - log.type = AO_LOG_TEMP_VOLT; - log.tick = ao_adc_ring[ao_log_adc_pos].tick; - log.u.temp_volt.temp = ao_adc_ring[ao_log_adc_pos].temp; - log.u.temp_volt.v_batt = ao_adc_ring[ao_log_adc_pos].v_batt; - ao_log_data(&log); - log.type = AO_LOG_DEPLOY; - log.tick = ao_adc_ring[ao_log_adc_pos].tick; - log.u.deploy.drogue = ao_adc_ring[ao_log_adc_pos].sense_d; - log.u.deploy.main = ao_adc_ring[ao_log_adc_pos].sense_m; - ao_log_data(&log); - } - ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); - } - /* Write state change to EEPROM */ - if (ao_flight_state != ao_log_state) { - ao_log_state = ao_flight_state; - log.type = AO_LOG_STATE; - log.tick = ao_flight_tick; - log.u.state.state = ao_log_state; - log.u.state.reason = 0; - ao_log_data(&log); - - if (ao_log_state == ao_flight_landed) - ao_log_stop(); - } - - /* Wait for a while */ - ao_delay(AO_MS_TO_TICKS(100)); - - /* Stop logging when told to */ - while (!ao_log_running) - ao_sleep(&ao_log_running); - } -} - /* * When erasing a flight log, make sure the config block * has an up-to-date version of the current flight number @@ -205,25 +89,12 @@ ao_log_slots() return (uint8_t) (ao_storage_config / ao_config.flight_log_max); } -static uint32_t +uint32_t ao_log_pos(uint8_t slot) { return ((slot) * ao_config.flight_log_max); } -static uint16_t -ao_log_flight(uint8_t slot) -{ - if (!ao_storage_read(ao_log_pos(slot), - &log, - sizeof (struct ao_log_record))) - return 0; - - if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) - return log.u.flight.flight; - return 0; -} - static uint16_t ao_log_max_flight(void) { @@ -244,7 +115,7 @@ ao_log_max_flight(void) return max_flight; } -static void +void ao_log_scan(void) __reentrant { uint8_t log_slot; @@ -364,20 +235,21 @@ ao_log_delete(void) __reentrant ao_log_current_pos = ao_log_pos(slot); ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; while (ao_log_current_pos < ao_log_end_pos) { + uint8_t i; + static __xdata uint8_t b; + /* * Check to see if we've reached the end of * the used memory to avoid re-erasing the same * memory over and over again */ - if (ao_storage_read(ao_log_current_pos, - &log, - sizeof (struct ao_log_record))) { - for (slot = 0; slot < sizeof (struct ao_log_record); slot++) - if (((uint8_t *) &log)[slot] != 0xff) + for (i = 0; i < 16; i++) { + if (ao_storage_read(ao_log_current_pos + i, &b, 1)) + if (b != 0xff) break; - if (slot == sizeof (struct ao_log_record)) - break; } + if (i == 16) + break; ao_storage_erase(ao_log_current_pos); ao_log_current_pos += ao_storage_block; } @@ -389,8 +261,6 @@ ao_log_delete(void) __reentrant printf("No such flight: %d\n", ao_cmd_lex_i); } - - __code struct ao_cmds ao_log_cmds[] = { { ao_log_list, "l\0List stored flight logs" }, { ao_log_delete, "d \0Delete stored flight" }, diff --git a/src/ao_log_big.c b/src/ao_log_big.c new file mode 100644 index 00000000..6db4a0ff --- /dev/null +++ b/src/ao_log_big.c @@ -0,0 +1,145 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static __xdata uint8_t ao_log_mutex; +static __xdata struct ao_log_record log; + +static uint8_t +ao_log_csum(__xdata uint8_t *b) __reentrant +{ + uint8_t sum = 0x5a; + uint8_t i; + + for (i = 0; i < sizeof (struct ao_log_record); i++) + sum += *b++; + return -sum; +} + +uint8_t +ao_log_data(__xdata struct ao_log_record *log) __reentrant +{ + uint8_t wrote = 0; + /* set checksum */ + log->csum = 0; + log->csum = ao_log_csum((__xdata uint8_t *) log); + ao_mutex_get(&ao_log_mutex); { + if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_stop(); + if (ao_log_running) { + wrote = 1; + ao_storage_write(ao_log_current_pos, + log, + sizeof (struct ao_log_record)); + ao_log_current_pos += sizeof (struct ao_log_record); + } + } ao_mutex_put(&ao_log_mutex); + return wrote; +} + +static uint8_t +ao_log_dump_check_data(void) +{ + if (ao_log_csum((uint8_t *) &log) != 0) + return 0; + return 1; +} + +static __xdata uint8_t ao_log_adc_pos; + +/* a hack to make sure that ao_log_records fill the eeprom block in even units */ +typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; + +void +ao_log(void) +{ + ao_storage_setup(); + + ao_log_scan(); + + while (!ao_log_running) + ao_sleep(&ao_log_running); + + log.type = AO_LOG_FLIGHT; + log.tick = ao_flight_tick; +#if HAS_ACCEL + log.u.flight.ground_accel = ao_ground_accel; +#endif + log.u.flight.flight = ao_flight_number; + ao_log_data(&log); + + /* Write the whole contents of the ring to the log + * when starting up. + */ + ao_log_adc_pos = ao_adc_ring_next(ao_flight_adc); + for (;;) { + /* Write samples to EEPROM */ + while (ao_log_adc_pos != ao_flight_adc) { + log.type = AO_LOG_SENSOR; + log.tick = ao_adc_ring[ao_log_adc_pos].tick; + log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel; + log.u.sensor.pres = ao_adc_ring[ao_log_adc_pos].pres; + ao_log_data(&log); + if ((ao_log_adc_pos & 0x1f) == 0) { + log.type = AO_LOG_TEMP_VOLT; + log.tick = ao_adc_ring[ao_log_adc_pos].tick; + log.u.temp_volt.temp = ao_adc_ring[ao_log_adc_pos].temp; + log.u.temp_volt.v_batt = ao_adc_ring[ao_log_adc_pos].v_batt; + ao_log_data(&log); + log.type = AO_LOG_DEPLOY; + log.tick = ao_adc_ring[ao_log_adc_pos].tick; + log.u.deploy.drogue = ao_adc_ring[ao_log_adc_pos].sense_d; + log.u.deploy.main = ao_adc_ring[ao_log_adc_pos].sense_m; + ao_log_data(&log); + } + ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); + } + /* Write state change to EEPROM */ + if (ao_flight_state != ao_log_state) { + ao_log_state = ao_flight_state; + log.type = AO_LOG_STATE; + log.tick = ao_flight_tick; + log.u.state.state = ao_log_state; + log.u.state.reason = 0; + ao_log_data(&log); + + if (ao_log_state == ao_flight_landed) + ao_log_stop(); + } + + /* Wait for a while */ + ao_delay(AO_MS_TO_TICKS(100)); + + /* Stop logging when told to */ + while (!ao_log_running) + ao_sleep(&ao_log_running); + } +} + +uint16_t +ao_log_flight(uint8_t slot) +{ + if (!ao_storage_read(ao_log_pos(slot), + &log, + sizeof (struct ao_log_record))) + return 0; + + if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) + return log.u.flight.flight; + return 0; +} diff --git a/src/ao_log_tiny.c b/src/ao_log_tiny.c new file mode 100644 index 00000000..877c1033 --- /dev/null +++ b/src/ao_log_tiny.c @@ -0,0 +1,82 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static __data uint16_t ao_log_tiny_interval; +static __data uint32_t ao_log_tiny_pos; + +#define AO_LOG_TINY_INTERVAL_ASCENT AO_MS_TO_TICKS(100) +#define AO_LOG_TINY_INTERVAL_DEFAULT AO_MS_TO_TICKS(1000) + +void +ao_log_tiny_set_interval(uint16_t ticks) +{ + ao_log_tiny_interval = ticks; +} + +static __xdata uint16_t ao_log_tiny_data_temp; + +#define ao_log_tiny_data(d) do { \ + ao_log_tiny_data_temp = (d); \ + ao_storage_write(ao_log_tiny_pos, &ao_log_tiny_data_temp, 2); \ + ao_log_tiny_pos += 2; \ + } while (0) + +void +ao_log(void) +{ + uint16_t time; + int16_t delay; + enum ao_flight_state ao_log_tiny_state; + + ao_storage_setup(); + + ao_log_tiny_state = ao_flight_invalid; + ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT; + while (!ao_log_running) + ao_sleep(&ao_log_running); + + time = ao_time(); + ao_log_tiny_data(ao_flight_number); + for (;;) { + if (ao_flight_state != ao_log_tiny_state) { + ao_log_tiny_data(ao_flight_state | 0x8000); + ao_log_tiny_state = ao_flight_state; + ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT; + if (ao_log_tiny_state <= ao_flight_coast) + ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; + } + ao_log_tiny_data(ao_flight_pres); // XXX change to alt + time += ao_log_tiny_interval; + delay = time - ao_time(); + if (delay > 0) + ao_delay(delay); + } +} + +uint16_t +ao_log_flight(uint8_t slot) +{ + static __xdata uint16_t flight; + + (void) slot; + ao_storage_read(0, &flight, 2); + if (flight == 0xffff) + flight = 0; + return flight; +} -- cgit v1.2.3 From 62eae8a17d870e8ac6937ba23da01a5fbc652c6c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 Mar 2011 16:53:11 -0700 Subject: altos: Add kalman filters for baro-only boards This adds a baro-only kalman filter to track the state of the rocket, and then uses it to control flight events instead of the existing ad-hoc mechanisms. Signed-off-by: Keith Packard --- src/ao_flight.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++-- src/ao_flight_test.c | 70 +++++++++++++++++++++++++++++----- src/ao_pins.h | 4 ++ 3 files changed, 165 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index 8e370c4f..e8130baa 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -31,6 +31,10 @@ #error Please define HAS_USB #endif +#ifndef USE_KALMAN +#error Please define USE_KALMAN +#endif + /* Main flight thread. */ __pdata enum ao_flight_state ao_flight_state; /* current flight state */ @@ -150,6 +154,62 @@ __pdata int16_t ao_old_vel_tick; __xdata int32_t ao_raw_accel_sum; #endif +#if USE_KALMAN +__pdata int16_t ao_ground_height; +__pdata int32_t ao_k_max_height; +__pdata int32_t ao_k_height; +__pdata int32_t ao_k_speed; +__pdata int32_t ao_k_accel; + +#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) +#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) + +#define from_fix(x) ((x) >> 16) + +#define AO_K0_100 to_fix16(0.05680323) +#define AO_K1_100 to_fix16(0.16608182) +#define AO_K2_100 to_fix16(0.24279580) + +#define AO_K_STEP_100 to_fix16(0.01) +#define AO_K_STEP_2_2_100 to_fix16(0.00005) + +#define AO_K0_10 to_fix16(0.23772023) +#define AO_K1_10 to_fix16(0.32214149) +#define AO_K2_10 to_fix16(0.21827159) + +#define AO_K_STEP_10 to_fix16(0.1) +#define AO_K_STEP_2_2_10 to_fix16(0.005) + +static void +ao_kalman_baro(void) +{ + int16_t err = ((ao_pres_to_altitude(ao_raw_pres) - ao_ground_height)) + - (int16_t) (ao_k_height >> 16); + +#ifdef AO_FLIGHT_TEST + if (ao_flight_tick - ao_flight_prev_tick > 5) { + ao_k_height += ((ao_k_speed >> 16) * AO_K_STEP_10 + + (ao_k_accel >> 16) * AO_K_STEP_2_2_10); + ao_k_speed += (ao_k_accel >> 16) * AO_K_STEP_10; + + /* correct */ + ao_k_height += (int32_t) AO_K0_10 * err; + ao_k_speed += (int32_t) AO_K1_10 * err; + ao_k_accel += (int32_t) AO_K2_10 * err; + return; + } +#endif + ao_k_height += ((ao_k_speed >> 16) * AO_K_STEP_100 + + (ao_k_accel >> 16) * AO_K_STEP_2_2_100); + ao_k_speed += (ao_k_accel >> 16) * AO_K_STEP_100; + + /* correct */ + ao_k_height += (int32_t) AO_K0_100 * err; + ao_k_speed += (int32_t) AO_K1_100 * err; + ao_k_accel += (int32_t) AO_K2_100 * err; +} +#endif + __xdata int32_t ao_raw_pres_sum; /* Landing is detected by getting constant readings from both pressure and accelerometer @@ -296,6 +356,10 @@ ao_flight(void) ao_flight_vel += (int32_t) ao_vel_change * (int32_t) ticks; #endif +#if USE_KALMAN + if (ao_flight_state > ao_flight_idle) + ao_kalman_baro(); +#endif ao_flight_adc = ao_adc_ring_next(ao_flight_adc); } @@ -333,6 +397,9 @@ ao_flight(void) ao_ground_pres = ao_raw_pres_sum >> 9; ao_min_pres = ao_ground_pres; ao_config_get(); +#if USE_KALMAN + ao_ground_height = ao_pres_to_altitude(ao_ground_pres); +#endif ao_main_pres = ao_altitude_to_pres(ao_pres_to_altitude(ao_ground_pres) + ao_config.main_deploy); #if HAS_ACCEL ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; @@ -369,7 +436,6 @@ ao_flight(void) { /* Set pad mode - we can fly! */ ao_flight_state = ao_flight_pad; - #if HAS_USB /* Disable the USB controller in flight mode * to save power @@ -421,14 +487,20 @@ ao_flight(void) * the barometer, but we use both to make sure this * transition is detected */ +#if USE_KALMAN + if ((ao_k_accel > to_fix32(20) && + ao_k_speed > to_fix32(5)) || + ao_k_height > to_fix32(20)) +#else if ( #if HAS_ACCEL (ao_flight_accel < ao_ground_accel - ACCEL_BOOST && ao_flight_vel > ACCEL_VEL_BOOST) || #endif ao_flight_pres < ao_ground_pres - BARO_LAUNCH) +#endif { -#if HAS_ACCEL +#if HAS_ACCEL || USE_KALMAN ao_flight_state = ao_flight_boost; #else ao_flight_state = ao_flight_coast; @@ -454,7 +526,7 @@ ao_flight(void) break; } break; -#if HAS_ACCEL +#if HAS_ACCEL || USE_KALMAN case ao_flight_boost: /* boost to fast: @@ -467,8 +539,13 @@ ao_flight(void) * deceleration, or by waiting until the maximum burn duration * (15 seconds) has past. */ +#if USE_KALMAN + if ((ao_k_accel < to_fix32(-10) && ao_k_height > to_fix32(100)) || + (int16_t) (ao_flight_tick - ao_launch_tick) > BOOST_TICKS_MAX) +#else if (ao_flight_accel > ao_ground_accel + ACCEL_COAST || (int16_t) (ao_flight_tick - ao_launch_tick) > BOOST_TICKS_MAX) +#endif { ao_flight_state = ao_flight_fast; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); @@ -492,20 +569,34 @@ ao_flight(void) * how big a pressure change the mach transition * generates would be useful here. */ +#if USE_KALMAN + if (ao_k_speed < to_fix32(200) || + ao_k_height < ao_k_max_height - to_fix32(500)) +#else if (ao_flight_vel < ACCEL_VEL_MACH || ao_flight_pres > ao_min_pres + BARO_COAST) +#endif { +#if HAS_ACCEL /* set min velocity to current velocity for * apogee detect */ ao_min_vel = abs(ao_flight_vel); +#endif ao_flight_state = ao_flight_coast; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } break; -#endif +#endif /* HAS_ACCEL */ case ao_flight_coast: +#if USE_KALMAN + /* apogee detect: coast to drogue deploy: + * + * speed: < 0 + */ + if (ao_k_speed < 0) +#else /* apogee detect: coast to drogue deploy: * * barometer: fall at least 10m @@ -517,6 +608,7 @@ ao_flight(void) * we'll trust to a single sensor for this test */ if (ao_flight_pres > ao_min_pres + BARO_APOGEE) +#endif { /* ignite the drogue charge */ ao_ignite(ao_igniter_drogue); @@ -569,7 +661,11 @@ ao_flight(void) * at that point. Perhaps also use the drogue sense lines * to notice continutity? */ +#if USE_KALMAN + if (from_fix(ao_k_height) < ao_config.main_deploy) +#else if (ao_flight_pres >= ao_main_pres) +#endif { ao_ignite(ao_igniter_main); ao_flight_state = ao_flight_main; diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index a635803f..16167644 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -21,6 +21,7 @@ #include #include #include +#include #define AO_HERTZ 100 @@ -62,6 +63,7 @@ enum ao_flight_state { struct ao_adc ao_adc_ring[AO_ADC_RING]; uint8_t ao_adc_head; +int ao_summary = 0; #define ao_led_on(l) #define ao_led_off(l) @@ -79,10 +81,13 @@ enum ao_igniter { ao_igniter_main = 1 }; +struct ao_adc ao_adc_static; + void ao_ignite(enum ao_igniter igniter) { - printf ("ignite %s\n", igniter == ao_igniter_drogue ? "drogue" : "main"); + printf ("ignite %s at %7.2f\n", igniter == ao_igniter_drogue ? "drogue" : "main", + (double) ao_adc_static.tick / 100.0); } struct ao_task { @@ -99,8 +104,6 @@ struct ao_task { #define AO_FLIGHT_TEST -struct ao_adc ao_adc_static; - FILE *emulator_in; void @@ -140,20 +143,37 @@ struct ao_config ao_config; #ifndef HAS_ACCEL #define HAS_ACCEL 1 #define HAS_ACCEL_REF 0 +#define USE_KALMAN 0 +#else +#define USE_KALMAN 1 #endif #include "ao_flight.c" +#define to_double(f) ((f) / 65536.0) + void ao_insert(void) { ao_adc_ring[ao_adc_head] = ao_adc_static; ao_adc_head = ao_adc_ring_next(ao_adc_head); + if (ao_summary) + return; if (ao_flight_state != ao_flight_startup) { +#if USE_KALMAN + printf("time %7.2f accel %d pres %d k_height %8.2f k_speed %8.5f k_accel %8.5f\n", + (double) ao_adc_static.tick / 100, + ao_adc_static.accel, + ao_adc_static.pres, + to_double(ao_k_height), + to_double(ao_k_speed), + to_double(ao_k_accel)); +#else printf("time %g accel %d pres %d\n", (double) ao_adc_static.tick / 100, ao_adc_static.accel, ao_adc_static.pres); +#endif } } @@ -269,6 +289,8 @@ ao_dump_state(void) { if (ao_flight_state == ao_flight_startup) return; + if (ao_summary) + return; #if HAS_ACCEL printf ("\t\t\t\t\t%s accel %g vel %g alt %d main %d\n", ao_state_names[ao_flight_state], @@ -286,14 +308,44 @@ ao_dump_state(void) exit(0); } +static const struct option options[] = { + { .name = "summary", .has_arg = 0, .val = 's' }, + { 0, 0, 0, 0}, +}; + +void run_flight_fixed(char *name, FILE *f, int summary) +{ + emulator_in = f; + ao_summary = summary; + ao_flight_init(); + ao_flight(); +} + int main (int argc, char **argv) { - emulator_in = fopen (argv[1], "r"); - if (!emulator_in) { - perror(argv[1]); - exit(1); + int summary = 0; + int c; + int i; + + while ((c = getopt_long(argc, argv, "s", options, NULL)) != -1) { + switch (c) { + case 's': + summary = 1; + break; + } } - ao_flight_init(); - ao_flight(); + + if (optind == argc) + run_flight_fixed("", stdin, summary); + else + for (i = optind; i < argc; i++) { + FILE *f = fopen(argv[i], "r"); + if (!f) { + perror(argv[i]); + continue; + } + run_flight_fixed(argv[i], f, summary); + fclose(f); + } } diff --git a/src/ao_pins.h b/src/ao_pins.h index 0de39970..353b5fd5 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -27,6 +27,7 @@ #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_DBG 1 + #define USE_KALMAN 0 #define DBG_ON_P1 1 #define DBG_ON_P0 0 #define IGNITE_ON_P2 1 @@ -50,6 +51,7 @@ #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_DBG 1 + #define USE_KALMAN 0 #define DBG_ON_P1 1 #define DBG_ON_P0 0 #define IGNITE_ON_P2 1 @@ -98,6 +100,7 @@ #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_DBG 0 + #define USE_KALMAN 1 #define IGNITE_ON_P2 0 #define IGNITE_ON_P0 1 #define PACKET_HAS_MASTER 0 @@ -118,6 +121,7 @@ #define HAS_SERIAL_1 1 #define HAS_ADC 1 #define HAS_DBG 0 + #define USE_KALMAN 0 #define HAS_EEPROM 1 #define DBG_ON_P1 0 #define DBG_ON_P0 1 -- cgit v1.2.3 From 32c51840c792a737019fbc9fe42f2ca073b71827 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 Mar 2011 19:49:46 -0700 Subject: altos: Tiny logging fixes. Scan at start, stop when land or full. Initialize the flight log for tiny systems by scanning the log area to find the current flight number and log area bounds. Stop logging data when the flight is over, or when the log area is full. Signed-off-by: Keith Packard --- src/ao_log_tiny.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/ao_log_tiny.c b/src/ao_log_tiny.c index 877c1033..157073d4 100644 --- a/src/ao_log_tiny.c +++ b/src/ao_log_tiny.c @@ -18,7 +18,6 @@ #include "ao.h" static __data uint16_t ao_log_tiny_interval; -static __data uint32_t ao_log_tiny_pos; #define AO_LOG_TINY_INTERVAL_ASCENT AO_MS_TO_TICKS(100) #define AO_LOG_TINY_INTERVAL_DEFAULT AO_MS_TO_TICKS(1000) @@ -31,11 +30,16 @@ ao_log_tiny_set_interval(uint16_t ticks) static __xdata uint16_t ao_log_tiny_data_temp; -#define ao_log_tiny_data(d) do { \ - ao_log_tiny_data_temp = (d); \ - ao_storage_write(ao_log_tiny_pos, &ao_log_tiny_data_temp, 2); \ - ao_log_tiny_pos += 2; \ - } while (0) +static void ao_log_tiny_data(uint16_t d) +{ + if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_stop(); + if (ao_log_running) { + ao_log_tiny_data_temp = (d); + ao_storage_write(ao_log_current_pos, &ao_log_tiny_data_temp, 2); + ao_log_current_pos += 2; + } +} void ao_log(void) @@ -46,6 +50,8 @@ ao_log(void) ao_storage_setup(); + ao_log_scan(); + ao_log_tiny_state = ao_flight_invalid; ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT; while (!ao_log_running) @@ -60,12 +66,17 @@ ao_log(void) ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT; if (ao_log_tiny_state <= ao_flight_coast) ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; + if (ao_log_tiny_state == ao_flight_landed) + ao_log_stop(); } ao_log_tiny_data(ao_flight_pres); // XXX change to alt time += ao_log_tiny_interval; delay = time - ao_time(); if (delay > 0) ao_delay(delay); + /* Stop logging when told to */ + while (!ao_log_running) + ao_sleep(&ao_log_running); } } -- cgit v1.2.3 From cbb968f5cf03625d453d84dc535758072a2c04c7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 Mar 2011 20:07:25 -0700 Subject: altos: Add TeleNano support This just uses the TeleMini bits, which should work fine for now. Signed-off-by: Keith Packard --- src/Makefile | 2 +- src/Makefile.proto | 31 +++++++++++++++++++++++++++++++ src/ao_adc.c | 30 ++++++++++++++++++++++++++++++ src/ao_pins.h | 22 ++++++++++++++++++++++ src/telenano-v0.1/.gitignore | 2 ++ src/telenano-v0.1/.sdcdbrc | 1 + src/telenano-v0.1/Makefile | 1 + src/telenano-v0.1/Makefile.defs | 9 +++++++++ 8 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 src/telenano-v0.1/.gitignore create mode 100644 src/telenano-v0.1/.sdcdbrc create mode 100644 src/telenano-v0.1/Makefile create mode 100644 src/telenano-v0.1/Makefile.defs (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 42383f88..a5dec57b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -9,7 +9,7 @@ include Version SUBDIRS=\ telemetrum-v1.1 telemetrum-v1.0 \ teledongle-v0.2 teledongle-v0.1 \ - telemini-v0.1 \ + telemini-v0.1 telenano-v0.1 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ tidongle test diff --git a/src/Makefile.proto b/src/Makefile.proto index 30e626ad..df514cfe 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -190,6 +190,37 @@ TMINI_BASE_SRC = \ $(TMINI_TASK_SRC) \ $(TMINI_MAIN_SRC) +# +# Sources for TeleNano +TNANO_DRIVER_SRC = \ + ao_adc.c \ + ao_ignite.c \ + ao_config.c \ + ao_storage.c \ + ao_intflash.c + +TNANO_TASK_SRC = \ + ao_flight.c \ + ao_log.c \ + ao_log_tiny.c \ + ao_report.c \ + ao_telemetry.c + +TNANO_MAIN_SRC = \ + ao_telemini.c + +TNANO_BASE_SRC = \ + $(ALTOS_SRC) \ + $(ALTOS_DRIVER_SRC) \ + $(TELE_DRIVER_SRC) \ + $(TELE_COMMON_SRC) \ + $(TNANO_DRIVER_SRC) \ + $(TNANO_TASK_SRC) \ + $(TNANO_MAIN_SRC) + +# +# TI Dongle sources +# TI_MAIN_SRC = \ ao_tidongle.c diff --git a/src/ao_adc.c b/src/ao_adc.c index ce935716..d77e7753 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -30,7 +30,11 @@ ao_adc_poll(void) #if HAS_ACCEL_REF ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 2; #else +# ifdef TELENANO_V_0_1 + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 1; +# else ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 0; +# endif #endif } @@ -62,6 +66,7 @@ ao_adc_isr(void) __interrupt 1 a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].accel + sequence); sequence++; } +#define GOT_ADC a[0] = ADCL; a[1] = ADCH; if (sequence < 6) { @@ -79,6 +84,7 @@ ao_adc_isr(void) __interrupt 1 #if IGNITE_ON_P0 /* TeleMini readings */ a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].pres); +#ifdef TELEMINI_V_0_1 switch (sequence) { case 0: /* pressure */ @@ -105,12 +111,36 @@ ao_adc_isr(void) __interrupt 1 sequence = 0; break; } +#define GOT_ADC +#endif +#ifdef TELENANO_V_0_1 + switch (sequence) { + case 1: + /* pressure */ + a += 0; + sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 3; + break; + case 3: + /* battery */ + a += 4; + sequence = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP; + break; + case ADCCON3_ECH_TEMP: + a += 2; + sequence = 0; + break; + } +#define GOT_ADC +#endif a[0] = ADCL; a[1] = ADCH; if (sequence) { /* Start next conversion */ ADCCON3 = sequence; } +#endif +#ifndef GOT_ADC +#error No known ADC configuration set #endif else { diff --git a/src/ao_pins.h b/src/ao_pins.h index 353b5fd5..b4f177bf 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -113,6 +113,28 @@ #define HAS_ACCEL 0 #endif +#if defined(TELENANO_V_0_1) + #define HAS_FLIGHT 1 + #define HAS_USB 0 + #define HAS_BEEP 0 + #define HAS_GPS 0 + #define HAS_SERIAL_1 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define HAS_DBG 0 + #define USE_KALMAN 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 1 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define AO_LED_GREEN 1 + #define AO_LED_RED 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL 0 +#endif + #if defined(TELEMETRUM_V_0_1) #define HAS_FLIGHT 1 #define HAS_USB 1 diff --git a/src/telenano-v0.1/.gitignore b/src/telenano-v0.1/.gitignore new file mode 100644 index 00000000..0412f7df --- /dev/null +++ b/src/telenano-v0.1/.gitignore @@ -0,0 +1,2 @@ +telenano-* +ao_product.h diff --git a/src/telenano-v0.1/.sdcdbrc b/src/telenano-v0.1/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telenano-v0.1/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telenano-v0.1/Makefile b/src/telenano-v0.1/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telenano-v0.1/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/telenano-v0.1/Makefile.defs b/src/telenano-v0.1/Makefile.defs new file mode 100644 index 00000000..34cf69d1 --- /dev/null +++ b/src/telenano-v0.1/Makefile.defs @@ -0,0 +1,9 @@ +PROG = telenano-v0.1-$(VERSION).ihx + +SRC = \ + $(TNANO_BASE_SRC) + +PRODUCT=TeleNano-v0.1 +PRODUCT_DEF=-DTELENANO_V_0_1 +IDPRODUCT=0x000a +CODESIZE=0x6700 -- cgit v1.2.3 From dbe915795c66995805b5f37e6eb698cf2c143e61 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 Mar 2011 20:26:12 -0700 Subject: altos: Fix mini/nano default log size to available flash space Also, remove accel cal code from boards without accel Signed-off-by: Keith Packard --- src/ao_config.c | 10 ++++++++-- src/ao_pins.h | 11 +++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao_config.c b/src/ao_config.c index c6d36247..771b21a1 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -27,7 +27,11 @@ __xdata uint8_t ao_config_mutex; #define AO_CONFIG_DEFAULT_CALLSIGN "N0CALL" #define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000 #define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 +#if USE_INTERNAL_EEPROM +#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_config +#else #define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 192 * (uint32_t) 1024) +#endif #if HAS_EEPROM static void @@ -186,6 +190,7 @@ ao_config_main_deploy_set(void) __reentrant ao_config_main_deploy_show(); } +#if HAS_ACCEL void ao_config_accel_calibrate_show(void) __reentrant { @@ -252,6 +257,7 @@ ao_config_accel_calibrate_set(void) __reentrant ao_mutex_put(&ao_config_mutex); ao_config_accel_calibrate_show(); } +#endif /* HAS_ACCEL */ void ao_config_apogee_delay_show(void) __reentrant @@ -356,10 +362,10 @@ __code struct ao_config_var ao_config_vars[] = { "r Set radio channel (freq = 434.550 + channel * .1)" }, { 'c', ao_config_callsign_set, ao_config_callsign_show, "c Set callsign broadcast in each packet (8 char max)" }, -#if HAS_ADC +#if HAS_ACCEL { 'a', ao_config_accel_calibrate_set, ao_config_accel_calibrate_show, "a <+g> <-g> Set accelerometer calibration (0 for auto)" }, -#endif /* HAS_ADC */ +#endif /* HAS_ACCEL */ { 'f', ao_config_radio_cal_set, ao_config_radio_cal_show, "f Set radio calibration value (cal = rf/(xtal/2^16))" }, #if HAS_EEPROM diff --git a/src/ao_pins.h b/src/ao_pins.h index b4f177bf..c602268b 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -26,6 +26,7 @@ #define HAS_SERIAL_1 1 #define HAS_ADC 1 #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 #define HAS_DBG 1 #define USE_KALMAN 0 #define DBG_ON_P1 1 @@ -50,6 +51,7 @@ #define HAS_SERIAL_1 1 #define HAS_ADC 1 #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 #define HAS_DBG 1 #define USE_KALMAN 0 #define DBG_ON_P1 1 @@ -99,6 +101,7 @@ #define HAS_SERIAL_1 0 #define HAS_ADC 1 #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 1 #define HAS_DBG 0 #define USE_KALMAN 1 #define IGNITE_ON_P2 0 @@ -121,6 +124,7 @@ #define HAS_SERIAL_1 0 #define HAS_ADC 1 #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 1 #define HAS_DBG 0 #define USE_KALMAN 1 #define IGNITE_ON_P2 0 @@ -145,6 +149,7 @@ #define HAS_DBG 0 #define USE_KALMAN 0 #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 #define DBG_ON_P1 0 #define DBG_ON_P0 1 #define IGNITE_ON_P2 1 @@ -270,6 +275,12 @@ #error Please define HAS_EEPROM #endif +#if HAS_EEPROM +#ifndef USE_INTERNAL_FLASH +#error Please define USE_INTERNAL_FLASH +#endif +#endif + #ifndef HAS_DBG #error Please define HAS_DBG #endif -- cgit v1.2.3 From c985bb6a19c710409629f3c095332ba7afcf5248 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 Mar 2011 20:36:59 -0700 Subject: altos/test: Add scripts to run lots of flights through the code This runs a long list of flights (there's a user-specific path pointing at the flights) and squawks if the baro and dual flight computers don't match. Signed-off-by: Keith Packard --- src/test/run-tests | 22 ++++++++++++++++ src/test/test-flights | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+) create mode 100755 src/test/run-tests create mode 100644 src/test/test-flights (limited to 'src') diff --git a/src/test/run-tests b/src/test/run-tests new file mode 100755 index 00000000..ec279776 --- /dev/null +++ b/src/test/run-tests @@ -0,0 +1,22 @@ +#!/bin/sh + +DIR=~/src/cc1111/flights + +while read flight; do + baro=`./ao_flight_test_baro -s $DIR/$flight | + awk '/drogue/ { printf "%s ", $4 } + /main/ { printf "%s\n", $4 }'` + full=`./ao_flight_test -s $DIR/$flight | + awk '/drogue/ { printf "%s ", $4 } + /main/ { printf "%s\n", $4 }'` + echo $flight $baro $full +done < test-flights | +awk '{ name = $1; + drogue_error = $2 - $4; + if (drogue_error < 0) drogue_error = -drogue_error; + main_error = $3 - $5; + if (main_error < 0) main_error = -main_error; + if (drogue_error > 4 || main_error > 4) + printf ("%s: baro drogue %f main %f. full drogue %f main %f\n", + name, $2, $3, $4, $5); + }' diff --git a/src/test/test-flights b/src/test/test-flights new file mode 100644 index 00000000..a9a2ecca --- /dev/null +++ b/src/test/test-flights @@ -0,0 +1,72 @@ +2009-06-03-serial-003-flight-002.eeprom +2009-06-05-serial-004-flight-008.eeprom +2009-06-06-serial-004-flight-009.eeprom +2009-06-14-serial-004-flight-010.eeprom +2009-06-20-serial-003-flight-003.eeprom +2009-07-04-serial-001-flight-006.eeprom +2009-07-18-serial-001-flight-007.eeprom +2009-08-22-serial-001-flight-001.eeprom +2009-08-22-serial-010-flight-001.eeprom +2009-09-05-serial-008-flight-002.eeprom +2009-09-05-serial-010-flight-002.eeprom +2009-09-05-serial-011-flight-001.eeprom +2009-09-11-serial-008-flight-003.eeprom +2009-09-12-serial-002-flight-002.eeprom +2009-09-12-serial-008-flight-005.eeprom +2009-09-12-serial-008-flight-007.eeprom +2009-09-19-serial-011-flight-002.eeprom +2009-10-03-serial-008-flight-009.eeprom +2009-10-03-serial-008-flight-010.eeprom +2009-10-03-serial-009-flight-001.eeprom +2009-10-03-serial-011-flight-003.eeprom +2009-10-17-serial-009-flight-002.eeprom +2009-11-14-serial-003-flight-005.eeprom +2009-11-14-serial-003-flight-006.eeprom +2009-11-21-serial-013-flight-001.eeprom +2009-11-21-serial-013-flight-002.eeprom +2010-02-13-serial-051-flight-002.eeprom +2010-02-13-serial-052-flight-002.eeprom +2010-02-28-serial-052-flight-003.eeprom +2010-02-28-serial-052-flight-004.eeprom +2010-03-06-serial-010-flight-004.eeprom +2010-03-06-serial-013-flight-003.eeprom +2010-03-06-serial-051-flight-003.eeprom +2010-03-06-serial-053-flight-004.eeprom +2010-05-08-serial-229-flight-002.eeprom +2010-05-28-serial-215-flight-002.eeprom +2010-05-28-serial-224-flight-001.eeprom +2010-05-29-serial-052-flight-005.eeprom +2010-05-30-serial-010-flight-005.eeprom +2010-05-30-serial-051-flight-004.eeprom +2010-05-30-serial-224-flight-003.eeprom +2010-05-30-serial-226-flight-001.eeprom +2010-05-31-serial-010-flight-006.eeprom +2010-05-31-serial-216-flight-001.eeprom +2010-05-31-serial-219-flight-001.eeprom +2010-05-31-serial-227-flight-003.eeprom +2010-06-05-serial-220-flight-001.eeprom +2010-06-26-serial-209-flight-003.eeprom +2010-06-26-serial-215-flight-004.eeprom +2010-06-26-serial-220-flight-002.eeprom +2010-06-26-serial-226-flight-002.eeprom +2010-06-27-serial-221-flight-002.eeprom +2010-07-17-serial-230-flight-001.eeprom +2010-07-18-serial-219-flight-002.eeprom +2010-08-07-serial-216-flight-003.eeprom +2010-08-07-serial-220-flight-003.eeprom +2010-08-12-serial-236-flight-001.eeprom +2010-08-21-serial-010-flight-007.eeprom +2010-08-21-serial-224-flight-004.eeprom +2010-08-21-serial-224-flight-005.eeprom +2010-08-21-serial-233-flight-002.eeprom +2010-09-03-serial-051-flight-005.eeprom +2010-09-03-serial-215-flight-005.eeprom +2010-09-24-serial-236-flight-006.eeprom +2010-09-25-serial-223-flight-001.eeprom +2010-10-17-serial-215-flight-006.eeprom +2010-10-23-serial-236-flight-008.eeprom +2011-01-30-serial-056-flight-001.eeprom +2011-01-30-serial-250-flight-002.eeprom +2011-02-19-serial-215-flight-007.eeprom +2011-02-19-serial-216-flight-006.eeprom +2011-02-19-serial-286-flight-001.eeprom -- cgit v1.2.3 From 7a4f6d5ad55637cde97a1e2f247f92df59bc2e14 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 Mar 2011 21:01:15 -0700 Subject: altos: Write height values to log for nano/mini This is a lot more useful than the old filtered pressure data. Signed-off-by: Keith Packard --- src/ao.h | 7 +++++++ src/ao_log_tiny.c | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index fd8c6034..63f80678 100644 --- a/src/ao.h +++ b/src/ao.h @@ -706,6 +706,13 @@ extern __pdata int16_t ao_ground_accel; extern __pdata int16_t ao_min_pres; extern __pdata uint16_t ao_launch_time; extern __xdata uint8_t ao_flight_force_idle; +#ifdef USE_KALMAN +extern __pdata int16_t ao_ground_height; +extern __pdata int32_t ao_k_max_height; +extern __pdata int32_t ao_k_height; +extern __pdata int32_t ao_k_speed; +extern __pdata int32_t ao_k_accel; +#endif /* Flight thread */ void diff --git a/src/ao_log_tiny.c b/src/ao_log_tiny.c index 157073d4..fad2a242 100644 --- a/src/ao_log_tiny.c +++ b/src/ao_log_tiny.c @@ -69,7 +69,7 @@ ao_log(void) if (ao_log_tiny_state == ao_flight_landed) ao_log_stop(); } - ao_log_tiny_data(ao_flight_pres); // XXX change to alt + ao_log_tiny_data(ao_k_height >> 16); time += ao_log_tiny_interval; delay = time - ao_time(); if (delay > 0) -- cgit v1.2.3 From 1aeb759c48f475ffaaae787515e080440c8386c3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Mar 2011 12:28:08 -0700 Subject: altos: Baro-only boards must not detect launch on accel or speed data The baro sensor generates too much noise to use small changes in computed speed or acceleration to cause a false launch detect. Signed-off-by: Keith Packard --- src/ao_flight.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index e8130baa..71dd4891 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -488,9 +488,20 @@ ao_flight(void) * transition is detected */ #if USE_KALMAN +#if HAS_ACCEL + /* + * With an accelerometer, either to detect launch + */ if ((ao_k_accel > to_fix32(20) && ao_k_speed > to_fix32(5)) || ao_k_height > to_fix32(20)) +#else + /* + * Without an accelerometer, the barometer is far too + * noisy to rely on speed or acceleration data + */ + if (ao_k_height > to_fix32(20)) +#endif #else if ( #if HAS_ACCEL -- cgit v1.2.3 From 5c28b9312d90a3a66016abc641c20bcd852d69f8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Mar 2011 23:27:15 -0700 Subject: altos: Don't init packet slave on TD. Make slave start optional Oops. TeleDongle was starting the packet slave code, which kinda wrecked its ability to receive telemetry packets. This patch simply removes the packet slave code from teledongle as it cannot be used (yet), it also makes the packet slave code initialization take a parameter which controls whether to start that by default; in the future, perhaps TeleDongle will gain a command to start packet slave mode. Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_packet_slave.c | 5 +++-- src/ao_teledongle.c | 1 - src/ao_telemetrum.c | 2 +- src/ao_telemini.c | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 63f80678..00c395d6 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1197,6 +1197,6 @@ void ao_packet_slave_stop(void); void -ao_packet_slave_init(void); +ao_packet_slave_init(uint8_t enable); #endif /* _AO_H_ */ diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index eb456dab..e40ddfec 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -58,10 +58,11 @@ ao_packet_slave_stop(void) } void -ao_packet_slave_init(void) +ao_packet_slave_init(uint8_t enable) { ao_add_stdio(ao_packet_pollchar, ao_packet_putchar, NULL); - ao_packet_slave_start(); + if (enable) + ao_packet_slave_start(); } diff --git a/src/ao_teledongle.c b/src/ao_teledongle.c index 505dc0cb..008b200a 100644 --- a/src/ao_teledongle.c +++ b/src/ao_teledongle.c @@ -31,7 +31,6 @@ main(void) ao_monitor_init(AO_LED_GREEN, TRUE); ao_rssi_init(AO_LED_RED); ao_radio_init(); - ao_packet_slave_init(); ao_packet_master_init(); #if HAS_DBG ao_dbg_init(); diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index ed43c447..4ace415c 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -59,7 +59,7 @@ main(void) ao_gps_report_init(); ao_telemetry_init(); ao_radio_init(); - ao_packet_slave_init(); + ao_packet_slave_init(TRUE); ao_igniter_init(); #if HAS_DBG ao_dbg_init(); diff --git a/src/ao_telemini.c b/src/ao_telemini.c index 97bc2cf4..dbc3b74c 100644 --- a/src/ao_telemini.c +++ b/src/ao_telemini.c @@ -42,9 +42,9 @@ main(void) ao_flight_init(); ao_log_init(); ao_report_init(); - ao_telemetry_init(); + ao_telemetry_tiny_init(); ao_radio_init(); - ao_packet_slave_init(); + ao_packet_slave_init(TRUE); ao_igniter_init(); ao_config_init(); ao_start_scheduler(); -- cgit v1.2.3 From 3f0bc801fd08a613c681504f0d1f9374486a2487 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Mar 2011 23:31:20 -0700 Subject: altos: Configure packet size from send/recv parameters. Instead of setting the packet size at configuration time, use the provided packet size to the send/recv functions to configure the radio. This eliminates many configuration calls, leaving us with 'RDF' mode and 'packet' mode, the latter working for telemetry and the bi-directional link. Signed-off-by: Keith Packard --- src/ao.h | 10 ++-------- src/ao_packet_master.c | 2 -- src/ao_packet_slave.c | 4 ---- src/ao_radio.c | 29 ++++++++++++++--------------- 4 files changed, 16 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 00c395d6..e076831d 100644 --- a/src/ao.h +++ b/src/ao.h @@ -962,18 +962,12 @@ void ao_radio_general_isr(void) __interrupt 16; void -ao_radio_get(void); +ao_radio_get(uint8_t len); #define ao_radio_put() ao_mutex_put(&ao_radio_mutex) void -ao_radio_set_fixed_pkt(size_t size); - -#define ao_radio_set_telemetry() \ - ao_radio_set_fixed_pkt(sizeof (struct ao_telemetry)) - -#define ao_radio_set_packet() \ - ao_radio_set_fixed_pkt(sizeof (struct ao_packet)) +ao_radio_set_packet(void); void ao_radio_send(__xdata void *data, uint8_t size) __reentrant; diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index 5c4ab0dd..069bc5df 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -75,7 +75,6 @@ void ao_packet_master(void) { ao_config_get(); - ao_radio_set_packet(); ao_tx_packet.addr = ao_serial_number; ao_tx_packet.len = AO_PACKET_SYN; ao_packet_master_time = ao_time(); @@ -99,7 +98,6 @@ ao_packet_master(void) ao_packet_master_sleeping = 0; } } - ao_radio_set_telemetry(); ao_exit(); } diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index e40ddfec..9f14052a 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -20,7 +20,6 @@ void ao_packet_slave(void) { - ao_radio_set_packet(); ao_tx_packet.addr = ao_serial_number; ao_tx_packet.len = AO_PACKET_SYN; while (ao_packet_enable) { @@ -51,9 +50,6 @@ ao_packet_slave_stop(void) ao_radio_recv_abort(); ao_delay(AO_MS_TO_TICKS(10)); } - ao_radio_get(); - ao_radio_set_telemetry(); - ao_radio_put(); } } diff --git a/src/ao_radio.c b/src/ao_radio.c index d7c00213..b5a67b99 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -264,12 +264,11 @@ ao_radio_general_isr(void) __interrupt 16 } void -ao_radio_set_fixed_pkt(size_t size) +ao_radio_set_packet(void) { uint8_t i; for (i = 0; i < sizeof (fixed_pkt_setup); i += 2) RF[fixed_pkt_setup[i]] = fixed_pkt_setup[i+1]; - RF[RF_PKTLEN_OFF] = size; } void @@ -285,7 +284,7 @@ ao_radio_idle(void) } void -ao_radio_get(void) +ao_radio_get(uint8_t len) { ao_config_get(); ao_mutex_get(&ao_radio_mutex); @@ -294,13 +293,14 @@ ao_radio_get(void) RF_FREQ2 = (uint8_t) (ao_config.radio_cal >> 16); RF_FREQ1 = (uint8_t) (ao_config.radio_cal >> 8); RF_FREQ0 = (uint8_t) (ao_config.radio_cal); + RF_PKTLEN = len; } void ao_radio_send(__xdata void *packet, uint8_t size) __reentrant { - ao_radio_get(); + ao_radio_get(size); ao_radio_done = 0; ao_dma_set_transfer(ao_radio_dma, packet, @@ -323,7 +323,7 @@ uint8_t ao_radio_recv(__xdata void *packet, uint8_t size) __reentrant { ao_radio_abort = 0; - ao_radio_get(); + ao_radio_get(size - 2); ao_dma_set_transfer(ao_radio_dma, &RFDXADDR, packet, @@ -375,12 +375,6 @@ ao_radio_rdf(int ms) uint8_t i; uint8_t pkt_len; - ao_radio_abort = 0; - ao_radio_get(); - ao_radio_done = 0; - for (i = 0; i < sizeof (rdf_setup); i += 2) - RF[rdf_setup[i]] = rdf_setup[i+1]; - /* * Compute the packet length as follows: * @@ -391,7 +385,12 @@ ao_radio_rdf(int ms) if (ms > (255 * 4)) ms = 255 * 4; pkt_len = ms >> 2; - RF[RF_PKTLEN_OFF] = pkt_len; + + ao_radio_abort = 0; + ao_radio_get(pkt_len); + ao_radio_done = 0; + for (i = 0; i < sizeof (rdf_setup); i += 2) + RF[rdf_setup[i]] = rdf_setup[i+1]; ao_dma_set_transfer(ao_radio_dma, &ao_radio_rdf_value, @@ -411,7 +410,7 @@ ao_radio_rdf(int ms) ao_dma_abort(ao_radio_dma); ao_radio_idle(); } - ao_radio_set_telemetry(); + ao_radio_set_packet(); ao_radio_put(); } @@ -438,7 +437,7 @@ ao_radio_test(void) if ((mode & 2) && !radio_on) { ao_set_monitor(0); ao_packet_slave_stop(); - ao_radio_get(); + ao_radio_get(0xff); RFST = RFST_STX; radio_on = 1; } @@ -465,7 +464,7 @@ 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_set_telemetry(); + ao_radio_set_packet(); ao_radio_dma_done = 1; ao_radio_dma = ao_dma_alloc(&ao_radio_dma_done); RFIF = 0; -- cgit v1.2.3 From 5ba75e95c98d3e441a58d6f75d328d579e1997fe Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Mar 2011 23:41:44 -0700 Subject: altos: Make telemetry interval more consistent Instead of using a delay between telemetry packets, use a telemetry period and compute an appropriate delay each time. This requires changing the ascent telemetry from a 50ms delay to a 100ms interval, to provide a regular 10 packets-per-second rate. Before, we counted on the telemetry packet taking about 50ms to send so that we would receive about 10 per second. This also eliminates delays during descent for RDF tones -- those will get transmitted in the interval between telemetry packets without interrupting the spacing of those packets. Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_telemetry.c | 48 ++++++++++++++++++++++++++++-------------------- 2 files changed, 29 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index e076831d..075ec63a 100644 --- a/src/ao.h +++ b/src/ao.h @@ -937,7 +937,7 @@ struct ao_telemetry_recv { /* Set delay between telemetry reports (0 to disable) */ #define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(1000) -#define AO_TELEMETRY_INTERVAL_FLIGHT AO_MS_TO_TICKS(50) +#define AO_TELEMETRY_INTERVAL_FLIGHT AO_MS_TO_TICKS(100) #define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(1000) void diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index dd79f3fc..6556ce32 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -27,6 +27,8 @@ __xdata uint16_t ao_rdf_time; void ao_telemetry(void) { + uint16_t time; + int16_t delay; static __xdata struct ao_telemetry telemetry; ao_config_get(); @@ -37,35 +39,41 @@ ao_telemetry(void) telemetry.flight = ao_log_full() ? 0 : ao_flight_number; telemetry.accel_plus_g = ao_config.accel_plus_g; telemetry.accel_minus_g = ao_config.accel_minus_g; - ao_rdf_time = ao_time(); for (;;) { while (ao_telemetry_interval == 0) ao_sleep(&ao_telemetry_interval); - telemetry.flight_state = ao_flight_state; + time = ao_rdf_time = ao_time(); + while (ao_telemetry_interval) { + telemetry.flight_state = ao_flight_state; #if HAS_ACCEL - telemetry.flight_accel = ao_flight_accel; - telemetry.ground_accel = ao_ground_accel; - telemetry.flight_vel = ao_flight_vel; + telemetry.flight_accel = ao_flight_accel; + telemetry.ground_accel = ao_ground_accel; + telemetry.flight_vel = ao_flight_vel; #endif - telemetry.flight_pres = ao_flight_pres; - telemetry.ground_pres = ao_ground_pres; + telemetry.flight_pres = ao_flight_pres; + telemetry.ground_pres = ao_ground_pres; #if HAS_ADC - ao_adc_get(&telemetry.adc); + ao_adc_get(&telemetry.adc); #endif #if HAS_GPS - ao_mutex_get(&ao_gps_mutex); - memcpy(&telemetry.gps, &ao_gps_data, sizeof (struct ao_gps_data)); - memcpy(&telemetry.gps_tracking, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data)); - ao_mutex_put(&ao_gps_mutex); + ao_mutex_get(&ao_gps_mutex); + memcpy(&telemetry.gps, &ao_gps_data, sizeof (struct ao_gps_data)); + memcpy(&telemetry.gps_tracking, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data)); + ao_mutex_put(&ao_gps_mutex); #endif - ao_radio_send(&telemetry, sizeof (telemetry)); - ao_delay(ao_telemetry_interval); - if (ao_rdf && - (int16_t) (ao_time() - ao_rdf_time) >= 0) - { - ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; - ao_radio_rdf(AO_RDF_LENGTH_MS); - ao_delay(ao_telemetry_interval); + ao_radio_send(&telemetry, sizeof (telemetry)); + if (ao_rdf && + (int16_t) (ao_time() - ao_rdf_time) >= 0) + { + ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; + ao_radio_rdf(AO_RDF_LENGTH_MS); + } + time += ao_telemetry_interval; + delay = time - ao_time(); + if (delay > 0) + ao_delay(delay); + else + time = ao_time(); } } } -- cgit v1.2.3 From 8950df02382f5f0aea5bac078fdf7134b98c43ed Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Mar 2011 23:46:18 -0700 Subject: altos: Split out tiny telemetry from full telemetry The TeleMini and TeleNano boards do not have either GPS or accelermeters, and they also run the kalman filter which produces standard unit measurements for the flight height/speed/accel values. This makes the telemetry significantly different. ao_telemetry_tiny.c sends the required data. Note that TeleNano sends the same telemetry as telemini at this point; there are a couple of values which are not useful, but the overhead of sending them is small enough that the hassle of having three telemetry formats seemed excessive. Signed-off-by: Keith Packard --- src/Makefile.proto | 4 +-- src/ao.h | 21 ++++++++++++ src/ao_telemetry_tiny.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 src/ao_telemetry_tiny.c (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index df514cfe..eabd17b9 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -176,7 +176,7 @@ TMINI_TASK_SRC = \ ao_log.c \ ao_log_tiny.c \ ao_report.c \ - ao_telemetry.c + ao_telemetry_tiny.c TMINI_MAIN_SRC = \ ao_telemini.c @@ -204,7 +204,7 @@ TNANO_TASK_SRC = \ ao_log.c \ ao_log_tiny.c \ ao_report.c \ - ao_telemetry.c + ao_telemetry_tiny.c TNANO_MAIN_SRC = \ ao_telemini.c diff --git a/src/ao.h b/src/ao.h index 075ec63a..0ba98dbd 100644 --- a/src/ao.h +++ b/src/ao.h @@ -925,6 +925,18 @@ struct ao_telemetry { struct ao_gps_tracking_data gps_tracking; }; +struct ao_telemetry_tiny { + uint16_t serial; + uint16_t flight; + uint8_t flight_state; + int16_t height; /* AGL in meters */ + int16_t speed; /* in m/s * 16 */ + int16_t accel; /* in m/s² * 16 */ + int16_t ground_pres; /* sensor units */ + struct ao_adc adc; /* raw ADC readings */ + char callsign[AO_MAX_CALLSIGN]; +}; + /* * ao_radio_recv tacks on rssi and status bytes */ @@ -934,6 +946,12 @@ struct ao_telemetry_recv { uint8_t status; }; +struct ao_telemetry_tiny_recv { + struct ao_telemetry_tiny telemetry_tiny; + int8_t rssi; + uint8_t status; +}; + /* Set delay between telemetry reports (0 to disable) */ #define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(1000) @@ -949,6 +967,9 @@ ao_rdf_set(uint8_t rdf); void ao_telemetry_init(void); +void +ao_telemetry_tiny_init(void); + /* * ao_radio.c */ diff --git a/src/ao_telemetry_tiny.c b/src/ao_telemetry_tiny.c new file mode 100644 index 00000000..83ba7fc0 --- /dev/null +++ b/src/ao_telemetry_tiny.c @@ -0,0 +1,91 @@ +/* + * 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" + +__xdata uint8_t ao_rdf = 0; +__xdata uint16_t ao_rdf_time; +__xdata uint16_t ao_telemetry_tiny_interval = 0; + +#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) +#define AO_RDF_LENGTH_MS 500 + +void +ao_telemetry_tiny(void) +{ + uint16_t time; + int16_t delay; + static __xdata struct ao_telemetry_tiny telemetry_tiny; + + ao_config_get(); + while (!ao_flight_number) + ao_sleep(&ao_flight_number); + memcpy(telemetry_tiny.callsign, ao_config.callsign, AO_MAX_CALLSIGN); + telemetry_tiny.serial = ao_serial_number; + telemetry_tiny.flight = ao_log_full() ? 0 : ao_flight_number; + for (;;) { + while (ao_telemetry_tiny_interval == 0) + ao_sleep(&ao_telemetry_tiny_interval); + time = ao_rdf_time = ao_time(); + while (ao_telemetry_tiny_interval) { + telemetry_tiny.flight_state = ao_flight_state; + telemetry_tiny.height = ao_k_height >> 16; + telemetry_tiny.speed = ao_k_speed >> 12; + telemetry_tiny.accel = ao_k_accel >> 12; + telemetry_tiny.ground_pres = ao_ground_pres; + ao_adc_get(&telemetry_tiny.adc); + ao_radio_send(&telemetry_tiny, sizeof (telemetry_tiny)); + if (ao_rdf && + (int16_t) (ao_time() - ao_rdf_time) >= 0) + { + ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; + ao_radio_rdf(AO_RDF_LENGTH_MS); + } + time += ao_telemetry_tiny_interval; + delay = time - ao_time(); + if (delay > 0) + ao_delay(delay); + else + time = ao_time(); + } + } +} + +void +ao_telemetry_set_interval(uint16_t interval) +{ + ao_telemetry_tiny_interval = interval; + ao_wakeup(&ao_telemetry_tiny_interval); +} + +void +ao_rdf_set(uint8_t rdf) +{ + ao_rdf = rdf; + if (rdf == 0) + ao_radio_rdf_abort(); + else + ao_rdf_time = ao_time(); +} + +__xdata struct ao_task ao_telemetry_tiny_task; + +void +ao_telemetry_tiny_init() +{ + ao_add_task(&ao_telemetry_tiny_task, ao_telemetry_tiny, "telemetry_tiny"); +} -- cgit v1.2.3 From 31feb7777f73fed61193d3404f457ea1a081fe9c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Mar 2011 23:49:41 -0700 Subject: altos: Split telenano main from telemini Eventually, telenano will run different code; prepare for this by creating a telenano-specific main routine. Signed-off-by: Keith Packard --- src/Makefile.proto | 2 +- src/ao_telenano.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 src/ao_telenano.c (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index eabd17b9..68fa4654 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -207,7 +207,7 @@ TNANO_TASK_SRC = \ ao_telemetry_tiny.c TNANO_MAIN_SRC = \ - ao_telemini.c + ao_telenano.c TNANO_BASE_SRC = \ $(ALTOS_SRC) \ diff --git a/src/ao_telenano.c b/src/ao_telenano.c new file mode 100644 index 00000000..dbc3b74c --- /dev/null +++ b/src/ao_telenano.c @@ -0,0 +1,51 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +/* stub so as telemini doesn't have monitor mode */ +void +ao_set_monitor(uint8_t monitoring) +{ + (void) monitoring; +} + +void +main(void) +{ + ao_clock_init(); + + + /* Turn on the red LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + + ao_timer_init(); + ao_adc_init(); + ao_cmd_init(); + ao_storage_init(); + ao_flight_init(); + ao_log_init(); + ao_report_init(); + ao_telemetry_tiny_init(); + ao_radio_init(); + ao_packet_slave_init(TRUE); + ao_igniter_init(); + ao_config_init(); + ao_start_scheduler(); +} -- cgit v1.2.3 From ad6bb342d237988404fa32540b38c61d6ddc1f0d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Mar 2011 23:51:02 -0700 Subject: altos: The kalman code requires a constant sample rate The kalman function can't handle a variable sample rate, so keep the ADC running at full speed for the whole flight instead of slowing it down after apogee. Signed-off-by: Keith Packard --- src/ao_flight.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index 71dd4891..493913b2 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -627,8 +627,10 @@ ao_flight(void) /* slow down the telemetry system */ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); +#if !USE_KALMAN /* slow down the ADC sample rate */ ao_timer_set_adc_interval(10); +#endif /* * Start recording min/max accel and pres for a while -- cgit v1.2.3 From be838db49d999426a9dd02c0166fe161722f1e61 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Mar 2011 23:53:08 -0700 Subject: altos: New telemetry report format (version 4). Supports tiny telemetry. This completely replaces the version 3 format with a much simpler and easier to parse scheme. It's described in detail in ao_telem.h, but the basic idea is that the whole line is split into name/value pairs, separated by whitespace. Every name is unique, and the values are either strings or integers. No extraneous formatting or units are provided. Signed-off-by: Keith Packard --- src/ao.h | 8 +- src/ao_gps_print.c | 145 +++++++++++++++------------------ src/ao_gps_sirf.c | 1 + src/ao_gps_test.c | 1 + src/ao_gps_test_skytraq.c | 1 + src/ao_monitor.c | 198 +++++++++++++++++++++++++++++++++++----------- src/ao_telem.h | 172 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 398 insertions(+), 128 deletions(-) create mode 100644 src/ao_telem.h (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 0ba98dbd..527390b0 100644 --- a/src/ao.h +++ b/src/ao.h @@ -841,6 +841,7 @@ ao_spi_init(void); #define AO_GPS_VALID (1 << 4) #define AO_GPS_RUNNING (1 << 5) #define AO_GPS_DATE_VALID (1 << 6) +#define AO_GPS_COURSE_VALID (1 << 7) extern __xdata uint16_t ao_gps_tick; @@ -905,8 +906,7 @@ ao_gps_report_init(void); * ao_telemetry.c */ -#define AO_MAX_CALLSIGN 8 -#define AO_TELEMETRY_VERSION 3 +#define AO_MAX_CALLSIGN 8 struct ao_telemetry { uint16_t serial; @@ -1020,6 +1020,10 @@ extern const char const * const ao_state_names[]; void ao_monitor(void); +#define AO_MONITORING_OFF 0 +#define AO_MONITORING_FULL 1 +#define AO_MONITORING_TINY 2 + void ao_set_monitor(uint8_t monitoring); diff --git a/src/ao_gps_print.c b/src/ao_gps_print.c index 11213174..ca071b42 100644 --- a/src/ao_gps_print.c +++ b/src/ao_gps_print.c @@ -18,86 +18,61 @@ #ifndef AO_GPS_TEST #include "ao.h" #endif - -struct ao_gps_split { - uint8_t positive; - uint8_t degrees; - uint8_t minutes; - uint16_t minutes_fraction; -}; - -static void -ao_gps_split(int32_t v, __xdata struct ao_gps_split *split) __reentrant -{ - uint32_t minutes_e7; - - split->positive = 1; - if (v < 0) { - v = -v; - split->positive = 0; - } - split->degrees = v / 10000000; - minutes_e7 = (v % 10000000) * 60; - split->minutes = minutes_e7 / 10000000; - split->minutes_fraction = (minutes_e7 % 10000000) / 1000; -} +#include "ao_telem.h" void ao_gps_print(__xdata struct ao_gps_data *gps_data) __reentrant { - printf("GPS %2d sat", + char state; + + if (gps_data->flags & AO_GPS_VALID) + state = AO_TELEM_GPS_STATE_LOCKED; + else if (gps_data->flags & AO_GPS_RUNNING) + state = AO_TELEM_GPS_STATE_UNLOCKED; + else + state = AO_TELEM_GPS_STATE_ERROR; + printf(AO_TELEM_GPS_STATE " %c " + AO_TELEM_GPS_NUM_SAT " %d ", + state, (gps_data->flags & AO_GPS_NUM_SAT_MASK) >> AO_GPS_NUM_SAT_SHIFT); - if (gps_data->flags & AO_GPS_VALID) { - static __xdata struct ao_gps_split lat, lon; - int16_t climb, climb_int, climb_frac; + if (!(gps_data->flags & AO_GPS_VALID)) + return; + printf(AO_TELEM_GPS_LATITUDE " %ld " + AO_TELEM_GPS_LONGITUDE " %ld " + AO_TELEM_GPS_ALTITUDE " %d ", + gps_data->latitude, + gps_data->longitude, + gps_data->altitude); - ao_gps_split(gps_data->latitude, &lat); - ao_gps_split(gps_data->longitude, &lon); - if (gps_data->flags & AO_GPS_DATE_VALID) - printf(" 20%02d-%02d-%02d", - gps_data->year, - gps_data->month, - gps_data->day); - else - printf (" 0000-00-00"); - printf(" %2d:%02d:%02d", - gps_data->hour, - gps_data->minute, - gps_data->second); - printf(" %2d°%02d.%04d'%c %2d°%02d.%04d'%c %5dm", - lat.degrees, - lat.minutes, - lat.minutes_fraction, - lat.positive ? 'N' : 'S', - lon.degrees, - lon.minutes, - lon.minutes_fraction, - lon.positive ? 'E' : 'W', - gps_data->altitude); - climb = gps_data->climb_rate; - if (climb >= 0) { - climb_int = climb / 100; - climb_frac = climb % 100; - } else { - climb = -climb; - climb_int = -(climb / 100); - climb_frac = climb % 100; - } - printf(" %5u.%02dm/s(H) %d° %5d.%02dm/s(V)", - gps_data->ground_speed / 100, - gps_data->ground_speed % 100, - gps_data->course * 2, - climb / 100, - climb % 100); - printf(" %d.%d(hdop) %5u(herr) %5u(verr)", - gps_data->hdop / 5, - (gps_data->hdop * 2) % 10, + if (gps_data->flags & AO_GPS_DATE_VALID) + printf(AO_TELEM_GPS_YEAR " %d " + AO_TELEM_GPS_MONTH " %d " + AO_TELEM_GPS_DAY " %d ", + gps_data->year, + gps_data->month, + gps_data->day); + + printf(AO_TELEM_GPS_HOUR " %d " + AO_TELEM_GPS_MINUTE " %d " + AO_TELEM_GPS_SECOND " %d ", + gps_data->hour, + gps_data->minute, + gps_data->second); + + printf(AO_TELEM_GPS_HDOP " %d ", + gps_data->hdop * 2); + + if (gps_data->flags & AO_GPS_COURSE_VALID) { + printf(AO_TELEM_GPS_HERROR " %d " + AO_TELEM_GPS_VERROR " %d " + AO_TELEM_GPS_VERTICAL_SPEED " %d " + AO_TELEM_GPS_HORIZONTAL_SPEED " %d " + AO_TELEM_GPS_COURSE " %d ", gps_data->h_error, - gps_data->v_error); - } else if (gps_data->flags & AO_GPS_RUNNING) { - printf(" unlocked"); - } else { - printf (" not-connected"); + gps_data->v_error, + gps_data->climb_rate, + gps_data->ground_speed, + (int) gps_data->course * 2); } } @@ -106,12 +81,11 @@ ao_gps_tracking_print(__xdata struct ao_gps_tracking_data *gps_tracking_data) __ { uint8_t c, n, v; __xdata struct ao_gps_sat_data *sat; - printf("SAT "); + n = gps_tracking_data->channels; - if (n == 0) { - printf("not-connected"); + if (n == 0) return; - } + sat = gps_tracking_data->sats; v = 0; for (c = 0; c < n; c++) { @@ -119,13 +93,20 @@ ao_gps_tracking_print(__xdata struct ao_gps_tracking_data *gps_tracking_data) __ v++; sat++; } - printf("%d ", v); + + printf (AO_TELEM_SAT_NUM " %d ", + v); + sat = gps_tracking_data->sats; + v = 0; for (c = 0; c < n; c++) { - if (sat->svid) - printf (" %3d %3d", - sat->svid, - sat->c_n_1); + if (sat->svid) { + printf (AO_TELEM_SAT_SVID "%d %d " + AO_TELEM_SAT_C_N_0 "%d %d ", + v, sat->svid, + v, sat->c_n_1); + v++; + } sat++; } } diff --git a/src/ao_gps_sirf.c b/src/ao_gps_sirf.c index a6167e6b..87b1d69c 100644 --- a/src/ao_gps_sirf.c +++ b/src/ao_gps_sirf.c @@ -405,6 +405,7 @@ ao_gps(void) __reentrant ao_gps_data.course = ao_sirf_data.course / 200; ao_gps_data.hdop = ao_sirf_data.hdop; ao_gps_data.climb_rate = ao_sirf_data.climb_rate; + ao_gps_data.flags |= AO_GPS_COURSE_VALID; if (ao_sirf_data.h_error > 6553500) ao_gps_data.h_error = 65535; else diff --git a/src/ao_gps_test.c b/src/ao_gps_test.c index edb51304..44efb50c 100644 --- a/src/ao_gps_test.c +++ b/src/ao_gps_test.c @@ -28,6 +28,7 @@ #define AO_GPS_VALID (1 << 4) #define AO_GPS_RUNNING (1 << 5) #define AO_GPS_DATE_VALID (1 << 6) +#define AO_GPS_COURSE_VALID (1 << 7) struct ao_gps_data { uint8_t year; diff --git a/src/ao_gps_test_skytraq.c b/src/ao_gps_test_skytraq.c index 4010e09c..b94e9bd2 100644 --- a/src/ao_gps_test_skytraq.c +++ b/src/ao_gps_test_skytraq.c @@ -28,6 +28,7 @@ #define AO_GPS_VALID (1 << 4) #define AO_GPS_RUNNING (1 << 5) #define AO_GPS_DATE_VALID (1 << 6) +#define AO_GPS_COURSE_VALID (1 << 7) struct ao_gps_data { uint8_t year; diff --git a/src/ao_monitor.c b/src/ao_monitor.c index 9c4be6fb..d6fd8305 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -16,6 +16,7 @@ */ #include "ao.h" +#include "ao_telem.h" __xdata uint8_t ao_monitoring; __pdata uint8_t ao_monitor_led; @@ -23,54 +24,163 @@ __pdata uint8_t ao_monitor_led; void ao_monitor(void) { - __xdata struct ao_telemetry_recv recv; __xdata char callsign[AO_MAX_CALLSIGN+1]; + __xdata union { + struct ao_telemetry_recv full; + struct ao_telemetry_tiny_recv tiny; + } u; + +#define recv (u.full) +#define recv_tiny (u.tiny) + uint8_t state; int16_t rssi; for (;;) { __critical while (!ao_monitoring) ao_sleep(&ao_monitoring); - if (!ao_radio_recv(&recv, sizeof (recv))) - continue; - state = recv.telemetry.flight_state; - - /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ - rssi = (int16_t) (recv.rssi >> 1) - 74; - memcpy(callsign, recv.telemetry.callsign, AO_MAX_CALLSIGN); - if (state > ao_flight_invalid) - state = ao_flight_invalid; - if (recv.status & PKT_APPEND_STATUS_1_CRC_OK) { - printf("VERSION %d CALL %s SERIAL %d FLIGHT %5u RSSI %4d STATUS %02x STATE %7s ", - AO_TELEMETRY_VERSION, - callsign, - recv.telemetry.serial, - recv.telemetry.flight, - rssi, recv.status, - ao_state_names[state]); - printf("%5u a: %5d p: %5d t: %5d v: %5d d: %5d m: %5d " - "fa: %5d ga: %d fv: %7ld fp: %5d gp: %5d a+: %5d a-: %5d ", - recv.telemetry.adc.tick, - recv.telemetry.adc.accel, - recv.telemetry.adc.pres, - recv.telemetry.adc.temp, - recv.telemetry.adc.v_batt, - recv.telemetry.adc.sense_d, - recv.telemetry.adc.sense_m, - recv.telemetry.flight_accel, - recv.telemetry.ground_accel, - recv.telemetry.flight_vel, - recv.telemetry.flight_pres, - recv.telemetry.ground_pres, - recv.telemetry.accel_plus_g, - recv.telemetry.accel_minus_g); - ao_gps_print(&recv.telemetry.gps); - putchar(' '); - ao_gps_tracking_print(&recv.telemetry.gps_tracking); - putchar('\n'); - ao_rssi_set(rssi); + if (ao_monitoring == AO_MONITORING_FULL) { + if (!ao_radio_recv(&recv, sizeof (struct ao_telemetry_recv))) + continue; + + state = recv.telemetry.flight_state; + + /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ + rssi = (int16_t) (recv.rssi >> 1) - 74; + memcpy(callsign, recv.telemetry.callsign, AO_MAX_CALLSIGN); + if (state > ao_flight_invalid) + state = ao_flight_invalid; + if (recv.status & PKT_APPEND_STATUS_1_CRC_OK) { + + /* General header fields */ + printf(AO_TELEM_VERSION " %d " + AO_TELEM_CALL " %s " + AO_TELEM_SERIAL " %d " + AO_TELEM_FLIGHT " %d " + AO_TELEM_RSSI " %d " + AO_TELEM_STATE " %s " + AO_TELEM_TICK " %d ", + AO_TELEMETRY_VERSION, + callsign, + recv.telemetry.serial, + recv.telemetry.flight, + rssi, + ao_state_names[state], + recv.telemetry.adc.tick); + + /* Raw sensor values */ + printf(AO_TELEM_RAW_ACCEL " %d " + AO_TELEM_RAW_BARO " %d " + AO_TELEM_RAW_THERMO " %d " + AO_TELEM_RAW_BATT " %d " + AO_TELEM_RAW_DROGUE " %d " + AO_TELEM_RAW_MAIN " %d ", + recv.telemetry.adc.accel, + recv.telemetry.adc.pres, + recv.telemetry.adc.temp, + recv.telemetry.adc.v_batt, + recv.telemetry.adc.sense_d, + recv.telemetry.adc.sense_m); + + /* Sensor calibration values */ + printf(AO_TELEM_CAL_ACCEL_GROUND " %d " + AO_TELEM_CAL_BARO_GROUND " %d " + AO_TELEM_CAL_ACCEL_PLUS " %d " + AO_TELEM_CAL_ACCEL_MINUS " %d ", + recv.telemetry.ground_accel, + recv.telemetry.ground_pres, + recv.telemetry.accel_plus_g, + recv.telemetry.accel_minus_g); + +#if 0 + /* Kalman state values */ + printf(AO_TELEM_KALMAN_HEIGHT " %d " + AO_TELEM_KALMAN_SPEED " %d " + AO_TELEM_KALMAN_ACCEL " %d ", + recv.telemetry.height, + recv.telemetry.speed, + recv.telemetry.accel); +#else + /* Ad-hoc flight values */ + printf(AO_TELEM_ADHOC_ACCEL " %d " + AO_TELEM_ADHOC_SPEED " %ld " + AO_TELEM_ADHOC_BARO " %d ", + recv.telemetry.flight_accel, + recv.telemetry.flight_vel, + recv.telemetry.flight_pres); +#endif + ao_gps_print(&recv.telemetry.gps); + ao_gps_tracking_print(&recv.telemetry.gps_tracking); + putchar('\n'); + ao_rssi_set(rssi); + } else { + printf("CRC INVALID RSSI %3d\n", rssi); + } } else { - printf("CRC INVALID RSSI %3d\n", rssi); + if (!ao_radio_recv(&recv_tiny, sizeof (struct ao_telemetry_tiny_recv))) + continue; + + state = recv_tiny.telemetry_tiny.flight_state; + + /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ + rssi = (int16_t) (recv_tiny.rssi >> 1) - 74; + memcpy(callsign, recv_tiny.telemetry_tiny.callsign, AO_MAX_CALLSIGN); + if (state > ao_flight_invalid) + state = ao_flight_invalid; + if (recv_tiny.status & PKT_APPEND_STATUS_1_CRC_OK) { + /* General header fields */ + printf(AO_TELEM_VERSION " %d " + AO_TELEM_CALL " %s " + AO_TELEM_SERIAL " %d " + AO_TELEM_FLIGHT " %d " + AO_TELEM_RSSI " %d " + AO_TELEM_STATE " %s " + AO_TELEM_TICK " %d ", + AO_TELEMETRY_VERSION, + callsign, + recv_tiny.telemetry_tiny.serial, + recv_tiny.telemetry_tiny.flight, + rssi, + ao_state_names[state], + recv_tiny.telemetry_tiny.adc.tick); + + /* Raw sensor values */ + printf(AO_TELEM_RAW_BARO " %d " + AO_TELEM_RAW_THERMO " %d " + AO_TELEM_RAW_BATT " %d " + AO_TELEM_RAW_DROGUE " %d " + AO_TELEM_RAW_MAIN " %d ", + recv_tiny.telemetry_tiny.adc.pres, + recv_tiny.telemetry_tiny.adc.temp, + recv_tiny.telemetry_tiny.adc.v_batt, + recv_tiny.telemetry_tiny.adc.sense_d, + recv_tiny.telemetry_tiny.adc.sense_m); + + /* Sensor calibration values */ + printf(AO_TELEM_CAL_BARO_GROUND " %d ", + recv_tiny.telemetry_tiny.ground_pres); + +#if 1 + /* Kalman state values */ + printf(AO_TELEM_KALMAN_HEIGHT " %d " + AO_TELEM_KALMAN_SPEED " %d " + AO_TELEM_KALMAN_ACCEL " %d\n", + recv_tiny.telemetry_tiny.height, + recv_tiny.telemetry_tiny.speed, + recv_tiny.telemetry_tiny.accel); +#else + /* Ad-hoc flight values */ + printf(AO_TELEM_ADHOC_ACCEL " %d " + AO_TELEM_ADHOC_SPEED " %ld " + AO_TELEM_ADHOC_BARO " %d\n", + recv_tiny.telemetry_tiny.flight_accel, + recv_tiny.telemetry_tiny.flight_vel, + recv_tiny.telemetry_tiny.flight_pres); +#endif + ao_rssi_set(rssi); + } else { + printf("CRC INVALID RSSI %3d\n", rssi); + } } ao_usb_flush(); ao_led_toggle(ao_monitor_led); @@ -82,21 +192,21 @@ __xdata struct ao_task ao_monitor_task; void ao_set_monitor(uint8_t monitoring) { + if (ao_monitoring) + ao_radio_recv_abort(); ao_monitoring = monitoring; ao_wakeup(&ao_monitoring); - if (!ao_monitoring) - ao_radio_recv_abort(); } static void set_monitor(void) { ao_cmd_hex(); - ao_set_monitor(ao_cmd_lex_i != 0); + ao_set_monitor(ao_cmd_lex_i); } __code struct ao_cmds ao_monitor_cmds[] = { - { set_monitor, "m <0 off, 1 on>\0Enable/disable radio monitoring" }, + { set_monitor, "m <0 off, 1 full, 2 tiny>\0Enable/disable radio monitoring" }, { 0, NULL }, }; diff --git a/src/ao_telem.h b/src/ao_telem.h new file mode 100644 index 00000000..b1624fe0 --- /dev/null +++ b/src/ao_telem.h @@ -0,0 +1,172 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_TELEM_H_ +#define _AO_TELEM_H_ + +#define AO_TELEMETRY_VERSION 4 + +/* + * Telemetry version 4 and higher format: + * + * General header fields + * + * Name Value + * + * VERSION Telemetry version number (4 or more). Must be first. + * c Callsign (string, no spaces allowed) + * n Flight unit serial number (integer) + * f Flight number (integer) + * r Packet RSSI value (integer) + * s Flight computer state (string, no spaces allowed) + * t Flight computer clock (integer in centiseconds) + */ + +#define AO_TELEM_VERSION "VERSION" +#define AO_TELEM_CALL "c" +#define AO_TELEM_SERIAL "n" +#define AO_TELEM_FLIGHT "f" +#define AO_TELEM_RSSI "r" +#define AO_TELEM_STATE "s" +#define AO_TELEM_TICK "t" + +/* + * Raw sensor values + * + * Name Value + * r_a Accelerometer reading (integer) + * r_b Barometer reading (integer) + * r_t Thermometer reading (integer) + * r_v Battery reading (integer) + * r_d Drogue continuity (integer) + * r_m Main continuity (integer) + */ + +#define AO_TELEM_RAW_ACCEL "r_a" +#define AO_TELEM_RAW_BARO "r_b" +#define AO_TELEM_RAW_THERMO "r_t" +#define AO_TELEM_RAW_BATT "r_v" +#define AO_TELEM_RAW_DROGUE "r_d" +#define AO_TELEM_RAW_MAIN "r_m" + +/* + * Sensor calibration values + * + * Name Value + * c_a Ground accelerometer reading (integer) + * c_b Ground barometer reading (integer) + * c_p Accelerometer reading for +1g + * c_m Accelerometer reading for -1g + */ + +#define AO_TELEM_CAL_ACCEL_GROUND "c_a" +#define AO_TELEM_CAL_BARO_GROUND "c_b" +#define AO_TELEM_CAL_ACCEL_PLUS "c_p" +#define AO_TELEM_CAL_ACCEL_MINUS "c_m" + +/* + * Kalman state values + * + * Name Value + * k_h Height above pad (integer, meters) + * k_s Vertical speeed (integer, m/s * 16) + * k_a Vertical acceleration (integer, m/s² * 16) + */ + +#define AO_TELEM_KALMAN_HEIGHT "k_h" +#define AO_TELEM_KALMAN_SPEED "k_s" +#define AO_TELEM_KALMAN_ACCEL "k_a" + +/* + * Ad-hoc flight values + * + * Name Value + * a_a Acceleration (integer, sensor units) + * a_s Speed (integer, integrated acceleration value) + * a_b Barometer reading (integer, sensor units) + */ + +#define AO_TELEM_ADHOC_ACCEL "a_a" +#define AO_TELEM_ADHOC_SPEED "a_s" +#define AO_TELEM_ADHOC_BARO "a_b" + +/* + * GPS values + * + * Name Value + * g_s GPS state (string): + * l locked + * u unlocked + * e error (missing or broken) + * g_n Number of sats used in solution + * g_ns Latitude (degrees * 10e7) + * g_ew Longitude (degrees * 10e7) + * g_a Altitude (integer meters) + * g_Y GPS year (integer) + * g_M GPS month (integer - 1-12) + * g_D GPS day (integer - 1-31) + * g_h GPS hour (integer - 0-23) + * g_m GPS minute (integer - 0-59) + * g_s GPS second (integer - 0-59) + * g_v GPS vertical speed (integer, cm/sec) + * g_s GPS horizontal speed (integer, cm/sec) + * g_c GPS course (integer, 0-359) + * g_hd GPS hdop (integer * 10) + * g_vd GPS vdop (integer * 10) + * g_he GPS h error (integer) + * g_ve GPS v error (integer) + */ + +#define AO_TELEM_GPS_STATE "g_s" +#define AO_TELEM_GPS_STATE_LOCKED 'l' +#define AO_TELEM_GPS_STATE_UNLOCKED 'u' +#define AO_TELEM_GPS_STATE_ERROR 'e' +#define AO_TELEM_GPS_NUM_SAT "g_n" +#define AO_TELEM_GPS_LATITUDE "g_ns" +#define AO_TELEM_GPS_LONGITUDE "g_ew" +#define AO_TELEM_GPS_ALTITUDE "g_a" +#define AO_TELEM_GPS_YEAR "g_Y" +#define AO_TELEM_GPS_MONTH "g_M" +#define AO_TELEM_GPS_DAY "g_D" +#define AO_TELEM_GPS_HOUR "g_h" +#define AO_TELEM_GPS_MINUTE "g_m" +#define AO_TELEM_GPS_SECOND "g_s" +#define AO_TELEM_GPS_VERTICAL_SPEED "g_v" +#define AO_TELEM_GPS_HORIZONTAL_SPEED "g_s" +#define AO_TELEM_GPS_COURSE "g_c" +#define AO_TELEM_GPS_HDOP "g_hd" +#define AO_TELEM_GPS_VDOP "g_vd" +#define AO_TELEM_GPS_HERROR "g_he" +#define AO_TELEM_GPS_VERROR "g_ve" + +/* + * GPS satellite values + * + * Name Value + * s_n Number of satellites reported (integer) + * s_v0 Space vehicle ID (integer) for report 0 + * s_c0 C/N0 number (integer) for report 0 + * s_v1 Space vehicle ID (integer) for report 1 + * s_c1 C/N0 number (integer) for report 1 + * ... + */ + +#define AO_TELEM_SAT_NUM "s_n" +#define AO_TELEM_SAT_SVID "s_v" +#define AO_TELEM_SAT_C_N_0 "s_c" + +#endif /* _AO_TELEM_H_ */ -- cgit v1.2.3 From ca3f03ef5c09446bebf0f5734f36a0248c457b1d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 19 Mar 2011 23:55:39 -0700 Subject: altos: Add .sdcdbrc file for teledongle My sdcdb script uses this to set command line options automatically Signed-off-by: Keith Packard --- src/teledongle-v0.2/.sdcdbrc | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/teledongle-v0.2/.sdcdbrc (limited to 'src') diff --git a/src/teledongle-v0.2/.sdcdbrc b/src/teledongle-v0.2/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/teledongle-v0.2/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. -- cgit v1.2.3 From 20427ae4965f756aac0cedc5179a1c45b9a781f2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 21 Mar 2011 19:59:27 +0900 Subject: altos: Add nickle kalman implementation. This generates the constants needed to implement Kalman filtering in the flight firmware. Signed-off-by: Keith Packard --- src/Makefile.proto | 9 + src/kalman/kalman.5c | 493 ++++++++++++++++++++++++++++++++++++++++++++ src/kalman/kalman_filter.5c | 308 +++++++++++++++++++++++++++ src/kalman/load_csv.5c | 63 ++++++ src/kalman/matrix.5c | 157 ++++++++++++++ src/kalman/plotaccel | 18 ++ src/kalman/plotkalman | 24 +++ src/make-kalman | 18 ++ 8 files changed, 1090 insertions(+) create mode 100755 src/kalman/kalman.5c create mode 100644 src/kalman/kalman_filter.5c create mode 100644 src/kalman/load_csv.5c create mode 100644 src/kalman/matrix.5c create mode 100644 src/kalman/plotaccel create mode 100755 src/kalman/plotkalman create mode 100644 src/make-kalman (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index 68fa4654..85c0c46e 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -5,6 +5,11 @@ vpath %.c .. vpath %.h .. vpath make-altitude .. +vpath make-kalman .. +vpath kalman.5c ../kalman +vpath kalman_filter.5c ../kalman +vpath load_csv.5c ../kalman +vpath matrix.5c ../kalman vpath ao-make-product.5c .. CC=sdcc @@ -25,6 +30,7 @@ INC = \ ao_pins.h \ cc1111.h \ altitude.h \ + ao_kalman.h \ 25lc1024.h # @@ -307,6 +313,9 @@ all: ../$(PROG) ../altitude.h: make-altitude nickle $< > $@ +../ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c + sh $< > $@ + ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/kalman/kalman.5c b/src/kalman/kalman.5c new file mode 100755 index 00000000..f7347184 --- /dev/null +++ b/src/kalman/kalman.5c @@ -0,0 +1,493 @@ +#!/usr/bin/env nickle + +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +autoimport ParseArgs; + +load "load_csv.5c" +import load_csv; + +load "matrix.5c" +import matrix; + +load "kalman_filter.5c" +import kalman; + +/* + * AltOS keeps speed and accel scaled + * by 4 bits to provide additional precision + */ +real height_scale = 1.0; +real accel_scale = 16.0; +real speed_scale = 16.0; + +/* + * State: + * + * x[0] = height + * x[1] = velocity + * x[2] = acceleration + */ + +/* + * Measurement + * + * z[0] = height + * z[1] = acceleration + */ + +real default_σ_m = 5; +real default_σ_h = 20; +real default_σ_a = 2; + +parameters_t param_both(real t, real σ_m, real σ_h, real σ_a) { + if (σ_m == 0) + σ_m = default_σ_m; + if (σ_h == 0) + σ_h = default_σ_h; + if (σ_a == 0) + σ_a = default_σ_a; + + σ_m = imprecise(σ_m) * accel_scale; + σ_h = imprecise(σ_h) * height_scale; + σ_a = imprecise(σ_a) * accel_scale; + + t = imprecise(t); + + return (parameters_t) { +/* + * Equation computing state k from state k-1 + * + * height = height- + velocity- * t + acceleration- * t² / 2 + * velocity = velocity- + acceleration- * t + * acceleration = acceleration- + */ + .a = (real[3,3]) { + { 1, + t * height_scale / speed_scale , t**2/2 * height_scale / accel_scale }, + { 0, 1, t * speed_scale / accel_scale }, + { 0, 0, 1 } + }, +/* + * Model error covariance. The only inaccuracy in the + * model is the assumption that acceleration is constant + */ + .q = (real[3,3]) { + { 0, 0, 0 }, + { 0, 0, 0 }, + {.0, 0, σ_m**2 }, + }, +/* + * Measurement error covariance + * Our sensors are independent, so + * this matrix is zero off-diagonal + */ + .r = (real[2,2]) { + { σ_h ** 2, 0 }, + { 0, σ_a ** 2 }, + }, +/* + * Extract measurements from state, + * this just pulls out the height and acceleration + * values. + */ + .h = (real[2,3]) { + { 1, 0, 0 }, + { 0, 0, 1 }, + }, + }; +} + +parameters_t param_baro(real t, real σ_m, real σ_h) { + if (σ_m == 0) + σ_m = default_σ_m; + if (σ_h == 0) + σ_h = default_σ_h; + + σ_m = imprecise(σ_m) * accel_scale; + σ_h = imprecise(σ_h) * height_scale; + + t = imprecise(t); + return (parameters_t) { +/* + * Equation computing state k from state k-1 + * + * height = height- + velocity- * t + acceleration- * t² / 2 + * velocity = velocity- + acceleration- * t + * acceleration = acceleration- + */ + .a = (real[3,3]) { + { 1, t * height_scale / speed_scale , t**2/2 * height_scale / accel_scale }, + { 0, 1, t * speed_scale / accel_scale }, + { 0, 0, 1 } + }, +/* + * Model error covariance. The only inaccuracy in the + * model is the assumption that acceleration is constant + */ + .q = (real[3,3]) { + { 0, 0, 0 }, + { 0, 0, 0 }, + {.0, 0, σ_m**2 }, + }, +/* + * Measurement error covariance + * Our sensors are independent, so + * this matrix is zero off-diagonal + */ + .r = (real[1,1]) { + { σ_h ** 2 }, + }, +/* + * Extract measurements from state, + * this just pulls out the height + * values. + */ + .h = (real[1,3]) { + { 1, 0, 0 }, + }, + }; +} + +parameters_t param_accel(real t, real σ_m, real σ_a) { + if (σ_m == 0) + σ_m = default_σ_m; + if (σ_a == 0) + σ_a = default_σ_a; + + σ_m = imprecise(σ_m) * accel_scale; + σ_a = imprecise(σ_a) * accel_scale; + + t = imprecise(t); + return (parameters_t) { +/* + * Equation computing state k from state k-1 + * + * height = height- + velocity- * t + acceleration- * t² / 2 + * velocity = velocity- + acceleration- * t + * acceleration = acceleration- + */ + .a = (real[3,3]) { + { 1, t * height_scale / speed_scale , t**2/2 * height_scale / accel_scale }, + { 0, 1, t * speed_scale / accel_scale }, + { 0, 0, 1 } + }, +/* + * Model error covariance. The only inaccuracy in the + * model is the assumption that acceleration is constant + */ + .q = (real[3,3]) { + { 0, 0, 0 }, + { 0, 0, 0 }, + {.0, 0, σ_m**2 }, + }, +/* + * Measurement error covariance + * Our sensors are independent, so + * this matrix is zero off-diagonal + */ + .r = (real[1,1]) { + { σ_a ** 2 }, + }, +/* + * Extract measurements from state, + * this just pulls out the acceleration + * values. + */ + .h = (real[1,3]) { + { 0, 0, 1 }, + }, + }; +} + +parameters_t param_vel(real t) { + static real σ_m = .1; + static real σ_v = imprecise(10); + + return (parameters_t) { +/* + * Equation computing state k from state k-1 + * + * height = height- + velocity- * t + acceleration- * t² / 2 + * velocity = velocity- + acceleration- * t + * acceleration = acceleration- + */ + .a = (real[3,3]) { + { 1, imprecise(t), imprecise((t**2)/2) }, + { 0, 1, imprecise(t) }, + { 0, 0, 1 } + }, +/* + * Model error covariance. The only inaccuracy in the + * model is the assumption that acceleration is constant + */ + .q = (real[3,3]) { + { 0, 0, 0 }, + { 0, 0, 0 }, + {.0, 0, σ_m**2 }, + }, +/* + * Measurement error covariance + * Our sensors are independent, so + * this matrix is zero off-diagonal + */ + .r = (real[1,1]) { + { σ_v ** 2 }, + }, +/* + * Extract measurements from state, + * this just pulls out the velocity + * values. + */ + .h = (real[1,3]) { + { 0, 1, 0 }, + }, + }; +} + +real max_baro_height = 18000; + +bool just_kalman = true; +real accel_input_scale = 1; + +void run_flight(string name, file f, bool summary) { + state_t current_both = { + .x = (real[3]) { 0, 0, 0 }, + .p = (real[3,3]) { { 0 ... } ... }, + }; + state_t current_accel = current_both; + state_t current_baro = current_both; + real t; + real kalman_apogee_time = -1; + real kalman_apogee = 0; + real raw_apogee_time_first; + real raw_apogee_time_last; + real raw_apogee = 0; + real default_descent_rate = 20; + real speed = 0; + real prev_acceleration = 0; + state_t apogee_state; + parameters_fast_t fast_both; + parameters_fast_t fast_baro; + parameters_fast_t fast_accel; + real fast_delta_t = 0; + bool fast = true; + + for (;;) { + record_t record = parse_record(f, accel_input_scale); + if (record.done) + break; + if (is_uninit(&t)) + t = record.time; + real delta_t = record.time - t; + if (delta_t <= 0) + continue; + t = record.time; + if (record.height > raw_apogee) { + raw_apogee_time_first = record.time; + raw_apogee = record.height; + } + if (record.height == raw_apogee) + raw_apogee_time_last = record.time; + + real acceleration = record.acceleration; + real height = record.height; + + speed = (speed + (acceleration + prev_acceleration / 2) * delta_t); + prev_acceleration = acceleration; + + vec_t z_both = (real[2]) { record.height * height_scale, record.acceleration * accel_scale }; + vec_t z_accel = (real[1]) { record.acceleration * accel_scale }; + vec_t z_baro = (real[1]) { record.height * height_scale }; + + + if (fast) { + if (delta_t != fast_delta_t) { + fast_both = convert_to_fast(param_both(delta_t, 0, 0, 0)); + fast_accel = convert_to_fast(param_accel(delta_t, 0, 0)); + fast_baro = convert_to_fast(param_baro(delta_t, 0, 0)); + fast_delta_t = delta_t; + } + + current_both.x = predict_fast(current_both.x, fast_both); + current_accel.x = predict_fast(current_accel.x, fast_accel); + current_baro.x = predict_fast(current_baro.x, fast_baro); + + current_both.x = correct_fast(current_both.x, z_both, fast_both); + current_accel.x = correct_fast(current_accel.x, z_accel, fast_accel); + current_baro.x = correct_fast(current_baro.x, z_baro, fast_baro); + } else { + parameters_t p_both = param_both(delta_t, 0, 0, 0); + parameters_t p_accel = param_accel(delta_t, 0, 0); + parameters_t p_baro = param_baro(delta_t, 0, 0); + + state_t pred_both = predict(current_both, p_both); + state_t pred_accel = predict(current_accel, p_accel); + state_t pred_baro = predict(current_baro, p_baro); + + state_t next_both = correct(pred_both, z_both, p_both); + state_t next_accel = correct(pred_accel, z_accel, p_accel); + state_t next_baro = correct(pred_baro, z_baro, p_baro); + current_both = next_both; + current_accel = next_accel; + current_baro = next_baro; + } + + printf ("%16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f %16.8f\n", + record.time, + record.height, speed, record.acceleration, + current_both.x[0] / height_scale, current_both.x[1] / speed_scale, current_both.x[2] / accel_scale, + current_accel.x[0] / height_scale, current_accel.x[1] / speed_scale, current_accel.x[2] / accel_scale, + current_baro.x[0] / height_scale, current_baro.x[1] / speed_scale, current_baro.x[2] / accel_scale); + if (kalman_apogee_time < 0) { + if (current_both.x[1] < -1 && current_accel.x[1] < -1 && current_baro.x[1] < -1) { + kalman_apogee = current_both.x[0]; + kalman_apogee_time = record.time; + break; + } + } + } + real raw_apogee_time = (raw_apogee_time_last + raw_apogee_time_first) / 2; + if (summary && !just_kalman) { + printf("%s: kalman (%8.2f m %6.2f s) raw (%8.2f m %6.2f s) error %6.2f s\n", + name, + kalman_apogee, kalman_apogee_time, + raw_apogee, raw_apogee_time, + kalman_apogee_time - raw_apogee_time); + } +} + +void main() { + bool summary = false; + int user_argind = 1; + real time_step = 0.01; + string compute = "none"; + string prefix = "AO_K"; + real σ_m = 1; + real σ_h = 4; + real σ_a = 1; + + ParseArgs::argdesc argd = { + .args = { + { .var = { .arg_flag = &summary }, + .abbr = 's', + .name = "summary", + .desc = "Print a summary of the flight" }, + { .var = { .arg_real = &max_baro_height }, + .abbr = 'm', + .name = "maxbaro", + .expr_name = "height", + .desc = "Set maximum usable barometer height" }, + { .var = { .arg_real = &accel_input_scale, }, + .abbr = 'a', + .name = "accel", + .expr_name = "", + .desc = "Set accelerometer scale factor" }, + { .var = { .arg_real = &time_step, }, + .abbr = 't', + .name = "time", + .expr_name = "", + .desc = "Set time step for convergence" }, + { .var = { .arg_string = &prefix }, + .abbr = 'p', + .name = "prefix", + .expr_name = "", + .desc = "Prefix for compute output" }, + { .var = { .arg_string = &compute }, + .abbr = 'c', + .name = "compute", + .expr_name = "{both,baro,accel}", + .desc = "Compute Kalman factor through convergence" }, + { .var = { .arg_real = &σ_m }, + .abbr = 'M', + .name = "model", + .expr_name = "", + .desc = "Model co-variance for acceleration" }, + { .var = { .arg_real = &σ_h }, + .abbr = 'H', + .name = "height", + .expr_name = "", + .desc = "Measure co-variance for height" }, + { .var = { .arg_real = &σ_a }, + .abbr = 'A', + .name = "accel", + .expr_name = "", + .desc = "Measure co-variance for acceleration" }, + }, + + .unknown = &user_argind, + }; + + ParseArgs::parseargs(&argd, &argv); + + if (compute != "none") { + parameters_t param; + + printf ("/* Kalman matrix for %s\n", compute); + printf (" * step = %f\n", time_step); + printf (" * σ_m = %f\n", σ_m); + switch (compute) { + case "both": + printf (" * σ_h = %f\n", σ_h); + printf (" * σ_a = %f\n", σ_a); + param = param_both(time_step, σ_m, σ_h, σ_a); + break; + case "accel": + printf (" * σ_a = %f\n", σ_a); + param = param_accel(time_step, σ_m, σ_a); + break; + case "baro": + printf (" * σ_h = %f\n", σ_h); + param = param_baro(time_step, σ_m, σ_h); + break; + } + printf (" */\n\n"); + mat_t k = converge(param); + int[] d = dims(k); + int time_inc = floor(1/time_step + 0.5); + if (d[1] == 2) { + for (int i = 0; i < d[0]; i++) + for (int j = 0; j < d[1]; j++) + printf ("#define %s_K%d%d_%d to_fix16(%12.10f)\n", + prefix, i, j, time_inc, k[i,j]); + } else { + for (int i = 0; i < d[0]; i++) { + printf ("#define %s_K%d_%d to_fix16(%12.10f)\n", + prefix, i, time_inc, k[i,0]); + } + } + printf ("\n"); + return; + } + string[dim(argv) - user_argind] rest = { [i] = argv[i+user_argind] }; + + # height_scale = accel_scale = speed_scale = 1; + + if (dim(rest) == 0) + run_flight("", stdin, summary); + else { + for (int i = 0; i < dim(rest); i++) { + twixt(file f = File::open(rest[i], "r"); File::close(f)) { + run_flight(rest[i], f, summary); + } + } + } +} +main(); +#kalman(stdin); +#dump(stdin); diff --git a/src/kalman/kalman_filter.5c b/src/kalman/kalman_filter.5c new file mode 100644 index 00000000..efbbf1ab --- /dev/null +++ b/src/kalman/kalman_filter.5c @@ -0,0 +1,308 @@ +load "matrix.5c" + +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +namespace kalman { + + import matrix; + + public typedef struct { + vec_t x; /* state */ + mat_t p; /* error estimate */ + mat_t k; /* kalman factor */ + } state_t; + + public typedef struct { + mat_t a; /* model */ + mat_t q; /* model error covariance */ + mat_t r; /* measurement error covariance */ + mat_t h; /* measurement from model */ + } parameters_t; + + public typedef struct { + mat_t a; /* model */ + mat_t k; /* kalman coefficient */ + mat_t h; /* measurement from model */ + } parameters_fast_t; + + vec_t measurement_from_state(vec_t x, mat_t h) { + return multiply_mat_vec(h, x); + } + + + void print_state(string name, state_t s) { + print_vec(sprintf("%s state", name), s.x); + print_mat(sprintf("%s error", name), s.p); + } + + public bool debug = false; + + public state_t predict (state_t s, parameters_t p) { + state_t n; + + if (debug) { + printf ("--------PREDICT--------\n"); + print_state("current", s); + } + + /* Predict state + * + * x': predicted state + * a: model + * x: previous state + * + * x' = a * x; + */ + + n.x = multiply_mat_vec(p.a, s.x); + + /* t0 = a * p */ + mat_t t0 = multiply (p.a, s.p); + if (debug) + print_mat("t0", t0); + + /* t1 = a * p * transpose(a) */ + + mat_t t1 = multiply (t0, transpose(p.a)); + + /* Predict error + * + * p': predicted error + * a: model + * p: previous error + * q: model error + * + * p' = a * p * transpose(a) + q + */ + + n.p = add(t1, p.q); + if (debug) + print_state("predict", n); + return n; + } + + public vec_t predict_fast(vec_t x, parameters_fast_t p) { + if (debug) { + printf ("--------FAST PREDICT--------\n"); + print_vec("current", x); + } + vec_t new = multiply_mat_vec(p.a, x); + if (debug) + print_vec("predict", new); + return new; + } + + public vec_t correct_fast(vec_t x, vec_t z, parameters_fast_t p) { + if (debug) { + printf ("--------FAST CORRECT--------\n"); + print_vec("measure", z); + print_vec("current", x); + } + vec_t model = multiply_mat_vec(p.h, x); + if (debug) + print_vec("extract model", model); + vec_t diff = vec_subtract(z, model); + if (debug) + print_vec("difference", diff); + vec_t adjust = multiply_mat_vec(p.k, diff); + if (debug) + print_vec("adjust", adjust); + + vec_t new = vec_add(x, + multiply_mat_vec(p.k, + vec_subtract(z, + multiply_mat_vec(p.h, x)))); + if (debug) + print_vec("correct", new); + return new; + } + + public state_t correct(state_t s, vec_t z, parameters_t p) { + state_t n; + + if (debug) { + printf ("--------CORRECT--------\n"); + print_vec("measure", z); + print_state("current", s); + } + + /* t0 = p * T(h) */ + + /* 3x2 = 3x3 * 3x2 */ + mat_t t0 = multiply(s.p, transpose(p.h)); + if (debug) + print_mat("t0", t0); + + /* t1 = h * p */ + + /* 2x3 = 2x3 * 3x3 */ + mat_t t1 = multiply(p.h, s.p); + if (debug) + print_mat("t1", t1); + + /* t2 = h * p * transpose(h) */ + + /* 2x2 = 2x3 * 3x2 */ + mat_t t2 = multiply(t1, transpose(p.h)); + if (debug) + print_mat("t2", t2); + + /* t3 = h * p * transpose(h) + r */ + + /* 2x2 = 2x2 + 2x2 */ + mat_t t3 = add(t2, p.r); + if (debug) + print_mat("t3", t3); + + /* t4 = inverse(h * p * transpose(h) + r) */ + + /* 2x2 = 2x2 */ + mat_t t4 = inverse(t3); + if (debug) + print_mat("t4", t4); + + /* Kalman value */ + + /* k: Kalman value + * p: error estimate + * h: state to measurement matrix + * r: measurement error covariance + * + * k = p * transpose(h) * inverse(h * p * transpose(h) + r) + * + * k = K(p) + */ + + /* 3x2 = 3x2 * 2x2 */ + mat_t k = multiply(t0, t4); + if (debug) + print_mat("k", k); + n.k = k; + + /* t5 = h * x */ + + /* 2 = 2x3 * 3 */ + vec_t t5 = multiply_mat_vec(p.h, s.x); + if (debug) + print_vec("t5", t5); + + /* t6 = z - h * x */ + + /* 2 = 2 - 2 */ + vec_t t6 = vec_subtract(z, t5); + if (debug) + print_vec("t6", t6); + + /* t7 = k * (z - h * x) */ + + /* 3 = 3x2 * 2 */ + vec_t t7 = multiply_mat_vec(k, t6); + if (debug) + print_vec("t7", t7); + + /* Correct state + * + * x: predicted state + * k: kalman value + * z: measurement + * h: state to measurement matrix + * x': corrected state + * + * x' = x + k * (z - h * x) + */ + + n.x = vec_add(s.x, t7); + if (debug) + print_vec("n->x", n.x); + + /* t8 = k * h */ + + /* 3x3 = 3x2 * 2x3 */ + mat_t t8 = multiply(k, p.h); + if (debug) + print_mat("t8", t8); + + /* t9 = 1 - k * h */ + + /* 3x3 = 3x3 - 3x3 */ + mat_t t9 = subtract(identity(dim(s.x)), t8); + if (debug) + print_mat("t9", t9); + + /* Correct error + * + * p: predicted error + * k: kalman value + * h: state to measurement matrix + * p': corrected error + * + * p' = (1 - k * h) * p + * + * p' = P(k,p) + */ + + /* 3x3 = 3x3 * 3x3 */ + n.p = multiply(t9, s.p); + if (debug) { + print_mat("n->p", n.p); +# print_state("correct", n); + } + return n; + } + + real distance(mat_t a, mat_t b) { + int[2] d = dims(a); + int i_max = d[0]; + int j_max = d[1]; + real s = 0; + + for (int i = 0; i < i_max; i++) + for (int j = 0; j < j_max; j++) + s += (a[i,j] - b[i,j]) ** 2; + return sqrt(s); + } + + public mat_t converge(parameters_t p) { + int model = dims(p.a)[0]; + int measure = dims(p.r)[0]; + int reps = 0; + state_t s = { + .x = (real[model]) { 0 ... }, + .p = (real[model,model]) { { 0 ... } ... }, + .k = (real[model,measure]) { { 0 ... } ... } + }; + + vec_t z = (real [measure]) { 0 ... }; + for (;;) { + state_t s_pre = predict(s, p); + state_t s_post = correct(s_pre, z, p); + real d = distance(s.k, s_post.k); + s = s_post; + reps++; + if (d < 1e-10 && reps > 10) + break; + } + return s.k; + } + + public parameters_fast_t convert_to_fast(parameters_t p) { + return (parameters_fast_t) { + .a = p.a, .k = converge(p), .h = p.h + }; + } +} diff --git a/src/kalman/load_csv.5c b/src/kalman/load_csv.5c new file mode 100644 index 00000000..15e83166 --- /dev/null +++ b/src/kalman/load_csv.5c @@ -0,0 +1,63 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +namespace load_csv { + string[*] parse_data(file f) { + while (!File::end(f)) { + string l = File::fgets(f); + if (l[0] == '#') + continue; + return String::parse_csv(l); + } + return (string[0]) {}; + } + + public typedef struct { + bool done; + real time; + real height; + real acceleration; + } record_t; + + public record_t parse_record(file f, real accel_scale) { + string[*] data = parse_data(f); + if (dim(data) == 0) + return (record_t) { .done = true }; + int time_off = 4; + int height_off = 11; + int accel_off = 8; + if (string_to_integer(data[0]) == 2) { + time_off = 4; + accel_off = 9; + height_off = 12; + } + return (record_t) { + .done = false, + .time = string_to_real(data[time_off]), + .height = imprecise(string_to_real(data[height_off])), + .acceleration = imprecise(string_to_real(data[accel_off]) * accel_scale) }; + } + + public void dump(file f) { + for (;;) { + record_t r = parse_record(f, 1); + if (r.done) + break; + printf ("%f %f %f\n", r.time, r.height, r.acceleration); + } + } +} diff --git a/src/kalman/matrix.5c b/src/kalman/matrix.5c new file mode 100644 index 00000000..667648f5 --- /dev/null +++ b/src/kalman/matrix.5c @@ -0,0 +1,157 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +namespace matrix { + public typedef real[*] vec_t; + public typedef real[*,*] mat_t; + + public mat_t transpose(mat_t m) { + int[2] d = dims(m); + return (real[d[1],d[0]]) { [i,j] = m[j,i] }; + } + + public void print_mat(string name, mat_t m) { + int[2] d = dims(m); + printf ("%s {\n", name); + for (int y = 0; y < d[0]; y++) { + for (int x = 0; x < d[1]; x++) + printf (" %14.8f", m[y,x]); + printf ("\n"); + } + printf ("}\n"); + } + + public void print_vec(string name, vec_t v) { + int d = dim(v); + printf ("%s {", name); + for (int x = 0; x < d; x++) + printf (" %14.8f", v[x]); + printf (" }\n"); + } + + public mat_t multiply(mat_t a, mat_t b) { + int[2] da = dims(a); + int[2] db = dims(b); + + assert(da[1] == db[0], "invalid matrix dimensions"); + + real dot(int rx, int ry) { + real r = 0.0; + for (int i = 0; i < da[1]; i++) + r += a[ry, i] * b[i, rx]; + return imprecise(r); + } + + mat_t r = (real[da[0], db[1]]) { [ry,rx] = dot(rx,ry) }; + return r; + } + + public mat_t multiply_mat_val(mat_t m, real value) { + int[2] d = dims(m); + for (int j = 0; j < d[1]; j++) + for (int i = 0; i < d[0]; i++) + m[i,j] *= value; + return m; + } + + public mat_t add(mat_t a, mat_t b) { + int[2] da = dims(a); + int[2] db = dims(b); + + assert(da[0] == db[0] && da[1] == db[1], "mismatching dim in plus"); + return (real[da[0], da[1]]) { [y,x] = a[y,x] + b[y,x] }; + } + + public mat_t subtract(mat_t a, mat_t b) { + int[2] da = dims(a); + int[2] db = dims(b); + + assert(da[0] == db[0] && da[1] == db[1], "mismatching dim in minus"); + return (real[da[0], da[1]]) { [y,x] = a[y,x] - b[y,x] }; + } + + public mat_t inverse(mat_t m) { + int[2] d = dims(m); + + real[1,1] inverse_1(real[1,1] m) { + return (real[1,1]) { { 1/m[0,0] } }; + } + + if (d[0] == 1 && d[1] == 1) + return inverse_1(m); + + real[2,2] inverse_2(real[2,2] m) { + real a = m[0,0], b = m[0,1]; + real c = m[1,0], d = m[1,1]; + real det = a * d - b * c; + return multiply_mat_val((real[2,2]) { + { d, -b }, { -c, a } }, 1/det); + } + + if (d[0] == 2 && d[1] == 2) + return inverse_2(m); + + real[3,3] inverse_3(real[3,3] m) { + real a = m[0,0], b = m[0,1], c = m[0, 2]; + real d = m[1,0], e = m[1,1], f = m[1, 2]; + real g = m[2,0], h = m[2,1], k = m[2, 2]; + real Z = a*(e*k-f*h) + b*(f*g - d*k) + c*(d*h-e*g); + real A = (e*k-f*h), B = (c*h-b*k), C=(b*f-c*e); + real D = (f*g-d*k), E = (a*k-c*g), F=(c*d-a*f); + real G = (d*h-e*g), H = (b*g-a*h), K=(a*e-b*d); + return multiply_mat_val((real[3,3]) { + { A, B, C }, { D, E, F }, { G, H, K }}, + 1/Z); + } + + if (d[0] == 3 && d[1] == 3) + return inverse_3(m); + assert(false, "cannot invert %v\n", d); + return m; + } + + public mat_t identity(int d) { + return (real[d,d]) { [i,j] = (i == j) ? 1 : 0 }; + } + + public vec_t vec_subtract(vec_t a, vec_t b) { + int da = dim(a); + int db = dim(b); + + assert(da == db, "mismatching dim in minus"); + return (real[da]) { [x] = a[x] - b[x] }; + } + + public vec_t vec_add(vec_t a, vec_t b) { + int da = dim(a); + int db = dim(b); + + assert(da == db, "mismatching dim in plus"); + return (real[da]) { [x] = a[x] + b[x] }; + } + + public vec_t multiply_vec_mat(vec_t v, mat_t m) { + mat_t r2 = matrix::multiply((real[dim(v),1]) { [y,x] = v[y] }, m); + return (real[dim(v)]) { [y] = r2[y,0] }; + } + + public vec_t multiply_mat_vec(mat_t m, vec_t v) { + mat_t r2 = matrix::multiply(m, (real[dim(v), 1]) { [y,x] = v[y] }); + int[2] d = dims(m); + return (real[d[0]]) { [y] = r2[y,0] }; + } +} diff --git a/src/kalman/plotaccel b/src/kalman/plotaccel new file mode 100644 index 00000000..fd540203 --- /dev/null +++ b/src/kalman/plotaccel @@ -0,0 +1,18 @@ +#!/bin/sh +for i in "$@"; do +gnuplot -p << EOF +set title "$i" +set ylabel "height (m)" +set y2label "velocity (m/s), acceleration (m/s²)" +set xlabel "time (s)" +set xtics border out nomirror +set ytics border out nomirror +set y2tics border out nomirror +plot "$i" using 1:3 with lines lt 1 axes x1y2 title "raw speed",\ + "$i" using 1:4 with lines lt 1 axes x1y2 title "raw accel",\ + "$i" using 1:6 with lines lt 2 axes x1y2 title "both speed",\ + "$i" using 1:7 with lines lt 2 axes x1y2 title "both accel",\ + "$i" using 1:9 with lines lt 3 axes x1y2 title "accel speed",\ + "$i" using 1:10 with lines lt 3 axes x1y2 title "accel accel" +EOF +done diff --git a/src/kalman/plotkalman b/src/kalman/plotkalman new file mode 100755 index 00000000..d2041dfb --- /dev/null +++ b/src/kalman/plotkalman @@ -0,0 +1,24 @@ +#!/bin/sh +for i in "$@"; do +gnuplot -p << EOF +set title "$i" +set ylabel "height (m)" +set y2label "velocity (m/s), acceleration (m/s²)" +set xlabel "time (s)" +set xtics border out nomirror +set ytics border out nomirror +set y2tics border out nomirror +plot "$i" using 1:2 with lines lt 1 axes x1y1 title "raw height",\ + "$i" using 1:3 with lines lt 1 axes x1y2 title "raw speed",\ + "$i" using 1:4 with lines lt 1 axes x1y2 title "raw accel",\ + "$i" using 1:5 with lines lt 2 axes x1y1 title "both height",\ + "$i" using 1:6 with lines lt 2 axes x1y2 title "both vel",\ + "$i" using 1:7 with lines lt 2 axes x1y2 title "both accel",\ + "$i" using 1:8 with lines lt 3 axes x1y1 title "accel height",\ + "$i" using 1:9 with lines lt 3 axes x1y2 title "accel vel",\ + "$i" using 1:10 with lines lt 3 axes x1y2 title "accel accel",\ + "$i" using 1:11 with lines lt 4 axes x1y1 title "baro height",\ + "$i" using 1:12 with lines lt 4 axes x1y2 title "baro vel",\ + "$i" using 1:13 with lines lt 4 axes x1y2 title "baro accel" +EOF +done diff --git a/src/make-kalman b/src/make-kalman new file mode 100644 index 00000000..80157c6b --- /dev/null +++ b/src/make-kalman @@ -0,0 +1,18 @@ +#!/bin/sh + +cd ../kalman + +SIGMA_ACCEL_MODEL=1 +SIGMA_BARO_MEASURE=8 +SIGMA_ACCEL_MEASURE=4 + +SIGMA="-M $SIGMA_ACCEL_MODEL -H $SIGMA_BARO_MEASURE -A $SIGMA_ACCEL_MEASURE" + +nickle kalman.5c -p AO_BOTH -c both -t 0.01 $SIGMA +nickle kalman.5c -p AO_BOTH -c both -t 0.1 $SIGMA + +nickle kalman.5c -p AO_ACCEL -c accel -t 0.01 $SIGMA +nickle kalman.5c -p AO_ACCEL -c accel -t 0.1 $SIGMA + +nickle kalman.5c -p AO_BARO -c baro -t 0.01 $SIGMA +nickle kalman.5c -p AO_BARO -c baro -t 0.1 $SIGMA -- cgit v1.2.3 From 7b009b2efe3af8722c358c304c2243652594e0d5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 22 Mar 2011 05:42:51 +0900 Subject: altos: Switch telemetrum over to kalman filter This changes the full telemetry stream to include kalman data instead of the old ad-hoc flight data. It's compatible in that the packet sizes are the same so teledongle can receive either and figure out which it has received. A few plotting and testing tools are added to make validating the new code easier. Signed-off-by: Keith Packard --- src/ao.h | 36 ++-- src/ao_flash.c | 8 +- src/ao_flight.c | 495 +++++++++++++++++++++--------------------------- src/ao_flight_test.c | 82 ++++---- src/ao_log_tiny.c | 2 +- src/ao_monitor.c | 34 ++-- src/ao_pins.h | 5 - src/ao_report.c | 2 +- src/ao_telemetry.c | 7 +- src/ao_telemetry_tiny.c | 6 +- src/test/.gitignore | 1 + src/test/Makefile | 13 +- src/test/plottest | 16 ++ src/test/run-one | 32 ++++ src/test/test-flights | 1 - 15 files changed, 367 insertions(+), 373 deletions(-) create mode 100755 src/test/plottest create mode 100755 src/test/run-one (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 527390b0..b88bef1f 100644 --- a/src/ao.h +++ b/src/ao.h @@ -34,7 +34,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 0x80 +#define AO_STACK_START 0x90 #define AO_STACK_END 0xfe #define AO_STACK_SIZE (AO_STACK_END - AO_STACK_START + 1) @@ -470,7 +470,7 @@ extern __xdata uint16_t ao_storage_unit; /* Initialize above values. Can only be called once the OS is running */ void -ao_storage_setup(void); +ao_storage_setup(void) __reentrant; /* Write data. Returns 0 on failure, 1 on success */ uint8_t @@ -698,21 +698,19 @@ enum ao_flight_state { extern __data uint8_t ao_flight_adc; extern __pdata enum ao_flight_state ao_flight_state; extern __pdata uint16_t ao_flight_tick; -extern __pdata int16_t ao_flight_accel; -extern __pdata int16_t ao_flight_pres; -extern __pdata int32_t ao_flight_vel; -extern __pdata int16_t ao_ground_pres; +extern __xdata int16_t ao_ground_pres; extern __pdata int16_t ao_ground_accel; -extern __pdata int16_t ao_min_pres; extern __pdata uint16_t ao_launch_time; extern __xdata uint8_t ao_flight_force_idle; -#ifdef USE_KALMAN extern __pdata int16_t ao_ground_height; -extern __pdata int32_t ao_k_max_height; -extern __pdata int32_t ao_k_height; -extern __pdata int32_t ao_k_speed; -extern __pdata int32_t ao_k_accel; -#endif +extern __pdata int16_t ao_max_height; +extern __pdata int16_t ao_height; /* meters */ +extern __pdata int16_t ao_speed; /* m/s * 16 */ +extern __pdata int16_t ao_accel; /* m/s² * 16 */ + +#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) +#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) +#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) /* Flight thread */ void @@ -912,10 +910,16 @@ struct ao_telemetry { uint16_t serial; uint16_t flight; uint8_t flight_state; - int16_t flight_accel; + int16_t accel; int16_t ground_accel; - int32_t flight_vel; - int16_t flight_pres; + union { + struct { + int16_t speed; + int16_t unused; + } k; + int32_t flight_vel; + } u; + int16_t height; int16_t ground_pres; int16_t accel_plus_g; int16_t accel_minus_g; diff --git a/src/ao_flash.c b/src/ao_flash.c index 3a264ceb..d323926f 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -93,12 +93,12 @@ static __pdata uint16_t ao_flash_block = FLASH_BLOCK_NONE; static __pdata uint8_t ao_flash_block_dirty; static __pdata uint8_t ao_flash_write_pending; static __pdata uint8_t ao_flash_setup_done; -static __data uint8_t ao_flash_block_shift; -static __data uint16_t ao_flash_block_size; -static __data uint16_t ao_flash_block_mask; +static __pdata uint8_t ao_flash_block_shift; +static __pdata uint16_t ao_flash_block_size; +static __pdata uint16_t ao_flash_block_mask; void -ao_storage_setup(void) +ao_storage_setup(void) __reentrant { uint8_t status; diff --git a/src/ao_flight.c b/src/ao_flight.c index 493913b2..c65670f0 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -31,22 +31,14 @@ #error Please define HAS_USB #endif -#ifndef USE_KALMAN -#error Please define USE_KALMAN -#endif - /* Main flight thread. */ __pdata enum ao_flight_state ao_flight_state; /* current flight state */ __pdata uint16_t ao_flight_tick; /* time of last data */ __pdata uint16_t ao_flight_prev_tick; /* time of previous data */ -__pdata int16_t ao_flight_pres; /* filtered pressure */ -__pdata int16_t ao_ground_pres; /* startup pressure */ -__pdata int16_t ao_min_pres; /* minimum recorded pressure */ +__xdata int16_t ao_ground_pres; /* startup pressure */ __pdata uint16_t ao_launch_tick; /* time of launch detect */ -__pdata int16_t ao_main_pres; /* pressure to eject main */ #if HAS_ACCEL -__pdata int16_t ao_flight_accel; /* filtered acceleration */ __pdata int16_t ao_ground_accel; /* startup acceleration */ #endif @@ -55,16 +47,8 @@ __pdata int16_t ao_ground_accel; /* startup acceleration */ * resting */ __pdata uint16_t ao_interval_end; -__pdata int16_t ao_interval_cur_min_pres; -__pdata int16_t ao_interval_cur_max_pres; -__pdata int16_t ao_interval_min_pres; -__pdata int16_t ao_interval_max_pres; -#if HAS_ACCEL -__pdata int16_t ao_interval_cur_min_accel; -__pdata int16_t ao_interval_cur_max_accel; -__pdata int16_t ao_interval_min_accel; -__pdata int16_t ao_interval_max_accel; -#endif +__pdata int16_t ao_interval_min_height; +__pdata int16_t ao_interval_max_height; __data uint8_t ao_flight_adc; __pdata int16_t ao_raw_pres; @@ -96,15 +80,8 @@ __pdata int16_t ao_accel_2g; */ #define GRAVITY 9.80665 -/* convert m/s to velocity count */ -#define VEL_MPS_TO_COUNT(mps) (((int32_t) (((mps) / GRAVITY) * (AO_HERTZ/2))) * (int32_t) ao_accel_2g) #define ACCEL_NOSE_UP (ao_accel_2g >> 2) -#define ACCEL_BOOST ao_accel_2g -#define ACCEL_COAST (ao_accel_2g >> 3) -#define ACCEL_INT_LAND (ao_accel_2g >> 3) -#define ACCEL_VEL_MACH VEL_MPS_TO_COUNT(200) -#define ACCEL_VEL_BOOST VEL_MPS_TO_COUNT(5) #endif @@ -127,91 +104,185 @@ __pdata int16_t ao_accel_2g; * 27 mV/kPa * 32767 / 3300 counts/mV = 268.1 counts/kPa */ -#define BARO_kPa 268 -#define BARO_LAUNCH (BARO_kPa / 5) /* .2kPa, or about 20m */ -#define BARO_APOGEE (BARO_kPa / 10) /* .1kPa, or about 10m */ -#define BARO_COAST (BARO_kPa * 5) /* 5kpa, or about 500m */ -#define BARO_MAIN (BARO_kPa) /* 1kPa, or about 100m */ -#define BARO_INT_LAND (BARO_kPa / 20) /* .05kPa, or about 5m */ -#define BARO_LAND (BARO_kPa * 10) /* 10kPa or about 1000m */ - /* We also have a clock, which can be used to sanity check things in * case of other failures */ #define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) -#if HAS_ACCEL -/* This value is scaled in a weird way. It's a running total of accelerometer - * readings minus the ground accelerometer reading. That means it measures - * velocity, and quite accurately too. As it gets updated 100 times a second, - * it's scaled by 100 - */ -__pdata int32_t ao_flight_vel; -__pdata int32_t ao_min_vel; -__pdata int32_t ao_old_vel; -__pdata int16_t ao_old_vel_tick; -__xdata int32_t ao_raw_accel_sum; -#endif - -#if USE_KALMAN -__pdata int16_t ao_ground_height; -__pdata int32_t ao_k_max_height; -__pdata int32_t ao_k_height; -__pdata int32_t ao_k_speed; -__pdata int32_t ao_k_accel; - #define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) #define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) - #define from_fix(x) ((x) >> 16) -#define AO_K0_100 to_fix16(0.05680323) -#define AO_K1_100 to_fix16(0.16608182) -#define AO_K2_100 to_fix16(0.24279580) +#include "ao_kalman.h" + +__pdata int16_t ao_ground_height; +__pdata int16_t ao_height; +__pdata int16_t ao_speed; +__pdata int16_t ao_accel; +__pdata int16_t ao_max_height; + +static __pdata int32_t ao_k_height; +static __pdata int32_t ao_k_speed; +static __pdata int32_t ao_k_accel; #define AO_K_STEP_100 to_fix16(0.01) #define AO_K_STEP_2_2_100 to_fix16(0.00005) -#define AO_K0_10 to_fix16(0.23772023) -#define AO_K1_10 to_fix16(0.32214149) -#define AO_K2_10 to_fix16(0.21827159) - #define AO_K_STEP_10 to_fix16(0.1) #define AO_K_STEP_2_2_10 to_fix16(0.005) +/* + * Above this height, the baro sensor doesn't work + */ +#define AO_MAX_BARO_HEIGHT 8000 + +/* + * Above this speed, baro measurements are unreliable + */ +#define AO_MAX_BARO_SPEED 300 + +static void +ao_kalman_predict(void) +{ +#ifdef AO_FLIGHT_TEST + if (ao_flight_tick - ao_flight_prev_tick > 5) { + ao_k_height += ((int32_t) ao_speed * AO_K_STEP_10 + + (int32_t) ao_accel * AO_K_STEP_2_2_10) >> 4; + ao_k_speed += (int32_t) ao_accel * AO_K_STEP_10; + + return; + } +#endif + ao_k_height += ((int32_t) ao_speed * AO_K_STEP_100 + + (int32_t) ao_accel * AO_K_STEP_2_2_100) >> 4; + ao_k_speed += (int32_t) ao_accel * AO_K_STEP_100; +} + +static __pdata int16_t ao_error_h; +static __pdata int16_t ao_raw_alt; +static __pdata int16_t ao_raw_height; +static __pdata int16_t ao_error_h_sq_avg; + static void -ao_kalman_baro(void) +ao_kalman_err_height(void) { - int16_t err = ((ao_pres_to_altitude(ao_raw_pres) - ao_ground_height)) - - (int16_t) (ao_k_height >> 16); + int16_t e; + ao_error_h = ao_raw_height - (int16_t) (ao_k_height >> 16); + + e = ao_error_h; + if (e < 0) + e = -e; + if (e > 127) + e = 127; + ao_error_h_sq_avg -= ao_error_h_sq_avg >> 4; + ao_error_h_sq_avg += (e * e) >> 4; +} +static void +ao_kalman_correct_baro(void) +{ + ao_kalman_err_height(); #ifdef AO_FLIGHT_TEST if (ao_flight_tick - ao_flight_prev_tick > 5) { - ao_k_height += ((ao_k_speed >> 16) * AO_K_STEP_10 + - (ao_k_accel >> 16) * AO_K_STEP_2_2_10); - ao_k_speed += (ao_k_accel >> 16) * AO_K_STEP_10; - - /* correct */ - ao_k_height += (int32_t) AO_K0_10 * err; - ao_k_speed += (int32_t) AO_K1_10 * err; - ao_k_accel += (int32_t) AO_K2_10 * err; + ao_k_height += (int32_t) AO_BARO_K0_10 * ao_error_h; + ao_k_speed += (int32_t) AO_BARO_K1_10 * ao_error_h; + ao_k_accel += (int32_t) AO_BARO_K2_10 * ao_error_h; return; } #endif - ao_k_height += ((ao_k_speed >> 16) * AO_K_STEP_100 + - (ao_k_accel >> 16) * AO_K_STEP_2_2_100); - ao_k_speed += (ao_k_accel >> 16) * AO_K_STEP_100; - - /* correct */ - ao_k_height += (int32_t) AO_K0_100 * err; - ao_k_speed += (int32_t) AO_K1_100 * err; - ao_k_accel += (int32_t) AO_K2_100 * err; + ao_k_height += (int32_t) AO_BARO_K0_100 * ao_error_h; + ao_k_speed += (int32_t) AO_BARO_K1_100 * ao_error_h; + ao_k_accel += (int32_t) AO_BARO_K2_100 * ao_error_h; } + +#if HAS_ACCEL +static __pdata int16_t ao_error_a; +static __pdata int32_t ao_accel_scale; + +static void +ao_kalman_err_accel(void) +{ + int32_t accel; + + accel = (ao_ground_accel - ao_raw_accel) * ao_accel_scale; + + /* Can't use ao_accel here as it is the pre-prediction value still */ + ao_error_a = (accel - ao_k_accel) >> 16; +} + +static void +ao_kalman_correct_both(void) +{ + ao_kalman_err_height(); + ao_kalman_err_accel(); + +#if 0 + /* + * Check to see if things are crazy here -- + * if the computed height is far above the + * measured height, we assume that the flight + * trajectory is not vertical, and so ignore + * the accelerometer for the remainder of the + * flight. + */ + if (ao_error_h_sq_avg > 10) + { + ao_kalman_correct_baro(); + return; + } +#endif + +#ifdef AO_FLIGHT_TEST + if (ao_flight_tick - ao_flight_prev_tick > 5) { + ao_k_height += + (int32_t) AO_BOTH_K00_10 * ao_error_h + + (int32_t) (AO_BOTH_K01_10 >> 4) * ao_error_a; + ao_k_speed += + ((int32_t) AO_BOTH_K10_10 << 4) * ao_error_h + + (int32_t) AO_BOTH_K11_10 * ao_error_a; + ao_k_accel += + ((int32_t) AO_BOTH_K20_10 << 4) * ao_error_h + + (int32_t) AO_BOTH_K21_10 * ao_error_a; + return; + } +#endif + ao_k_height += + (int32_t) AO_BOTH_K00_100 * ao_error_h + + (int32_t) AO_BOTH_K01_100 * ao_error_a; + ao_k_speed += + (int32_t) AO_BOTH_K10_100 * ao_error_h + + (int32_t) AO_BOTH_K11_100 * ao_error_a; + ao_k_accel += + (int32_t) AO_BOTH_K20_100 * ao_error_h + + (int32_t) AO_BOTH_K21_100 * ao_error_a; +} + +static void +ao_kalman_correct_accel(void) +{ + ao_kalman_err_accel(); + +#ifdef AO_FLIGHT_TEST + if (ao_flight_tick - ao_flight_prev_tick > 5) { + ao_k_height +=(int32_t) AO_ACCEL_K0_10 * ao_error_a; + ao_k_speed += (int32_t) AO_ACCEL_K1_10 * ao_error_a; + ao_k_accel += (int32_t) AO_ACCEL_K2_10 * ao_error_a; + return; + } #endif + ao_k_height += (int32_t) AO_ACCEL_K0_100 * ao_error_a; + ao_k_speed += (int32_t) AO_ACCEL_K1_100 * ao_error_a; + ao_k_accel += (int32_t) AO_ACCEL_K2_100 * ao_error_a; +} +#endif /* HAS_ACCEL */ __xdata int32_t ao_raw_pres_sum; +#ifdef HAS_ACCEL +__xdata int32_t ao_raw_accel_sum; +#endif + /* Landing is detected by getting constant readings from both pressure and accelerometer * for a fairly long time (AO_INTERVAL_TICKS) */ @@ -235,10 +306,6 @@ ao_flight(void) ao_wakeup(DATA_TO_XDATA(&ao_flight_adc)); ao_sleep(DATA_TO_XDATA(&ao_adc_head)); while (ao_flight_adc != ao_adc_head) { -#if HAS_ACCEL - __pdata uint8_t ticks; - __pdata int16_t ao_vel_change; -#endif __xdata struct ao_adc *ao_adc; ao_flight_prev_tick = ao_flight_tick; @@ -246,9 +313,8 @@ ao_flight(void) ao_adc = &ao_adc_ring[ao_flight_adc]; ao_flight_tick = ao_adc->tick; ao_raw_pres = ao_adc->pres; - ao_flight_pres -= ao_flight_pres >> 4; - ao_flight_pres += ao_raw_pres >> 4; - + ao_raw_alt = ao_pres_to_altitude(ao_raw_pres); + ao_raw_height = ao_raw_alt - ao_ground_height; #if HAS_ACCEL ao_raw_accel = ao_adc->accel; #if HAS_ACCEL_REF @@ -335,45 +401,31 @@ ao_flight(void) ao_raw_accel = (uint16_t) ((((uint32_t) ao_raw_accel << 16) / (ao_accel_ref[ao_flight_adc] << 1))) >> 1; ao_adc->accel = ao_raw_accel; #endif - - ao_flight_accel -= ao_flight_accel >> 4; - ao_flight_accel += ao_raw_accel >> 4; - /* Update velocity - * - * The accelerometer is mounted so that - * acceleration yields negative values - * while deceleration yields positive values, - * so subtract instead of add. - */ - ticks = ao_flight_tick - ao_flight_prev_tick; - ao_vel_change = ao_ground_accel - (((ao_raw_accel + 1) >> 1) + ((ao_raw_accel_prev + 1) >> 1)); - ao_raw_accel_prev = ao_raw_accel; - - /* one is a common interval */ - if (ticks == 1) - ao_flight_vel += (int32_t) ao_vel_change; - else - ao_flight_vel += (int32_t) ao_vel_change * (int32_t) ticks; #endif -#if USE_KALMAN - if (ao_flight_state > ao_flight_idle) - ao_kalman_baro(); -#endif - ao_flight_adc = ao_adc_ring_next(ao_flight_adc); - } - - if (ao_flight_pres < ao_min_pres) - ao_min_pres = ao_flight_pres; + if (ao_flight_state > ao_flight_idle) { + ao_kalman_predict(); #if HAS_ACCEL - if (ao_flight_vel >= 0) { - if (ao_flight_vel < ao_min_vel) - ao_min_vel = ao_flight_vel; - } else { - if (-ao_flight_vel < ao_min_vel) - ao_min_vel = -ao_flight_vel; + if (ao_flight_state <= ao_flight_coast) { +#ifndef FORCE_ACCEL + if (/*ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED) &&*/ + ao_raw_alt < AO_MAX_BARO_HEIGHT) + ao_kalman_correct_both(); + else +#endif + ao_kalman_correct_accel(); + } else +#endif + if (ao_raw_alt < AO_MAX_BARO_HEIGHT || ao_flight_state >= ao_flight_drogue) + ao_kalman_correct_baro(); + ao_height = from_fix(ao_k_height); + ao_speed = from_fix(ao_k_speed); + ao_accel = from_fix(ao_k_accel); + if (ao_height > ao_max_height) + ao_max_height = ao_height; + } + ao_flight_adc = ao_adc_ring_next(ao_flight_adc); } -#endif switch (ao_flight_state) { case ao_flight_startup: @@ -391,35 +443,25 @@ ao_flight(void) ++nsamples; continue; } + ao_config_get(); #if HAS_ACCEL ao_ground_accel = ao_raw_accel_sum >> 9; + ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; + ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; #endif ao_ground_pres = ao_raw_pres_sum >> 9; - ao_min_pres = ao_ground_pres; - ao_config_get(); -#if USE_KALMAN ao_ground_height = ao_pres_to_altitude(ao_ground_pres); -#endif - ao_main_pres = ao_altitude_to_pres(ao_pres_to_altitude(ao_ground_pres) + ao_config.main_deploy); -#if HAS_ACCEL - ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; - ao_flight_vel = 0; - ao_min_vel = 0; - ao_old_vel = ao_flight_vel; - ao_old_vel_tick = ao_flight_tick; -#endif /* Check to see what mode we should go to. * - Invalid mode if accel cal appears to be out * - pad mode if we're upright, * - idle mode otherwise */ - ao_config_get(); #if HAS_ACCEL if (ao_config.accel_plus_g == 0 || ao_config.accel_minus_g == 0 || - ao_flight_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || - ao_flight_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) + ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || + ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) { /* Detected an accel value outside -1.5g to 1.5g * (or uncalibrated values), so we go into invalid mode @@ -430,7 +472,7 @@ ao_flight(void) #endif if (!ao_flight_force_idle #if HAS_ACCEL - && ao_flight_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP + && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP #endif ) { @@ -465,57 +507,27 @@ ao_flight(void) break; case ao_flight_pad: -#if HAS_ACCEL - /* Trim velocity - * - * Once a second, remove any velocity from - * a second ago - */ - if ((int16_t) (ao_flight_tick - ao_old_vel_tick) >= AO_SEC_TO_TICKS(1)) { - ao_old_vel_tick = ao_flight_tick; - ao_flight_vel -= ao_old_vel; - ao_old_vel = ao_flight_vel; - } -#endif /* pad to boost: * - * accelerometer: > 2g AND velocity > 5m/s - * OR * barometer: > 20m vertical motion + * OR + * accelerometer: > 2g AND velocity > 5m/s * * The accelerometer should always detect motion before * the barometer, but we use both to make sure this - * transition is detected + * transition is detected. If the device + * doesn't have an accelerometer, then ignore the + * speed and acceleration as they are quite noisy + * on the pad. */ -#if USE_KALMAN + if (ao_height > AO_M_TO_HEIGHT(20) #if HAS_ACCEL - /* - * With an accelerometer, either to detect launch - */ - if ((ao_k_accel > to_fix32(20) && - ao_k_speed > to_fix32(5)) || - ao_k_height > to_fix32(20)) -#else - /* - * Without an accelerometer, the barometer is far too - * noisy to rely on speed or acceleration data - */ - if (ao_k_height > to_fix32(20)) -#endif -#else - if ( -#if HAS_ACCEL - (ao_flight_accel < ao_ground_accel - ACCEL_BOOST && - ao_flight_vel > ACCEL_VEL_BOOST) || -#endif - ao_flight_pres < ao_ground_pres - BARO_LAUNCH) + || (ao_accel > AO_MSS_TO_ACCEL(20) && + ao_speed > AO_MS_TO_SPEED(5)) #endif + ) { -#if HAS_ACCEL || USE_KALMAN ao_flight_state = ao_flight_boost; -#else - ao_flight_state = ao_flight_coast; -#endif ao_launch_tick = ao_flight_tick; /* start logging data */ @@ -537,7 +549,6 @@ ao_flight(void) break; } break; -#if HAS_ACCEL || USE_KALMAN case ao_flight_boost: /* boost to fast: @@ -550,13 +561,8 @@ ao_flight(void) * deceleration, or by waiting until the maximum burn duration * (15 seconds) has past. */ -#if USE_KALMAN - if ((ao_k_accel < to_fix32(-10) && ao_k_height > to_fix32(100)) || - (int16_t) (ao_flight_tick - ao_launch_tick) > BOOST_TICKS_MAX) -#else - if (ao_flight_accel > ao_ground_accel + ACCEL_COAST || + if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || (int16_t) (ao_flight_tick - ao_launch_tick) > BOOST_TICKS_MAX) -#endif { ao_flight_state = ao_flight_fast; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); @@ -564,62 +570,28 @@ ao_flight(void) } break; case ao_flight_fast: - - /* fast to coast: - * - * accelerometer: integrated velocity < 200 m/s - * OR - * barometer: fall at least 500m from max altitude - * - * This extra state is required to avoid mis-detecting - * apogee due to mach transitions. - * - * XXX this is essentially a single-detector test - * as the 500m altitude change would likely result - * in a loss of the rocket. More data on precisely - * how big a pressure change the mach transition - * generates would be useful here. + /* + * This is essentially the same as coast, + * but the barometer is being ignored as + * it may be unreliable. */ -#if USE_KALMAN - if (ao_k_speed < to_fix32(200) || - ao_k_height < ao_k_max_height - to_fix32(500)) -#else - if (ao_flight_vel < ACCEL_VEL_MACH || - ao_flight_pres > ao_min_pres + BARO_COAST) -#endif - { -#if HAS_ACCEL - /* set min velocity to current velocity for - * apogee detect - */ - ao_min_vel = abs(ao_flight_vel); -#endif + if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) { ao_flight_state = ao_flight_coast; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + break; } break; -#endif /* HAS_ACCEL */ case ao_flight_coast: -#if USE_KALMAN /* apogee detect: coast to drogue deploy: * * speed: < 0 - */ - if (ao_k_speed < 0) -#else - /* apogee detect: coast to drogue deploy: - * - * barometer: fall at least 10m * - * It would be nice to use the accelerometer - * to detect apogee as well, but tests have - * shown that flights far from vertical would - * grossly mis-detect apogee. So, for now, - * we'll trust to a single sensor for this test + * Also make sure the model altitude is tracking + * the measured altitude reasonably closely; otherwise + * we're probably transsonic. */ - if (ao_flight_pres > ao_min_pres + BARO_APOGEE) -#endif + if (ao_speed < 0 && (ao_raw_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100)) { /* ignite the drogue charge */ ao_ignite(ao_igniter_drogue); @@ -627,32 +599,15 @@ ao_flight(void) /* slow down the telemetry system */ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); -#if !USE_KALMAN - /* slow down the ADC sample rate */ - ao_timer_set_adc_interval(10); -#endif - /* - * Start recording min/max accel and pres for a while + * Start recording min/max height * to figure out when the rocket has landed */ - /* Set the 'last' limits to max range to prevent - * early resting detection - */ -#if HAS_ACCEL - ao_interval_min_accel = 0; - ao_interval_max_accel = 0x7fff; -#endif - ao_interval_min_pres = 0; - ao_interval_max_pres = 0x7fff; /* initialize interval values */ ao_interval_end = ao_flight_tick + AO_INTERVAL_TICKS; - ao_interval_cur_min_pres = ao_interval_cur_max_pres = ao_flight_pres; -#if HAS_ACCEL - ao_interval_cur_min_accel = ao_interval_cur_max_accel = ao_flight_accel; -#endif + ao_interval_min_height = ao_interval_max_height = ao_height; /* and enter drogue state */ ao_flight_state = ao_flight_drogue; @@ -674,11 +629,7 @@ ao_flight(void) * at that point. Perhaps also use the drogue sense lines * to notice continutity? */ -#if USE_KALMAN - if (from_fix(ao_k_height) < ao_config.main_deploy) -#else - if (ao_flight_pres >= ao_main_pres) -#endif + if (ao_height <= ao_config.main_deploy) { ao_ignite(ao_igniter_main); ao_flight_state = ao_flight_main; @@ -690,39 +641,17 @@ ao_flight(void) /* drogue/main to land: * - * accelerometer: value stable - * AND * barometer: altitude stable and within 1000m of the launch altitude */ - if (ao_flight_pres < ao_interval_cur_min_pres) - ao_interval_cur_min_pres = ao_flight_pres; - if (ao_flight_pres > ao_interval_cur_max_pres) - ao_interval_cur_max_pres = ao_flight_pres; -#if HAS_ACCEL - if (ao_flight_accel < ao_interval_cur_min_accel) - ao_interval_cur_min_accel = ao_flight_accel; - if (ao_flight_accel > ao_interval_cur_max_accel) - ao_interval_cur_max_accel = ao_flight_accel; -#endif + if (ao_height < ao_interval_min_height) + ao_interval_min_height = ao_height; + if (ao_height > ao_interval_max_height) + ao_interval_max_height = ao_height; if ((int16_t) (ao_flight_tick - ao_interval_end) >= 0) { - ao_interval_max_pres = ao_interval_cur_max_pres; - ao_interval_min_pres = ao_interval_cur_min_pres; - ao_interval_cur_min_pres = ao_interval_cur_max_pres = ao_flight_pres; -#if HAS_ACCEL - ao_interval_max_accel = ao_interval_cur_max_accel; - ao_interval_min_accel = ao_interval_cur_min_accel; - ao_interval_cur_min_accel = ao_interval_cur_max_accel = ao_flight_accel; -#endif - ao_interval_end = ao_flight_tick + AO_INTERVAL_TICKS; - - if ( -#if HAS_ACCEL - (uint16_t) (ao_interval_max_accel - ao_interval_min_accel) < (uint16_t) ACCEL_INT_LAND && -#endif - ao_flight_pres > ao_ground_pres - BARO_LAND && - (uint16_t) (ao_interval_max_pres - ao_interval_min_pres) < (uint16_t) BARO_INT_LAND) + if (ao_height < AO_M_TO_HEIGHT(1000) && + ao_interval_max_height - ao_interval_min_height < AO_M_TO_HEIGHT(5)) { ao_flight_state = ao_flight_landed; @@ -733,6 +662,8 @@ ao_flight(void) ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } + ao_interval_min_height = ao_interval_max_height = ao_height; + ao_interval_end = ao_flight_tick + AO_INTERVAL_TICKS; } break; case ao_flight_landed: diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 16167644..e7bfbdd2 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -29,6 +29,10 @@ #define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) #define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) +#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) +#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) +#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) + /* * One set of samples read from the A/D converter */ @@ -143,15 +147,26 @@ struct ao_config ao_config; #ifndef HAS_ACCEL #define HAS_ACCEL 1 #define HAS_ACCEL_REF 0 -#define USE_KALMAN 0 -#else -#define USE_KALMAN 1 #endif #include "ao_flight.c" #define to_double(f) ((f) / 65536.0) +#define GRAVITY 9.80665 +extern int16_t ao_ground_accel, ao_raw_accel; +extern int16_t ao_accel_2g; + +int32_t drogue_height; +int32_t main_height; + +int tick_offset; +uint16_t prev_tick; +static int ao_records_read = 0; +static int ao_eof_read = 0; +static int ao_flight_ground_accel; +static int ao_flight_started = 0; + void ao_insert(void) { @@ -159,33 +174,39 @@ ao_insert(void) ao_adc_head = ao_adc_ring_next(ao_adc_head); if (ao_summary) return; - if (ao_flight_state != ao_flight_startup) { -#if USE_KALMAN - printf("time %7.2f accel %d pres %d k_height %8.2f k_speed %8.5f k_accel %8.5f\n", - (double) ao_adc_static.tick / 100, - ao_adc_static.accel, - ao_adc_static.pres, - to_double(ao_k_height), - to_double(ao_k_speed), - to_double(ao_k_accel)); -#else - printf("time %g accel %d pres %d\n", - (double) ao_adc_static.tick / 100, - ao_adc_static.accel, - ao_adc_static.pres); -#endif + if (ao_flight_state == ao_flight_startup) + return; + { + double height = ao_pres_to_altitude(ao_raw_pres) - ao_ground_height; + double accel = ((ao_flight_ground_accel - ao_adc_static.accel) * GRAVITY * 2.0) / + (ao_config.accel_minus_g - ao_config.accel_plus_g); + + if (!tick_offset) + tick_offset = ao_adc_static.tick; + if (!drogue_height && ao_flight_state >= ao_flight_drogue) + drogue_height = ao_k_height; + if (!main_height && ao_flight_state >= ao_flight_main) + main_height = ao_k_height; + if ((prev_tick - ao_adc_static.tick) > 0) + tick_offset += 65536; + prev_tick = ao_adc_static.tick; + printf("%7.2f height %g accel %g state %s k_height %g k_speed %g k_accel %g drogue %g main %g error %d\n", + (double) (ao_adc_static.tick + tick_offset) / 100, + height, + accel, + ao_state_names[ao_flight_state], + ao_k_height / 65536.0, + ao_k_speed / 65536.0 / 16.0, + ao_k_accel / 65536.0 / 16.0, + drogue_height / 65536.0, + main_height / 65536.0, + ao_error_h_sq_avg); } } -static int ao_records_read = 0; -static int ao_eof_read = 0; -static int ao_flight_ground_accel; -static int ao_flight_started = 0; - void ao_sleep(void *wchan) { - ao_dump_state(); if (wchan == &ao_adc_head) { char type; uint16_t tick; @@ -291,19 +312,6 @@ ao_dump_state(void) return; if (ao_summary) return; -#if HAS_ACCEL - printf ("\t\t\t\t\t%s accel %g vel %g alt %d main %d\n", - ao_state_names[ao_flight_state], - (ao_ground_accel - ao_flight_accel) / COUNTS_PER_G * GRAVITY, - (double) ao_flight_vel / 100 / COUNTS_PER_G * GRAVITY, - ao_pres_to_altitude(ao_flight_pres) - ao_pres_to_altitude(ao_ground_pres), - ao_pres_to_altitude(ao_main_pres) - ao_pres_to_altitude(ao_ground_pres)); -#else - printf ("\t\t\t\t\t%s alt %d main %d\n", - ao_state_names[ao_flight_state], - ao_pres_to_altitude(ao_flight_pres) - ao_pres_to_altitude(ao_ground_pres), - ao_pres_to_altitude(ao_main_pres) - ao_pres_to_altitude(ao_ground_pres)); -#endif if (ao_flight_state == ao_flight_landed) exit(0); } diff --git a/src/ao_log_tiny.c b/src/ao_log_tiny.c index fad2a242..f0c0662a 100644 --- a/src/ao_log_tiny.c +++ b/src/ao_log_tiny.c @@ -69,7 +69,7 @@ ao_log(void) if (ao_log_tiny_state == ao_flight_landed) ao_log_stop(); } - ao_log_tiny_data(ao_k_height >> 16); + ao_log_tiny_data(ao_height); time += ao_log_tiny_interval; delay = time - ao_time(); if (delay > 0) diff --git a/src/ao_monitor.c b/src/ao_monitor.c index d6fd8305..8f290071 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -92,23 +92,23 @@ ao_monitor(void) recv.telemetry.accel_plus_g, recv.telemetry.accel_minus_g); -#if 0 - /* Kalman state values */ - printf(AO_TELEM_KALMAN_HEIGHT " %d " - AO_TELEM_KALMAN_SPEED " %d " - AO_TELEM_KALMAN_ACCEL " %d ", - recv.telemetry.height, - recv.telemetry.speed, - recv.telemetry.accel); -#else - /* Ad-hoc flight values */ - printf(AO_TELEM_ADHOC_ACCEL " %d " - AO_TELEM_ADHOC_SPEED " %ld " - AO_TELEM_ADHOC_BARO " %d ", - recv.telemetry.flight_accel, - recv.telemetry.flight_vel, - recv.telemetry.flight_pres); -#endif + if (recv.telemetry.u.k.unused == 0x8000) { + /* Kalman state values */ + printf(AO_TELEM_KALMAN_HEIGHT " %d " + AO_TELEM_KALMAN_SPEED " %d " + AO_TELEM_KALMAN_ACCEL " %d ", + recv.telemetry.height, + recv.telemetry.u.k.speed, + recv.telemetry.accel); + } else { + /* Ad-hoc flight values */ + printf(AO_TELEM_ADHOC_ACCEL " %d " + AO_TELEM_ADHOC_SPEED " %ld " + AO_TELEM_ADHOC_BARO " %d ", + recv.telemetry.accel, + recv.telemetry.u.flight_vel, + recv.telemetry.height); + } ao_gps_print(&recv.telemetry.gps); ao_gps_tracking_print(&recv.telemetry.gps_tracking); putchar('\n'); diff --git a/src/ao_pins.h b/src/ao_pins.h index c602268b..a4a93aab 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -28,7 +28,6 @@ #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 0 #define HAS_DBG 1 - #define USE_KALMAN 0 #define DBG_ON_P1 1 #define DBG_ON_P0 0 #define IGNITE_ON_P2 1 @@ -53,7 +52,6 @@ #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 0 #define HAS_DBG 1 - #define USE_KALMAN 0 #define DBG_ON_P1 1 #define DBG_ON_P0 0 #define IGNITE_ON_P2 1 @@ -103,7 +101,6 @@ #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 1 #define HAS_DBG 0 - #define USE_KALMAN 1 #define IGNITE_ON_P2 0 #define IGNITE_ON_P0 1 #define PACKET_HAS_MASTER 0 @@ -126,7 +123,6 @@ #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 1 #define HAS_DBG 0 - #define USE_KALMAN 1 #define IGNITE_ON_P2 0 #define IGNITE_ON_P0 1 #define PACKET_HAS_MASTER 0 @@ -147,7 +143,6 @@ #define HAS_SERIAL_1 1 #define HAS_ADC 1 #define HAS_DBG 0 - #define USE_KALMAN 0 #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 0 #define DBG_ON_P1 0 diff --git a/src/ao_report.c b/src/ao_report.c index 3223390f..4f7fd657 100644 --- a/src/ao_report.c +++ b/src/ao_report.c @@ -87,7 +87,7 @@ ao_report_digit(uint8_t digit) __reentrant static void ao_report_altitude(void) { - __xdata int16_t agl = ao_pres_to_altitude(ao_min_pres) - ao_pres_to_altitude(ao_ground_pres); + __xdata int16_t agl = ao_max_height; __xdata uint8_t digits[10]; __xdata uint8_t ndigits, i; diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 6556ce32..9a86882f 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -45,12 +45,13 @@ ao_telemetry(void) time = ao_rdf_time = ao_time(); while (ao_telemetry_interval) { telemetry.flight_state = ao_flight_state; + telemetry.height = ao_height; + telemetry.u.k.speed = ao_speed; + telemetry.accel = ao_accel; + telemetry.u.k.unused = 0x8000; #if HAS_ACCEL - telemetry.flight_accel = ao_flight_accel; telemetry.ground_accel = ao_ground_accel; - telemetry.flight_vel = ao_flight_vel; #endif - telemetry.flight_pres = ao_flight_pres; telemetry.ground_pres = ao_ground_pres; #if HAS_ADC ao_adc_get(&telemetry.adc); diff --git a/src/ao_telemetry_tiny.c b/src/ao_telemetry_tiny.c index 83ba7fc0..6f2ddda1 100644 --- a/src/ao_telemetry_tiny.c +++ b/src/ao_telemetry_tiny.c @@ -43,9 +43,9 @@ ao_telemetry_tiny(void) time = ao_rdf_time = ao_time(); while (ao_telemetry_tiny_interval) { telemetry_tiny.flight_state = ao_flight_state; - telemetry_tiny.height = ao_k_height >> 16; - telemetry_tiny.speed = ao_k_speed >> 12; - telemetry_tiny.accel = ao_k_accel >> 12; + telemetry_tiny.height = ao_height; + telemetry_tiny.speed = ao_speed; + telemetry_tiny.accel = ao_accel; telemetry_tiny.ground_pres = ao_ground_pres; ao_adc_get(&telemetry_tiny.adc); ao_radio_send(&telemetry_tiny, sizeof (telemetry_tiny)); diff --git a/src/test/.gitignore b/src/test/.gitignore index 0a43de8a..33c7ef35 100644 --- a/src/test/.gitignore +++ b/src/test/.gitignore @@ -1,5 +1,6 @@ ao_flight_test ao_flight_test_baro +ao_flight_test_accel ao_gps_test ao_gps_test_skytraq ao_convert_test diff --git a/src/test/Makefile b/src/test/Makefile index 853713fa..433f749b 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,6 +1,7 @@ vpath % .. +vpath % ../kalman -PROGS=ao_flight_test ao_flight_test_baro ao_gps_test ao_gps_test_skytraq ao_convert_test +PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_gps_test ao_gps_test_skytraq ao_convert_test CFLAGS=-I.. -I. @@ -11,12 +12,15 @@ clean: install: -ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c altitude.h +ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c altitude.h ao_kalman.h cc -g -o $@ $< -ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c altitude.h +ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c altitude.h ao_kalman.h cc -g -o $@ -DHAS_ACCEL=0 ../ao_flight_test.c +ao_flight_test_accel: ao_flight_test.c ao_host.h ao_flight.c altitude.h ao_kalman.h + cc -g -o $@ -DFORCE_ACCEL=1 ../ao_flight_test.c + ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h cc -g -o $@ $< @@ -25,3 +29,6 @@ ao_gps_test_skytraq: ao_gps_test_skytraq.c ao_gps_skytraq.c ao_gps_print.c ao_ho ao_convert_test: ao_convert_test.c ao_convert.c altitude.h cc -g -o $@ $< + +../ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c + sh $< > $@ diff --git a/src/test/plottest b/src/test/plottest new file mode 100755 index 00000000..76af5ee7 --- /dev/null +++ b/src/test/plottest @@ -0,0 +1,16 @@ +gnuplot -persist << EOF +set ylabel "altitude (m)" +set y2label "velocity (m/s), acceleration(m/s²)" +set xlabel "time (s)" +set xtics border out nomirror +set ytics border out nomirror +set y2tics border out nomirror +plot "$1" using 1:3 with lines axes x1y1 title "raw height",\ +"$1" using 1:5 with lines axes x1y2 title "raw accel",\ +"$1" using 1:9 with lines axes x1y1 title "height",\ +"$1" using 1:11 with lines axes x1y2 title "speed",\ +"$1" using 1:13 with lines axes x1y2 title "accel",\ +"$1" using 1:15 with lines axes x1y1 title "drogue",\ +"$1" using 1:17 with lines axes x1y1 title "main",\ +"$1" using 1:19 with lines axes x1y1 title "error" +EOF diff --git a/src/test/run-one b/src/test/run-one new file mode 100755 index 00000000..f9d21576 --- /dev/null +++ b/src/test/run-one @@ -0,0 +1,32 @@ +#!/bin/sh + +./ao_flight_test "$1" > run-out.full +./ao_flight_test_baro "$1" > run-out.baro +./ao_flight_test_accel "$1" > run-out.accel + +gnuplot -persist << EOF +set ylabel "altitude (m)" +set y2label "velocity (m/s), acceleration(m/s²)" +set xlabel "time (s)" +set xtics border out nomirror +set ytics border out nomirror +set y2tics border out nomirror +set title "$1" +plot "run-out.full" using 1:3 with lines lw 2 lt 1 axes x1y1 title "raw height",\ +"run-out.full" using 1:5 with lines lw 2 lt 1 axes x1y2 title "raw accel",\ +"run-out.full" using 1:9 with lines lt 2 axes x1y1 title "full height",\ +"run-out.full" using 1:11 with lines lt 2 axes x1y2 title "full speed",\ +"run-out.full" using 1:13 with lines lt 2 axes x1y2 title "full accel",\ +"run-out.full" using 1:15 with lines lt 2 axes x1y1 title "full drogue",\ +"run-out.full" using 1:17 with lines lt 2 axes x1y1 title "full main", \ +"run-out.baro" using 1:9 with lines lt 3 axes x1y1 title "baro height",\ +"run-out.baro" using 1:11 with lines lt 3 axes x1y2 title "baro speed",\ +"run-out.baro" using 1:13 with lines lt 3 axes x1y2 title "baro accel",\ +"run-out.baro" using 1:15 with lines lt 3 axes x1y1 title "baro drogue",\ +"run-out.baro" using 1:17 with lines lt 3 axes x1y1 title "baro main",\ +"run-out.accel" using 1:9 with lines lt 4 axes x1y1 title "accel height",\ +"run-out.accel" using 1:11 with lines lt 4 axes x1y2 title "accel speed",\ +"run-out.accel" using 1:13 with lines lt 4 axes x1y2 title "accel accel",\ +"run-out.accel" using 1:15 with lines lt 4 axes x1y1 title "accel drogue",\ +"run-out.accel" using 1:17 with lines lt 4 axes x1y1 title "accel main" +EOF diff --git a/src/test/test-flights b/src/test/test-flights index a9a2ecca..afdaba5a 100644 --- a/src/test/test-flights +++ b/src/test/test-flights @@ -7,7 +7,6 @@ 2009-07-18-serial-001-flight-007.eeprom 2009-08-22-serial-001-flight-001.eeprom 2009-08-22-serial-010-flight-001.eeprom -2009-09-05-serial-008-flight-002.eeprom 2009-09-05-serial-010-flight-002.eeprom 2009-09-05-serial-011-flight-001.eeprom 2009-09-11-serial-008-flight-003.eeprom -- cgit v1.2.3 From c14d6c5ace1d67bd948273ceb7eb6807b29c3806 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 22 Mar 2011 08:51:23 +0900 Subject: altos: Compute a 'trust' value for the barometer Instead of making the baro use/don't-use decision binary, use a 'trust value' which slowly migrates from baro+accel to accel-only mode. This eliminates bumps in the data from a rapid shift. Signed-off-by: Keith Packard --- src/ao_flight.c | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index c65670f0..b86603e4 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -135,7 +135,7 @@ static __pdata int32_t ao_k_accel; /* * Above this height, the baro sensor doesn't work */ -#define AO_MAX_BARO_HEIGHT 8000 +#define AO_MAX_BARO_HEIGHT 12000 /* * Above this speed, baro measurements are unreliable @@ -168,6 +168,11 @@ static void ao_kalman_err_height(void) { int16_t e; + int16_t height_distrust; +#if HAS_ACCEL + int16_t speed_distrust; +#endif + ao_error_h = ao_raw_height - (int16_t) (ao_k_height >> 16); e = ao_error_h; @@ -177,6 +182,31 @@ ao_kalman_err_height(void) e = 127; ao_error_h_sq_avg -= ao_error_h_sq_avg >> 4; ao_error_h_sq_avg += (e * e) >> 4; + + height_distrust = ao_raw_height - AO_MAX_BARO_HEIGHT; +#ifdef AO_FLIGHT_TEST + if (height_distrust > 0) + printf ("height_distrust %d\n", height_distrust); +#endif +#if HAS_ACCEL + speed_distrust = (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) >> 4; +#ifdef AO_FLIGHT_TEST + if (speed_distrust > 0) + printf ("speed distrust %d\n", speed_distrust); +#endif + if (speed_distrust <= 0) + speed_distrust = 0; + else if (speed_distrust > height_distrust) + height_distrust = speed_distrust; +#endif + if (height_distrust <= 0) + height_distrust = 0; + + if (height_distrust) { + if (height_distrust > 0x100) + height_distrust = 0x100; + ao_error_h = (int16_t) ((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8; + } } static void @@ -407,16 +437,13 @@ ao_flight(void) ao_kalman_predict(); #if HAS_ACCEL if (ao_flight_state <= ao_flight_coast) { -#ifndef FORCE_ACCEL - if (/*ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED) &&*/ - ao_raw_alt < AO_MAX_BARO_HEIGHT) - ao_kalman_correct_both(); - else +#ifdef FORCE_ACCEL + ao_kalman_correct_accel(); +#else + ao_kalman_correct_both(); #endif - ao_kalman_correct_accel(); } else #endif - if (ao_raw_alt < AO_MAX_BARO_HEIGHT || ao_flight_state >= ao_flight_drogue) ao_kalman_correct_baro(); ao_height = from_fix(ao_k_height); ao_speed = from_fix(ao_k_speed); -- cgit v1.2.3 From 6864e06d88a5b908cffa7c4cd2be8969ff46ce4d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 22 Mar 2011 16:51:04 +0900 Subject: altos/kalman: Kalman terms can be > 1, use 32-bit fixed point Because speed and acceleration are scaled by 16, it's fairly common for the kalman terms to end up larger than 1. Instead of trying to fuss with 16-bit values and shifts, just use 32-bit values. Signed-off-by: Keith Packard --- src/kalman/kalman.5c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/kalman/kalman.5c b/src/kalman/kalman.5c index f7347184..cfb7abea 100755 --- a/src/kalman/kalman.5c +++ b/src/kalman/kalman.5c @@ -460,19 +460,17 @@ void main() { mat_t k = converge(param); int[] d = dims(k); int time_inc = floor(1/time_step + 0.5); - if (d[1] == 2) { - for (int i = 0; i < d[0]; i++) - for (int j = 0; j < d[1]; j++) - printf ("#define %s_K%d%d_%d to_fix16(%12.10f)\n", - prefix, i, j, time_inc, k[i,j]); - } else { - for (int i = 0; i < d[0]; i++) { - printf ("#define %s_K%d_%d to_fix16(%12.10f)\n", - prefix, i, time_inc, k[i,0]); + for (int i = 0; i < d[0]; i++) + for (int j = 0; j < d[1]; j++) { + string name; + if (d[1] == 1) + name = sprintf("%s_K%d_%d", prefix, i, time_inc); + else + name = sprintf("%s_K%d%d_%d", prefix, i, j, time_inc); + printf ("#define %s to_fix32(%12.10f)\n", name, k[i,j]); } - } printf ("\n"); - return; + exit(0); } string[dim(argv) - user_argind] rest = { [i] = argv[i+user_argind] }; -- cgit v1.2.3 From f3053b1f3c85d4fd84b3c6cc87858f433166df34 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 22 Mar 2011 17:04:07 +0900 Subject: altos: Clean up some debug stuff in ao_flight.c Remove some spurious printf debugging. Remove an attempt at discovering broken accelerometer code. Signed-off-by: Keith Packard --- src/ao_flight.c | 24 ------------------------ 1 file changed, 24 deletions(-) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index b86603e4..7f194e04 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -184,16 +184,8 @@ ao_kalman_err_height(void) ao_error_h_sq_avg += (e * e) >> 4; height_distrust = ao_raw_height - AO_MAX_BARO_HEIGHT; -#ifdef AO_FLIGHT_TEST - if (height_distrust > 0) - printf ("height_distrust %d\n", height_distrust); -#endif #if HAS_ACCEL speed_distrust = (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) >> 4; -#ifdef AO_FLIGHT_TEST - if (speed_distrust > 0) - printf ("speed distrust %d\n", speed_distrust); -#endif if (speed_distrust <= 0) speed_distrust = 0; else if (speed_distrust > height_distrust) @@ -247,22 +239,6 @@ ao_kalman_correct_both(void) ao_kalman_err_height(); ao_kalman_err_accel(); -#if 0 - /* - * Check to see if things are crazy here -- - * if the computed height is far above the - * measured height, we assume that the flight - * trajectory is not vertical, and so ignore - * the accelerometer for the remainder of the - * flight. - */ - if (ao_error_h_sq_avg > 10) - { - ao_kalman_correct_baro(); - return; - } -#endif - #ifdef AO_FLIGHT_TEST if (ao_flight_tick - ao_flight_prev_tick > 5) { ao_k_height += -- cgit v1.2.3 From f30de5766c1eefb18c7d024a2cf10ce02de41071 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 22 Mar 2011 21:29:05 +0900 Subject: altos: Add ao_flight_debug code Trace the kalman filter to make sure it's working. Signed-off-by: Keith Packard --- src/ao_flight.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index 7f194e04..4c65344f 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -153,6 +153,11 @@ ao_kalman_predict(void) return; } + if (ao_flight_debug) { + printf ("predict speed %g + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), ao_accel / 16.0, AO_K_STEP_100 / 65536.0, + (ao_k_speed + (int32_t) ao_accel * AO_K_STEP_100) / (65536.0 * 16.0)); + } #endif ao_k_height += ((int32_t) ao_speed * AO_K_STEP_100 + (int32_t) ao_accel * AO_K_STEP_2_2_100) >> 4; @@ -195,9 +200,21 @@ ao_kalman_err_height(void) height_distrust = 0; if (height_distrust) { +#ifdef AO_FLIGHT_TEST + int old_ao_error_h = ao_error_h; +#endif if (height_distrust > 0x100) height_distrust = 0x100; ao_error_h = (int16_t) ((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8; +#ifdef AO_FLIGHT_TEST + if (ao_flight_debug) { + printf("over height %g over speed %g distrust: %g height: error %d -> %d\n", + (double) (ao_raw_height - AO_MAX_BARO_HEIGHT), + (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) / 16.0, + height_distrust / 256.0, + old_ao_error_h, ao_error_h); + } +#endif } } @@ -241,6 +258,15 @@ ao_kalman_correct_both(void) #ifdef AO_FLIGHT_TEST if (ao_flight_tick - ao_flight_prev_tick > 5) { + if (ao_flight_debug) { + printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), + (double) ao_error_h, AO_BOTH_K10_10 / 65536.0, + (double) ao_error_a, AO_BOTH_K11_10 / 65536.0, + (ao_k_speed + + (int32_t) AO_BOTH_K10_10 * ao_error_h + + (int32_t) AO_BOTH_K11_10 * ao_error_a) / (65536.0 * 16.0)); + } ao_k_height += (int32_t) AO_BOTH_K00_10 * ao_error_h + (int32_t) (AO_BOTH_K01_10 >> 4) * ao_error_a; @@ -252,6 +278,15 @@ ao_kalman_correct_both(void) (int32_t) AO_BOTH_K21_10 * ao_error_a; return; } + if (ao_flight_debug) { + printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), + (double) ao_error_h, AO_BOTH_K10_100 / 65536.0, + (double) ao_error_a, AO_BOTH_K11_100 / 65536.0, + (ao_k_speed + + (int32_t) AO_BOTH_K10_100 * ao_error_h + + (int32_t) AO_BOTH_K11_100 * ao_error_a) / (65536.0 * 16.0)); + } #endif ao_k_height += (int32_t) AO_BOTH_K00_100 * ao_error_h + @@ -264,23 +299,23 @@ ao_kalman_correct_both(void) (int32_t) AO_BOTH_K21_100 * ao_error_a; } +#ifdef FORCE_ACCEL static void ao_kalman_correct_accel(void) { ao_kalman_err_accel(); -#ifdef AO_FLIGHT_TEST if (ao_flight_tick - ao_flight_prev_tick > 5) { ao_k_height +=(int32_t) AO_ACCEL_K0_10 * ao_error_a; ao_k_speed += (int32_t) AO_ACCEL_K1_10 * ao_error_a; ao_k_accel += (int32_t) AO_ACCEL_K2_10 * ao_error_a; return; } -#endif ao_k_height += (int32_t) AO_ACCEL_K0_100 * ao_error_a; ao_k_speed += (int32_t) AO_ACCEL_K1_100 * ao_error_a; ao_k_accel += (int32_t) AO_ACCEL_K2_100 * ao_error_a; } +#endif #endif /* HAS_ACCEL */ __xdata int32_t ao_raw_pres_sum; -- cgit v1.2.3 From a80d3836cfce3d4cfa7a71068539415c2dc421cd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 22 Mar 2011 21:50:29 +0900 Subject: altos: Missing parens and some bad arithmetic in the kalman code Fixed point computations are a pain. Signed-off-by: Keith Packard --- src/ao_flight.c | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index 4c65344f..39325a69 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -140,7 +140,7 @@ static __pdata int32_t ao_k_accel; /* * Above this speed, baro measurements are unreliable */ -#define AO_MAX_BARO_SPEED 300 +#define AO_MAX_BARO_SPEED 200 static void ao_kalman_predict(void) @@ -185,12 +185,20 @@ ao_kalman_err_height(void) e = -e; if (e > 127) e = 127; +#if HAS_ACCEL + ao_error_h_sq_avg -= ao_error_h_sq_avg >> 2; + ao_error_h_sq_avg += (e * e) >> 2; +#else ao_error_h_sq_avg -= ao_error_h_sq_avg >> 4; ao_error_h_sq_avg += (e * e) >> 4; +#endif height_distrust = ao_raw_height - AO_MAX_BARO_HEIGHT; #if HAS_ACCEL - speed_distrust = (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) >> 4; + /* speed is stored * 16, but we need to ramp between 200 and 328, so + * we want to multiply by 2. The result is a shift by 3. + */ + speed_distrust = (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) >> (4 - 1); if (speed_distrust <= 0) speed_distrust = 0; else if (speed_distrust > height_distrust) @@ -205,7 +213,7 @@ ao_kalman_err_height(void) #endif if (height_distrust > 0x100) height_distrust = 0x100; - ao_error_h = (int16_t) ((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8; + ao_error_h = (int16_t) (((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8); #ifdef AO_FLIGHT_TEST if (ao_flight_debug) { printf("over height %g over speed %g distrust: %g height: error %d -> %d\n", @@ -269,12 +277,12 @@ ao_kalman_correct_both(void) } ao_k_height += (int32_t) AO_BOTH_K00_10 * ao_error_h + - (int32_t) (AO_BOTH_K01_10 >> 4) * ao_error_a; + (int32_t) AO_BOTH_K01_10 * ao_error_a; ao_k_speed += - ((int32_t) AO_BOTH_K10_10 << 4) * ao_error_h + + (int32_t) AO_BOTH_K10_10 * ao_error_h + (int32_t) AO_BOTH_K11_10 * ao_error_a; ao_k_accel += - ((int32_t) AO_BOTH_K20_10 << 4) * ao_error_h + + (int32_t) AO_BOTH_K20_10 * ao_error_h + (int32_t) AO_BOTH_K21_10 * ao_error_a; return; } @@ -602,23 +610,31 @@ ao_flight(void) if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || (int16_t) (ao_flight_tick - ao_launch_tick) > BOOST_TICKS_MAX) { +#if HAS_ACCEL ao_flight_state = ao_flight_fast; +#else + ao_flight_state = ao_flight_coast; +#endif ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); break; } break; +#if HAS_ACCEL case ao_flight_fast: /* * This is essentially the same as coast, * but the barometer is being ignored as * it may be unreliable. */ - if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) { + if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED) && + (ao_raw_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 30)) + { ao_flight_state = ao_flight_coast; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); break; } break; +#endif case ao_flight_coast: /* apogee detect: coast to drogue deploy: @@ -629,7 +645,11 @@ ao_flight(void) * the measured altitude reasonably closely; otherwise * we're probably transsonic. */ - if (ao_speed < 0 && (ao_raw_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100)) + if (ao_speed < 0 +#if !HAS_ACCEL + && (ao_raw_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 30) +#endif + ) { /* ignite the drogue charge */ ao_ignite(ao_igniter_drogue); -- cgit v1.2.3 From 7d7b476564a16eda81ab3406f70a21995e1b464e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 22 Mar 2011 21:51:52 +0900 Subject: altos: Fix up flight code testing This automates flight code testing by reporting mis-detected apogee or main events. Signed-off-by: Keith Packard --- src/ao_flight_test.c | 138 ++++++++++++++++++++++++++++++++++++-------------- src/test/run-one | 26 ++++++---- src/test/run-tests | 34 ++++++------- src/test/test-flights | 1 - 4 files changed, 131 insertions(+), 68 deletions(-) (limited to 'src') diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index e7bfbdd2..51a5965c 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -22,6 +22,7 @@ #include #include #include +#include #define AO_HERTZ 100 @@ -87,11 +88,27 @@ enum ao_igniter { struct ao_adc ao_adc_static; +int drogue_height; +double drogue_time; +int main_height; +double main_time; + +int tick_offset; + +static int32_t ao_k_height; + void ao_ignite(enum ao_igniter igniter) { - printf ("ignite %s at %7.2f\n", igniter == ao_igniter_drogue ? "drogue" : "main", - (double) ao_adc_static.tick / 100.0); + double time = (double) (ao_adc_static.tick + tick_offset) / 100; + + if (igniter == ao_igniter_drogue) { + drogue_time = time; + drogue_height = ao_k_height >> 16; + } else { + main_time = time; + main_height = ao_k_height >> 16; + } } struct ao_task { @@ -108,7 +125,12 @@ struct ao_task { #define AO_FLIGHT_TEST +int ao_flight_debug; + FILE *emulator_in; +char *emulator_app; +char *emulator_name; +double emulator_error_max = 10; void ao_dump_state(void); @@ -157,51 +179,84 @@ struct ao_config ao_config; extern int16_t ao_ground_accel, ao_raw_accel; extern int16_t ao_accel_2g; -int32_t drogue_height; -int32_t main_height; - -int tick_offset; uint16_t prev_tick; static int ao_records_read = 0; static int ao_eof_read = 0; static int ao_flight_ground_accel; static int ao_flight_started = 0; +static int ao_test_max_height; +static double ao_test_max_height_time; +static int ao_test_main_height; +static double ao_test_main_height_time; void ao_insert(void) { + double time; + ao_adc_ring[ao_adc_head] = ao_adc_static; ao_adc_head = ao_adc_ring_next(ao_adc_head); - if (ao_summary) - return; - if (ao_flight_state == ao_flight_startup) - return; - { + if (ao_flight_state != ao_flight_startup) { double height = ao_pres_to_altitude(ao_raw_pres) - ao_ground_height; double accel = ((ao_flight_ground_accel - ao_adc_static.accel) * GRAVITY * 2.0) / (ao_config.accel_minus_g - ao_config.accel_plus_g); if (!tick_offset) - tick_offset = ao_adc_static.tick; - if (!drogue_height && ao_flight_state >= ao_flight_drogue) - drogue_height = ao_k_height; - if (!main_height && ao_flight_state >= ao_flight_main) - main_height = ao_k_height; - if ((prev_tick - ao_adc_static.tick) > 0) + tick_offset = -ao_adc_static.tick; + if ((prev_tick - ao_adc_static.tick) > 0x400) tick_offset += 65536; prev_tick = ao_adc_static.tick; - printf("%7.2f height %g accel %g state %s k_height %g k_speed %g k_accel %g drogue %g main %g error %d\n", - (double) (ao_adc_static.tick + tick_offset) / 100, - height, - accel, - ao_state_names[ao_flight_state], - ao_k_height / 65536.0, - ao_k_speed / 65536.0 / 16.0, - ao_k_accel / 65536.0 / 16.0, - drogue_height / 65536.0, - main_height / 65536.0, - ao_error_h_sq_avg); + time = (double) (ao_adc_static.tick + tick_offset) / 100; + if (!ao_summary) { + printf("%7.2f height %g accel %g state %s k_height %g k_speed %g k_accel %g drogue %d main %d error %d\n", + time, + height, + accel, + ao_state_names[ao_flight_state], + ao_k_height / 65536.0, + ao_k_speed / 65536.0 / 16.0, + ao_k_accel / 65536.0 / 16.0, + drogue_height, + main_height, + ao_error_h_sq_avg); + } + + if (ao_test_max_height < height) { + ao_test_max_height = height; + ao_test_max_height_time = time; + } + if (height > ao_config.main_deploy) { + ao_test_main_height_time = time; + ao_test_main_height = height; + } + } +} + +void +ao_test_exit(void) +{ + double drogue_error; + double main_error; + + if (!ao_test_main_height_time) { + ao_test_main_height_time = ao_test_max_height_time; + ao_test_main_height = ao_test_max_height; + } + drogue_error = fabs(ao_test_max_height_time - drogue_time); + main_error = fabs(ao_test_main_height_time - main_time); + if (drogue_error > emulator_error_max || main_error > emulator_error_max) { + printf ("%s %s\n", + emulator_app, emulator_name); + printf ("\tApogee error %g\n", drogue_error); + printf ("\tMain error %g\n", main_error); + printf ("\tActual: apogee: %d at %7.2f main: %d at %7.2f\n", + ao_test_max_height, ao_test_max_height_time, + ao_test_main_height, ao_test_main_height_time); + printf ("\tComputed: apogee: %d at %7.2f main: %d at %7.2f\n", + drogue_height, drogue_time, main_height, main_time); + exit (1); } + exit(0); } void @@ -228,8 +283,9 @@ ao_sleep(void *wchan) if (!fgets(line, sizeof (line), emulator_in)) { if (++ao_eof_read >= 1000) { - printf ("no more data, exiting simulation\n"); - exit(0); + if (!ao_summary) + printf ("no more data, exiting simulation\n"); + ao_test_exit(); } ao_adc_static.tick += 10; ao_insert(); @@ -247,10 +303,10 @@ ao_sleep(void *wchan) tick = strtoul(words[1], NULL, 16); a = strtoul(words[2], NULL, 16); b = strtoul(words[3], NULL, 16); - } else if (nword >= 6 && strcmp(words[0], "Accel")) { + } else if (nword >= 6 && strcmp(words[0], "Accel") == 0) { ao_config.accel_plus_g = atoi(words[3]); ao_config.accel_minus_g = atoi(words[5]); - } else if (nword >= 4 && strcmp(words[0], "Main")) { + } else if (nword >= 4 && strcmp(words[0], "Main") == 0) { ao_config.main_deploy = atoi(words[2]); } else if (nword >= 36 && strcmp(words[0], "CALL") == 0) { tick = atoi(words[10]); @@ -308,21 +364,17 @@ ao_sleep(void *wchan) void ao_dump_state(void) { - if (ao_flight_state == ao_flight_startup) - return; - if (ao_summary) - return; - if (ao_flight_state == ao_flight_landed) - exit(0); } static const struct option options[] = { { .name = "summary", .has_arg = 0, .val = 's' }, + { .name = "debug", .has_arg = 0, .val = 'd' }, { 0, 0, 0, 0}, }; void run_flight_fixed(char *name, FILE *f, int summary) { + emulator_name = name; emulator_in = f; ao_summary = summary; ao_flight_init(); @@ -336,11 +388,19 @@ main (int argc, char **argv) int c; int i; - while ((c = getopt_long(argc, argv, "s", options, NULL)) != -1) { +#if HAS_ACCEL + emulator_app="full"; +#else + emulator_app="baro"; +#endif + while ((c = getopt_long(argc, argv, "sd", options, NULL)) != -1) { switch (c) { case 's': summary = 1; break; + case 'd': + ao_flight_debug = 1; + break; } } diff --git a/src/test/run-one b/src/test/run-one index f9d21576..d661abec 100755 --- a/src/test/run-one +++ b/src/test/run-one @@ -1,17 +1,24 @@ #!/bin/sh -./ao_flight_test "$1" > run-out.full -./ao_flight_test_baro "$1" > run-out.baro -./ao_flight_test_accel "$1" > run-out.accel +for i in "$@"; do +./ao_flight_test "$i" > run-out.full +./ao_flight_test_baro "$i" > run-out.baro +#./ao_flight_test_accel "$i" > run-out.accel -gnuplot -persist << EOF +#"run-out.accel" using 1:9 with lines lt 4 axes x1y1 title "accel height",\ +#"run-out.accel" using 1:11 with lines lt 4 axes x1y2 title "accel speed",\ +#"run-out.accel" using 1:13 with lines lt 4 axes x1y2 title "accel accel",\ +#"run-out.accel" using 1:15 with lines lt 4 axes x1y1 title "accel drogue",\ +#"run-out.accel" using 1:17 with lines lt 4 axes x1y1 title "accel main",\ + +gnuplot << EOF set ylabel "altitude (m)" set y2label "velocity (m/s), acceleration(m/s²)" set xlabel "time (s)" set xtics border out nomirror set ytics border out nomirror set y2tics border out nomirror -set title "$1" +set title "$i" plot "run-out.full" using 1:3 with lines lw 2 lt 1 axes x1y1 title "raw height",\ "run-out.full" using 1:5 with lines lw 2 lt 1 axes x1y2 title "raw accel",\ "run-out.full" using 1:9 with lines lt 2 axes x1y1 title "full height",\ @@ -23,10 +30,7 @@ plot "run-out.full" using 1:3 with lines lw 2 lt 1 axes x1y1 title "raw height", "run-out.baro" using 1:11 with lines lt 3 axes x1y2 title "baro speed",\ "run-out.baro" using 1:13 with lines lt 3 axes x1y2 title "baro accel",\ "run-out.baro" using 1:15 with lines lt 3 axes x1y1 title "baro drogue",\ -"run-out.baro" using 1:17 with lines lt 3 axes x1y1 title "baro main",\ -"run-out.accel" using 1:9 with lines lt 4 axes x1y1 title "accel height",\ -"run-out.accel" using 1:11 with lines lt 4 axes x1y2 title "accel speed",\ -"run-out.accel" using 1:13 with lines lt 4 axes x1y2 title "accel accel",\ -"run-out.accel" using 1:15 with lines lt 4 axes x1y1 title "accel drogue",\ -"run-out.accel" using 1:17 with lines lt 4 axes x1y1 title "accel main" +"run-out.baro" using 1:17 with lines lt 3 axes x1y1 title "baro main" +pause mouse close EOF +done \ No newline at end of file diff --git a/src/test/run-tests b/src/test/run-tests index ec279776..11b4c95c 100755 --- a/src/test/run-tests +++ b/src/test/run-tests @@ -2,21 +2,21 @@ DIR=~/src/cc1111/flights +bad_baro=0 +bad_full=0 while read flight; do - baro=`./ao_flight_test_baro -s $DIR/$flight | - awk '/drogue/ { printf "%s ", $4 } - /main/ { printf "%s\n", $4 }'` - full=`./ao_flight_test -s $DIR/$flight | - awk '/drogue/ { printf "%s ", $4 } - /main/ { printf "%s\n", $4 }'` - echo $flight $baro $full -done < test-flights | -awk '{ name = $1; - drogue_error = $2 - $4; - if (drogue_error < 0) drogue_error = -drogue_error; - main_error = $3 - $5; - if (main_error < 0) main_error = -main_error; - if (drogue_error > 4 || main_error > 4) - printf ("%s: baro drogue %f main %f. full drogue %f main %f\n", - name, $2, $3, $4, $5); - }' + if ./ao_flight_test_baro -s $DIR/$flight; then + : + else + ((bad_baro++)) + fi + if ./ao_flight_test -s $DIR/$flight; then + : + else + ((bad_full++)) + fi +done < test-flights +echo baro errors $bad_baro +echo full errors $bad_full +((bad = bad_baro + bad_full)) +exit $bad \ No newline at end of file diff --git a/src/test/test-flights b/src/test/test-flights index afdaba5a..0b90d9e0 100644 --- a/src/test/test-flights +++ b/src/test/test-flights @@ -63,7 +63,6 @@ 2010-09-24-serial-236-flight-006.eeprom 2010-09-25-serial-223-flight-001.eeprom 2010-10-17-serial-215-flight-006.eeprom -2010-10-23-serial-236-flight-008.eeprom 2011-01-30-serial-056-flight-001.eeprom 2011-01-30-serial-250-flight-002.eeprom 2011-02-19-serial-215-flight-007.eeprom -- cgit v1.2.3 From 3d2042ccc2d29e4cb8ea39c5c69d07cb7e3daeea Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 22 Mar 2011 16:55:08 +0900 Subject: altos: Restore sensible kalman values Now that the kalman code seems to work correctly, restore the sensor errors and model errors to match reality Signed-off-by: Keith Packard --- src/make-kalman | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/make-kalman b/src/make-kalman index 80157c6b..6fb181ec 100644 --- a/src/make-kalman +++ b/src/make-kalman @@ -2,17 +2,15 @@ cd ../kalman -SIGMA_ACCEL_MODEL=1 -SIGMA_BARO_MEASURE=8 -SIGMA_ACCEL_MEASURE=4 +SIGMA_BOTH="-M 2 -H 4 -A 4" +SIGMA_BARO="-M 2 -H 4 -A 4" +SIGMA_ACCEL="-M 2 -H 4 -A 4" -SIGMA="-M $SIGMA_ACCEL_MODEL -H $SIGMA_BARO_MEASURE -A $SIGMA_ACCEL_MEASURE" +nickle kalman.5c -p AO_BOTH -c both -t 0.01 $SIGMA_BOTH +nickle kalman.5c -p AO_BOTH -c both -t 0.1 $SIGMA_BOTH -nickle kalman.5c -p AO_BOTH -c both -t 0.01 $SIGMA -nickle kalman.5c -p AO_BOTH -c both -t 0.1 $SIGMA +nickle kalman.5c -p AO_ACCEL -c accel -t 0.01 $SIGMA_ACCEL +nickle kalman.5c -p AO_ACCEL -c accel -t 0.1 $SIGMA_ACCEL -nickle kalman.5c -p AO_ACCEL -c accel -t 0.01 $SIGMA -nickle kalman.5c -p AO_ACCEL -c accel -t 0.1 $SIGMA - -nickle kalman.5c -p AO_BARO -c baro -t 0.01 $SIGMA -nickle kalman.5c -p AO_BARO -c baro -t 0.1 $SIGMA +nickle kalman.5c -p AO_BARO -c baro -t 0.01 $SIGMA_BARO +nickle kalman.5c -p AO_BARO -c baro -t 0.1 $SIGMA_BARO -- cgit v1.2.3 From 32364c9e0d346e0e5d517e18d4e90b8ff2fa944f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 23 Mar 2011 10:33:38 +0900 Subject: altos: Ignore alt error for fast->coast. Allow larger error for baro apogee. With the fixed kalman filter, transitions across mach don't cause bumps in the merged filter. And, with working kalman bits, the signal for broken baro detection is stronger and so we can allow for baro apogee detection in cases where noise occurs close to apogee. Bump the kalman filter to trust the baro less so that the model tracks across mach. Signed-off-by: Keith Packard --- src/ao_flight.c | 5 ++--- src/make-kalman | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index 39325a69..88f0544f 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -626,8 +626,7 @@ ao_flight(void) * but the barometer is being ignored as * it may be unreliable. */ - if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED) && - (ao_raw_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 30)) + if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) { ao_flight_state = ao_flight_coast; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); @@ -647,7 +646,7 @@ ao_flight(void) */ if (ao_speed < 0 #if !HAS_ACCEL - && (ao_raw_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 30) + && (ao_raw_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) #endif ) { diff --git a/src/make-kalman b/src/make-kalman index 6fb181ec..5a25e1ec 100644 --- a/src/make-kalman +++ b/src/make-kalman @@ -2,8 +2,8 @@ cd ../kalman -SIGMA_BOTH="-M 2 -H 4 -A 4" -SIGMA_BARO="-M 2 -H 4 -A 4" +SIGMA_BOTH="-M 2 -H 6 -A 2" +SIGMA_BARO="-M 2 -H 6 -A 2" SIGMA_ACCEL="-M 2 -H 4 -A 4" nickle kalman.5c -p AO_BOTH -c both -t 0.01 $SIGMA_BOTH -- cgit v1.2.3 From 43a94380032300a2e33e1faa1efe93e858e0a2cf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 23 Mar 2011 10:37:39 +0900 Subject: altos: Exit flight test at landing. Allow description in test flight list Signed-off-by: Keith Packard --- src/ao_flight_test.c | 77 +++++++++++++++++++++++++++------------------------- src/test/run-one | 3 +- src/test/run-tests | 2 +- 3 files changed, 43 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 51a5965c..91aa0f73 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -130,7 +130,7 @@ int ao_flight_debug; FILE *emulator_in; char *emulator_app; char *emulator_name; -double emulator_error_max = 10; +double emulator_error_max = 4; void ao_dump_state(void); @@ -189,6 +189,33 @@ static double ao_test_max_height_time; static int ao_test_main_height; static double ao_test_main_height_time; +void +ao_test_exit(void) +{ + double drogue_error; + double main_error; + + if (!ao_test_main_height_time) { + ao_test_main_height_time = ao_test_max_height_time; + ao_test_main_height = ao_test_max_height; + } + drogue_error = fabs(ao_test_max_height_time - drogue_time); + main_error = fabs(ao_test_main_height_time - main_time); + if (drogue_error > emulator_error_max || main_error > emulator_error_max) { + printf ("%s %s\n", + emulator_app, emulator_name); + printf ("\tApogee error %g\n", drogue_error); + printf ("\tMain error %g\n", main_error); + printf ("\tActual: apogee: %d at %7.2f main: %d at %7.2f\n", + ao_test_max_height, ao_test_max_height_time, + ao_test_main_height, ao_test_main_height_time); + printf ("\tComputed: apogee: %d at %7.2f main: %d at %7.2f\n", + drogue_height, drogue_time, main_height, main_time); + exit (1); + } + exit(0); +} + void ao_insert(void) { @@ -207,6 +234,16 @@ ao_insert(void) tick_offset += 65536; prev_tick = ao_adc_static.tick; time = (double) (ao_adc_static.tick + tick_offset) / 100; + + if (ao_test_max_height < height) { + ao_test_max_height = height; + ao_test_max_height_time = time; + } + if (height > ao_config.main_deploy) { + ao_test_main_height_time = time; + ao_test_main_height = height; + } + if (!ao_summary) { printf("%7.2f height %g accel %g state %s k_height %g k_speed %g k_accel %g drogue %d main %d error %d\n", time, @@ -219,44 +256,10 @@ ao_insert(void) drogue_height, main_height, ao_error_h_sq_avg); + if (ao_flight_state == ao_flight_landed) + ao_test_exit(); } - - if (ao_test_max_height < height) { - ao_test_max_height = height; - ao_test_max_height_time = time; - } - if (height > ao_config.main_deploy) { - ao_test_main_height_time = time; - ao_test_main_height = height; - } - } -} - -void -ao_test_exit(void) -{ - double drogue_error; - double main_error; - - if (!ao_test_main_height_time) { - ao_test_main_height_time = ao_test_max_height_time; - ao_test_main_height = ao_test_max_height; - } - drogue_error = fabs(ao_test_max_height_time - drogue_time); - main_error = fabs(ao_test_main_height_time - main_time); - if (drogue_error > emulator_error_max || main_error > emulator_error_max) { - printf ("%s %s\n", - emulator_app, emulator_name); - printf ("\tApogee error %g\n", drogue_error); - printf ("\tMain error %g\n", main_error); - printf ("\tActual: apogee: %d at %7.2f main: %d at %7.2f\n", - ao_test_max_height, ao_test_max_height_time, - ao_test_main_height, ao_test_main_height_time); - printf ("\tComputed: apogee: %d at %7.2f main: %d at %7.2f\n", - drogue_height, drogue_time, main_height, main_time); - exit (1); } - exit(0); } void diff --git a/src/test/run-one b/src/test/run-one index d661abec..7d0f95ae 100755 --- a/src/test/run-one +++ b/src/test/run-one @@ -3,13 +3,14 @@ for i in "$@"; do ./ao_flight_test "$i" > run-out.full ./ao_flight_test_baro "$i" > run-out.baro -#./ao_flight_test_accel "$i" > run-out.accel +#./ao_flight_test_accel "$i" > run-out.accel #"run-out.accel" using 1:9 with lines lt 4 axes x1y1 title "accel height",\ #"run-out.accel" using 1:11 with lines lt 4 axes x1y2 title "accel speed",\ #"run-out.accel" using 1:13 with lines lt 4 axes x1y2 title "accel accel",\ #"run-out.accel" using 1:15 with lines lt 4 axes x1y1 title "accel drogue",\ #"run-out.accel" using 1:17 with lines lt 4 axes x1y1 title "accel main",\ +# gnuplot << EOF set ylabel "altitude (m)" diff --git a/src/test/run-tests b/src/test/run-tests index 11b4c95c..3e0cad3c 100755 --- a/src/test/run-tests +++ b/src/test/run-tests @@ -4,7 +4,7 @@ DIR=~/src/cc1111/flights bad_baro=0 bad_full=0 -while read flight; do +while read flight description; do if ./ao_flight_test_baro -s $DIR/$flight; then : else -- cgit v1.2.3 From 1e976a105423f2da1842f70da531c9051ba88a7f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 23 Mar 2011 10:42:31 +0900 Subject: Add description to test flights --- src/test/test-flights | 140 +++++++++++++++++++++++++------------------------- 1 file changed, 70 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/test/test-flights b/src/test/test-flights index 0b90d9e0..f6b3b992 100644 --- a/src/test/test-flights +++ b/src/test/test-flights @@ -1,70 +1,70 @@ -2009-06-03-serial-003-flight-002.eeprom -2009-06-05-serial-004-flight-008.eeprom -2009-06-06-serial-004-flight-009.eeprom -2009-06-14-serial-004-flight-010.eeprom -2009-06-20-serial-003-flight-003.eeprom -2009-07-04-serial-001-flight-006.eeprom -2009-07-18-serial-001-flight-007.eeprom -2009-08-22-serial-001-flight-001.eeprom -2009-08-22-serial-010-flight-001.eeprom -2009-09-05-serial-010-flight-002.eeprom -2009-09-05-serial-011-flight-001.eeprom -2009-09-11-serial-008-flight-003.eeprom -2009-09-12-serial-002-flight-002.eeprom -2009-09-12-serial-008-flight-005.eeprom -2009-09-12-serial-008-flight-007.eeprom -2009-09-19-serial-011-flight-002.eeprom -2009-10-03-serial-008-flight-009.eeprom -2009-10-03-serial-008-flight-010.eeprom -2009-10-03-serial-009-flight-001.eeprom -2009-10-03-serial-011-flight-003.eeprom -2009-10-17-serial-009-flight-002.eeprom -2009-11-14-serial-003-flight-005.eeprom -2009-11-14-serial-003-flight-006.eeprom -2009-11-21-serial-013-flight-001.eeprom -2009-11-21-serial-013-flight-002.eeprom -2010-02-13-serial-051-flight-002.eeprom -2010-02-13-serial-052-flight-002.eeprom -2010-02-28-serial-052-flight-003.eeprom -2010-02-28-serial-052-flight-004.eeprom -2010-03-06-serial-010-flight-004.eeprom -2010-03-06-serial-013-flight-003.eeprom -2010-03-06-serial-051-flight-003.eeprom -2010-03-06-serial-053-flight-004.eeprom -2010-05-08-serial-229-flight-002.eeprom -2010-05-28-serial-215-flight-002.eeprom -2010-05-28-serial-224-flight-001.eeprom -2010-05-29-serial-052-flight-005.eeprom -2010-05-30-serial-010-flight-005.eeprom -2010-05-30-serial-051-flight-004.eeprom -2010-05-30-serial-224-flight-003.eeprom -2010-05-30-serial-226-flight-001.eeprom -2010-05-31-serial-010-flight-006.eeprom -2010-05-31-serial-216-flight-001.eeprom -2010-05-31-serial-219-flight-001.eeprom -2010-05-31-serial-227-flight-003.eeprom -2010-06-05-serial-220-flight-001.eeprom -2010-06-26-serial-209-flight-003.eeprom -2010-06-26-serial-215-flight-004.eeprom -2010-06-26-serial-220-flight-002.eeprom -2010-06-26-serial-226-flight-002.eeprom -2010-06-27-serial-221-flight-002.eeprom -2010-07-17-serial-230-flight-001.eeprom -2010-07-18-serial-219-flight-002.eeprom -2010-08-07-serial-216-flight-003.eeprom -2010-08-07-serial-220-flight-003.eeprom -2010-08-12-serial-236-flight-001.eeprom -2010-08-21-serial-010-flight-007.eeprom -2010-08-21-serial-224-flight-004.eeprom -2010-08-21-serial-224-flight-005.eeprom -2010-08-21-serial-233-flight-002.eeprom -2010-09-03-serial-051-flight-005.eeprom -2010-09-03-serial-215-flight-005.eeprom -2010-09-24-serial-236-flight-006.eeprom -2010-09-25-serial-223-flight-001.eeprom -2010-10-17-serial-215-flight-006.eeprom -2011-01-30-serial-056-flight-001.eeprom -2011-01-30-serial-250-flight-002.eeprom -2011-02-19-serial-215-flight-007.eeprom -2011-02-19-serial-216-flight-006.eeprom -2011-02-19-serial-286-flight-001.eeprom +2009-06-03-serial-003-flight-002.eeprom PSAS flight on research motor.Lots of ugly bumps. +2009-06-05-serial-004-flight-008.eeprom Add June 2009 Lil Nuke flight +2009-06-06-serial-004-flight-009.eeprom Another Lil nuke flight? 700m, subsonic. +2009-06-14-serial-004-flight-010.eeprom Lil nuke flies again. 450m, subsonic. +2009-06-20-serial-003-flight-003.eeprom Transonic flight. 2100m, single deploy. +2009-07-04-serial-001-flight-006.eeprom Subsonic, 1100m, noisy descent. +2009-07-18-serial-001-flight-007.eeprom Transonic, 1900m, noisy descent. +2009-08-22-serial-001-flight-001.eeprom Transonic 2200m. noisy descent +2009-08-22-serial-010-flight-001.eeprom Subsonic, laggy baro. 400m +2009-09-05-serial-010-flight-002.eeprom Subsonic, fairly quick baro. 600m +2009-09-05-serial-011-flight-001.eeprom Subsonic, 1800m. Early Ejection confuses apogee detect. +2009-09-11-serial-008-flight-003.eeprom Subsonic, 200m, early ejection. +2009-09-12-serial-002-flight-002.eeprom Subsonic. 1200m. Very nice baro velocity +2009-09-12-serial-008-flight-005.eeprom Low flight. 220m, 100m/s. +2009-09-12-serial-008-flight-007.eeprom Model flight. +2009-09-19-serial-011-flight-002.eeprom Subsonic, but noisy baro. +2009-10-03-serial-008-flight-009.eeprom Transonic baro bump. 1600m. +2009-10-03-serial-008-flight-010.eeprom Barely transonic, but other baro bumps. +2009-10-03-serial-009-flight-001.eeprom Add Ofest ToT flight (drag race with Candy Cane). subsonic, but a bit of baro noise. +2009-10-03-serial-011-flight-003.eeprom Add Ofest G-spot flight. transonic bump, ugly looking data. +2009-10-17-serial-009-flight-002.eeprom Clean looking subsonic flight, small baro slump at max-Q +2009-11-14-serial-003-flight-005.eeprom Model flight. +2009-11-14-serial-003-flight-006.eeprom Model flight. +2009-11-21-serial-013-flight-001.eeprom ToT AMW J450ST with Jason Chamberlin strontium nitrate igniter +2009-11-21-serial-013-flight-002.eeprom ToT - CTI 1009J420CL pro38 6xl +2010-02-13-serial-051-flight-002.eeprom G-Spot at Albuquerque Rocket Society launch site in Rio Rancho, NM Cesaroni 229H255WT-14A +2010-02-13-serial-052-flight-002.eeprom Add Grappler flight at OROC February model launch +2010-02-28-serial-052-flight-003.eeprom LDDD Tillamook airport, 2010-02-28, H252 +2010-02-28-serial-052-flight-004.eeprom LDDD Tillamook airport, 2010-02-28, I161 +2010-03-06-serial-010-flight-004.eeprom Robert's Lil Nuke at Hudson Ranch on a CTI 108G57CL Pro29 +2010-03-06-serial-013-flight-003.eeprom Trick-O-Treat at Hudson Ranch on a J595BS +2010-03-06-serial-051-flight-003.eeprom G-Spot at Hudson Ranch on an H180W +2010-03-06-serial-053-flight-004.eeprom Horizon Rebuilt at Hudson Ranch on a J530IM with MAWD as backup +2010-05-08-serial-229-flight-002.eeprom First customer flight on a sparky. +2010-05-28-serial-215-flight-002.eeprom Mike's L1 cert flight. Congrats! +2010-05-28-serial-224-flight-001.eeprom Bill Mott's amram +2010-05-29-serial-052-flight-005.eeprom LDDD on J335 at MHM +2010-05-30-serial-010-flight-005.eeprom Robert's Lil Nuke on a 84G88 Smoky Sam at Mile High Mayhem 2010 Version 0.1 TeleMetrum with 5010 GPS board. +2010-05-30-serial-051-flight-004.eeprom Bdale's G-Spot on a CTI 298H159 Green3 at Mile High Mayhem 2010 +2010-05-30-serial-224-flight-003.eeprom Bill Mott's L3 cert flight +2010-05-30-serial-226-flight-001.eeprom Robert's RG-2 on a 159G54RL at Mile High Mayhem. Very noise accel data, early apogee +2010-05-31-serial-010-flight-006.eeprom Robert's Lil Nuke with a v0.1 TeleMetrum and 5010 GPS board flying on a 159G118 Blue Streak on the last day of Mile High Mayhem 2010 +2010-05-31-serial-216-flight-001.eeprom Sharp Stick in the Sky on an "I something" EX motor from James Russell +2010-05-31-serial-219-flight-001.eeprom Candy Cane on CTI K300 at MHM. +2010-05-31-serial-227-flight-003.eeprom Mike's Rocket on J285 for successful L2 cert at MHM +2010-06-05-serial-220-flight-001.eeprom Mini-mmuchness on 159G54RL, Sunday at MHM 2010 +2010-06-26-serial-209-flight-003.eeprom Tripoli Colorado Spring Fling with COSROCS at the Buffalo Ranch +2010-06-26-serial-215-flight-004.eeprom Tripoli Colorado Spring Fling with COSROCS at the Buffalo Ranch +2010-06-26-serial-220-flight-002.eeprom Mini Mmuchness on CTI H120CL to 1975m, OROC June 2010 +2010-06-26-serial-226-flight-002.eeprom Tripoli Colorado Spring Fling with COSROCS at the Buffalo Ranch +2010-06-27-serial-221-flight-002.eeprom PSAS LV2c on N2000 at OROC june launch +2010-07-17-serial-230-flight-001.eeprom Mike Ward's Level 1 cert flight on H225 +2010-07-18-serial-219-flight-002.eeprom MMuchness on M1230 for successful L3 cert flight +2010-08-07-serial-216-flight-003.eeprom Sharp stick on I300T at Metra's august launch. Main out at apogee. +2010-08-07-serial-220-flight-003.eeprom Mini-mmuchness flight at Metra after debconf. Unstable on G80. ABNORMAL FLIGHT. +2010-08-12-serial-236-flight-001.eeprom Edgar's L1 flight, Madcow Momba on Aerotech H128 +2010-08-21-serial-010-flight-007.eeprom Robert's Lil Nuke, flying on a CTI Pro29 2-grain 110G250 Vmax. Just awesome! PFND. +2010-08-21-serial-224-flight-004.eeprom Anthony Towns' LDDD clone, successful L1 cert on a CTI Pro38 2-grain 266H125 classic. Airframe was set up for apogee-only with motor based ejection. The BP charge was larger than necessary, caused nose cone to snap back against aft airframe. Minor damage to leading edge of aft airframe, big chunk of the nose cone skin cracked away. Same problem Bdale saw on Sharp Stick's nosecone, also from Performance Rocketry, where there was apparently an air bubble below the gel coat. Determination was that damage was cosmetic and would not affect cert... confirmed by successful L2 later in the day! +2010-08-21-serial-224-flight-005.eeprom Anthony Towns' LDDD clone, successful L2 cert on a CTI Pro38 5-grain 58J357 blue streak. Perfect drogueless dual deploy! 0.8-0.9 grams aft charge and about 1.0 grams forward. Flew without ground testing charges due to time pressure before waiver closed for the day. About as close to the waiver as you'd ever want to be on a cert flight, again demonstrating that OpenRocket under-estimates apogee ... approximately 6800 ft predicted... +2010-08-21-serial-233-flight-002.eeprom Tim van Milligan's 5.5" L2 airframe, flying on a CTI Pro38 6-grain 774J410 red, TM indicated a problem with the apogee igniter continuity, noticed during countdown, turned out to be a loose wire! Perfect dual deploy flight once that was fixed. +2010-09-03-serial-051-flight-005.eeprom G-spot on an old Aerotech H125-20W single use 29mm motor. It appears the ejection at apogee actually happened much later, perhaps as much as 10 seconds late! +2010-09-03-serial-215-flight-005.eeprom Horizon Rebuild on a K490 Green3 reload. PFND. About 1.4 grams each end. +2010-09-24-serial-236-flight-006.eeprom LDDD on I236 in Sheridan on 2010-09-24 to 1216m +2010-09-25-serial-223-flight-001.eeprom Bdale's 10" Goblin, flying on a CTI Pro75 M1300 Imax dual thrust during Chili Blaster 2 at Hudson Ranch. First flight after rebuild to do dual deploy from one bay with ARRD and 15' surplus "+ sign" parachute. +2010-10-17-serial-215-flight-006.eeprom Horizon Rebuild on CTI J595BS at Tripoli Colorado launch site near Hartsel, CO +2011-01-30-serial-056-flight-001.eeprom Group project 5.5" Polecat Thumper airframe built in the Quay West Suites in Brisbane, Australia, during LCA 2011 by Bdale, Keith, Mike Beattie, and Anthony Towns. Flown at QRS club launch on an Aerotech J315R 54mm 2-grain motor. +2011-01-30-serial-250-flight-002.eeprom Group project 5.5" Polecat Thumper airframe built in the Quay West Suites in Brisbane, Australia, during LCA 2011 by Bdale, Keith, Mike Beattie, and Anthony Towns. Flown at QRS club launch on an Aerotech J315R 54mm 2-grain motor. +2011-02-19-serial-215-flight-007.eeprom Horizon Rebuild on a CTI Pro38 6xl J600R at Hudson Ranch 1.0 grams BP rear, 1.5 grams front Perfect drogueless dual deploy flight with no damage! +2011-02-19-serial-216-flight-006.eeprom Sharp Stick on a CTI Pro38 3-grain I345WT at Hudson Ranch Added more kevlar to the aft end, flew with 1.3 grams BP rear and 1.0 front. Perfect drogueless dual deploy flight, and no damage! +2011-02-19-serial-286-flight-001.eeprom Vertical Assault on a CTI Pro38 6xl J595BS at Hudson Ranch 1.5 grams BP rear, 1.8 grams BP front Perfect drogueless dual deploy flight, with no damage! -- cgit v1.2.3 From f3e68341f6f5daaf26dd162e4f9a06c29988986a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 24 Mar 2011 05:27:57 +0900 Subject: altosui: Add support for telemetry version 4 New telemetry format needed to support TeleNano and TeleMini Signed-off-by: Keith Packard --- altosui/AltosAscent.java | 21 ++- altosui/AltosCSV.java | 29 ++-- altosui/AltosDataPointReader.java | 2 + altosui/AltosDescent.java | 57 +++++++- altosui/AltosFlightUI.java | 23 +++- altosui/AltosGPS.java | 47 ++++++- altosui/AltosLanded.java | 31 ++++- altosui/AltosPad.java | 41 +++++- altosui/AltosRecord.java | 83 +++++++++-- altosui/AltosSiteMap.java | 2 - altosui/AltosState.java | 15 +- altosui/AltosTelemetry.java | 267 +++++++++++++++++++++++++++++++++--- altosui/AltosTelemetryIterable.java | 1 - altosui/AltosUI.java | 2 +- altosui/Makefile.am | 1 + src/ao_telem.h | 8 +- 16 files changed, 550 insertions(+), 80 deletions(-) (limited to 'src') diff --git a/altosui/AltosAscent.java b/altosui/AltosAscent.java index 64bdcf30..0fbc5de2 100644 --- a/altosui/AltosAscent.java +++ b/altosui/AltosAscent.java @@ -87,6 +87,16 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { void reset() { value.setText(""); } + + void show() { + label.show(); + value.show(); + } + + void hide() { + label.hide(); + value.hide(); + } public AscentValue (GridBagLayout layout, int y, String text) { GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; @@ -247,6 +257,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { class Lat extends AscentValue { void show (AltosState state, int crc_errors) { + show(); if (state.gps != null) value.setText(pos(state.gps.lat,"N", "S")); else @@ -261,6 +272,7 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { class Lon extends AscentValue { void show (AltosState state, int crc_errors) { + show(); if (state.gps != null) value.setText(pos(state.gps.lon,"E", "W")); else @@ -284,8 +296,13 @@ public class AltosAscent extends JComponent implements AltosFlightDisplay { } public void show(AltosState state, int crc_errors) { - lat.show(state, crc_errors); - lon.show(state, crc_errors); + if (state.gps != null) { + lat.show(state, crc_errors); + lon.show(state, crc_errors); + } else { + lat.hide(); + lon.hide(); + } height.show(state, crc_errors); main.show(state, crc_errors); apogee.show(state, crc_errors); diff --git a/altosui/AltosCSV.java b/altosui/AltosCSV.java index df98b2b4..5277c160 100644 --- a/altosui/AltosCSV.java +++ b/altosui/AltosCSV.java @@ -60,7 +60,7 @@ public class AltosCSV implements AltosWriter { * drogue (V) * main (V) * - * GPS data + * GPS data (if available) * connected (1/0) * locked (1/0) * nsat (used for solution) @@ -179,12 +179,14 @@ public class AltosCSV implements AltosWriter { } } - void write_header() { + void write_header(boolean gps) { out.printf("#"); write_general_header(); out.printf(","); write_flight_header(); out.printf(","); write_basic_header(); - out.printf(","); write_gps_header(); - out.printf(","); write_gps_sat_header(); + if (gps) { + out.printf(","); write_gps_header(); + out.printf(","); write_gps_sat_header(); + } out.printf ("\n"); } @@ -192,9 +194,12 @@ public class AltosCSV implements AltosWriter { state = new AltosState(record, state); write_general(record); out.printf(","); write_flight(record); out.printf(","); - write_basic(record); out.printf(","); - write_gps(record); out.printf(","); - write_gps_sat(record); + write_basic(record); + if (record.gps != null) { + out.printf(","); + write_gps(record); out.printf(","); + write_gps_sat(record); + } out.printf ("\n"); } @@ -206,7 +211,7 @@ public class AltosCSV implements AltosWriter { public void write(AltosRecord record) { if (!header_written) { - write_header(); + write_header(record.gps != null); header_written = true; } if (!seen_boost) { @@ -240,12 +245,16 @@ public class AltosCSV implements AltosWriter { write(r); } - public AltosCSV(File in_name) throws FileNotFoundException { + public AltosCSV(PrintStream in_out, File in_name) { name = in_name; - out = new PrintStream(name); + out = in_out; pad_records = new LinkedList(); } + public AltosCSV(File in_name) throws FileNotFoundException { + this(new PrintStream(in_name), in_name); + } + public AltosCSV(String in_string) throws FileNotFoundException { this(new File(in_string)); } diff --git a/altosui/AltosDataPointReader.java b/altosui/AltosDataPointReader.java index 7704310b..ee57d2ce 100644 --- a/altosui/AltosDataPointReader.java +++ b/altosui/AltosDataPointReader.java @@ -15,6 +15,8 @@ class AltosDataPointReader implements Iterable { AltosState state; AltosRecord record; + final static int MISSING = AltosRecord.MISSING; + public AltosDataPointReader(Iterable reader) { this.iter = reader.iterator(); this.state = null; diff --git a/altosui/AltosDescent.java b/altosui/AltosDescent.java index 16ccd458..594a7a09 100644 --- a/altosui/AltosDescent.java +++ b/altosui/AltosDescent.java @@ -37,6 +37,19 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { AltosLights lights; abstract void show(AltosState state, int crc_errors); + + void show() { + label.show(); + value.show(); + lights.show(); + } + + void hide() { + label.hide(); + value.hide(); + lights.hide(); + } + void reset() { value.setText(""); lights.set(false); @@ -90,6 +103,16 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { abstract void show(AltosState state, int crc_errors); + void show() { + label.show(); + value.show(); + } + + void hide() { + label.hide(); + value.hide(); + } + void show(String format, double v) { value.setText(String.format(format, v)); } @@ -134,12 +157,27 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { value2.setText(""); } + void show() { + label.show(); + value1.show(); + value2.show(); + } + + void hide() { + label.hide(); + value1.hide(); + value2.hide(); + } + abstract void show(AltosState state, int crc_errors); + void show(String v1, String v2) { + show(); value1.setText(v1); value2.setText(v2); } void show(String f1, double v1, String f2, double v2) { + show(); value1.setText(String.format(f1, v1)); value2.setText(String.format(f2, v2)); } @@ -260,6 +298,7 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { class Main extends DescentStatus { void show (AltosState state, int crc_errors) { + show(); value.setText(String.format("%4.2f V", state.main_sense)); lights.set(state.main_sense > 3.2); } @@ -324,11 +363,19 @@ public class AltosDescent extends JComponent implements AltosFlightDisplay { public void show(AltosState state, int crc_errors) { height.show(state, crc_errors); speed.show(state, crc_errors); - bearing.show(state, crc_errors); - range.show(state, crc_errors); - elevation.show(state, crc_errors); - lat.show(state, crc_errors); - lon.show(state, crc_errors); + if (state.gps != null) { + bearing.show(state, crc_errors); + range.show(state, crc_errors); + elevation.show(state, crc_errors); + lat.show(state, crc_errors); + lon.show(state, crc_errors); + } else { + bearing.hide(); + range.hide(); + elevation.hide(); + lat.hide(); + lon.hide(); + } main.show(state, crc_errors); apogee.show(state, crc_errors); } diff --git a/altosui/AltosFlightUI.java b/altosui/AltosFlightUI.java index 7fcfb8be..68e0ef87 100644 --- a/altosui/AltosFlightUI.java +++ b/altosui/AltosFlightUI.java @@ -29,9 +29,6 @@ import java.util.prefs.*; import java.util.concurrent.LinkedBlockingQueue; public class AltosFlightUI extends JFrame implements AltosFlightDisplay { - String[] statusNames = { "Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" }; - Object[][] statusData = { { "0", "pad", "-50", "0" } }; - AltosVoice voice; AltosFlightReader reader; AltosDisplayThread thread; @@ -43,6 +40,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { AltosDescent descent; AltosLanded landed; AltosSiteMap sitemap; + boolean has_map; private AltosFlightStatus flightStatus; private AltosInfoTable flightInfo; @@ -85,6 +83,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { public void show(AltosState state, int crc_errors) { JComponent tab = which_tab(state); + try { pad.show(state, crc_errors); ascent.show(state, crc_errors); descent.show(state, crc_errors); @@ -97,7 +96,21 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { } flightStatus.show(state, crc_errors); flightInfo.show(state, crc_errors); - sitemap.show(state, crc_errors); + if (state.gps != null) { + if (!has_map) { + pane.add("Site Map", sitemap); + has_map = true; + } + sitemap.show(state, crc_errors); + } else { + if (has_map) { + pane.remove(sitemap); + has_map = false; + } + } + } catch (Exception e) { + System.out.print("Show exception" + e); + } } public void set_exit_on_close() { @@ -169,7 +182,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay { pane.add("Table", new JScrollPane(flightInfo)); sitemap = new AltosSiteMap(); - pane.add("Site Map", sitemap); + has_map = false; /* Make the tabbed pane use the rest of the window space */ c.gridx = 0; diff --git a/altosui/AltosGPS.java b/altosui/AltosGPS.java index 83821842..0dbc8364 100644 --- a/altosui/AltosGPS.java +++ b/altosui/AltosGPS.java @@ -26,10 +26,11 @@ public class AltosGPS { int c_n0; } + final static int MISSING = AltosRecord.MISSING; + int nsat; boolean locked; boolean connected; - boolean date_valid; double lat; /* degrees (+N -S) */ double lon; /* degrees (+E -W) */ int alt; /* m */ @@ -40,11 +41,11 @@ public class AltosGPS { int minute; int second; - int gps_extended; /* has extra data */ double ground_speed; /* m/s */ int course; /* degrees */ double climb_rate; /* m/s */ - double hdop; /* unitless? */ + double hdop; /* unitless */ + double vdop; /* unitless */ int h_error; /* m */ int v_error; /* m */ @@ -73,6 +74,44 @@ public class AltosGPS { hour = minute = second = 0; } + public AltosGPS(AltosTelemetryMap map) throws ParseException { + String state = map.get_string(AltosTelemetry.AO_TELEM_GPS_STATE, + AltosTelemetry.AO_TELEM_GPS_STATE_ERROR); + + nsat = map.get_int(AltosTelemetry.AO_TELEM_GPS_NUM_SAT, 0); + if (state.equals(AltosTelemetry.AO_TELEM_GPS_STATE_LOCKED)) { + connected = true; + locked = true; + lat = map.get_double(AltosTelemetry.AO_TELEM_GPS_LATITUDE, MISSING, 1.0e-7); + lon = map.get_double(AltosTelemetry.AO_TELEM_GPS_LONGITUDE, MISSING, 1.0e-7); + alt = map.get_int(AltosTelemetry.AO_TELEM_GPS_ALTITUDE, MISSING); + year = map.get_int(AltosTelemetry.AO_TELEM_GPS_YEAR, MISSING); + if (year != MISSING) + year += 2000; + month = map.get_int(AltosTelemetry.AO_TELEM_GPS_MONTH, MISSING); + day = map.get_int(AltosTelemetry.AO_TELEM_GPS_DAY, MISSING); + + hour = map.get_int(AltosTelemetry.AO_TELEM_GPS_HOUR, 0); + minute = map.get_int(AltosTelemetry.AO_TELEM_GPS_MINUTE, 0); + second = map.get_int(AltosTelemetry.AO_TELEM_GPS_SECOND, 0); + + ground_speed = map.get_double(AltosTelemetry.AO_TELEM_GPS_HORIZONTAL_SPEED, + AltosRecord.MISSING, 1/100.0); + course = map.get_int(AltosTelemetry.AO_TELEM_GPS_COURSE, + AltosRecord.MISSING); + hdop = map.get_double(AltosTelemetry.AO_TELEM_GPS_HDOP, MISSING, 1.0); + vdop = map.get_double(AltosTelemetry.AO_TELEM_GPS_VDOP, MISSING, 1.0); + h_error = map.get_int(AltosTelemetry.AO_TELEM_GPS_HERROR, MISSING); + v_error = map.get_int(AltosTelemetry.AO_TELEM_GPS_VERROR, MISSING); + } else if (state.equals(AltosTelemetry.AO_TELEM_GPS_STATE_UNLOCKED)) { + connected = true; + locked = false; + } else { + connected = false; + locked = false; + } + } + public AltosGPS(String[] words, int i, int version) throws ParseException { AltosParse.word(words[i++], "GPS"); nsat = AltosParse.parse_int(words[i++]); @@ -184,7 +223,6 @@ public class AltosGPS { nsat = old.nsat; locked = old.locked; connected = old.connected; - date_valid = old.date_valid; lat = old.lat; /* degrees (+N -S) */ lon = old.lon; /* degrees (+E -W) */ alt = old.alt; /* m */ @@ -195,7 +233,6 @@ public class AltosGPS { minute = old.minute; second = old.second; - gps_extended = old.gps_extended; /* has extra data */ ground_speed = old.ground_speed; /* m/s */ course = old.course; /* degrees */ climb_rate = old.climb_rate; /* m/s */ diff --git a/altosui/AltosLanded.java b/altosui/AltosLanded.java index d34efe6d..0717ffe2 100644 --- a/altosui/AltosLanded.java +++ b/altosui/AltosLanded.java @@ -42,10 +42,22 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { value.setText(""); } + void show() { + label.show(); + value.show(); + } + + void hide() { + label.hide(); + value.hide(); + } + void show(String format, double v) { + show(); value.setText(String.format(format, v)); } + public LandedValue (GridBagLayout layout, int y, String text) { GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; @@ -86,6 +98,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { class Lat extends LandedValue { void show (AltosState state, int crc_errors) { + show(); if (state.gps != null) value.setText(pos(state.gps.lat,"N", "S")); else @@ -100,6 +113,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { class Lon extends LandedValue { void show (AltosState state, int crc_errors) { + show(); if (state.gps != null) value.setText(pos(state.gps.lon,"E", "W")); else @@ -114,6 +128,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { class Bearing extends LandedValue { void show (AltosState state, int crc_errors) { + show(); if (state.from_pad != null) show("%3.0f°", state.from_pad.bearing); else @@ -128,6 +143,7 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { class Distance extends LandedValue { void show (AltosState state, int crc_errors) { + show(); if (state.from_pad != null) show("%6.0f m", state.from_pad.distance); else @@ -184,10 +200,17 @@ public class AltosLanded extends JComponent implements AltosFlightDisplay { } public void show(AltosState state, int crc_errors) { - bearing.show(state, crc_errors); - distance.show(state, crc_errors); - lat.show(state, crc_errors); - lon.show(state, crc_errors); + if (state.gps != null) { + bearing.show(state, crc_errors); + distance.show(state, crc_errors); + lat.show(state, crc_errors); + lon.show(state, crc_errors); + } else { + bearing.hide(); + distance.hide(); + lat.hide(); + lon.hide(); + } height.show(state, crc_errors); speed.show(state, crc_errors); accel.show(state, crc_errors); diff --git a/altosui/AltosPad.java b/altosui/AltosPad.java index e345e5da..2f59e879 100644 --- a/altosui/AltosPad.java +++ b/altosui/AltosPad.java @@ -42,6 +42,18 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { lights.set(false); } + public void show() { + label.show(); + value.show(); + lights.show(); + } + + public void hide() { + label.hide(); + value.hide(); + lights.hide(); + } + public LaunchStatus (GridBagLayout layout, int y, String text) { GridBagConstraints c = new GridBagConstraints(); c.weighty = 1; @@ -83,6 +95,16 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { JTextField value; void show(AltosState state, int crc_errors) {} + void show() { + label.show(); + value.show(); + } + + void hide() { + label.hide(); + value.hide(); + } + void reset() { value.setText(""); } @@ -151,6 +173,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { class GPSLocked extends LaunchStatus { void show (AltosState state, int crc_errors) { + show(); value.setText(String.format("%4d sats", state.gps.nsat)); lights.set(state.gps.locked && state.gps.nsat >= 4); } @@ -163,6 +186,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { class GPSReady extends LaunchStatus { void show (AltosState state, int crc_errors) { + show(); if (state.gps_ready) value.setText("Ready"); else @@ -189,6 +213,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { class PadLat extends LaunchValue { void show (AltosState state, int crc_errors) { + show(); value.setText(pos(state.pad_lat,"N", "S")); } public PadLat (GridBagLayout layout, int y) { @@ -200,6 +225,7 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { class PadLon extends LaunchValue { void show (AltosState state, int crc_errors) { + show(); value.setText(pos(state.pad_lon,"E", "W")); } public PadLon (GridBagLayout layout, int y) { @@ -235,11 +261,18 @@ public class AltosPad extends JComponent implements AltosFlightDisplay { battery.show(state, crc_errors); apogee.show(state, crc_errors); main.show(state, crc_errors); - gps_locked.show(state, crc_errors); - gps_ready.show(state, crc_errors); - pad_lat.show(state, crc_errors); - pad_lon.show(state, crc_errors); pad_alt.show(state, crc_errors); + if (state.gps != null) { + gps_locked.show(state, crc_errors); + gps_ready.show(state, crc_errors); + pad_lat.show(state, crc_errors); + pad_lon.show(state, crc_errors); + } else { + gps_locked.hide(); + gps_ready.hide(); + pad_lat.hide(); + pad_lon.hide(); + } } public AltosPad() { diff --git a/altosui/AltosRecord.java b/altosui/AltosRecord.java index 1160a273..46e96b95 100644 --- a/altosui/AltosRecord.java +++ b/altosui/AltosRecord.java @@ -23,6 +23,8 @@ import java.util.HashMap; import java.io.*; public class AltosRecord { + final static int MISSING = 0x7fffffff; + int version; String callsign; int serial; @@ -31,19 +33,27 @@ public class AltosRecord { int status; int state; int tick; + int accel; int pres; int temp; int batt; int drogue; int main; - int flight_accel; + int ground_accel; - int flight_vel; - int flight_pres; int ground_pres; int accel_plus_g; int accel_minus_g; + + double acceleration; + double speed; + double height; + + int flight_accel; + int flight_vel; + int flight_pres; + AltosGPS gps; double time; /* seconds since boost */ @@ -72,46 +82,82 @@ public class AltosRecord { } public double raw_pressure() { + if (pres == MISSING) + return MISSING; return barometer_to_pressure(pres); } public double filtered_pressure() { + if (flight_pres == MISSING) + return MISSING; return barometer_to_pressure(flight_pres); } public double ground_pressure() { + if (ground_pres == MISSING) + return MISSING; return barometer_to_pressure(ground_pres); } - public double filtered_altitude() { - return AltosConvert.pressure_to_altitude(filtered_pressure()); - } - public double raw_altitude() { - return AltosConvert.pressure_to_altitude(raw_pressure()); + double p = raw_pressure(); + if (p == MISSING) + return MISSING; + return AltosConvert.pressure_to_altitude(p); } public double ground_altitude() { - return AltosConvert.pressure_to_altitude(ground_pressure()); + double p = ground_pressure(); + if (p == MISSING) + return MISSING; + return AltosConvert.pressure_to_altitude(p); + } + + public double filtered_altitude() { + if (height != MISSING && ground_pres != MISSING) + return height + ground_altitude(); + + double p = filtered_pressure(); + if (p == MISSING) + return MISSING; + return AltosConvert.pressure_to_altitude(p); } public double filtered_height() { - return filtered_altitude() - ground_altitude(); + if (height != MISSING) + return height; + + double f = filtered_altitude(); + double g = ground_altitude(); + if (f == MISSING || g == MISSING) + return MISSING; + return f - g; } public double raw_height() { - return raw_altitude() - ground_altitude(); + double r = raw_altitude(); + double g = ground_altitude(); + + if (r == MISSING || g == MISSING) + return MISSING; + return r - g; } public double battery_voltage() { + if (batt == MISSING) + return MISSING; return AltosConvert.cc_battery_to_voltage(batt); } public double main_voltage() { + if (main == MISSING) + return MISSING; return AltosConvert.cc_ignitor_to_voltage(main); } public double drogue_voltage() { + if (drogue == MISSING) + return MISSING; return AltosConvert.cc_ignitor_to_voltage(drogue); } @@ -131,6 +177,8 @@ public class AltosRecord { } public double temperature() { + if (temp == MISSING) + return MISSING; return thermometer_to_temperature(temp); } @@ -139,13 +187,22 @@ public class AltosRecord { return counts_per_g / 9.80665; } + public double acceleration() { + if (acceleration != MISSING) + return acceleration; + + if (ground_accel == MISSING || accel == MISSING) + return MISSING; return (ground_accel - accel) / accel_counts_per_mss(); } public double accel_speed() { - double speed = flight_vel / (accel_counts_per_mss() * 100.0); - return speed; + if (speed != MISSING) + return speed; + if (flight_vel == MISSING) + return MISSING; + return flight_vel / (accel_counts_per_mss() * 100.0); } public String state() { diff --git a/altosui/AltosSiteMap.java b/altosui/AltosSiteMap.java index d6bd6d1f..f4b6b7e0 100644 --- a/altosui/AltosSiteMap.java +++ b/altosui/AltosSiteMap.java @@ -228,8 +228,6 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay { int last_state = -1; public void show(final AltosState state, final int crc_errors) { // if insufficient gps data, nothing to update - if (state.gps == null) - return; if (!state.gps.locked && state.gps.nsat < 4) return; diff --git a/altosui/AltosState.java b/altosui/AltosState.java index ec499d5a..4e165f80 100644 --- a/altosui/AltosState.java +++ b/altosui/AltosState.java @@ -79,7 +79,8 @@ public class AltosState { data = cur; ground_altitude = data.ground_altitude(); - height = data.filtered_altitude() - ground_altitude; + height = data.filtered_height(); + System.out.printf("height %g\n", height); report_time = System.currentTimeMillis(); @@ -114,10 +115,14 @@ public class AltosState { /* compute barometric speed */ double height_change = height - prev_state.height; - if (time_change > 0) - baro_speed = (prev_state.baro_speed * 3 + (height_change / time_change)) / 4.0; - else - baro_speed = prev_state.baro_speed; + if (data.speed != AltosRecord.MISSING) + baro_speed = data.speed; + else { + if (time_change > 0) + baro_speed = (prev_state.baro_speed * 3 + (height_change / time_change)) / 4.0; + else + baro_speed = prev_state.baro_speed; + } } else { npad = 0; ngps = 0; diff --git a/altosui/AltosTelemetry.java b/altosui/AltosTelemetry.java index bdb6466a..3eb0efa8 100644 --- a/altosui/AltosTelemetry.java +++ b/altosui/AltosTelemetry.java @@ -27,10 +27,40 @@ import java.util.HashMap; /* - * The telemetry data stream is a bit of a mess at present, with no consistent - * formatting. In particular, the GPS data is formatted for viewing instead of parsing. - * However, the key feature is that every telemetry line contains all of the information - * necessary to describe the current rocket state, including the calibration values + * Version 4 is a replacement with consistent syntax. Each telemetry line + * contains a sequence of space-separated names and values, the values are + * either integers or strings. The names are all unique. All values are + * optional + * + * VERSION 4 c KD7SQG n 236 f 18 r -25 s pad t 513 r_a 15756 r_b 26444 r_t 20944 + * r_v 26640 r_d 512 r_m 208 c_a 15775 c_b 26439 c_p 15749 c_m 16281 a_a 15764 + * a_s 0 a_b 26439 g_s u g_n 0 s_n 0 + * + * VERSION 4 c KD7SQG n 19 f 0 r -23 s pad t 513 r_b 26372 r_t 21292 r_v 26788 + * r_d 136 r_m 140 c_b 26370 k_h 0 k_s 0 k_a 0 + * + * General header fields + * + * Name Value + * + * VERSION Telemetry version number (4 or more). Must be first. + * c Callsign (string, no spaces allowed) + * n Flight unit serial number (integer) + * f Flight number (integer) + * r Packet RSSI value (integer) + * s Flight computer state (string, no spaces allowed) + * t Flight computer clock (integer in centiseconds) + * + * Version 3 is Version 2 with fixed RSSI numbers -- the radio reports + * in 1/2dB increments while this protocol provides only integers. So, + * the syntax didn't change just the interpretation of the RSSI + * values. + * + * Version 2 of the telemetry data stream is a bit of a mess, with no + * consistent formatting. In particular, the GPS data is formatted for + * viewing instead of parsing. However, the key feature is that every + * telemetry line contains all of the information necessary to + * describe the current rocket state, including the calibration values * for accelerometer and barometer. * * GPS unlocked: @@ -47,25 +77,201 @@ import java.util.HashMap; * GPS 9 sat 2010-02-13 17:16:51 35°20.0803'N 106°45.2235'W 1790m \ * 0.00m/s(H) 0° 0.00m/s(V) 1.0(hdop) 0(herr) 0(verr) \ * SAT 10 29 30 24 28 5 25 21 20 15 33 1 23 30 24 18 26 10 29 2 26 + * */ public class AltosTelemetry extends AltosRecord { - public AltosTelemetry(String line) throws ParseException, AltosCRCException { - String[] words = line.split("\\s+"); - int i = 0; + /* + * General header fields + * + * Name Value + * + * VERSION Telemetry version number (4 or more). Must be first. + * c Callsign (string, no spaces allowed) + * n Flight unit serial number (integer) + * f Flight number (integer) + * r Packet RSSI value (integer) + * s Flight computer state (string, no spaces allowed) + * t Flight computer clock (integer in centiseconds) + */ - if (words[i].equals("CRC") && words[i+1].equals("INVALID")) { - i += 2; - AltosParse.word(words[i++], "RSSI"); - rssi = AltosParse.parse_int(words[i++]); - throw new AltosCRCException(rssi); - } - if (words[i].equals("CALL")) { - version = 0; - } else { - AltosParse.word (words[i++], "VERSION"); - version = AltosParse.parse_int(words[i++]); - } + final static String AO_TELEM_VERSION = "VERSION"; + final static String AO_TELEM_CALL = "c"; + final static String AO_TELEM_SERIAL = "n"; + final static String AO_TELEM_FLIGHT = "f"; + final static String AO_TELEM_RSSI = "r"; + final static String AO_TELEM_STATE = "s"; + final static String AO_TELEM_TICK = "t"; + + /* + * Raw sensor values + * + * Name Value + * r_a Accelerometer reading (integer) + * r_b Barometer reading (integer) + * r_t Thermometer reading (integer) + * r_v Battery reading (integer) + * r_d Drogue continuity (integer) + * r_m Main continuity (integer) + */ + + final static String AO_TELEM_RAW_ACCEL = "r_a"; + final static String AO_TELEM_RAW_BARO = "r_b"; + final static String AO_TELEM_RAW_THERMO = "r_t"; + final static String AO_TELEM_RAW_BATT = "r_v"; + final static String AO_TELEM_RAW_DROGUE = "r_d"; + final static String AO_TELEM_RAW_MAIN = "r_m"; + + /* + * Sensor calibration values + * + * Name Value + * c_a Ground accelerometer reading (integer) + * c_b Ground barometer reading (integer) + * c_p Accelerometer reading for +1g + * c_m Accelerometer reading for -1g + */ + + final static String AO_TELEM_CAL_ACCEL_GROUND = "c_a"; + final static String AO_TELEM_CAL_BARO_GROUND = "c_b"; + final static String AO_TELEM_CAL_ACCEL_PLUS = "c_p"; + final static String AO_TELEM_CAL_ACCEL_MINUS = "c_m"; + + /* + * Kalman state values + * + * Name Value + * k_h Height above pad (integer, meters) + * k_s Vertical speeed (integer, m/s * 16) + * k_a Vertical acceleration (integer, m/s² * 16) + */ + + final static String AO_TELEM_KALMAN_HEIGHT = "k_h"; + final static String AO_TELEM_KALMAN_SPEED = "k_s"; + final static String AO_TELEM_KALMAN_ACCEL = "k_a"; + + /* + * Ad-hoc flight values + * + * Name Value + * a_a Acceleration (integer, sensor units) + * a_s Speed (integer, integrated acceleration value) + * a_b Barometer reading (integer, sensor units) + */ + + final static String AO_TELEM_ADHOC_ACCEL = "a_a"; + final static String AO_TELEM_ADHOC_SPEED = "a_s"; + final static String AO_TELEM_ADHOC_BARO = "a_b"; + + /* + * GPS values + * + * Name Value + * g_s GPS state (string): + * l locked + * u unlocked + * e error (missing or broken) + * g_n Number of sats used in solution + * g_ns Latitude (degrees * 10e7) + * g_ew Longitude (degrees * 10e7) + * g_a Altitude (integer meters) + * g_Y GPS year (integer) + * g_M GPS month (integer - 1-12) + * g_D GPS day (integer - 1-31) + * g_h GPS hour (integer - 0-23) + * g_m GPS minute (integer - 0-59) + * g_s GPS second (integer - 0-59) + * g_v GPS vertical speed (integer, cm/sec) + * g_s GPS horizontal speed (integer, cm/sec) + * g_c GPS course (integer, 0-359) + * g_hd GPS hdop (integer * 10) + * g_vd GPS vdop (integer * 10) + * g_he GPS h error (integer) + * g_ve GPS v error (integer) + */ + + final static String AO_TELEM_GPS_STATE = "g"; + final static String AO_TELEM_GPS_STATE_LOCKED = "l"; + final static String AO_TELEM_GPS_STATE_UNLOCKED = "u"; + final static String AO_TELEM_GPS_STATE_ERROR = "e"; + final static String AO_TELEM_GPS_NUM_SAT = "g_n"; + final static String AO_TELEM_GPS_LATITUDE = "g_ns"; + final static String AO_TELEM_GPS_LONGITUDE = "g_ew"; + final static String AO_TELEM_GPS_ALTITUDE = "g_a"; + final static String AO_TELEM_GPS_YEAR = "g_Y"; + final static String AO_TELEM_GPS_MONTH = "g_M"; + final static String AO_TELEM_GPS_DAY = "g_D"; + final static String AO_TELEM_GPS_HOUR = "g_h"; + final static String AO_TELEM_GPS_MINUTE = "g_m"; + final static String AO_TELEM_GPS_SECOND = "g_s"; + final static String AO_TELEM_GPS_VERTICAL_SPEED = "g_v"; + final static String AO_TELEM_GPS_HORIZONTAL_SPEED = "g_g"; + final static String AO_TELEM_GPS_COURSE = "g_c"; + final static String AO_TELEM_GPS_HDOP = "g_hd"; + final static String AO_TELEM_GPS_VDOP = "g_vd"; + final static String AO_TELEM_GPS_HERROR = "g_he"; + final static String AO_TELEM_GPS_VERROR = "g_ve"; + + /* + * GPS satellite values + * + * Name Value + * s_n Number of satellites reported (integer) + * s_v0 Space vehicle ID (integer) for report 0 + * s_c0 C/N0 number (integer) for report 0 + * s_v1 Space vehicle ID (integer) for report 1 + * s_c1 C/N0 number (integer) for report 1 + * ... + */ + + final static String AO_TELEM_SAT_NUM = "s_n"; + final static String AO_TELEM_SAT_SVID = "s_v"; + final static String AO_TELEM_SAT_C_N_0 = "s_c"; + + private void parse_v4(String[] words, int i) throws ParseException { + AltosTelemetryMap map = new AltosTelemetryMap(words, i); + + callsign = map.get_string(AO_TELEM_CALL, "N0CALL"); + serial = map.get_int(AO_TELEM_SERIAL, MISSING); + flight = map.get_int(AO_TELEM_FLIGHT, MISSING); + rssi = map.get_int(AO_TELEM_RSSI, MISSING); + state = Altos.state(map.get_string(AO_TELEM_STATE, "invalid")); + tick = map.get_int(AO_TELEM_TICK, 0); + + /* raw sensor values */ + accel = map.get_int(AO_TELEM_RAW_ACCEL, MISSING); + pres = map.get_int(AO_TELEM_RAW_BARO, MISSING); + temp = map.get_int(AO_TELEM_RAW_THERMO, MISSING); + batt = map.get_int(AO_TELEM_RAW_BATT, MISSING); + drogue = map.get_int(AO_TELEM_RAW_DROGUE, MISSING); + main = map.get_int(AO_TELEM_RAW_MAIN, MISSING); + + /* sensor calibration information */ + ground_accel = map.get_int(AO_TELEM_CAL_ACCEL_GROUND, MISSING); + ground_pres = map.get_int(AO_TELEM_CAL_BARO_GROUND, MISSING); + accel_plus_g = map.get_int(AO_TELEM_CAL_ACCEL_PLUS, MISSING); + accel_minus_g = map.get_int(AO_TELEM_CAL_ACCEL_MINUS, MISSING); + + /* flight computer values */ + acceleration = map.get_int(AO_TELEM_KALMAN_ACCEL, MISSING); + if (acceleration != MISSING) + acceleration /= 16.0; + speed = map.get_int(AO_TELEM_KALMAN_SPEED, MISSING); + if (speed != MISSING) + speed /= 16.0; + height = map.get_int(AO_TELEM_KALMAN_HEIGHT, MISSING); + + flight_accel = map.get_int(AO_TELEM_ADHOC_ACCEL, MISSING); + flight_vel = map.get_int(AO_TELEM_ADHOC_SPEED, MISSING); + flight_pres = map.get_int(AO_TELEM_ADHOC_BARO, MISSING); + + if (map.has(AO_TELEM_GPS_STATE)) + gps = new AltosGPS(map); + else + gps = null; + } + + private void parse_legacy(String[] words, int i) throws ParseException { AltosParse.word (words[i++], "CALL"); callsign = words[i++]; @@ -140,4 +346,27 @@ public class AltosTelemetry extends AltosRecord { gps = new AltosGPS(words, i, version); } + + public AltosTelemetry(String line) throws ParseException, AltosCRCException { + String[] words = line.split("\\s+"); + int i = 0; + + if (words[i].equals("CRC") && words[i+1].equals("INVALID")) { + i += 2; + AltosParse.word(words[i++], "RSSI"); + rssi = AltosParse.parse_int(words[i++]); + throw new AltosCRCException(rssi); + } + if (words[i].equals("CALL")) { + version = 0; + } else { + AltosParse.word (words[i++], "VERSION"); + version = AltosParse.parse_int(words[i++]); + } + + if (version < 4) + parse_legacy(words, i); + else + parse_v4(words, i); + } } diff --git a/altosui/AltosTelemetryIterable.java b/altosui/AltosTelemetryIterable.java index a71ab872..14b5f27f 100644 --- a/altosui/AltosTelemetryIterable.java +++ b/altosui/AltosTelemetryIterable.java @@ -63,7 +63,6 @@ public class AltosTelemetryIterable extends AltosRecordIterable { } catch (ParseException pe) { System.out.printf("parse exception %s\n", pe.getMessage()); } catch (AltosCRCException ce) { - System.out.printf("crc error\n"); } } } catch (IOException io) { diff --git a/altosui/AltosUI.java b/altosui/AltosUI.java index 90e3d7f0..4d17b0d2 100644 --- a/altosui/AltosUI.java +++ b/altosui/AltosUI.java @@ -328,7 +328,7 @@ public class AltosUI extends JFrame { if (input.equals(output)) { System.out.printf("Not processing '%s'\n", input); } else { - AltosWriter writer = open_csv(output); + AltosWriter writer = open_csv("/dev/stdout"); if (writer != null) { writer.write(iterable); writer.close(); diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 288fca0e..49f34ce3 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -65,6 +65,7 @@ altosui_JAVA = \ AltosRecord.java \ AltosRecordIterable.java \ AltosTelemetryReader.java \ + AltosTelemetryMap.java \ AltosReplayReader.java \ AltosRomconfig.java \ AltosRomconfigUI.java \ diff --git a/src/ao_telem.h b/src/ao_telem.h index b1624fe0..1a8da291 100644 --- a/src/ao_telem.h +++ b/src/ao_telem.h @@ -108,7 +108,7 @@ * GPS values * * Name Value - * g_s GPS state (string): + * g GPS state (string): * l locked * u unlocked * e error (missing or broken) @@ -123,7 +123,7 @@ * g_m GPS minute (integer - 0-59) * g_s GPS second (integer - 0-59) * g_v GPS vertical speed (integer, cm/sec) - * g_s GPS horizontal speed (integer, cm/sec) + * g_g GPS horizontal speed (integer, cm/sec) * g_c GPS course (integer, 0-359) * g_hd GPS hdop (integer * 10) * g_vd GPS vdop (integer * 10) @@ -131,7 +131,7 @@ * g_ve GPS v error (integer) */ -#define AO_TELEM_GPS_STATE "g_s" +#define AO_TELEM_GPS_STATE "g" #define AO_TELEM_GPS_STATE_LOCKED 'l' #define AO_TELEM_GPS_STATE_UNLOCKED 'u' #define AO_TELEM_GPS_STATE_ERROR 'e' @@ -146,7 +146,7 @@ #define AO_TELEM_GPS_MINUTE "g_m" #define AO_TELEM_GPS_SECOND "g_s" #define AO_TELEM_GPS_VERTICAL_SPEED "g_v" -#define AO_TELEM_GPS_HORIZONTAL_SPEED "g_s" +#define AO_TELEM_GPS_HORIZONTAL_SPEED "g_g" #define AO_TELEM_GPS_COURSE "g_c" #define AO_TELEM_GPS_HDOP "g_hd" #define AO_TELEM_GPS_VDOP "g_vd" -- cgit v1.2.3 From 3945d8f986d8f4bd3186a2cbaed5186e49d59839 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 26 Mar 2011 23:15:36 -0700 Subject: altos: Variable log rate in full logging code too With the fixed ADC rate used to get better data during flight, the logging code now needs to vary the data storage rate so that descent data is recorded at 10 samples/second while ascent data is recorded at 1 sample per second. Having the logging code do this itself eliminates any interaction with the flight code. Signed-off-by: Keith Packard --- src/ao_log_big.c | 52 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/ao_log_big.c b/src/ao_log_big.c index 6db4a0ff..8379ab5f 100644 --- a/src/ao_log_big.c +++ b/src/ao_log_big.c @@ -65,9 +65,16 @@ static __xdata uint8_t ao_log_adc_pos; /* a hack to make sure that ao_log_records fill the eeprom block in even units */ typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; +#define AO_SENSOR_INTERVAL_ASCENT 1 +#define AO_SENSOR_INTERVAL_DESCENT 10 +#define AO_OTHER_INTERVAL 32 + void ao_log(void) { + uint16_t next_sensor; + uint16_t next_other; + ao_storage_setup(); ao_log_scan(); @@ -76,7 +83,7 @@ ao_log(void) ao_sleep(&ao_log_running); log.type = AO_LOG_FLIGHT; - log.tick = ao_flight_tick; + next_other = next_sensor = log.tick = ao_flight_tick; #if HAS_ACCEL log.u.flight.ground_accel = ao_ground_accel; #endif @@ -90,36 +97,41 @@ ao_log(void) for (;;) { /* Write samples to EEPROM */ while (ao_log_adc_pos != ao_flight_adc) { - log.type = AO_LOG_SENSOR; log.tick = ao_adc_ring[ao_log_adc_pos].tick; - log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel; - log.u.sensor.pres = ao_adc_ring[ao_log_adc_pos].pres; - ao_log_data(&log); - if ((ao_log_adc_pos & 0x1f) == 0) { + if ((int16_t) (log.tick - next_sensor) >= 0) { + log.type = AO_LOG_SENSOR; + log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel; + log.u.sensor.pres = ao_adc_ring[ao_log_adc_pos].pres; + ao_log_data(&log); + if (ao_flight_state <= ao_flight_coast) + next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; + else + next_sensor = log.tick + AO_SENSOR_INTERVAL_DESCENT; + } + if ((int16_t) (log.tick - next_other) >= 0) { log.type = AO_LOG_TEMP_VOLT; - log.tick = ao_adc_ring[ao_log_adc_pos].tick; log.u.temp_volt.temp = ao_adc_ring[ao_log_adc_pos].temp; log.u.temp_volt.v_batt = ao_adc_ring[ao_log_adc_pos].v_batt; ao_log_data(&log); log.type = AO_LOG_DEPLOY; - log.tick = ao_adc_ring[ao_log_adc_pos].tick; log.u.deploy.drogue = ao_adc_ring[ao_log_adc_pos].sense_d; log.u.deploy.main = ao_adc_ring[ao_log_adc_pos].sense_m; ao_log_data(&log); + next_other = log.tick + AO_OTHER_INTERVAL; } ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); - } - /* Write state change to EEPROM */ - if (ao_flight_state != ao_log_state) { - ao_log_state = ao_flight_state; - log.type = AO_LOG_STATE; - log.tick = ao_flight_tick; - log.u.state.state = ao_log_state; - log.u.state.reason = 0; - ao_log_data(&log); - - if (ao_log_state == ao_flight_landed) - ao_log_stop(); + /* Write state change to EEPROM */ + if (ao_flight_state != ao_log_state) { + ao_log_state = ao_flight_state; + log.type = AO_LOG_STATE; + log.tick = ao_flight_tick; + log.u.state.state = ao_log_state; + log.u.state.reason = 0; + ao_log_data(&log); + + if (ao_log_state == ao_flight_landed) + ao_log_stop(); + } } /* Wait for a while */ -- cgit v1.2.3 From 7ce8c9081e703d1405c2595ab9bda0cfa218c6c4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 26 Mar 2011 23:38:54 -0700 Subject: altos: full logging must flush pending data before checking state Flight state must be checked only after any pending data have been written to the log as the 'current' flight state is only valid when the pending data values have been processed. This ensures that the 'boost' state is not marked until the full ring of data is written. This ensures that the data processing code can find the barometer values from before boost to get an idea of the ground pressure value. Signed-off-by: Keith Packard --- src/ao_log_big.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/ao_log_big.c b/src/ao_log_big.c index 8379ab5f..ab6b02f5 100644 --- a/src/ao_log_big.c +++ b/src/ao_log_big.c @@ -72,8 +72,7 @@ typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; void ao_log(void) { - uint16_t next_sensor; - uint16_t next_other; + uint16_t next_sensor, next_other; ao_storage_setup(); @@ -83,7 +82,7 @@ ao_log(void) ao_sleep(&ao_log_running); log.type = AO_LOG_FLIGHT; - next_other = next_sensor = log.tick = ao_flight_tick; + log.tick = ao_flight_tick; #if HAS_ACCEL log.u.flight.ground_accel = ao_ground_accel; #endif @@ -94,6 +93,8 @@ ao_log(void) * when starting up. */ ao_log_adc_pos = ao_adc_ring_next(ao_flight_adc); + next_other = next_sensor = ao_adc_ring[ao_log_adc_pos].tick; + ao_log_state = ao_flight_startup; for (;;) { /* Write samples to EEPROM */ while (ao_log_adc_pos != ao_flight_adc) { @@ -103,7 +104,7 @@ ao_log(void) log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel; log.u.sensor.pres = ao_adc_ring[ao_log_adc_pos].pres; ao_log_data(&log); - if (ao_flight_state <= ao_flight_coast) + if (ao_log_state <= ao_flight_coast) next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; else next_sensor = log.tick + AO_SENSOR_INTERVAL_DESCENT; @@ -120,18 +121,18 @@ ao_log(void) next_other = log.tick + AO_OTHER_INTERVAL; } ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); - /* Write state change to EEPROM */ - if (ao_flight_state != ao_log_state) { - ao_log_state = ao_flight_state; - log.type = AO_LOG_STATE; - log.tick = ao_flight_tick; - log.u.state.state = ao_log_state; - log.u.state.reason = 0; - ao_log_data(&log); - - if (ao_log_state == ao_flight_landed) - ao_log_stop(); - } + } + /* Write state change to EEPROM */ + if (ao_flight_state != ao_log_state) { + ao_log_state = ao_flight_state; + log.type = AO_LOG_STATE; + log.tick = ao_flight_tick; + log.u.state.state = ao_log_state; + log.u.state.reason = 0; + ao_log_data(&log); + + if (ao_log_state == ao_flight_landed) + ao_log_stop(); } /* Wait for a while */ -- cgit v1.2.3 From c754759a2d503633d527da4ebb20eb859cd506fd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 Mar 2011 17:54:44 -0700 Subject: altos: Split up flight code into separate flight/sample/kalman bits The flight code mashed together data processing, filtering and actual flight managament into one giant pile. Split things up so that we have: ao_sample.c: Sensor data processing. Reads the ring, handles calibration ao_kalman.c: Filter the data to track the accel/speed/height values ao_flight.c: Flight state management, specific to rocketry. The plan is to re-use ao_sample.c and ao_kalman.c for hardware not specifically designed for rocketry, like TeleNano. Signed-off-by: Keith Packard --- src/Makefile.proto | 6 + src/ao.h | 131 +++++++++++++-- src/ao_adc.c | 2 +- src/ao_config.c | 6 +- src/ao_flight.c | 452 ++------------------------------------------------- src/ao_flight_test.c | 43 ++++- src/ao_kalman.c | 245 ++++++++++++++++++++++++++++ src/ao_log_big.c | 8 +- src/ao_sample.c | 206 +++++++++++++++++++++++ src/ao_stdio.c | 2 +- 10 files changed, 635 insertions(+), 466 deletions(-) create mode 100644 src/ao_kalman.c create mode 100644 src/ao_sample.c (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index 85c0c46e..8dd21a64 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -147,6 +147,8 @@ SKY_DRIVER_SRC = \ # TM_TASK_SRC = \ ao_flight.c \ + ao_sample.c \ + ao_kalman.c \ ao_log.c \ ao_log_big.c \ ao_report.c \ @@ -179,6 +181,8 @@ TMINI_DRIVER_SRC = \ TMINI_TASK_SRC = \ ao_flight.c \ + ao_sample.c \ + ao_kalman.c \ ao_log.c \ ao_log_tiny.c \ ao_report.c \ @@ -207,6 +211,8 @@ TNANO_DRIVER_SRC = \ TNANO_TASK_SRC = \ ao_flight.c \ + ao_sample.c \ + ao_kalman.c \ ao_log.c \ ao_log_tiny.c \ ao_report.c \ diff --git a/src/ao.h b/src/ao.h index b88bef1f..42c3edda 100644 --- a/src/ao.h +++ b/src/ao.h @@ -695,22 +695,10 @@ enum ao_flight_state { ao_flight_invalid = 9 }; -extern __data uint8_t ao_flight_adc; extern __pdata enum ao_flight_state ao_flight_state; -extern __pdata uint16_t ao_flight_tick; -extern __xdata int16_t ao_ground_pres; -extern __pdata int16_t ao_ground_accel; + extern __pdata uint16_t ao_launch_time; extern __xdata uint8_t ao_flight_force_idle; -extern __pdata int16_t ao_ground_height; -extern __pdata int16_t ao_max_height; -extern __pdata int16_t ao_height; /* meters */ -extern __pdata int16_t ao_speed; /* m/s * 16 */ -extern __pdata int16_t ao_accel; /* m/s² * 16 */ - -#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) -#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) -#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) /* Flight thread */ void @@ -720,6 +708,121 @@ ao_flight(void); void ao_flight_init(void); +/* + * ao_sample.c + */ + +/* + * Barometer calibration + * + * We directly sample the barometer. The specs say: + * + * Pressure range: 15-115 kPa + * Voltage at 115kPa: 2.82 + * Output scale: 27mV/kPa + * + * If we want to detect launch with the barometer, we need + * a large enough bump to not be fooled by noise. At typical + * launch elevations (0-2000m), a 200Pa pressure change cooresponds + * to about a 20m elevation change. This is 5.4mV, or about 3LSB. + * As all of our calculations are done in 16 bits, we'll actually see a change + * of 16 times this though + * + * 27 mV/kPa * 32767 / 3300 counts/mV = 268.1 counts/kPa + */ + +/* Accelerometer calibration + * + * We're sampling the accelerometer through a resistor divider which + * consists of 5k and 10k resistors. This multiplies the values by 2/3. + * That goes into the cc1111 A/D converter, which is running at 11 bits + * of precision with the bits in the MSB of the 16 bit value. Only positive + * values are used, so values should range from 0-32752 for 0-3.3V. The + * specs say we should see 40mV/g (uncalibrated), multiply by 2/3 for what + * the A/D converter sees (26.67 mV/g). We should see 32752/3300 counts/mV, + * for a final computation of: + * + * 26.67 mV/g * 32767/3300 counts/mV = 264.8 counts/g + * + * Zero g was measured at 16000 (we would expect 16384). + * Note that this value is only require to tell if the + * rocket is standing upright. Once that is determined, + * the value of the accelerometer is averaged for 100 samples + * to find the resting accelerometer value, which is used + * for all further flight computations + */ + +#define GRAVITY 9.80665 + +/* + * Above this height, the baro sensor doesn't work + */ +#define AO_MAX_BARO_HEIGHT 12000 + +/* + * Above this speed, baro measurements are unreliable + */ +#define AO_MAX_BARO_SPEED 200 + +#define ACCEL_NOSE_UP (ao_accel_2g >> 2) + +/* + * Speed and acceleration are scaled by 16 to provide a bit more + * resolution while still having reasonable range. Note that this + * limits speed to 2047m/s (around mach 6) and acceleration to + * 2047m/s² (over 200g) + */ + +#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) +#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) +#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) + +extern __pdata uint16_t ao_sample_tick; /* time of last data */ +extern __pdata int16_t ao_sample_pres; /* most recent pressure sensor reading */ +extern __pdata int16_t ao_sample_alt; /* MSL of ao_sample_pres */ +extern __pdata int16_t ao_sample_height; /* AGL of ao_sample_pres */ +extern __data uint8_t ao_sample_adc; /* Ring position of last processed sample */ + +#if HAS_ACCEL +extern __pdata int16_t ao_sample_accel; /* most recent accel sensor reading */ +#endif + +extern __xdata int16_t ao_ground_pres; /* startup pressure */ +extern __xdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ + +#if HAS_ACCEL +extern __xdata int16_t ao_ground_accel; /* startup acceleration */ +extern __xdata int16_t ao_accel_2g; /* factory accel calibration */ +extern __xdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +#endif + +void ao_sample_init(void); + +/* returns FALSE in preflight mode, TRUE in flight mode */ +uint8_t ao_sample(void); + +/* + * ao_kalman.c + */ + +#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) +#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) +#define from_fix(x) ((x) >> 16) + +extern __pdata int16_t ao_height; /* meters */ +extern __pdata int16_t ao_speed; /* m/s * 16 */ +extern __pdata int16_t ao_accel; /* m/s² * 16 */ +extern __pdata int16_t ao_max_height; /* max of ao_height */ + +extern __pdata int16_t ao_error_h; +extern __pdata int16_t ao_error_h_sq_avg; + +#if HAS_ACCEL +extern __pdata int16_t ao_error_a; +#endif + +void ao_kalman(void); + /* * ao_report.c */ @@ -1054,7 +1157,7 @@ extern __xdata uint8_t ao_stdin_ready; void ao_add_stdio(char (*pollchar)(void), void (*putchar)(char) __reentrant, - void (*flush)(void)); + void (*flush)(void)) __reentrant; /* * ao_ignite.c diff --git a/src/ao_adc.c b/src/ao_adc.c index d77e7753..48568383 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -41,7 +41,7 @@ ao_adc_poll(void) void ao_adc_get(__xdata struct ao_adc *packet) { - uint8_t i = ao_adc_ring_prev(ao_flight_adc); + uint8_t i = ao_adc_ring_prev(ao_sample_adc); memcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); } diff --git a/src/ao_config.c b/src/ao_config.c index 771b21a1..319febb9 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -215,10 +215,10 @@ ao_config_accel_calibrate_auto(char *orientation) __reentrant puts("Calibrating..."); flush(); i = ACCEL_CALIBRATE_SAMPLES; accel_total = 0; - cal_adc_ring = ao_flight_adc; + cal_adc_ring = ao_sample_adc; while (i) { - ao_sleep(DATA_TO_XDATA(&ao_flight_adc)); - while (i && cal_adc_ring != ao_flight_adc) { + ao_sleep(DATA_TO_XDATA(&ao_sample_adc)); + while (i && cal_adc_ring != ao_sample_adc) { accel_total += (int32_t) ao_adc_ring[cal_adc_ring].accel; cal_adc_ring = ao_adc_ring_next(cal_adc_ring); i--; diff --git a/src/ao_flight.c b/src/ao_flight.c index 88f0544f..94fbf178 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -34,13 +34,7 @@ /* Main flight thread. */ __pdata enum ao_flight_state ao_flight_state; /* current flight state */ -__pdata uint16_t ao_flight_tick; /* time of last data */ -__pdata uint16_t ao_flight_prev_tick; /* time of previous data */ -__xdata int16_t ao_ground_pres; /* startup pressure */ __pdata uint16_t ao_launch_tick; /* time of launch detect */ -#if HAS_ACCEL -__pdata int16_t ao_ground_accel; /* startup acceleration */ -#endif /* * track min/max data over a long interval to detect @@ -50,59 +44,7 @@ __pdata uint16_t ao_interval_end; __pdata int16_t ao_interval_min_height; __pdata int16_t ao_interval_max_height; -__data uint8_t ao_flight_adc; -__pdata int16_t ao_raw_pres; -__xdata uint8_t ao_flight_force_idle; - -#if HAS_ACCEL -__pdata int16_t ao_raw_accel, ao_raw_accel_prev; -__pdata int16_t ao_accel_2g; - -/* Accelerometer calibration - * - * We're sampling the accelerometer through a resistor divider which - * consists of 5k and 10k resistors. This multiplies the values by 2/3. - * That goes into the cc1111 A/D converter, which is running at 11 bits - * of precision with the bits in the MSB of the 16 bit value. Only positive - * values are used, so values should range from 0-32752 for 0-3.3V. The - * specs say we should see 40mV/g (uncalibrated), multiply by 2/3 for what - * the A/D converter sees (26.67 mV/g). We should see 32752/3300 counts/mV, - * for a final computation of: - * - * 26.67 mV/g * 32767/3300 counts/mV = 264.8 counts/g - * - * Zero g was measured at 16000 (we would expect 16384). - * Note that this value is only require to tell if the - * rocket is standing upright. Once that is determined, - * the value of the accelerometer is averaged for 100 samples - * to find the resting accelerometer value, which is used - * for all further flight computations - */ - -#define GRAVITY 9.80665 - -#define ACCEL_NOSE_UP (ao_accel_2g >> 2) - -#endif - -/* - * Barometer calibration - * - * We directly sample the barometer. The specs say: - * - * Pressure range: 15-115 kPa - * Voltage at 115kPa: 2.82 - * Output scale: 27mV/kPa - * - * If we want to detect launch with the barometer, we need - * a large enough bump to not be fooled by noise. At typical - * launch elevations (0-2000m), a 200Pa pressure change cooresponds - * to about a 20m elevation change. This is 5.4mV, or about 3LSB. - * As all of our calculations are done in 16 bits, we'll actually see a change - * of 16 times this though - * - * 27 mV/kPa * 32767 / 3300 counts/mV = 268.1 counts/kPa - */ +__xdata uint8_t ao_flight_force_idle; /* We also have a clock, which can be used to sanity check things in * case of other failures @@ -110,228 +52,6 @@ __pdata int16_t ao_accel_2g; #define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) -#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) -#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) -#define from_fix(x) ((x) >> 16) - -#include "ao_kalman.h" - -__pdata int16_t ao_ground_height; -__pdata int16_t ao_height; -__pdata int16_t ao_speed; -__pdata int16_t ao_accel; -__pdata int16_t ao_max_height; - -static __pdata int32_t ao_k_height; -static __pdata int32_t ao_k_speed; -static __pdata int32_t ao_k_accel; - -#define AO_K_STEP_100 to_fix16(0.01) -#define AO_K_STEP_2_2_100 to_fix16(0.00005) - -#define AO_K_STEP_10 to_fix16(0.1) -#define AO_K_STEP_2_2_10 to_fix16(0.005) - -/* - * Above this height, the baro sensor doesn't work - */ -#define AO_MAX_BARO_HEIGHT 12000 - -/* - * Above this speed, baro measurements are unreliable - */ -#define AO_MAX_BARO_SPEED 200 - -static void -ao_kalman_predict(void) -{ -#ifdef AO_FLIGHT_TEST - if (ao_flight_tick - ao_flight_prev_tick > 5) { - ao_k_height += ((int32_t) ao_speed * AO_K_STEP_10 + - (int32_t) ao_accel * AO_K_STEP_2_2_10) >> 4; - ao_k_speed += (int32_t) ao_accel * AO_K_STEP_10; - - return; - } - if (ao_flight_debug) { - printf ("predict speed %g + (%g * %g) = %g\n", - ao_k_speed / (65536.0 * 16.0), ao_accel / 16.0, AO_K_STEP_100 / 65536.0, - (ao_k_speed + (int32_t) ao_accel * AO_K_STEP_100) / (65536.0 * 16.0)); - } -#endif - ao_k_height += ((int32_t) ao_speed * AO_K_STEP_100 + - (int32_t) ao_accel * AO_K_STEP_2_2_100) >> 4; - ao_k_speed += (int32_t) ao_accel * AO_K_STEP_100; -} - -static __pdata int16_t ao_error_h; -static __pdata int16_t ao_raw_alt; -static __pdata int16_t ao_raw_height; -static __pdata int16_t ao_error_h_sq_avg; - -static void -ao_kalman_err_height(void) -{ - int16_t e; - int16_t height_distrust; -#if HAS_ACCEL - int16_t speed_distrust; -#endif - - ao_error_h = ao_raw_height - (int16_t) (ao_k_height >> 16); - - e = ao_error_h; - if (e < 0) - e = -e; - if (e > 127) - e = 127; -#if HAS_ACCEL - ao_error_h_sq_avg -= ao_error_h_sq_avg >> 2; - ao_error_h_sq_avg += (e * e) >> 2; -#else - ao_error_h_sq_avg -= ao_error_h_sq_avg >> 4; - ao_error_h_sq_avg += (e * e) >> 4; -#endif - - height_distrust = ao_raw_height - AO_MAX_BARO_HEIGHT; -#if HAS_ACCEL - /* speed is stored * 16, but we need to ramp between 200 and 328, so - * we want to multiply by 2. The result is a shift by 3. - */ - speed_distrust = (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) >> (4 - 1); - if (speed_distrust <= 0) - speed_distrust = 0; - else if (speed_distrust > height_distrust) - height_distrust = speed_distrust; -#endif - if (height_distrust <= 0) - height_distrust = 0; - - if (height_distrust) { -#ifdef AO_FLIGHT_TEST - int old_ao_error_h = ao_error_h; -#endif - if (height_distrust > 0x100) - height_distrust = 0x100; - ao_error_h = (int16_t) (((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8); -#ifdef AO_FLIGHT_TEST - if (ao_flight_debug) { - printf("over height %g over speed %g distrust: %g height: error %d -> %d\n", - (double) (ao_raw_height - AO_MAX_BARO_HEIGHT), - (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) / 16.0, - height_distrust / 256.0, - old_ao_error_h, ao_error_h); - } -#endif - } -} - -static void -ao_kalman_correct_baro(void) -{ - ao_kalman_err_height(); -#ifdef AO_FLIGHT_TEST - if (ao_flight_tick - ao_flight_prev_tick > 5) { - ao_k_height += (int32_t) AO_BARO_K0_10 * ao_error_h; - ao_k_speed += (int32_t) AO_BARO_K1_10 * ao_error_h; - ao_k_accel += (int32_t) AO_BARO_K2_10 * ao_error_h; - return; - } -#endif - ao_k_height += (int32_t) AO_BARO_K0_100 * ao_error_h; - ao_k_speed += (int32_t) AO_BARO_K1_100 * ao_error_h; - ao_k_accel += (int32_t) AO_BARO_K2_100 * ao_error_h; -} - -#if HAS_ACCEL -static __pdata int16_t ao_error_a; -static __pdata int32_t ao_accel_scale; - -static void -ao_kalman_err_accel(void) -{ - int32_t accel; - - accel = (ao_ground_accel - ao_raw_accel) * ao_accel_scale; - - /* Can't use ao_accel here as it is the pre-prediction value still */ - ao_error_a = (accel - ao_k_accel) >> 16; -} - -static void -ao_kalman_correct_both(void) -{ - ao_kalman_err_height(); - ao_kalman_err_accel(); - -#ifdef AO_FLIGHT_TEST - if (ao_flight_tick - ao_flight_prev_tick > 5) { - if (ao_flight_debug) { - printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", - ao_k_speed / (65536.0 * 16.0), - (double) ao_error_h, AO_BOTH_K10_10 / 65536.0, - (double) ao_error_a, AO_BOTH_K11_10 / 65536.0, - (ao_k_speed + - (int32_t) AO_BOTH_K10_10 * ao_error_h + - (int32_t) AO_BOTH_K11_10 * ao_error_a) / (65536.0 * 16.0)); - } - ao_k_height += - (int32_t) AO_BOTH_K00_10 * ao_error_h + - (int32_t) AO_BOTH_K01_10 * ao_error_a; - ao_k_speed += - (int32_t) AO_BOTH_K10_10 * ao_error_h + - (int32_t) AO_BOTH_K11_10 * ao_error_a; - ao_k_accel += - (int32_t) AO_BOTH_K20_10 * ao_error_h + - (int32_t) AO_BOTH_K21_10 * ao_error_a; - return; - } - if (ao_flight_debug) { - printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", - ao_k_speed / (65536.0 * 16.0), - (double) ao_error_h, AO_BOTH_K10_100 / 65536.0, - (double) ao_error_a, AO_BOTH_K11_100 / 65536.0, - (ao_k_speed + - (int32_t) AO_BOTH_K10_100 * ao_error_h + - (int32_t) AO_BOTH_K11_100 * ao_error_a) / (65536.0 * 16.0)); - } -#endif - ao_k_height += - (int32_t) AO_BOTH_K00_100 * ao_error_h + - (int32_t) AO_BOTH_K01_100 * ao_error_a; - ao_k_speed += - (int32_t) AO_BOTH_K10_100 * ao_error_h + - (int32_t) AO_BOTH_K11_100 * ao_error_a; - ao_k_accel += - (int32_t) AO_BOTH_K20_100 * ao_error_h + - (int32_t) AO_BOTH_K21_100 * ao_error_a; -} - -#ifdef FORCE_ACCEL -static void -ao_kalman_correct_accel(void) -{ - ao_kalman_err_accel(); - - if (ao_flight_tick - ao_flight_prev_tick > 5) { - ao_k_height +=(int32_t) AO_ACCEL_K0_10 * ao_error_a; - ao_k_speed += (int32_t) AO_ACCEL_K1_10 * ao_error_a; - ao_k_accel += (int32_t) AO_ACCEL_K2_10 * ao_error_a; - return; - } - ao_k_height += (int32_t) AO_ACCEL_K0_100 * ao_error_a; - ao_k_speed += (int32_t) AO_ACCEL_K1_100 * ao_error_a; - ao_k_accel += (int32_t) AO_ACCEL_K2_100 * ao_error_a; -} -#endif -#endif /* HAS_ACCEL */ - -__xdata int32_t ao_raw_pres_sum; - -#ifdef HAS_ACCEL -__xdata int32_t ao_raw_accel_sum; -#endif - /* Landing is detected by getting constant readings from both pressure and accelerometer * for a fairly long time (AO_INTERVAL_TICKS) */ @@ -342,162 +62,20 @@ __xdata int32_t ao_raw_accel_sum; void ao_flight(void) { - __pdata static uint16_t nsamples = 0; - - ao_flight_adc = ao_adc_head; - ao_raw_pres = 0; -#if HAS_ACCEL - ao_raw_accel_prev = 0; - ao_raw_accel = 0; -#endif - ao_flight_tick = 0; + ao_sample_init(); + ao_flight_state = ao_flight_startup; for (;;) { - ao_wakeup(DATA_TO_XDATA(&ao_flight_adc)); - ao_sleep(DATA_TO_XDATA(&ao_adc_head)); - while (ao_flight_adc != ao_adc_head) { - __xdata struct ao_adc *ao_adc; - ao_flight_prev_tick = ao_flight_tick; - - /* Capture a sample */ - ao_adc = &ao_adc_ring[ao_flight_adc]; - ao_flight_tick = ao_adc->tick; - ao_raw_pres = ao_adc->pres; - ao_raw_alt = ao_pres_to_altitude(ao_raw_pres); - ao_raw_height = ao_raw_alt - ao_ground_height; -#if HAS_ACCEL - ao_raw_accel = ao_adc->accel; -#if HAS_ACCEL_REF - /* - * Ok, the math here is a bit tricky. - * - * ao_raw_accel: ADC output for acceleration - * ao_accel_ref: ADC output for the 5V reference. - * ao_cook_accel: Corrected acceleration value - * Vcc: 3.3V supply to the CC1111 - * Vac: 5V supply to the accelerometer - * accel: input voltage to accelerometer ADC pin - * ref: input voltage to 5V reference ADC pin - * - * - * Measured acceleration is ratiometric to Vcc: - * - * ao_raw_accel accel - * ------------ = ----- - * 32767 Vcc - * - * Measured 5v reference is also ratiometric to Vcc: - * - * ao_accel_ref ref - * ------------ = ----- - * 32767 Vcc - * - * - * ao_accel_ref = 32767 * (ref / Vcc) - * - * Acceleration is measured ratiometric to the 5V supply, - * so what we want is: - * - * ao_cook_accel accel - * ------------- = ----- - * 32767 ref - * - * - * accel Vcc - * = ----- * --- - * Vcc ref - * - * ao_raw_accel 32767 - * = ------------ * ------------ - * 32737 ao_accel_ref - * - * Multiply through by 32767: - * - * ao_raw_accel * 32767 - * ao_cook_accel = -------------------- - * ao_accel_ref - * - * Now, the tricky part. Getting this to compile efficiently - * and keeping all of the values in-range. - * - * First off, we need to use a shift of 16 instead of * 32767 as SDCC - * does the obvious optimizations for byte-granularity shifts: - * - * ao_cook_accel = (ao_raw_accel << 16) / ao_accel_ref - * - * Next, lets check our input ranges: - * - * 0 <= ao_raw_accel <= 0x7fff (singled ended ADC conversion) - * 0x7000 <= ao_accel_ref <= 0x7fff (the 5V ref value is close to 0x7fff) - * - * Plugging in our input ranges, we get an output range of 0 - 0x12490, - * which is 17 bits. That won't work. If we take the accel ref and shift - * by a bit, we'll change its range: - * - * 0xe000 <= ao_accel_ref<<1 <= 0xfffe - * - * ao_cook_accel = (ao_raw_accel << 16) / (ao_accel_ref << 1) - * - * Now the output range is 0 - 0x9248, which nicely fits in 16 bits. It - * is, however, one bit too large for our signed computations. So, we - * take the result and shift that by a bit: - * - * ao_cook_accel = ((ao_raw_accel << 16) / (ao_accel_ref << 1)) >> 1 - * - * This finally creates an output range of 0 - 0x4924. As the ADC only - * provides 11 bits of data, we haven't actually lost any precision, - * just dropped a bit of noise off the low end. - */ - ao_raw_accel = (uint16_t) ((((uint32_t) ao_raw_accel << 16) / (ao_accel_ref[ao_flight_adc] << 1))) >> 1; - ao_adc->accel = ao_raw_accel; -#endif -#endif - if (ao_flight_state > ao_flight_idle) { - ao_kalman_predict(); -#if HAS_ACCEL - if (ao_flight_state <= ao_flight_coast) { -#ifdef FORCE_ACCEL - ao_kalman_correct_accel(); -#else - ao_kalman_correct_both(); -#endif - } else -#endif - ao_kalman_correct_baro(); - ao_height = from_fix(ao_k_height); - ao_speed = from_fix(ao_k_speed); - ao_accel = from_fix(ao_k_accel); - if (ao_height > ao_max_height) - ao_max_height = ao_height; - } - ao_flight_adc = ao_adc_ring_next(ao_flight_adc); - } + /* + * Process ADC samples, just looping + * until the sensors are calibrated. + */ + if (!ao_sample()) + continue; switch (ao_flight_state) { case ao_flight_startup: - /* startup state: - * - * Collect 512 samples of acceleration and pressure - * data and average them to find the resting values - */ - if (nsamples < 512) { -#if HAS_ACCEL - ao_raw_accel_sum += ao_raw_accel; -#endif - ao_raw_pres_sum += ao_raw_pres; - ++nsamples; - continue; - } - ao_config_get(); -#if HAS_ACCEL - ao_ground_accel = ao_raw_accel_sum >> 9; - ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; - ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; -#endif - ao_ground_pres = ao_raw_pres_sum >> 9; - ao_ground_height = ao_pres_to_altitude(ao_ground_pres); - /* Check to see what mode we should go to. * - Invalid mode if accel cal appears to be out * - pad mode if we're upright, @@ -574,7 +152,7 @@ ao_flight(void) ) { ao_flight_state = ao_flight_boost; - ao_launch_tick = ao_flight_tick; + ao_launch_tick = ao_sample_tick; /* start logging data */ ao_log_start(); @@ -608,7 +186,7 @@ ao_flight(void) * (15 seconds) has past. */ if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || - (int16_t) (ao_flight_tick - ao_launch_tick) > BOOST_TICKS_MAX) + (int16_t) (ao_sample_tick - ao_launch_tick) > BOOST_TICKS_MAX) { #if HAS_ACCEL ao_flight_state = ao_flight_fast; @@ -646,7 +224,7 @@ ao_flight(void) */ if (ao_speed < 0 #if !HAS_ACCEL - && (ao_raw_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) + && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) #endif ) { @@ -662,7 +240,7 @@ ao_flight(void) */ /* initialize interval values */ - ao_interval_end = ao_flight_tick + AO_INTERVAL_TICKS; + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; ao_interval_min_height = ao_interval_max_height = ao_height; @@ -706,7 +284,7 @@ ao_flight(void) if (ao_height > ao_interval_max_height) ao_interval_max_height = ao_height; - if ((int16_t) (ao_flight_tick - ao_interval_end) >= 0) { + if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { if (ao_height < AO_M_TO_HEIGHT(1000) && ao_interval_max_height - ao_interval_min_height < AO_M_TO_HEIGHT(5)) { @@ -720,7 +298,7 @@ ao_flight(void) ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } ao_interval_min_height = ao_interval_max_height = ao_height; - ao_interval_end = ao_flight_tick + AO_INTERVAL_TICKS; + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; } break; case ao_flight_landed: diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 91aa0f73..f41acbca 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -53,6 +53,22 @@ struct ao_adc { #define __code #define __reentrant +#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) +#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) +#define from_fix(x) ((x) >> 16) + +/* + * Above this height, the baro sensor doesn't work + */ +#define AO_MAX_BARO_HEIGHT 12000 + +/* + * Above this speed, baro measurements are unreliable + */ +#define AO_MAX_BARO_SPEED 200 + +#define ACCEL_NOSE_UP (ao_accel_2g >> 2) + enum ao_flight_state { ao_flight_startup = 0, ao_flight_idle = 1, @@ -66,6 +82,11 @@ enum ao_flight_state { ao_flight_invalid = 9 }; +extern enum ao_flight_state ao_flight_state; + +#define FALSE 0 +#define TRUE 1 + struct ao_adc ao_adc_ring[AO_ADC_RING]; uint8_t ao_adc_head; int ao_summary = 0; @@ -171,15 +192,25 @@ struct ao_config ao_config; #define HAS_ACCEL_REF 0 #endif -#include "ao_flight.c" - -#define to_double(f) ((f) / 65536.0) - #define GRAVITY 9.80665 -extern int16_t ao_ground_accel, ao_raw_accel; +extern int16_t ao_ground_accel, ao_flight_accel; extern int16_t ao_accel_2g; +extern uint16_t ao_sample_tick; + +extern int16_t ao_sample_height; +extern int16_t ao_sample_accel; +extern int32_t ao_accel_scale; + +int ao_sample_prev_tick; uint16_t prev_tick; + +#include "ao_kalman.c" +#include "ao_sample.c" +#include "ao_flight.c" + +#define to_double(f) ((f) / 65536.0) + static int ao_records_read = 0; static int ao_eof_read = 0; static int ao_flight_ground_accel; @@ -224,7 +255,7 @@ ao_insert(void) ao_adc_ring[ao_adc_head] = ao_adc_static; ao_adc_head = ao_adc_ring_next(ao_adc_head); if (ao_flight_state != ao_flight_startup) { - double height = ao_pres_to_altitude(ao_raw_pres) - ao_ground_height; + double height = ao_pres_to_altitude(ao_sample_pres) - ao_ground_height; double accel = ((ao_flight_ground_accel - ao_adc_static.accel) * GRAVITY * 2.0) / (ao_config.accel_minus_g - ao_config.accel_plus_g); diff --git a/src/ao_kalman.c b/src/ao_kalman.c new file mode 100644 index 00000000..ee99f375 --- /dev/null +++ b/src/ao_kalman.c @@ -0,0 +1,245 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#endif + +#include "ao_kalman.h" + +static __pdata int32_t ao_k_height; +static __pdata int32_t ao_k_speed; +static __pdata int32_t ao_k_accel; + +#define AO_K_STEP_100 to_fix16(0.01) +#define AO_K_STEP_2_2_100 to_fix16(0.00005) + +#define AO_K_STEP_10 to_fix16(0.1) +#define AO_K_STEP_2_2_10 to_fix16(0.005) + +__pdata int16_t ao_height; +__pdata int16_t ao_speed; +__pdata int16_t ao_accel; +__pdata int16_t ao_max_height; + +__pdata int16_t ao_error_h; +__pdata int16_t ao_error_h_sq_avg; + +#if HAS_ACCEL +__pdata int16_t ao_error_a; +#endif + +static void +ao_kalman_predict(void) +{ +#ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 5) { + ao_k_height += ((int32_t) ao_speed * AO_K_STEP_10 + + (int32_t) ao_accel * AO_K_STEP_2_2_10) >> 4; + ao_k_speed += (int32_t) ao_accel * AO_K_STEP_10; + + return; + } + if (ao_flight_debug) { + printf ("predict speed %g + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), ao_accel / 16.0, AO_K_STEP_100 / 65536.0, + (ao_k_speed + (int32_t) ao_accel * AO_K_STEP_100) / (65536.0 * 16.0)); + } +#endif + ao_k_height += ((int32_t) ao_speed * AO_K_STEP_100 + + (int32_t) ao_accel * AO_K_STEP_2_2_100) >> 4; + ao_k_speed += (int32_t) ao_accel * AO_K_STEP_100; +} + +static void +ao_kalman_err_height(void) +{ + int16_t e; + int16_t height_distrust; +#if HAS_ACCEL + int16_t speed_distrust; +#endif + + ao_error_h = ao_sample_height - (int16_t) (ao_k_height >> 16); + + e = ao_error_h; + if (e < 0) + e = -e; + if (e > 127) + e = 127; +#if HAS_ACCEL + ao_error_h_sq_avg -= ao_error_h_sq_avg >> 2; + ao_error_h_sq_avg += (e * e) >> 2; +#else + ao_error_h_sq_avg -= ao_error_h_sq_avg >> 4; + ao_error_h_sq_avg += (e * e) >> 4; +#endif + + height_distrust = ao_sample_height - AO_MAX_BARO_HEIGHT; +#if HAS_ACCEL + /* speed is stored * 16, but we need to ramp between 200 and 328, so + * we want to multiply by 2. The result is a shift by 3. + */ + speed_distrust = (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) >> (4 - 1); + if (speed_distrust <= 0) + speed_distrust = 0; + else if (speed_distrust > height_distrust) + height_distrust = speed_distrust; +#endif + if (height_distrust <= 0) + height_distrust = 0; + + if (height_distrust) { +#ifdef AO_FLIGHT_TEST + int old_ao_error_h = ao_error_h; +#endif + if (height_distrust > 0x100) + height_distrust = 0x100; + ao_error_h = (int16_t) (((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8); +#ifdef AO_FLIGHT_TEST + if (ao_flight_debug) { + printf("over height %g over speed %g distrust: %g height: error %d -> %d\n", + (double) (ao_sample_height - AO_MAX_BARO_HEIGHT), + (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) / 16.0, + height_distrust / 256.0, + old_ao_error_h, ao_error_h); + } +#endif + } +} + +static void +ao_kalman_correct_baro(void) +{ + ao_kalman_err_height(); +#ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 5) { + ao_k_height += (int32_t) AO_BARO_K0_10 * ao_error_h; + ao_k_speed += (int32_t) AO_BARO_K1_10 * ao_error_h; + ao_k_accel += (int32_t) AO_BARO_K2_10 * ao_error_h; + return; + } +#endif + ao_k_height += (int32_t) AO_BARO_K0_100 * ao_error_h; + ao_k_speed += (int32_t) AO_BARO_K1_100 * ao_error_h; + ao_k_accel += (int32_t) AO_BARO_K2_100 * ao_error_h; +} + +#if HAS_ACCEL + +static void +ao_kalman_err_accel(void) +{ + int32_t accel; + + accel = (ao_ground_accel - ao_sample_accel) * ao_accel_scale; + + /* Can't use ao_accel here as it is the pre-prediction value still */ + ao_error_a = (accel - ao_k_accel) >> 16; +} + +static void +ao_kalman_correct_both(void) +{ + ao_kalman_err_height(); + ao_kalman_err_accel(); + +#ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 5) { + if (ao_flight_debug) { + printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), + (double) ao_error_h, AO_BOTH_K10_10 / 65536.0, + (double) ao_error_a, AO_BOTH_K11_10 / 65536.0, + (ao_k_speed + + (int32_t) AO_BOTH_K10_10 * ao_error_h + + (int32_t) AO_BOTH_K11_10 * ao_error_a) / (65536.0 * 16.0)); + } + ao_k_height += + (int32_t) AO_BOTH_K00_10 * ao_error_h + + (int32_t) AO_BOTH_K01_10 * ao_error_a; + ao_k_speed += + (int32_t) AO_BOTH_K10_10 * ao_error_h + + (int32_t) AO_BOTH_K11_10 * ao_error_a; + ao_k_accel += + (int32_t) AO_BOTH_K20_10 * ao_error_h + + (int32_t) AO_BOTH_K21_10 * ao_error_a; + return; + } + if (ao_flight_debug) { + printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), + (double) ao_error_h, AO_BOTH_K10_100 / 65536.0, + (double) ao_error_a, AO_BOTH_K11_100 / 65536.0, + (ao_k_speed + + (int32_t) AO_BOTH_K10_100 * ao_error_h + + (int32_t) AO_BOTH_K11_100 * ao_error_a) / (65536.0 * 16.0)); + } +#endif + ao_k_height += + (int32_t) AO_BOTH_K00_100 * ao_error_h + + (int32_t) AO_BOTH_K01_100 * ao_error_a; + ao_k_speed += + (int32_t) AO_BOTH_K10_100 * ao_error_h + + (int32_t) AO_BOTH_K11_100 * ao_error_a; + ao_k_accel += + (int32_t) AO_BOTH_K20_100 * ao_error_h + + (int32_t) AO_BOTH_K21_100 * ao_error_a; +} + +#ifdef FORCE_ACCEL +static void +ao_kalman_correct_accel(void) +{ + ao_kalman_err_accel(); + + if (ao_sample_tick - ao_sample_prev_tick > 5) { + ao_k_height +=(int32_t) AO_ACCEL_K0_10 * ao_error_a; + ao_k_speed += (int32_t) AO_ACCEL_K1_10 * ao_error_a; + ao_k_accel += (int32_t) AO_ACCEL_K2_10 * ao_error_a; + return; + } + ao_k_height += (int32_t) AO_ACCEL_K0_100 * ao_error_a; + ao_k_speed += (int32_t) AO_ACCEL_K1_100 * ao_error_a; + ao_k_accel += (int32_t) AO_ACCEL_K2_100 * ao_error_a; +} +#endif +#endif /* HAS_ACCEL */ + +void +ao_kalman(void) +{ + ao_kalman_predict(); +#if HAS_ACCEL + if (ao_flight_state <= ao_flight_coast) { +#ifdef FORCE_ACCEL + ao_kalman_correct_accel(); +#else + ao_kalman_correct_both(); +#endif + } else +#endif + ao_kalman_correct_baro(); + ao_height = from_fix(ao_k_height); + ao_speed = from_fix(ao_k_speed); + ao_accel = from_fix(ao_k_accel); + if (ao_height > ao_max_height) + ao_max_height = ao_height; +#ifdef AO_FLIGHT_TEST + ao_sample_prev_tick = ao_sample_tick; +#endif +} diff --git a/src/ao_log_big.c b/src/ao_log_big.c index ab6b02f5..0c6cff85 100644 --- a/src/ao_log_big.c +++ b/src/ao_log_big.c @@ -82,7 +82,7 @@ ao_log(void) ao_sleep(&ao_log_running); log.type = AO_LOG_FLIGHT; - log.tick = ao_flight_tick; + log.tick = ao_sample_tick; #if HAS_ACCEL log.u.flight.ground_accel = ao_ground_accel; #endif @@ -92,12 +92,12 @@ ao_log(void) /* Write the whole contents of the ring to the log * when starting up. */ - ao_log_adc_pos = ao_adc_ring_next(ao_flight_adc); + ao_log_adc_pos = ao_adc_ring_next(ao_sample_adc); next_other = next_sensor = ao_adc_ring[ao_log_adc_pos].tick; ao_log_state = ao_flight_startup; for (;;) { /* Write samples to EEPROM */ - while (ao_log_adc_pos != ao_flight_adc) { + while (ao_log_adc_pos != ao_sample_adc) { log.tick = ao_adc_ring[ao_log_adc_pos].tick; if ((int16_t) (log.tick - next_sensor) >= 0) { log.type = AO_LOG_SENSOR; @@ -126,7 +126,7 @@ ao_log(void) if (ao_flight_state != ao_log_state) { ao_log_state = ao_flight_state; log.type = AO_LOG_STATE; - log.tick = ao_flight_tick; + log.tick = ao_sample_tick; log.u.state.state = ao_log_state; log.u.state.reason = 0; ao_log_data(&log); diff --git a/src/ao_sample.c b/src/ao_sample.c new file mode 100644 index 00000000..ef403393 --- /dev/null +++ b/src/ao_sample.c @@ -0,0 +1,206 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#endif + +/* + * Current sensor values + */ + +__pdata uint16_t ao_sample_tick; /* time of last data */ +__pdata int16_t ao_sample_pres; +__pdata int16_t ao_sample_alt; +__pdata int16_t ao_sample_height; +#if HAS_ACCEL +__pdata int16_t ao_sample_accel; +#endif + +__data uint8_t ao_sample_adc; + +/* + * Sensor calibration values + */ + +__xdata int16_t ao_ground_pres; /* startup pressure */ +__xdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ + +#if HAS_ACCEL +__xdata int16_t ao_ground_accel; /* startup acceleration */ +__xdata int16_t ao_accel_2g; /* factory accel calibration */ +__xdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +#endif + +static __xdata uint8_t ao_preflight; /* in preflight mode */ + +static __xdata uint16_t nsamples; +__xdata int32_t ao_sample_pres_sum; +#if HAS_ACCEL +__xdata int32_t ao_sample_accel_sum; +#endif + +static void +ao_sample_preflight(void) +{ + /* startup state: + * + * Collect 512 samples of acceleration and pressure + * data and average them to find the resting values + */ + if (nsamples < 512) { +#if HAS_ACCEL + ao_sample_accel_sum += ao_sample_accel; +#endif + ao_sample_pres_sum += ao_sample_pres; + ++nsamples; + ao_preflight = FALSE; + } + ao_config_get(); +#if HAS_ACCEL + ao_ground_accel = ao_sample_accel_sum >> 9; + ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; + ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; +#endif + ao_ground_pres = ao_sample_pres_sum >> 9; + ao_ground_height = ao_pres_to_altitude(ao_ground_pres); +} + +uint8_t +ao_sample(void) +{ + ao_wakeup(DATA_TO_XDATA(&ao_sample_adc)); + ao_sleep(DATA_TO_XDATA(&ao_adc_head)); + while (ao_sample_adc != ao_adc_head) { + __xdata struct ao_adc *ao_adc; + + /* Capture a sample */ + ao_adc = &ao_adc_ring[ao_sample_adc]; + ao_sample_tick = ao_adc->tick; + ao_sample_pres = ao_adc->pres; + ao_sample_alt = ao_pres_to_altitude(ao_sample_pres); + ao_sample_height = ao_sample_alt - ao_ground_height; +#if HAS_ACCEL + ao_sample_accel = ao_adc->accel; +#if HAS_ACCEL_REF + /* + * Ok, the math here is a bit tricky. + * + * ao_sample_accel: ADC output for acceleration + * ao_accel_ref: ADC output for the 5V reference. + * ao_cook_accel: Corrected acceleration value + * Vcc: 3.3V supply to the CC1111 + * Vac: 5V supply to the accelerometer + * accel: input voltage to accelerometer ADC pin + * ref: input voltage to 5V reference ADC pin + * + * + * Measured acceleration is ratiometric to Vcc: + * + * ao_sample_accel accel + * ------------ = ----- + * 32767 Vcc + * + * Measured 5v reference is also ratiometric to Vcc: + * + * ao_accel_ref ref + * ------------ = ----- + * 32767 Vcc + * + * + * ao_accel_ref = 32767 * (ref / Vcc) + * + * Acceleration is measured ratiometric to the 5V supply, + * so what we want is: + * + * ao_cook_accel accel + * ------------- = ----- + * 32767 ref + * + * + * accel Vcc + * = ----- * --- + * Vcc ref + * + * ao_sample_accel 32767 + * = ------------ * ------------ + * 32737 ao_accel_ref + * + * Multiply through by 32767: + * + * ao_sample_accel * 32767 + * ao_cook_accel = -------------------- + * ao_accel_ref + * + * Now, the tricky part. Getting this to compile efficiently + * and keeping all of the values in-range. + * + * First off, we need to use a shift of 16 instead of * 32767 as SDCC + * does the obvious optimizations for byte-granularity shifts: + * + * ao_cook_accel = (ao_sample_accel << 16) / ao_accel_ref + * + * Next, lets check our input ranges: + * + * 0 <= ao_sample_accel <= 0x7fff (singled ended ADC conversion) + * 0x7000 <= ao_accel_ref <= 0x7fff (the 5V ref value is close to 0x7fff) + * + * Plugging in our input ranges, we get an output range of 0 - 0x12490, + * which is 17 bits. That won't work. If we take the accel ref and shift + * by a bit, we'll change its range: + * + * 0xe000 <= ao_accel_ref<<1 <= 0xfffe + * + * ao_cook_accel = (ao_sample_accel << 16) / (ao_accel_ref << 1) + * + * Now the output range is 0 - 0x9248, which nicely fits in 16 bits. It + * is, however, one bit too large for our signed computations. So, we + * take the result and shift that by a bit: + * + * ao_cook_accel = ((ao_sample_accel << 16) / (ao_accel_ref << 1)) >> 1 + * + * This finally creates an output range of 0 - 0x4924. As the ADC only + * provides 11 bits of data, we haven't actually lost any precision, + * just dropped a bit of noise off the low end. + */ + ao_sample_accel = (uint16_t) ((((uint32_t) ao_sample_accel << 16) / (ao_accel_ref[ao_sample_adc] << 1))) >> 1; + ao_adc->accel = ao_sample_accel; +#endif +#endif + + if (ao_preflight) + ao_sample_preflight(); + else + ao_kalman(); + ao_sample_adc = ao_adc_ring_next(ao_sample_adc); + } + return !ao_preflight; +} + +void +ao_sample_init(void) +{ + nsamples = 0; + ao_sample_pres_sum = 0; + ao_sample_pres = 0; +#if HAS_ACCEL + ao_sample_accel_sum = 0; + ao_sample_accel = 0; +#endif + ao_sample_adc = ao_adc_head; + ao_preflight = TRUE; +} diff --git a/src/ao_stdio.c b/src/ao_stdio.c index 78bbd3c3..6e1f5eff 100644 --- a/src/ao_stdio.c +++ b/src/ao_stdio.c @@ -66,7 +66,7 @@ getchar(void) __reentrant __critical void ao_add_stdio(char (*pollchar)(void), void (*putchar)(char), - void (*flush)(void)) + void (*flush)(void)) __reentrant { if (ao_num_stdios == AO_NUM_STDIOS) ao_panic(AO_PANIC_STDIO); -- cgit v1.2.3 From c6e7e812d67f91c63ba4982f7a899a72584027de Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 Mar 2011 18:18:50 -0700 Subject: altos: Create custom nano flight code No igniters, just 'pad/drogue/landed' modes (where 'drogue' == 'flying'). A constant 1Hz telemetry and RDF rate. Signed-off-by: Keith Packard --- src/Makefile.proto | 3 +- src/ao.h | 7 ++++ src/ao_flight_nano.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/ao_pins.h | 12 ++++++ src/ao_report.c | 4 ++ src/ao_telenano.c | 3 +- 6 files changed, 141 insertions(+), 4 deletions(-) create mode 100644 src/ao_flight_nano.c (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index 8dd21a64..5aad445f 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -204,13 +204,12 @@ TMINI_BASE_SRC = \ # Sources for TeleNano TNANO_DRIVER_SRC = \ ao_adc.c \ - ao_ignite.c \ ao_config.c \ ao_storage.c \ ao_intflash.c TNANO_TASK_SRC = \ - ao_flight.c \ + ao_flight_nano.c \ ao_sample.c \ ao_kalman.c \ ao_log.c \ diff --git a/src/ao.h b/src/ao.h index 42c3edda..89109fd9 100644 --- a/src/ao.h +++ b/src/ao.h @@ -708,6 +708,13 @@ ao_flight(void); void ao_flight_init(void); +/* + * ao_flight_nano.c + */ + +void +ao_flight_nano_init(void); + /* * ao_sample.c */ diff --git a/src/ao_flight_nano.c b/src/ao_flight_nano.c new file mode 100644 index 00000000..64c1d8db --- /dev/null +++ b/src/ao_flight_nano.c @@ -0,0 +1,116 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +/* Main flight thread. */ + +__pdata enum ao_flight_state ao_flight_state; /* current flight state */ +__pdata uint16_t ao_launch_tick; /* time of launch detect */ + +/* + * track min/max data over a long interval to detect + * resting + */ +__pdata uint16_t ao_interval_end; +__pdata int16_t ao_interval_min_height; +__pdata int16_t ao_interval_max_height; + +__xdata uint8_t ao_flight_force_idle; + +/* Landing is detected by getting constant readings from both pressure and accelerometer + * for a fairly long time (AO_INTERVAL_TICKS) + */ +#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(5) + +static void +ao_flight_nano(void) +{ + ao_sample_init(); + ao_flight_state = ao_flight_startup; + + for (;;) { + /* + * Process ADC samples, just looping + * until the sensors are calibrated. + */ + if (!ao_sample()) + continue; + + switch (ao_flight_state) { + case ao_flight_startup: + if (ao_flight_force_idle) { + /* Set idle mode */ + ao_flight_state = ao_flight_idle; + } else { + ao_flight_state = ao_flight_pad; + /* Disable packet mode in pad state */ + ao_packet_slave_stop(); + + /* Turn on telemetry system */ + ao_rdf_set(1); + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); + } + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + + /* wakeup threads due to state change */ + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + break; + case ao_flight_pad: + if (ao_height> AO_M_TO_HEIGHT(20)) { + ao_flight_state = ao_flight_drogue; + ao_launch_tick = ao_sample_tick; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + case ao_flight_drogue: + /* drogue/main to land: + * + * barometer: altitude stable + */ + + if (ao_height < ao_interval_min_height) + ao_interval_min_height = ao_height; + if (ao_height > ao_interval_max_height) + ao_interval_max_height = ao_height; + + if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { + if (ao_interval_max_height - ao_interval_min_height < AO_M_TO_HEIGHT(5)) + { + ao_flight_state = ao_flight_landed; + + /* turn off the ADC capture */ + ao_timer_set_adc_interval(0); + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + ao_interval_min_height = ao_interval_max_height = ao_height; + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + } + break; + } + } +} + +static __xdata struct ao_task flight_task; + +void +ao_flight_nano_init(void) +{ + ao_flight_state = ao_flight_startup; + ao_add_task(&flight_task, ao_flight_nano, "flight"); +} diff --git a/src/ao_pins.h b/src/ao_pins.h index a4a93aab..30f2decc 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -40,6 +40,7 @@ #define HAS_EXTERNAL_TEMP 0 #define HAS_ACCEL_REF 0 #define HAS_ACCEL 1 + #define HAS_IGNITE 1 #endif #if defined(TELEMETRUM_V_1_1) @@ -68,6 +69,7 @@ #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ #define M25_MAX_CHIPS 1 #define HAS_ACCEL 1 + #define HAS_IGNITE 1 #endif #if defined(TELEDONGLE_V_0_2) @@ -89,6 +91,7 @@ #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 + #define HAS_IGNITE 0 #endif #if defined(TELEMINI_V_0_1) @@ -111,6 +114,7 @@ #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define HAS_EXTERNAL_TEMP 0 #define HAS_ACCEL 0 + #define HAS_IGNITE 1 #endif #if defined(TELENANO_V_0_1) @@ -133,6 +137,7 @@ #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define HAS_EXTERNAL_TEMP 0 #define HAS_ACCEL 0 + #define HAS_IGNITE 0 #endif #if defined(TELEMETRUM_V_0_1) @@ -159,6 +164,7 @@ #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 #define HAS_ACCEL 1 + #define HAS_IGNITE 1 #endif #if defined(TELEDONGLE_V_0_1) @@ -180,6 +186,7 @@ #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define SPI_CS_ON_P1 0 #define SPI_CS_ON_P0 1 + #define HAS_IGNITE 0 #endif #if defined(TIDONGLE) @@ -200,6 +207,7 @@ #define LEDS_AVAILABLE (AO_LED_RED) #define SPI_CS_ON_P1 0 #define SPI_CS_ON_P0 1 + #define HAS_IGNITE 0 #endif #if DBG_ON_P1 @@ -280,6 +288,10 @@ #error Please define HAS_DBG #endif +#ifndef HAS_IGNITE +#error Please define HAS_IGNITE +#endif + #ifndef PACKET_HAS_MASTER #error Please define PACKET_HAS_MASTER #endif diff --git a/src/ao_report.c b/src/ao_report.c index 4f7fd657..b9dc5bb4 100644 --- a/src/ao_report.c +++ b/src/ao_report.c @@ -109,6 +109,7 @@ ao_report_altitude(void) } } +#if HAS_IGNITE static uint8_t ao_report_igniter_ready(enum ao_igniter igniter) { @@ -146,6 +147,7 @@ ao_report_continuity(void) __reentrant while (c-- && ao_flight_state == ao_flight_pad) pause(AO_MS_TO_TICKS(100)); } +#endif void ao_report(void) @@ -155,10 +157,12 @@ ao_report(void) if (ao_flight_state == ao_flight_landed) ao_report_altitude(); ao_report_beep(); +#if HAS_IGNITE if (ao_flight_state == ao_flight_idle) ao_report_continuity(); while (ao_flight_state == ao_flight_pad) ao_report_continuity(); +#endif __critical { while (ao_report_state == ao_flight_state) ao_sleep(DATA_TO_XDATA(&ao_flight_state)); diff --git a/src/ao_telenano.c b/src/ao_telenano.c index dbc3b74c..47b7b3c3 100644 --- a/src/ao_telenano.c +++ b/src/ao_telenano.c @@ -39,13 +39,12 @@ main(void) ao_adc_init(); ao_cmd_init(); ao_storage_init(); - ao_flight_init(); + ao_flight_nano_init(); ao_log_init(); ao_report_init(); ao_telemetry_tiny_init(); ao_radio_init(); ao_packet_slave_init(TRUE); - ao_igniter_init(); ao_config_init(); ao_start_scheduler(); } -- cgit v1.2.3 From 08e6bbef2c3529dfd468ef221c526fc9f3ed5b81 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 29 Mar 2011 10:08:46 -0700 Subject: altos: ao_sample_preflight was exiting preflight mode immediately Need to stay in pre-flight mode until we've gotten enough sensor data to calibrate things appropriately. The conversion from a unified ao_flight.c file was just broken here. Signed-off-by: Keith Packard --- src/ao_sample.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/ao_sample.c b/src/ao_sample.c index ef403393..84cf1e00 100644 --- a/src/ao_sample.c +++ b/src/ao_sample.c @@ -68,16 +68,17 @@ ao_sample_preflight(void) #endif ao_sample_pres_sum += ao_sample_pres; ++nsamples; - ao_preflight = FALSE; - } - ao_config_get(); + } else { + ao_config_get(); #if HAS_ACCEL - ao_ground_accel = ao_sample_accel_sum >> 9; - ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; - ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; + ao_ground_accel = ao_sample_accel_sum >> 9; + ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; + ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; #endif - ao_ground_pres = ao_sample_pres_sum >> 9; - ao_ground_height = ao_pres_to_altitude(ao_ground_pres); + ao_ground_pres = ao_sample_pres_sum >> 9; + ao_ground_height = ao_pres_to_altitude(ao_ground_pres); + ao_preflight = FALSE; + } } uint8_t -- cgit v1.2.3 From 011e37f27b3926a42c8c1a74e0f179bb48829ec7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 29 Mar 2011 18:10:46 -0700 Subject: altos: Run RDF beacon after apogee instead of waiting for landing This provides tracking when GPS fails, or on TeleMini. Signed-off-by: Keith Packard --- src/ao_flight.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index 94fbf178..c6cbbf7c 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -234,6 +234,9 @@ ao_flight(void) /* slow down the telemetry system */ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); + /* Turn the RDF beacon back on */ + ao_rdf_set(1); + /* * Start recording min/max height * to figure out when the rocket has landed @@ -292,8 +295,6 @@ ao_flight(void) /* turn off the ADC capture */ ao_timer_set_adc_interval(0); - /* Enable RDF beacon */ - ao_rdf_set(1); ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } -- cgit v1.2.3 From 87bff181a95f6bf92c2cec350d331ba6af779e80 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 29 Mar 2011 18:11:47 -0700 Subject: altos: Enable logging during nano flights Not having logging wasn't very useful. Signed-off-by: Keith Packard --- src/ao_flight_nano.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/ao_flight_nano.c b/src/ao_flight_nano.c index 64c1d8db..32770227 100644 --- a/src/ao_flight_nano.c +++ b/src/ao_flight_nano.c @@ -75,6 +75,10 @@ ao_flight_nano(void) if (ao_height> AO_M_TO_HEIGHT(20)) { ao_flight_state = ao_flight_drogue; ao_launch_tick = ao_sample_tick; + + /* start logging data */ + ao_log_start(); + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } break; -- cgit v1.2.3 From a9dae18a664f70b668159487015e61be7f776926 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 31 Mar 2011 20:51:15 -0700 Subject: altos: Reflect ao_flight split in ao_flight_test dependencies Need to rebuild ao_flight_test when any of the flight sources change Signed-off-by: Keith Packard --- src/test/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/test/Makefile b/src/test/Makefile index 433f749b..33203ffd 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -12,13 +12,13 @@ clean: install: -ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c altitude.h ao_kalman.h +ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h cc -g -o $@ $< -ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c altitude.h ao_kalman.h +ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h cc -g -o $@ -DHAS_ACCEL=0 ../ao_flight_test.c -ao_flight_test_accel: ao_flight_test.c ao_host.h ao_flight.c altitude.h ao_kalman.h +ao_flight_test_accel: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h cc -g -o $@ -DFORCE_ACCEL=1 ../ao_flight_test.c ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h -- cgit v1.2.3 From 8a14142e7b37031a51409f121b913fe793bf3603 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 31 Mar 2011 20:53:12 -0700 Subject: altos: Baro useful ceiling is MSL, not AGL Use MSL instead of AGL for detecting over-range baro sensor values. Always trust baro sensor during descent; it'll get there eventually. Signed-off-by: Keith Packard --- src/ao_kalman.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/ao_kalman.c b/src/ao_kalman.c index ee99f375..fb75fba9 100644 --- a/src/ao_kalman.c +++ b/src/ao_kalman.c @@ -89,7 +89,9 @@ ao_kalman_err_height(void) ao_error_h_sq_avg += (e * e) >> 4; #endif - height_distrust = ao_sample_height - AO_MAX_BARO_HEIGHT; + if (ao_flight_state >= ao_flight_drogue) + return; + height_distrust = ao_sample_alt - AO_MAX_BARO_HEIGHT; #if HAS_ACCEL /* speed is stored * 16, but we need to ramp between 200 and 328, so * we want to multiply by 2. The result is a shift by 3. @@ -100,10 +102,7 @@ ao_kalman_err_height(void) else if (speed_distrust > height_distrust) height_distrust = speed_distrust; #endif - if (height_distrust <= 0) - height_distrust = 0; - - if (height_distrust) { + if (height_distrust > 0) { #ifdef AO_FLIGHT_TEST int old_ao_error_h = ao_error_h; #endif @@ -113,7 +112,7 @@ ao_kalman_err_height(void) #ifdef AO_FLIGHT_TEST if (ao_flight_debug) { printf("over height %g over speed %g distrust: %g height: error %d -> %d\n", - (double) (ao_sample_height - AO_MAX_BARO_HEIGHT), + (double) (ao_sample_alt - AO_MAX_BARO_HEIGHT), (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) / 16.0, height_distrust / 256.0, old_ao_error_h, ao_error_h); -- cgit v1.2.3 From c0971abc02b05d136aea257f3f40ba3b22b1d441 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 31 Mar 2011 20:55:18 -0700 Subject: altos: Make ao_flight_test show true height but report saturated height To simulate a saturated baro sensor, clip baro data at a specified altitude. Continue to report the 'true' altitude in the output so that the resulting graphs are useful. Signed-off-by: Keith Packard --- src/ao_flight_test.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index f41acbca..57785442 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -41,6 +41,7 @@ struct ao_adc { uint16_t tick; /* tick when the sample was read */ int16_t accel; /* accelerometer */ int16_t pres; /* pressure sensor */ + int16_t pres_real; /* unclipped */ int16_t temp; /* temperature sensor */ int16_t v_batt; /* battery voltage */ int16_t sense_d; /* drogue continuity sense */ @@ -61,6 +62,8 @@ struct ao_adc { * Above this height, the baro sensor doesn't work */ #define AO_MAX_BARO_HEIGHT 12000 +#define AO_BARO_SATURATE 13000 +#define AO_MIN_BARO_VALUE ao_altitude_to_pres(AO_BARO_SATURATE) /* * Above this speed, baro measurements are unreliable @@ -201,6 +204,8 @@ extern uint16_t ao_sample_tick; extern int16_t ao_sample_height; extern int16_t ao_sample_accel; extern int32_t ao_accel_scale; +extern int16_t ao_ground_height; +extern int16_t ao_sample_alt; int ao_sample_prev_tick; uint16_t prev_tick; @@ -255,7 +260,7 @@ ao_insert(void) ao_adc_ring[ao_adc_head] = ao_adc_static; ao_adc_head = ao_adc_ring_next(ao_adc_head); if (ao_flight_state != ao_flight_startup) { - double height = ao_pres_to_altitude(ao_sample_pres) - ao_ground_height; + double height = ao_pres_to_altitude(ao_adc_static.pres_real) - ao_ground_height; double accel = ((ao_flight_ground_accel - ao_adc_static.accel) * GRAVITY * 2.0) / (ao_config.accel_minus_g - ao_config.accel_plus_g); @@ -373,6 +378,9 @@ ao_sleep(void *wchan) case 'A': ao_adc_static.tick = tick; ao_adc_static.accel = a; + ao_adc_static.pres_real = b; + if (b < AO_MIN_BARO_VALUE) + b = AO_MIN_BARO_VALUE; ao_adc_static.pres = b; ao_records_read++; ao_insert(); -- cgit v1.2.3 From 8e74cf6d1c70a7a17d01c20f6831571245392498 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 31 Mar 2011 20:58:14 -0700 Subject: altos: Add initial TeleBT code Prototyping with a TeleMetrum v0.1 board and a serial link to a bluetooth module. Signed-off-by: Keith Packard --- src/Makefile | 1 + src/Makefile.proto | 26 ++++++++++++++++ src/ao.h | 20 +++++++++++- src/ao_btm.c | 72 +++++++++++++++++++++++++++++++++++++++++++ src/ao_pins.h | 35 +++++++++++++++++++++ src/ao_serial.c | 42 +++++++++++++++++++++++++ src/ao_stdio.c | 2 +- src/ao_telebt.c | 41 ++++++++++++++++++++++++ src/telebt-v0.0/.gitignore | 2 ++ src/telebt-v0.0/.sdcdbrc | 1 + src/telebt-v0.0/Makefile.defs | 8 +++++ 11 files changed, 248 insertions(+), 2 deletions(-) create mode 100644 src/ao_btm.c create mode 100644 src/ao_telebt.c create mode 100644 src/telebt-v0.0/.gitignore create mode 100644 src/telebt-v0.0/.sdcdbrc create mode 100644 src/telebt-v0.0/Makefile.defs (limited to 'src') diff --git a/src/Makefile b/src/Makefile index a5dec57b..d83ec668 100644 --- a/src/Makefile +++ b/src/Makefile @@ -10,6 +10,7 @@ SUBDIRS=\ telemetrum-v1.1 telemetrum-v1.0 \ teledongle-v0.2 teledongle-v0.1 \ telemini-v0.1 telenano-v0.1 \ + telebt-v0.0 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ tidongle test diff --git a/src/Makefile.proto b/src/Makefile.proto index 5aad445f..ca68edbc 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -136,12 +136,20 @@ M25_DRIVER_SRC = \ # SIRF_DRIVER_SRC = \ ao_gps_sirf.c + # # Skytraq driver source # SKY_DRIVER_SRC = \ ao_gps_skytraq.c + +# +# BTM-182 driver source +# +BTM_DRIVER_SRC = \ + ao_btm.c + # # Tasks run on TeleMetrum # @@ -229,6 +237,24 @@ TNANO_BASE_SRC = \ $(TNANO_TASK_SRC) \ $(TNANO_MAIN_SRC) +# +# Sources for TeleDongle +# + +TBT_MAIN_SRC = \ + ao_telebt.c + +TBT_BASE_SRC = \ + $(ALTOS_SRC) \ + $(ALTOS_DRIVER_SRC) \ + $(TELE_RECEIVER_SRC) \ + $(TELE_COMMON_SRC) \ + $(SERIAL_DRIVER_SRC) \ + $(USB_DRIVER_SRC) \ + $(BTM_DRIVER_SRC) \ + $(DBG_SRC) \ + $(TBT_MAIN_SRC) + # # TI Dongle sources # diff --git a/src/ao.h b/src/ao.h index 89109fd9..64f33f0b 100644 --- a/src/ao.h +++ b/src/ao.h @@ -903,6 +903,10 @@ ao_dbg_init(void); #endif #if HAS_SERIAL_1 +#ifndef USE_SERIAL_STDIN +#error Please define USE_SERIAL_STDIN +#endif + void ao_serial_rx1_isr(void) __interrupt 3; @@ -912,12 +916,21 @@ ao_serial_tx1_isr(void) __interrupt 14; char ao_serial_getchar(void) __critical; +#if USE_SERIAL_STDIN +char +ao_serial_pollchar(void) __critical; + +void +ao_serial_set_stdin(uint8_t stdin); +#endif + void ao_serial_putchar(char c) __critical; #define AO_SERIAL_SPEED_4800 0 #define AO_SERIAL_SPEED_9600 1 -#define AO_SERIAL_SPEED_57600 2 +#define AO_SERIAL_SPEED_19200 2 +#define AO_SERIAL_SPEED_57600 3 void ao_serial_set_speed(uint8_t speed); @@ -1332,4 +1345,9 @@ ao_packet_slave_stop(void); void ao_packet_slave_init(uint8_t enable); +/* ao_btm.c */ + +void +ao_btm_init(void); + #endif /* _AO_H_ */ diff --git a/src/ao_btm.c b/src/ao_btm.c new file mode 100644 index 00000000..224d3e81 --- /dev/null +++ b/src/ao_btm.c @@ -0,0 +1,72 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +uint8_t ao_btm_enable; +extern volatile __xdata struct ao_fifo ao_usart1_rx_fifo; + +void +ao_btm(void) +{ + char c; + while (ao_btm_enable) { + c = ao_serial_pollchar(); + if (c != AO_READ_AGAIN) + ao_usb_putchar(c); + else { + ao_usb_flush(); + ao_sleep(&ao_usart1_rx_fifo); + } + } + ao_exit(); +} + +__xdata struct ao_task ao_btm_task; + +static void +ao_btm_forward(void) +{ + char c; + ao_btm_enable = 1; + flush(); + ao_add_task(&ao_btm_task, ao_btm, "btm"); + + while ((c = ao_usb_getchar()) != '~') { + if (c == '\n') c = '\r'; + ao_serial_putchar(c); + } + ao_btm_enable = 0; + while (ao_btm_task.wchan) { + ao_wakeup(&ao_usart1_rx_fifo); + ao_delay(AO_MS_TO_TICKS(10)); + } +} + +__code struct ao_cmds ao_btm_cmds[] = { + { ao_btm_forward, "B \0BTM serial link." }, + { 0, NULL }, +}; + + +void +ao_btm_init (void) +{ + ao_serial_init(); + ao_serial_set_speed(AO_SERIAL_SPEED_19200); + ao_cmd_register(&ao_btm_cmds[0]); +} diff --git a/src/ao_pins.h b/src/ao_pins.h index 30f2decc..a4ebd63b 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -25,6 +25,7 @@ #define HAS_GPS 1 #define HAS_SERIAL_1 1 #define HAS_ADC 1 + #define USE_SERIAL_STDIN 0 #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 0 #define HAS_DBG 1 @@ -49,6 +50,7 @@ #define HAS_BEEP 1 #define HAS_GPS 1 #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 0 @@ -77,6 +79,7 @@ #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 @@ -100,6 +103,7 @@ #define HAS_BEEP 0 #define HAS_GPS 0 #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 1 @@ -123,6 +127,7 @@ #define HAS_BEEP 0 #define HAS_GPS 0 #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 #define USE_INTERNAL_FLASH 1 @@ -146,6 +151,7 @@ #define HAS_BEEP 1 #define HAS_GPS 1 #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_DBG 0 #define HAS_EEPROM 1 @@ -172,6 +178,7 @@ #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 #define HAS_ADC 0 #define HAS_DBG 0 #define HAS_EEPROM 0 @@ -194,6 +201,7 @@ #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 @@ -210,6 +218,29 @@ #define HAS_IGNITE 0 #endif +#if defined(TELEBT_V_0_0) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 1 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_IGNITE 0 +#endif + #if DBG_ON_P1 #define DBG_CLOCK (1 << 4) /* mi0 */ @@ -270,6 +301,10 @@ #error Please define HAS_SERIAL_1 #endif +#ifndef USE_SERIAL_STDIN +#error Please define USE_SERIAL_STDIN +#endif + #ifndef HAS_ADC #error Please define HAS_ADC #endif diff --git a/src/ao_serial.c b/src/ao_serial.c index dd383fca..b8e9d2bf 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -20,12 +20,20 @@ volatile __xdata struct ao_fifo ao_usart1_rx_fifo; volatile __xdata struct ao_fifo ao_usart1_tx_fifo; +#if USE_SERIAL_STDIN +__pdata uint8_t ao_serial_stdin; +#endif + void ao_serial_rx1_isr(void) __interrupt 3 { if (!ao_fifo_full(ao_usart1_rx_fifo)) ao_fifo_insert(ao_usart1_rx_fifo, U1DBUF); ao_wakeup(&ao_usart1_rx_fifo); +#if USE_SERIAL_STDIN + if (ao_serial_stdin) + ao_wakeup(&ao_stdin_ready); +#endif } static __xdata uint8_t ao_serial_tx1_started; @@ -69,6 +77,29 @@ ao_serial_getchar(void) __critical return c; } +#if USE_SERIAL_STDIN +char +ao_serial_pollchar(void) __critical +{ + char c; +#if 0 + if (!ao_serial_stdin) + return AO_READ_AGAIN; +#endif + if (ao_fifo_empty(ao_usart1_rx_fifo)) + return AO_READ_AGAIN; + ao_fifo_remove(ao_usart1_rx_fifo,c); + return c; +} + +void +ao_serial_set_stdin(uint8_t stdin) +{ + ao_serial_stdin = stdin; +} + +#endif + void ao_serial_putchar(char c) __critical { @@ -109,6 +140,10 @@ static const struct { /* .baud = */ 163, /* .gcr = */ (8 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB }, + /* [AO_SERIAL_SPEED_19200] = */ { + /* .baud = */ 163, + /* .gcr = */ (9 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB + }, /* [AO_SERIAL_SPEED_57600] = */ { /* .baud = */ 59, /* .gcr = */ (11 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB @@ -156,4 +191,11 @@ ao_serial_init(void) IEN2 |= IEN2_UTX1IE; ao_cmd_register(&ao_serial_cmds[0]); +#if 0 +#if USE_SERIAL_STDIN + ao_add_stdio(ao_serial_pollchar, + ao_serial_putchar, + NULL); +#endif +#endif } diff --git a/src/ao_stdio.c b/src/ao_stdio.c index 6e1f5eff..c7080ec1 100644 --- a/src/ao_stdio.c +++ b/src/ao_stdio.c @@ -21,7 +21,7 @@ * Basic I/O functions to support SDCC stdio package */ -#define AO_NUM_STDIOS 2 +#define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) static __xdata struct ao_stdio stdios[AO_NUM_STDIOS]; static __data int8_t ao_cur_stdio; diff --git a/src/ao_telebt.c b/src/ao_telebt.c new file mode 100644 index 00000000..295f0cec --- /dev/null +++ b/src/ao_telebt.c @@ -0,0 +1,41 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +void +main(void) +{ + ao_clock_init(); + + /* Turn on the LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + ao_timer_init(); + ao_cmd_init(); + ao_usb_init(); + ao_monitor_init(AO_LED_GREEN, TRUE); + ao_rssi_init(AO_LED_RED); + ao_radio_init(); + ao_packet_master_init(); + ao_btm_init(); +#if HAS_DBG + ao_dbg_init(); +#endif + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/telebt-v0.0/.gitignore b/src/telebt-v0.0/.gitignore new file mode 100644 index 00000000..1acfbfcc --- /dev/null +++ b/src/telebt-v0.0/.gitignore @@ -0,0 +1,2 @@ +telebt-* +ao_product.h diff --git a/src/telebt-v0.0/.sdcdbrc b/src/telebt-v0.0/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telebt-v0.0/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telebt-v0.0/Makefile.defs b/src/telebt-v0.0/Makefile.defs new file mode 100644 index 00000000..f0bb5e0c --- /dev/null +++ b/src/telebt-v0.0/Makefile.defs @@ -0,0 +1,8 @@ +PROG = telebt-v0.0-$(VERSION).ihx + +SRC = \ + $(TBT_BASE_SRC) + +PRODUCT=TeleBT-v0.0 +PRODUCT_DEF=-DTELEBT_V_0_0 +IDPRODUCT=0x000e -- cgit v1.2.3 From ce18eaa28b1385c962c09459cbc5f20e234d9ad5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Apr 2011 14:03:25 -0700 Subject: altos: Add P2SEL_*_MASK defines to cc1111.h These are used to avoid having the code "know" which selections are 1 and which are 0 bits. Signed-off-by: Keith Packard --- src/cc1111.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/cc1111.h b/src/cc1111.h index effb1a68..a72d7416 100644 --- a/src/cc1111.h +++ b/src/cc1111.h @@ -565,14 +565,19 @@ sfr at 0xF5 P2SEL; #define P2SEL_PRI3P1_MASK (1 << 6) #define P2SEL_PRI2P1_USART1 (0 << 5) #define P2SEL_PRI2P1_TIMER3 (1 << 5) +#define P2SEL_PRI2P1_MASK (1 << 5) #define P2SEL_PRI1P1_TIMER1 (0 << 4) #define P2SEL_PRI1P1_TIMER4 (1 << 4) +#define P2SEL_PRI1P1_MASK (1 << 4) #define P2SEL_PRI0P1_USART0 (0 << 3) #define P2SEL_PRI0P1_TIMER1 (1 << 3) +#define P2SEL_PRI0P1_MASK (1 << 3) #define P2SEL_SELP2_4_GPIO (0 << 2) #define P2SEL_SELP2_4_PERIPHERAL (1 << 2) +#define P2SEL_SELP2_4_MASK (1 << 2) #define P2SEL_SELP2_3_GPIO (0 << 1) #define P2SEL_SELP2_3_PERIPHERAL (1 << 1) +#define P2SEL_SELP2_3_MASK (1 << 1) #define P2SEL_SELP2_0_GPIO (0 << 0) #define P2SEL_SELP2_0_PERIPHERAL (1 << 0) #define P2SEL_SELP2_0_MASK (1 << 0) -- cgit v1.2.3 From 359ba0d9fc2c5947e6adc98bebcd061069c61e79 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Apr 2011 14:04:58 -0700 Subject: altos: expose set of available stdio values This lets external code manipulate which connection to communicate over. Signed-off-by: Keith Packard --- src/ao.h | 3 +++ src/ao_stdio.c | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 64f33f0b..2d2bbf82 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1169,6 +1169,9 @@ struct ao_stdio { void (*flush)(void); }; +extern __data int8_t ao_cur_stdio; +extern __data int8_t ao_num_stdios; + void flush(void); diff --git a/src/ao_stdio.c b/src/ao_stdio.c index c7080ec1..3dd457f7 100644 --- a/src/ao_stdio.c +++ b/src/ao_stdio.c @@ -24,8 +24,8 @@ #define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) static __xdata struct ao_stdio stdios[AO_NUM_STDIOS]; -static __data int8_t ao_cur_stdio; -static __data int8_t ao_num_stdios; +__data int8_t ao_cur_stdio; +__data int8_t ao_num_stdios; void putchar(char c) -- cgit v1.2.3 From 01952da35a57ae4da062facb26b3c6d7de29190f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Apr 2011 14:07:23 -0700 Subject: altos: Provide for a pre-filter on commands This allows for external code to see each command line before it is processed and potentially skip it. Signed-off-by: Keith Packard --- src/ao.h | 8 ++++++++ src/ao_cmd.c | 5 +++++ 2 files changed, 13 insertions(+) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 2d2bbf82..77f3259e 100644 --- a/src/ao.h +++ b/src/ao.h @@ -403,6 +403,14 @@ ao_cmd_register(__code struct ao_cmds *cmds); void ao_cmd_init(void); +#if HAS_CMD_FILTER +/* + * Provided by an external module to filter raw command lines + */ +uint8_t +ao_cmd_filter(void); +#endif + /* * ao_dma.c */ diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 6007773c..50d5b96f 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -275,6 +275,11 @@ ao_cmd(void) lex_echo = 1; for (;;) { readline(); +#if HAS_CMD_FILTER + if (ao_cmd_filter()) + continue; + cmd_i = 0; +#endif ao_cmd_lex(); ao_cmd_white(); c = ao_cmd_lex_c; -- cgit v1.2.3 From 39bde78edc863d9d2ef50a59b8f28ab6274892b4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Apr 2011 14:08:37 -0700 Subject: altos: Allow any stdio to be used with packet forwarding There's no reason to restrict packet forwarding to work only from USB. Signed-off-by: Keith Packard --- src/ao_packet_master.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index 069bc5df..e721ffba 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -26,7 +26,7 @@ ao_packet_getchar(void) __critical break; if (ao_packet_master_sleeping) ao_wakeup(&ao_packet_master_sleeping); - ao_usb_flush(); + flush(); ao_sleep(&ao_stdin_ready); } return c; @@ -39,7 +39,7 @@ ao_packet_echo(void) __reentrant while (ao_packet_enable) { c = ao_packet_getchar(); if (c != AO_READ_AGAIN) - ao_usb_putchar(c); + putchar(c); } ao_exit(); } @@ -112,7 +112,7 @@ ao_packet_forward(void) __reentrant ao_set_monitor(0); ao_add_task(&ao_packet_task, ao_packet_master, "master"); ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); - while ((c = ao_usb_getchar()) != '~') { + while ((c = getchar()) != '~') { if (c == '\r') c = '\n'; ao_packet_putchar(c); } -- cgit v1.2.3 From 4f243a282f9aeb7433ccb2942850d380a091e603 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Apr 2011 14:10:37 -0700 Subject: altos: Remove serial monitor command This takes up space and isn't that useful these days Signed-off-by: Keith Packard --- src/ao_serial.c | 23 ----------------------- 1 file changed, 23 deletions(-) (limited to 'src') diff --git a/src/ao_serial.c b/src/ao_serial.c index b8e9d2bf..d6395810 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -58,8 +58,6 @@ ao_serial_tx1_isr(void) __interrupt 14 ao_wakeup(&ao_usart1_tx_fifo); } -static __pdata serial_echo; - char ao_serial_getchar(void) __critical { @@ -67,13 +65,6 @@ ao_serial_getchar(void) __critical while (ao_fifo_empty(ao_usart1_rx_fifo)) ao_sleep(&ao_usart1_rx_fifo); ao_fifo_remove(ao_usart1_rx_fifo, c); - if (serial_echo) { - printf("%02x ", ((int) c) & 0xff); - if (c >= ' ') - putchar(c); - putchar('\n'); - flush(); - } return c; } @@ -116,18 +107,6 @@ ao_serial_drain(void) __critical ao_sleep(&ao_usart1_tx_fifo); } -static void -monitor_serial(void) -{ - ao_cmd_hex(); - serial_echo = ao_cmd_lex_i != 0; -} - -__code struct ao_cmds ao_serial_cmds[] = { - { monitor_serial, "M \0Monitor serial data" }, - { 0, NULL }, -}; - static const struct { uint8_t baud; uint8_t gcr; @@ -189,8 +168,6 @@ ao_serial_init(void) IEN0 |= IEN0_URX1IE; IEN2 |= IEN2_UTX1IE; - - ao_cmd_register(&ao_serial_cmds[0]); #if 0 #if USE_SERIAL_STDIN ao_add_stdio(ao_serial_pollchar, -- cgit v1.2.3 From 9f8a96a8516e13878b329dbf1da855ed9a3219c4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Apr 2011 14:11:44 -0700 Subject: altos: Make ao_serial_drain public Allow external code to discard serial input Signed-off-by: Keith Packard --- src/ao.h | 3 +++ src/ao_serial.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 77f3259e..b92e623f 100644 --- a/src/ao.h +++ b/src/ao.h @@ -935,6 +935,9 @@ ao_serial_set_stdin(uint8_t stdin); void ao_serial_putchar(char c) __critical; +void +ao_serial_drain(void) __critical; + #define AO_SERIAL_SPEED_4800 0 #define AO_SERIAL_SPEED_9600 1 #define AO_SERIAL_SPEED_19200 2 diff --git a/src/ao_serial.c b/src/ao_serial.c index d6395810..e9373e23 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -100,7 +100,7 @@ ao_serial_putchar(char c) __critical ao_serial_tx1_start(); } -static void +void ao_serial_drain(void) __critical { while (!ao_fifo_empty(ao_usart1_tx_fifo)) -- cgit v1.2.3 From 92386f2e8419c4df125692cc998eb72ec49bf991 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Apr 2011 14:12:56 -0700 Subject: altos: Clean up usage of serial port for stdio Code wanting to use this must invoke ao_add_stdio; that way the link can be configured before command processing starts. Signed-off-by: Keith Packard --- src/ao_serial.c | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) (limited to 'src') diff --git a/src/ao_serial.c b/src/ao_serial.c index e9373e23..dc68f862 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -20,10 +20,6 @@ volatile __xdata struct ao_fifo ao_usart1_rx_fifo; volatile __xdata struct ao_fifo ao_usart1_tx_fifo; -#if USE_SERIAL_STDIN -__pdata uint8_t ao_serial_stdin; -#endif - void ao_serial_rx1_isr(void) __interrupt 3 { @@ -31,8 +27,7 @@ ao_serial_rx1_isr(void) __interrupt 3 ao_fifo_insert(ao_usart1_rx_fifo, U1DBUF); ao_wakeup(&ao_usart1_rx_fifo); #if USE_SERIAL_STDIN - if (ao_serial_stdin) - ao_wakeup(&ao_stdin_ready); + ao_wakeup(&ao_stdin_ready); #endif } @@ -73,22 +68,11 @@ char ao_serial_pollchar(void) __critical { char c; -#if 0 - if (!ao_serial_stdin) - return AO_READ_AGAIN; -#endif if (ao_fifo_empty(ao_usart1_rx_fifo)) return AO_READ_AGAIN; ao_fifo_remove(ao_usart1_rx_fifo,c); return c; } - -void -ao_serial_set_stdin(uint8_t stdin) -{ - ao_serial_stdin = stdin; -} - #endif void @@ -168,11 +152,4 @@ ao_serial_init(void) IEN0 |= IEN0_URX1IE; IEN2 |= IEN2_UTX1IE; -#if 0 -#if USE_SERIAL_STDIN - ao_add_stdio(ao_serial_pollchar, - ao_serial_putchar, - NULL); -#endif -#endif } -- cgit v1.2.3 From 4e2c18249e16c98cf5f7dccdf8d3b84bc473863a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Apr 2011 16:48:12 -0700 Subject: altos: Clean up serial initialization Flush serial input buffers when switching speeds. Ensure pin configuration is correct. Signed-off-by: Keith Packard --- src/ao_serial.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao_serial.c b/src/ao_serial.c index dc68f862..9c0b798d 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -119,6 +119,7 @@ ao_serial_set_speed(uint8_t speed) ao_serial_drain(); if (speed > AO_SERIAL_SPEED_57600) return; + U1UCR |= UxUCR_FLUSH; U1BAUD = ao_serial_speeds[speed].baud; U1GCR = ao_serial_speeds[speed].gcr; } @@ -129,7 +130,8 @@ ao_serial_init(void) /* Set up the USART pin assignment */ PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_2; - /* ee has already set the P2SEL bits */ + P2SEL = (P2SEL & ~(P2SEL_PRI3P1_MASK | P2SEL_PRI2P1_MASK)) | + (P2SEL_PRI3P1_USART1 | P2SEL_PRI2P1_USART1); /* Make the USART pins be controlled by the USART */ P1SEL |= (1 << 6) | (1 << 7); @@ -143,7 +145,7 @@ ao_serial_init(void) /* Reasonable serial parameters */ U1UCR = (UxUCR_FLUSH | UxUCR_FLOW_DISABLE | - UxUCR_D9_ODD_PARITY | + UxUCR_D9_EVEN_PARITY | UxUCR_BIT9_8_BITS | UxUCR_PARITY_DISABLE | UxUCR_SPB_1_STOP_BIT | -- cgit v1.2.3 From a5d60fdb9c969c1516feb76a16001c9688112c4c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Apr 2011 17:25:07 -0700 Subject: altos: Make cmd echo per-connection instead of global Allow different connections to use different echo values, permitting the packet link to turn off echo while the USB link still has it on. Signed-off-by: Keith Packard --- src/ao.h | 5 +++++ src/ao_cmd.c | 17 ++++++++--------- src/ao_stdio.c | 25 ++++++++++++++++--------- 3 files changed, 29 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index b92e623f..9b375894 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1178,8 +1178,10 @@ struct ao_stdio { char (*pollchar)(void); void (*putchar)(char c) __reentrant; void (*flush)(void); + uint8_t echo; }; +extern __xdata struct ao_stdio ao_stdios[]; extern __data int8_t ao_cur_stdio; extern __data int8_t ao_num_stdios; @@ -1188,6 +1190,9 @@ flush(void); extern __xdata uint8_t ao_stdin_ready; +uint8_t +ao_echo(void); + void ao_add_stdio(char (*pollchar)(void), void (*putchar)(char) __reentrant, diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 50d5b96f..c738a3e0 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -21,7 +21,6 @@ __xdata uint16_t ao_cmd_lex_i; __xdata uint32_t ao_cmd_lex_u32; __xdata char ao_cmd_lex_c; __xdata enum ao_cmd_status ao_cmd_status; -static __xdata uint8_t lex_echo; #define CMD_LEN 32 @@ -41,7 +40,7 @@ static void readline(void) { __xdata char c; - if (lex_echo) + if (ao_echo()) put_string("> "); cmd_len = 0; for (;;) { @@ -50,7 +49,7 @@ readline(void) /* backspace/delete */ if (c == '\010' || c == '\177') { if (cmd_len != 0) { - if (lex_echo) + if (ao_echo()) put_string("\010 \010"); --cmd_len; } @@ -60,7 +59,7 @@ readline(void) /* ^U */ if (c == '\025') { while (cmd_len != 0) { - if (lex_echo) + if (ao_echo()) put_string("\010 \010"); --cmd_len; } @@ -72,18 +71,18 @@ readline(void) c = '\n'; if (c == '\n') { - if (lex_echo) + if (ao_echo()) putchar('\n'); break; } if (cmd_len >= CMD_LEN - 2) { - if (lex_echo) + if (ao_echo()) putchar('\007'); continue; } cmd_line[cmd_len++] = c; - if (lex_echo) + if (ao_echo()) putchar(c); } cmd_line[cmd_len++] = '\n'; @@ -198,7 +197,8 @@ static void echo(void) { ao_cmd_hex(); - lex_echo = ao_cmd_lex_i != 0; + if (ao_cmd_status == ao_cmd_success) + ao_stdios[ao_cur_stdio].echo = ao_cmd_lex_i != 0; } static void @@ -272,7 +272,6 @@ ao_cmd(void) __code struct ao_cmds * __xdata cs; void (*__xdata func)(void); - lex_echo = 1; for (;;) { readline(); #if HAS_CMD_FILTER diff --git a/src/ao_stdio.c b/src/ao_stdio.c index 3dd457f7..ec3b6607 100644 --- a/src/ao_stdio.c +++ b/src/ao_stdio.c @@ -23,7 +23,7 @@ #define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) -static __xdata struct ao_stdio stdios[AO_NUM_STDIOS]; +__xdata struct ao_stdio ao_stdios[AO_NUM_STDIOS]; __data int8_t ao_cur_stdio; __data int8_t ao_num_stdios; @@ -31,15 +31,15 @@ void putchar(char c) { if (c == '\n') - (*stdios[ao_cur_stdio].putchar)('\r'); - (*stdios[ao_cur_stdio].putchar)(c); + (*ao_stdios[ao_cur_stdio].putchar)('\r'); + (*ao_stdios[ao_cur_stdio].putchar)(c); } void flush(void) { - if (stdios[ao_cur_stdio].flush) - stdios[ao_cur_stdio].flush(); + if (ao_stdios[ao_cur_stdio].flush) + ao_stdios[ao_cur_stdio].flush(); } __xdata uint8_t ao_stdin_ready; @@ -51,7 +51,7 @@ getchar(void) __reentrant __critical int8_t stdio = ao_cur_stdio; for (;;) { - c = stdios[stdio].pollchar(); + c = ao_stdios[stdio].pollchar(); if (c != AO_READ_AGAIN) break; if (++stdio == ao_num_stdios) @@ -63,6 +63,12 @@ getchar(void) __reentrant __critical return c; } +uint8_t +ao_echo(void) +{ + return ao_stdios[ao_cur_stdio].echo; +} + void ao_add_stdio(char (*pollchar)(void), void (*putchar)(char), @@ -70,8 +76,9 @@ ao_add_stdio(char (*pollchar)(void), { if (ao_num_stdios == AO_NUM_STDIOS) ao_panic(AO_PANIC_STDIO); - stdios[ao_num_stdios].pollchar = pollchar; - stdios[ao_num_stdios].putchar = putchar; - stdios[ao_num_stdios].flush = flush; + ao_stdios[ao_num_stdios].pollchar = pollchar; + ao_stdios[ao_num_stdios].putchar = putchar; + ao_stdios[ao_num_stdios].flush = flush; + ao_stdios[ao_num_stdios].echo = 1; ao_num_stdios++; } -- cgit v1.2.3 From 8db5c52f1c76a05020e4e0afbe4ea27485ad9f82 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Apr 2011 17:26:08 -0700 Subject: altos: Clean up BT serial communcations Disable echo on both ends in command mode to eliminate looping error values. Switch to 57600 baud to improve performance. Signed-off-by: Keith Packard --- src/ao_btm.c | 231 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- src/ao_pins.h | 1 + 2 files changed, 214 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/ao_btm.c b/src/ao_btm.c index 224d3e81..c7024ed3 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -17,56 +17,251 @@ #include "ao.h" -uint8_t ao_btm_enable; +uint8_t ao_btm_running; +uint8_t ao_btm_stdio; +__xdata uint8_t ao_btm_connected; +uint8_t ao_btm_chat; + +__xdata char ao_btm_buffer[1024]; +int ao_btm_ptr; + +#define AO_BTM_MAX_REPLY 16 +__xdata char ao_btm_reply[AO_BTM_MAX_REPLY]; + extern volatile __xdata struct ao_fifo ao_usart1_rx_fifo; +/* + * Read a line of data from the serial port, truncating + * it after a few characters. + */ + +uint8_t +ao_btm_get_line(void) +{ + uint8_t ao_btm_reply_len = 0; + char c; + + for (;;) { + + while ((c = ao_serial_pollchar()) != AO_READ_AGAIN) { + if (ao_btm_reply_len < sizeof (ao_btm_reply)) + ao_btm_reply[ao_btm_reply_len++] = c; + if (ao_btm_ptr < sizeof (ao_btm_buffer)) + ao_btm_buffer[ao_btm_ptr++] = c; + if (c == '\r' || c == '\n') + goto done; + } + for (c = 0; c < 10; c++) { + ao_delay(AO_MS_TO_TICKS(10)); + if (!ao_fifo_empty(ao_usart1_rx_fifo)) + break; + } + if (c == 10) + goto done; + } +done: + for (c = ao_btm_reply_len; c < sizeof (ao_btm_reply);) + ao_btm_reply[c++] = '\0'; + return ao_btm_reply_len; +} + +/* + * Drain the serial port completely + */ void -ao_btm(void) +ao_btm_drain() +{ + while (ao_btm_get_line()) + ; +} + +void +ao_btm_echo(uint8_t echo) +{ + ao_stdios[ao_btm_stdio].echo = echo; +} + +/* + * A command line pre-processor to detect connect/disconnect messages + * and update the internal state + */ + +uint8_t +ao_cmd_filter(void) +{ + ao_cmd_lex(); + while (ao_cmd_lex_c != '\n') { + if (ao_match_word("CONNECT")) { + ao_btm_connected = 1; + ao_btm_echo(1); + ao_wakeup(&ao_btm_connected); + return 1; + } + if (ao_match_word("DISCONNECT")) { + ao_btm_connected = 0; + ao_btm_echo(0); + ao_wakeup(&ao_btm_connected); + return 1; + } + if (ao_match_word("ERROR")) + return 1; + if (ao_match_word("OK")) + return 1; + ao_cmd_lex(); + } + ao_cmd_status = 0; + return !ao_btm_connected; +} + +/* + * A wrapper for ao_serial_pollchar that + * doesn't return any characters while we're + * initializing the bluetooth device + */ +char +ao_btm_pollchar(void) { char c; - while (ao_btm_enable) { - c = ao_serial_pollchar(); - if (c != AO_READ_AGAIN) - ao_usb_putchar(c); - else { - ao_usb_flush(); - ao_sleep(&ao_usart1_rx_fifo); + if (!ao_btm_running) + return AO_READ_AGAIN; + c = ao_serial_pollchar(); + if (c != AO_READ_AGAIN) + if (ao_btm_ptr < sizeof (ao_btm_buffer)) + ao_btm_buffer[ao_btm_ptr++] = c; + return c; +} + +/* + * Wait for the bluetooth device to return + * status from the previously executed command + */ +uint8_t +ao_btm_wait_reply(void) +{ + for (;;) { + ao_btm_get_line(); + if (!strcmp(ao_btm_reply, "OK")) + return 1; + if (!strcmp(ao_btm_reply, "ERROR")) + return -1; + if (ao_btm_reply[0] == '\0') + return 0; + } +} + +void +ao_btm_cmd(__code char *cmd) +{ + ao_cur_stdio = ao_btm_stdio; + printf(cmd); + ao_btm_wait_reply(); +} + +/* + * A thread to initialize the bluetooth device and + * hang around to blink the LED when connected + */ +void +ao_btm(void) +{ + ao_serial_set_speed(AO_SERIAL_SPEED_19200); + ao_add_stdio(ao_btm_pollchar, + ao_serial_putchar, + NULL); + ao_btm_stdio = ao_num_stdios - 1; + ao_cur_stdio = ao_btm_stdio; + ao_btm_echo(0); + ao_btm_drain(); + ao_delay(AO_SEC_TO_TICKS(1)); + printf("+++"); + ao_btm_drain(); + ao_delay(AO_SEC_TO_TICKS(1)); + printf("\r"); + ao_btm_drain(); + ao_btm_cmd("ATQ0\r"); + ao_btm_cmd("ATE0\r"); + ao_btm_cmd("ATH\r"); + ao_delay(AO_SEC_TO_TICKS(1)); + ao_btm_cmd("ATC0\r"); + ao_btm_cmd("ATL4\r"); + ao_serial_set_speed(AO_SERIAL_SPEED_57600); + ao_btm_drain(); + printf("ATN=TeleBT-%d\r", ao_serial_number); + ao_btm_wait_reply(); + ao_btm_running = 1; + for (;;) { + while (!ao_btm_connected && !ao_btm_chat) + ao_sleep(&ao_btm_connected); + if (ao_btm_chat) { + ao_btm_running = 0; + while (ao_btm_chat) { + char c; + c = ao_serial_pollchar(); + if (c != AO_READ_AGAIN) + ao_usb_putchar(c); + else { + ao_usb_flush(); + ao_sleep(&ao_usart1_rx_fifo); + } + } + ao_btm_running = 1; + } + while (ao_btm_connected) { + ao_led_for(AO_LED_GREEN, AO_MS_TO_TICKS(20)); + ao_delay(AO_SEC_TO_TICKS(3)); } } - ao_exit(); } -__xdata struct ao_task ao_btm_task; +__xdata struct ao_task ao_btm_task; +/* + * Connect directly to the bluetooth device, mostly + * useful for testing + */ static void ao_btm_forward(void) { char c; - ao_btm_enable = 1; - flush(); - ao_add_task(&ao_btm_task, ao_btm, "btm"); + ao_btm_chat = 1; + ao_wakeup(&ao_btm_connected); + ao_usb_flush(); while ((c = ao_usb_getchar()) != '~') { if (c == '\n') c = '\r'; ao_serial_putchar(c); } - ao_btm_enable = 0; - while (ao_btm_task.wchan) { + ao_btm_chat = 0; + while (!ao_btm_running) { ao_wakeup(&ao_usart1_rx_fifo); ao_delay(AO_MS_TO_TICKS(10)); } } +/* + * Dump everything received from the bluetooth device during startup + */ +static void +ao_btm_dump(void) +{ + int i; + + for (i = 0; i < ao_btm_ptr; i++) + putchar(ao_btm_buffer[i]); + putchar('\n'); +} + __code struct ao_cmds ao_btm_cmds[] = { - { ao_btm_forward, "B \0BTM serial link." }, + { ao_btm_forward, "B\0BTM serial link." }, + { ao_btm_dump, "d\0Dump btm buffer." }, { 0, NULL }, }; - void ao_btm_init (void) { ao_serial_init(); ao_serial_set_speed(AO_SERIAL_SPEED_19200); + ao_add_task(&ao_btm_task, ao_btm, "bt"); ao_cmd_register(&ao_btm_cmds[0]); } diff --git a/src/ao_pins.h b/src/ao_pins.h index a4ebd63b..ed42df8b 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -224,6 +224,7 @@ #define HAS_BEEP 0 #define HAS_SERIAL_1 1 #define USE_SERIAL_STDIN 1 + #define HAS_CMD_FILTER 1 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 -- cgit v1.2.3 From 1a54a58d72147888f783a3caf364479efff4ed9b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 7 Apr 2011 22:00:38 -0700 Subject: altos: Use PIO(6) on BTM to monitor BT connection. Fix BTM init. PIo(6) appears to be an active-low indication of the Bluetooth connection status. Hook this up using an interrupt to track the link state instead of using in-band status messages. Signed-off-by: Keith Packard --- src/ao.h | 5 ++ src/ao_btm.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++----------- src/ao_pins.h | 1 + src/ao_usb.c | 4 + src/cc1111.h | 8 ++ 5 files changed, 203 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 9b375894..dad1f3df 100644 --- a/src/ao.h +++ b/src/ao.h @@ -107,6 +107,7 @@ ao_start_scheduler(void); #define AO_PANIC_REBOOT 8 /* Reboot failed */ #define AO_PANIC_FLASH 9 /* Invalid flash part (or wrong blocksize) */ #define AO_PANIC_USB 10 /* Trying to send USB packet while busy */ +#define AO_PANIC_BT 11 /* Communications with bluetooth device failed */ /* Stop the operating system, beeping and blinking the reason */ void @@ -1366,6 +1367,10 @@ ao_packet_slave_init(uint8_t enable); /* ao_btm.c */ +/* Shared by USB, so the USB code calls this function */ +void +ao_btm_isr(void); + void ao_btm_init(void); diff --git a/src/ao_btm.c b/src/ao_btm.c index c7024ed3..71907f86 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -18,12 +18,47 @@ #include "ao.h" uint8_t ao_btm_running; -uint8_t ao_btm_stdio; +int8_t ao_btm_stdio; __xdata uint8_t ao_btm_connected; uint8_t ao_btm_chat; __xdata char ao_btm_buffer[1024]; int ao_btm_ptr; +char ao_btm_dir; + +uint8_t ao_btm_send_chars = 0; + +void +ao_btm_putchar(char c); + +static void +ao_btm_add_char(char c) +{ + if (ao_btm_ptr < sizeof (ao_btm_buffer)) + ao_btm_buffer[ao_btm_ptr++] = c; +} + +static void +ao_btm_log_char(char c, char dir) +{ + if (dir != ao_btm_dir) { + ao_btm_add_char(dir); + ao_btm_dir = dir; + } + ao_btm_add_char(c); +} + +static void +ao_btm_log_out_char(char c) +{ + ao_btm_log_char(c, '>'); +} + +static void +ao_btm_log_in_char(char c) +{ + ao_btm_log_char(c, '<'); +} #define AO_BTM_MAX_REPLY 16 __xdata char ao_btm_reply[AO_BTM_MAX_REPLY]; @@ -44,10 +79,9 @@ ao_btm_get_line(void) for (;;) { while ((c = ao_serial_pollchar()) != AO_READ_AGAIN) { + ao_btm_log_in_char(c); if (ao_btm_reply_len < sizeof (ao_btm_reply)) ao_btm_reply[ao_btm_reply_len++] = c; - if (ao_btm_ptr < sizeof (ao_btm_buffer)) - ao_btm_buffer[ao_btm_ptr++] = c; if (c == '\r' || c == '\n') goto done; } @@ -89,20 +123,14 @@ ao_btm_echo(uint8_t echo) uint8_t ao_cmd_filter(void) { + if (ao_cur_stdio != ao_btm_stdio) + return 0; ao_cmd_lex(); while (ao_cmd_lex_c != '\n') { - if (ao_match_word("CONNECT")) { - ao_btm_connected = 1; - ao_btm_echo(1); - ao_wakeup(&ao_btm_connected); + if (ao_match_word("CONNECT")) return 1; - } - if (ao_match_word("DISCONNECT")) { - ao_btm_connected = 0; - ao_btm_echo(0); - ao_wakeup(&ao_btm_connected); + if (ao_match_word("DISCONNECT")) return 1; - } if (ao_match_word("ERROR")) return 1; if (ao_match_word("OK")) @@ -126,11 +154,25 @@ ao_btm_pollchar(void) return AO_READ_AGAIN; c = ao_serial_pollchar(); if (c != AO_READ_AGAIN) - if (ao_btm_ptr < sizeof (ao_btm_buffer)) - ao_btm_buffer[ao_btm_ptr++] = c; + ao_btm_log_in_char(c); return c; } +void +ao_btm_putchar(char c) +{ + if (!ao_btm_send_chars) { + ao_btm_log_out_char(c); + ao_serial_putchar(c); + } +} + +void +ao_btm_stdio_putchar(char c) { + if (ao_btm_connected) + ao_btm_putchar(c); +} + /* * Wait for the bluetooth device to return * status from the previously executed command @@ -140,9 +182,9 @@ ao_btm_wait_reply(void) { for (;;) { ao_btm_get_line(); - if (!strcmp(ao_btm_reply, "OK")) + if (!strncmp(ao_btm_reply, "OK", 2)) return 1; - if (!strcmp(ao_btm_reply, "ERROR")) + if (!strncmp(ao_btm_reply, "ERROR", 5)) return -1; if (ao_btm_reply[0] == '\0') return 0; @@ -150,13 +192,50 @@ ao_btm_wait_reply(void) } void +ao_btm_string(__code char *cmd) +{ + char c; + + while (c = *cmd++) + ao_btm_putchar(c); +} + +uint8_t ao_btm_cmd(__code char *cmd) { - ao_cur_stdio = ao_btm_stdio; - printf(cmd); - ao_btm_wait_reply(); + ao_btm_drain(); + ao_btm_string(cmd); + return ao_btm_wait_reply(); +} + +uint8_t +ao_btm_set_name(void) +{ + char sn[7]; + char *s = sn + 7; + char c; + int n; + ao_btm_string("ATN=TeleBT-"); + *--s = '\0'; + n = ao_serial_number; + do { + *--s = '0' + n % 10; + } while (n /= 10); + while ((c = *s++)) + ao_btm_putchar(c); + return ao_btm_wait_reply(); } +uint8_t +ao_btm_try_speed(uint8_t speed) +{ + ao_serial_set_speed(speed); + ao_btm_drain(); + (void) ao_btm_cmd("\rATE0\rATQ0\r"); + if (ao_btm_cmd("AT\r") == 1) + return 1; + return 0; +} /* * A thread to initialize the bluetooth device and * hang around to blink the LED when connected @@ -164,30 +243,36 @@ ao_btm_cmd(__code char *cmd) void ao_btm(void) { - ao_serial_set_speed(AO_SERIAL_SPEED_19200); ao_add_stdio(ao_btm_pollchar, - ao_serial_putchar, + ao_btm_stdio_putchar, NULL); ao_btm_stdio = ao_num_stdios - 1; - ao_cur_stdio = ao_btm_stdio; ao_btm_echo(0); - ao_btm_drain(); - ao_delay(AO_SEC_TO_TICKS(1)); - printf("+++"); - ao_btm_drain(); - ao_delay(AO_SEC_TO_TICKS(1)); - printf("\r"); - ao_btm_drain(); - ao_btm_cmd("ATQ0\r"); + + /* + * The first time we connect, the BTM-180 comes up at 19200 baud. + * After that, it will remember and come up at 57600 baud. So, see + * if it is already running at 57600 baud, and if that doesn't work + * then tell it to switch to 57600 from 19200 baud. + */ + while (!ao_btm_try_speed(AO_SERIAL_SPEED_57600)) { + if (ao_btm_try_speed(AO_SERIAL_SPEED_19200)) + ao_btm_cmd("ATL4\r"); + ao_delay(AO_SEC_TO_TICKS(1)); + } + + /* Disable echo */ ao_btm_cmd("ATE0\r"); - ao_btm_cmd("ATH\r"); - ao_delay(AO_SEC_TO_TICKS(1)); - ao_btm_cmd("ATC0\r"); - ao_btm_cmd("ATL4\r"); - ao_serial_set_speed(AO_SERIAL_SPEED_57600); - ao_btm_drain(); - printf("ATN=TeleBT-%d\r", ao_serial_number); - ao_btm_wait_reply(); + + /* Enable flow control */ + ao_btm_cmd("ATC1\r"); + + /* Set the reported name to something we can find on the host */ + ao_btm_set_name(); + + /* Turn off status reporting */ + ao_btm_cmd("ATQ1\r"); + ao_btm_running = 1; for (;;) { while (!ao_btm_connected && !ao_btm_chat) @@ -197,9 +282,10 @@ ao_btm(void) while (ao_btm_chat) { char c; c = ao_serial_pollchar(); - if (c != AO_READ_AGAIN) + if (c != AO_READ_AGAIN) { + ao_btm_log_in_char(c); ao_usb_putchar(c); - else { + } else { ao_usb_flush(); ao_sleep(&ao_usart1_rx_fifo); } @@ -229,7 +315,7 @@ ao_btm_forward(void) ao_usb_flush(); while ((c = ao_usb_getchar()) != '~') { if (c == '\n') c = '\r'; - ao_serial_putchar(c); + ao_btm_putchar(c); } ao_btm_chat = 0; while (!ao_btm_running) { @@ -245,15 +331,56 @@ static void ao_btm_dump(void) { int i; + char c; - for (i = 0; i < ao_btm_ptr; i++) - putchar(ao_btm_buffer[i]); + for (i = 0; i < ao_btm_ptr; i++) { + c = ao_btm_buffer[i]; + if (c < ' ' && c != '\n') + printf("\\%03o", ((int) c) & 0xff); + else + putchar(ao_btm_buffer[i]); + } putchar('\n'); } +static void +ao_btm_speed(void) +{ + ao_cmd_decimal(); + if (ao_cmd_lex_u32 == 57600) + ao_serial_set_speed(AO_SERIAL_SPEED_57600); + else if (ao_cmd_lex_u32 == 19200) + ao_serial_set_speed(AO_SERIAL_SPEED_19200); + else + ao_cmd_status = ao_cmd_syntax_error; +} + +void +ao_btm_check_link() __critical +{ + if (P2_1) { + ao_btm_connected = 0; + PICTL |= PICTL_P2ICON; + } else { + ao_btm_connected = 1; + PICTL &= ~PICTL_P2ICON; + } +} + +void +ao_btm_isr(void) +{ + if (P2IFG & (1 << 1)) { + ao_btm_check_link(); + ao_wakeup(&ao_btm_connected); + } + P2IFG = 0; +} + __code struct ao_cmds ao_btm_cmds[] = { { ao_btm_forward, "B\0BTM serial link." }, { ao_btm_dump, "d\0Dump btm buffer." }, + { ao_btm_speed, "s <19200,57600>\0Set btm serial speed." }, { 0, NULL }, }; @@ -262,6 +389,20 @@ ao_btm_init (void) { ao_serial_init(); ao_serial_set_speed(AO_SERIAL_SPEED_19200); + + /* + * Configure link status line + */ + + /* Set P2_1 to input, pull-down */ + P2DIR &= ~(1 << 1); + P2INP |= P2INP_MDP2_1_TRISTATE; + + /* Enable P2 interrupts */ + IEN2 |= IEN2_P2IE; + ao_btm_check_link(); + PICTL |= PICTL_P2IEN; + ao_add_task(&ao_btm_task, ao_btm, "bt"); ao_cmd_register(&ao_btm_cmds[0]); } diff --git a/src/ao_pins.h b/src/ao_pins.h index ed42df8b..1344dcaa 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -228,6 +228,7 @@ #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 + #define HAS_BTM 1 #define DBG_ON_P1 0 #define DBG_ON_P0 1 #define IGNITE_ON_P2 0 diff --git a/src/ao_usb.c b/src/ao_usb.c index b4e3f1fe..ece6756a 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -46,6 +46,7 @@ void ao_usb_isr(void) __interrupt 6 { USBIF = 0; + IRCON2 &= ~IRCON2_USBIF; ao_usb_iif |= USBIIF; if (ao_usb_iif & 1) ao_wakeup(&ao_usb_task); @@ -57,6 +58,9 @@ ao_usb_isr(void) __interrupt 6 if (USBCIF & USBCIF_RSTIF) ao_usb_set_interrupts(); +#if HAS_BTM + ao_btm_isr(); +#endif } struct ao_usb_setup { diff --git a/src/cc1111.h b/src/cc1111.h index a72d7416..a07490e5 100644 --- a/src/cc1111.h +++ b/src/cc1111.h @@ -662,6 +662,14 @@ sfr at 0x8B P2IFG; #define P0IFG_USB_RESUME (1 << 7) +sfr at 0x8C PICTL; +#define PICTL_P2IEN (1 << 5) +#define PICTL_P0IENH (1 << 4) +#define PICTL_P0IENL (1 << 3) +#define PICTL_P2ICON (1 << 2) +#define PICTL_P1ICON (1 << 1) +#define PICTL_P0ICON (1 << 0) + /* GPIO pins */ sfr at 0x80 P0; -- cgit v1.2.3 From 7f49d694e776819e03b2c708e1c4ee23ba311430 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Apr 2011 22:53:12 -0700 Subject: altos/altosui: Log averaged baro sensor data in Tm/Tn Instead of logging the best height guess from the kalman filter, log barometer data. The logged data consists of the average value betwen log points to reduce noise. Signed-off-by: Keith Packard --- altosui/Altos.java | 2 +- altosui/AltosDataPoint.java | 1 + altosui/AltosDataPointReader.java | 1 + altosui/AltosEepromDownload.java | 3 ++- altosui/AltosEepromIterable.java | 9 +++++++-- altosui/AltosGraphUI.java | 2 +- src/ao_log_tiny.c | 35 +++++++++++++++++++++++++---------- 7 files changed, 38 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/altosui/Altos.java b/altosui/Altos.java index 1f791da5..54aced32 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -34,7 +34,7 @@ public class Altos { static final int AO_LOG_GPS_ALT = 'H'; static final int AO_LOG_GPS_SAT = 'V'; static final int AO_LOG_GPS_DATE = 'Y'; - static final int AO_LOG_HEIGHT = 'h'; + static final int AO_LOG_PRESSURE = 'P'; /* Added for header fields in eeprom files */ static final int AO_LOG_CONFIG_VERSION = 1000; diff --git a/altosui/AltosDataPoint.java b/altosui/AltosDataPoint.java index 66313e03..5e077320 100644 --- a/altosui/AltosDataPoint.java +++ b/altosui/AltosDataPoint.java @@ -25,5 +25,6 @@ interface AltosDataPoint { double battery_voltage(); double drogue_voltage(); double main_voltage(); + boolean has_accel(); } diff --git a/altosui/AltosDataPointReader.java b/altosui/AltosDataPointReader.java index 4335421c..fa48013f 100644 --- a/altosui/AltosDataPointReader.java +++ b/altosui/AltosDataPointReader.java @@ -59,6 +59,7 @@ class AltosDataPointReader implements Iterable { public double battery_voltage() { return record.battery_voltage(); } public double drogue_voltage() { return record.drogue_voltage(); } public double main_voltage() { return record.main_voltage(); } + public boolean has_accel() { return has_accel; } }; } diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index fad16460..a42f401c 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -162,7 +162,8 @@ public class AltosEepromDownload implements Runnable { } else { if (v != 0xffff) any_valid = true; - r = new AltosEepromRecord(Altos.AO_LOG_HEIGHT, tiny_tick, v, 0); + + r = new AltosEepromRecord(Altos.AO_LOG_PRESSURE, tiny_tick, 0, v); /* * The flight software records ascent data every 100ms, and descent diff --git a/altosui/AltosEepromIterable.java b/altosui/AltosEepromIterable.java index 624e1dd3..16349b88 100644 --- a/altosui/AltosEepromIterable.java +++ b/altosui/AltosEepromIterable.java @@ -134,8 +134,13 @@ public class AltosEepromIterable extends AltosRecordIterable { eeprom.seen |= seen_sensor; has_accel = true; break; - case Altos.AO_LOG_HEIGHT: - state.height = (short) record.a; + case Altos.AO_LOG_PRESSURE: + state.pres = record.b; + state.flight_pres = state.pres; + if (eeprom.n_pad_samples == 0) { + eeprom.n_pad_samples++; + state.ground_pres = state.pres; + } eeprom.seen |= seen_sensor; break; case Altos.AO_LOG_TEMP_VOLT: diff --git a/altosui/AltosGraphUI.java b/altosui/AltosGraphUI.java index e98c302b..4b994b47 100644 --- a/altosui/AltosGraphUI.java +++ b/altosui/AltosGraphUI.java @@ -35,7 +35,7 @@ public class AltosGraphUI extends JFrame AltosGraphTime.Element speed = new AltosGraphTime.TimeSeries("Speed (m/s)", "Vertical Speed", green) { public void gotTimeData(double time, AltosDataPoint d) { - if (d.state() < Altos.ao_flight_drogue) { + if (d.state() < Altos.ao_flight_drogue && d.has_accel()) { series.add(time, d.accel_speed()); } else { series.add(time, d.baro_speed()); diff --git a/src/ao_log_tiny.c b/src/ao_log_tiny.c index f0c0662a..6c2468fc 100644 --- a/src/ao_log_tiny.c +++ b/src/ao_log_tiny.c @@ -44,9 +44,12 @@ static void ao_log_tiny_data(uint16_t d) void ao_log(void) { - uint16_t time; - int16_t delay; + uint16_t last_time; + uint16_t now; enum ao_flight_state ao_log_tiny_state; + int32_t sum; + int16_t count; + uint8_t ao_log_adc; ao_storage_setup(); @@ -57,9 +60,19 @@ ao_log(void) while (!ao_log_running) ao_sleep(&ao_log_running); - time = ao_time(); ao_log_tiny_data(ao_flight_number); + ao_log_tiny_data(ao_ground_pres); + sum = 0; + count = 0; + ao_log_adc = ao_sample_adc; + last_time = ao_time(); for (;;) { + ao_sleep(DATA_TO_XDATA(&ao_sample_adc)); + while (ao_log_adc != ao_sample_adc) { + sum += ao_adc_ring[ao_log_adc].pres; + count++; + ao_log_adc = ao_adc_ring_next(ao_log_adc); + } if (ao_flight_state != ao_log_tiny_state) { ao_log_tiny_data(ao_flight_state | 0x8000); ao_log_tiny_state = ao_flight_state; @@ -69,14 +82,16 @@ ao_log(void) if (ao_log_tiny_state == ao_flight_landed) ao_log_stop(); } - ao_log_tiny_data(ao_height); - time += ao_log_tiny_interval; - delay = time - ao_time(); - if (delay > 0) - ao_delay(delay); /* Stop logging when told to */ - while (!ao_log_running) - ao_sleep(&ao_log_running); + if (!ao_log_running) + ao_exit(); + now = ao_time(); + if ((int16_t) (now - (last_time + ao_log_tiny_interval)) >= 0 && count) { + ao_log_tiny_data(sum / count); + sum = 0; + count = 0; + last_time = now; + } } } -- cgit v1.2.3 From c269e263a6accd815ed5d08c0f5a6c3d5b9d3853 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 14 Apr 2011 09:38:48 -0700 Subject: altos: Write a few pre-launch samples for Tm/Tn devices Record pre-launch samples in a small ring and flush that to flash when launch is detected. This provides a complete record of the flight, rather than simply starting after launch detect. Signed-off-by: Keith Packard --- src/ao_log_tiny.c | 91 +++++++++++++++++++++++++++++++++++++++++++------------ src/ao_pins.h | 1 + 2 files changed, 72 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/ao_log_tiny.c b/src/ao_log_tiny.c index 6c2468fc..d26e0080 100644 --- a/src/ao_log_tiny.c +++ b/src/ao_log_tiny.c @@ -19,8 +19,14 @@ static __data uint16_t ao_log_tiny_interval; -#define AO_LOG_TINY_INTERVAL_ASCENT AO_MS_TO_TICKS(100) #define AO_LOG_TINY_INTERVAL_DEFAULT AO_MS_TO_TICKS(1000) +#if USE_FAST_ASCENT_LOG +#define AO_LOG_TINY_INTERVAL_ASCENT AO_MS_TO_TICKS(100) +#define AO_PAD_RING 8 +#else +#define AO_LOG_TINY_INTERVAL_ASCENT AO_LOG_TINY_INTERVAL_DEFAULT +#define AO_PAD_RING 2 +#endif void ao_log_tiny_set_interval(uint16_t ticks) @@ -28,19 +34,47 @@ ao_log_tiny_set_interval(uint16_t ticks) ao_log_tiny_interval = ticks; } -static __xdata uint16_t ao_log_tiny_data_temp; static void ao_log_tiny_data(uint16_t d) { if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) ao_log_stop(); if (ao_log_running) { - ao_log_tiny_data_temp = (d); - ao_storage_write(ao_log_current_pos, &ao_log_tiny_data_temp, 2); + ao_storage_write(ao_log_current_pos, DATA_TO_XDATA(&d), 2); ao_log_current_pos += 2; } } +static __xdata uint16_t ao_log_pad_ring[AO_PAD_RING]; +static __pdata uint8_t ao_log_pad_ring_pos; + +#define ao_pad_ring_next(n) (((n) + 1) & (AO_PAD_RING - 1)) + +static void ao_log_tiny_queue(uint16_t d) +{ + ao_log_pad_ring[ao_log_pad_ring_pos] = d; + ao_log_pad_ring_pos = ao_pad_ring_next(ao_log_pad_ring_pos); +} + +static void ao_log_tiny_start(void) +{ + uint8_t p; + uint16_t d; + + ao_log_tiny_data(ao_flight_number); + ao_log_tiny_data(ao_ground_pres); + p = ao_log_pad_ring_pos; + do { + d = ao_log_pad_ring[p]; + /* + * ignore unwritten slots + */ + if (d) + ao_log_tiny_data(d); + p = ao_pad_ring_next(p); + } while (p != ao_log_pad_ring_pos); +} + void ao_log(void) { @@ -50,44 +84,61 @@ ao_log(void) int32_t sum; int16_t count; uint8_t ao_log_adc; + uint8_t ao_log_started = 0; ao_storage_setup(); ao_log_scan(); ao_log_tiny_state = ao_flight_invalid; - ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT; - while (!ao_log_running) - ao_sleep(&ao_log_running); - - ao_log_tiny_data(ao_flight_number); - ao_log_tiny_data(ao_ground_pres); + ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; sum = 0; count = 0; ao_log_adc = ao_sample_adc; last_time = ao_time(); for (;;) { + + /* + * Add in pending sample data + */ ao_sleep(DATA_TO_XDATA(&ao_sample_adc)); while (ao_log_adc != ao_sample_adc) { sum += ao_adc_ring[ao_log_adc].pres; count++; ao_log_adc = ao_adc_ring_next(ao_log_adc); } - if (ao_flight_state != ao_log_tiny_state) { - ao_log_tiny_data(ao_flight_state | 0x8000); - ao_log_tiny_state = ao_flight_state; - ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT; - if (ao_log_tiny_state <= ao_flight_coast) - ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; - if (ao_log_tiny_state == ao_flight_landed) - ao_log_stop(); + if (ao_log_running) { + if (!ao_log_started) { + ao_log_tiny_start(); + ao_log_started = 1; + } + if (ao_flight_state != ao_log_tiny_state) { + ao_log_tiny_data(ao_flight_state | 0x8000); + ao_log_tiny_state = ao_flight_state; + ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT; +#if AO_LOG_TINY_INTERVAL_ASCENT != AO_LOG_TINY_INTERVAL_DEFAULT + if (ao_log_tiny_state <= ao_flight_coast) + ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; +#endif + if (ao_log_tiny_state == ao_flight_landed) + ao_log_stop(); + } } + /* Stop logging when told to */ - if (!ao_log_running) + if (!ao_log_running && ao_log_started) ao_exit(); + + /* + * Write out the sample when finished + */ now = ao_time(); if ((int16_t) (now - (last_time + ao_log_tiny_interval)) >= 0 && count) { - ao_log_tiny_data(sum / count); + count = sum / count; + if (ao_log_started) + ao_log_tiny_data(count); + else + ao_log_tiny_queue(count); sum = 0; count = 0; last_time = now; diff --git a/src/ao_pins.h b/src/ao_pins.h index 30f2decc..2161c5d2 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -108,6 +108,7 @@ #define IGNITE_ON_P0 1 #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 + #define USE_FAST_ASCENT_LOG 1 #define AO_LED_GREEN 1 #define AO_LED_RED 2 -- cgit v1.2.3 From 8de9d3cbfcd1db7b554fb761296a8de09aafc8c3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Apr 2011 10:25:47 -0700 Subject: altos: Add delays to bt startup sequence The BT device takes a few seconds after power-up before it is ready to receive commands. Signed-off-by: Keith Packard --- src/ao_btm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/ao_btm.c b/src/ao_btm.c index 71907f86..4f56c382 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -249,6 +249,8 @@ ao_btm(void) ao_btm_stdio = ao_num_stdios - 1; ao_btm_echo(0); + ao_delay(AO_SEC_TO_TICKS(3)); + /* * The first time we connect, the BTM-180 comes up at 19200 baud. * After that, it will remember and come up at 57600 baud. So, see @@ -256,6 +258,7 @@ ao_btm(void) * then tell it to switch to 57600 from 19200 baud. */ while (!ao_btm_try_speed(AO_SERIAL_SPEED_57600)) { + ao_delay(AO_SEC_TO_TICKS(1)); if (ao_btm_try_speed(AO_SERIAL_SPEED_19200)) ao_btm_cmd("ATL4\r"); ao_delay(AO_SEC_TO_TICKS(1)); -- cgit v1.2.3 From e3d501940718428135e04995dff7fef691c08a20 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Apr 2011 13:20:19 -0700 Subject: altos: Solidify BT connections Use delays while sending commands to BT module. Don't use BT for stdio until the module is initialized. Add \r to name setting command Don't require 'connected' signal for command input. Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_btm.c | 41 ++++++++++++++++++++--------------------- src/ao_stdio.c | 4 ++-- 3 files changed, 23 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index dad1f3df..226f9a22 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1194,7 +1194,7 @@ extern __xdata uint8_t ao_stdin_ready; uint8_t ao_echo(void); -void +int8_t ao_add_stdio(char (*pollchar)(void), void (*putchar)(char) __reentrant, void (*flush)(void)) __reentrant; diff --git a/src/ao_btm.c b/src/ao_btm.c index 4f56c382..784a566f 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -26,8 +26,6 @@ __xdata char ao_btm_buffer[1024]; int ao_btm_ptr; char ao_btm_dir; -uint8_t ao_btm_send_chars = 0; - void ao_btm_putchar(char c); @@ -109,6 +107,9 @@ ao_btm_drain() ; } +/* + * Set the stdio echo for the bluetooth link + */ void ao_btm_echo(uint8_t echo) { @@ -138,7 +139,7 @@ ao_cmd_filter(void) ao_cmd_lex(); } ao_cmd_status = 0; - return !ao_btm_connected; + return 0; } /* @@ -161,16 +162,10 @@ ao_btm_pollchar(void) void ao_btm_putchar(char c) { - if (!ao_btm_send_chars) { - ao_btm_log_out_char(c); - ao_serial_putchar(c); - } -} - -void -ao_btm_stdio_putchar(char c) { - if (ao_btm_connected) - ao_btm_putchar(c); + ao_btm_log_out_char(c); + ao_serial_putchar(c); + if (!ao_btm_running) + ao_delay(1); } /* @@ -211,12 +206,13 @@ ao_btm_cmd(__code char *cmd) uint8_t ao_btm_set_name(void) { - char sn[7]; - char *s = sn + 7; + char sn[8]; + char *s = sn + 8; char c; int n; ao_btm_string("ATN=TeleBT-"); *--s = '\0'; + *--s = '\r'; n = ao_serial_number; do { *--s = '0' + n % 10; @@ -236,6 +232,7 @@ ao_btm_try_speed(uint8_t speed) return 1; return 0; } + /* * A thread to initialize the bluetooth device and * hang around to blink the LED when connected @@ -243,12 +240,9 @@ ao_btm_try_speed(uint8_t speed) void ao_btm(void) { - ao_add_stdio(ao_btm_pollchar, - ao_btm_stdio_putchar, - NULL); - ao_btm_stdio = ao_num_stdios - 1; - ao_btm_echo(0); - + /* + * Wait for the bluetooth device to boot + */ ao_delay(AO_SEC_TO_TICKS(3)); /* @@ -276,6 +270,11 @@ ao_btm(void) /* Turn off status reporting */ ao_btm_cmd("ATQ1\r"); + ao_btm_stdio = ao_add_stdio(ao_btm_pollchar, + ao_btm_putchar, + NULL); + ao_btm_echo(0); + ao_btm_running = 1; for (;;) { while (!ao_btm_connected && !ao_btm_chat) diff --git a/src/ao_stdio.c b/src/ao_stdio.c index ec3b6607..6b890832 100644 --- a/src/ao_stdio.c +++ b/src/ao_stdio.c @@ -69,7 +69,7 @@ ao_echo(void) return ao_stdios[ao_cur_stdio].echo; } -void +int8_t ao_add_stdio(char (*pollchar)(void), void (*putchar)(char), void (*flush)(void)) __reentrant @@ -80,5 +80,5 @@ ao_add_stdio(char (*pollchar)(void), ao_stdios[ao_num_stdios].putchar = putchar; ao_stdios[ao_num_stdios].flush = flush; ao_stdios[ao_num_stdios].echo = 1; - ao_num_stdios++; + return ao_num_stdios++; } -- cgit v1.2.3 From ce7cf0c5ddc5405f6f474f4e20752fc0b02f3ecb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Apr 2011 13:27:40 -0700 Subject: altos: Simplify BT communications Eliminate stdio I/O wrappers Signed-off-by: Keith Packard --- src/ao_btm.c | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/ao_btm.c b/src/ao_btm.c index 784a566f..6ba5eb1a 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -143,29 +143,16 @@ ao_cmd_filter(void) } /* - * A wrapper for ao_serial_pollchar that - * doesn't return any characters while we're - * initializing the bluetooth device + * Delay between command charaters; the BT module + * can't keep up with 57600 baud */ -char -ao_btm_pollchar(void) -{ - char c; - if (!ao_btm_running) - return AO_READ_AGAIN; - c = ao_serial_pollchar(); - if (c != AO_READ_AGAIN) - ao_btm_log_in_char(c); - return c; -} void ao_btm_putchar(char c) { ao_btm_log_out_char(c); ao_serial_putchar(c); - if (!ao_btm_running) - ao_delay(1); + ao_delay(1); } /* @@ -270,8 +257,8 @@ ao_btm(void) /* Turn off status reporting */ ao_btm_cmd("ATQ1\r"); - ao_btm_stdio = ao_add_stdio(ao_btm_pollchar, - ao_btm_putchar, + ao_btm_stdio = ao_add_stdio(ao_serial_pollchar, + ao_serial_putchar, NULL); ao_btm_echo(0); -- cgit v1.2.3 From 0195ff442c1da5d363dfda3f88f41865d0c6b469 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Apr 2011 13:31:10 -0700 Subject: altos: Remove bt debug command This will permit some additional cleanups. Signed-off-by: Keith Packard --- src/ao_btm.c | 42 +----------------------------------------- 1 file changed, 1 insertion(+), 41 deletions(-) (limited to 'src') diff --git a/src/ao_btm.c b/src/ao_btm.c index 6ba5eb1a..aa7a7101 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -20,7 +20,6 @@ uint8_t ao_btm_running; int8_t ao_btm_stdio; __xdata uint8_t ao_btm_connected; -uint8_t ao_btm_chat; __xdata char ao_btm_buffer[1024]; int ao_btm_ptr; @@ -264,23 +263,8 @@ ao_btm(void) ao_btm_running = 1; for (;;) { - while (!ao_btm_connected && !ao_btm_chat) + while (!ao_btm_connected) ao_sleep(&ao_btm_connected); - if (ao_btm_chat) { - ao_btm_running = 0; - while (ao_btm_chat) { - char c; - c = ao_serial_pollchar(); - if (c != AO_READ_AGAIN) { - ao_btm_log_in_char(c); - ao_usb_putchar(c); - } else { - ao_usb_flush(); - ao_sleep(&ao_usart1_rx_fifo); - } - } - ao_btm_running = 1; - } while (ao_btm_connected) { ao_led_for(AO_LED_GREEN, AO_MS_TO_TICKS(20)); ao_delay(AO_SEC_TO_TICKS(3)); @@ -290,29 +274,6 @@ ao_btm(void) __xdata struct ao_task ao_btm_task; -/* - * Connect directly to the bluetooth device, mostly - * useful for testing - */ -static void -ao_btm_forward(void) -{ - char c; - - ao_btm_chat = 1; - ao_wakeup(&ao_btm_connected); - ao_usb_flush(); - while ((c = ao_usb_getchar()) != '~') { - if (c == '\n') c = '\r'; - ao_btm_putchar(c); - } - ao_btm_chat = 0; - while (!ao_btm_running) { - ao_wakeup(&ao_usart1_rx_fifo); - ao_delay(AO_MS_TO_TICKS(10)); - } -} - /* * Dump everything received from the bluetooth device during startup */ @@ -367,7 +328,6 @@ ao_btm_isr(void) } __code struct ao_cmds ao_btm_cmds[] = { - { ao_btm_forward, "B\0BTM serial link." }, { ao_btm_dump, "d\0Dump btm buffer." }, { ao_btm_speed, "s <19200,57600>\0Set btm serial speed." }, { 0, NULL }, -- cgit v1.2.3 From 7f5c9986dfa2d130b6c8c14308638cce49391a6e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Apr 2011 13:42:30 -0700 Subject: altos: remove BT logging code This was used to debug the serial line startup. Signed-off-by: Keith Packard --- src/ao_btm.c | 73 ------------------------------------------------------------ 1 file changed, 73 deletions(-) (limited to 'src') diff --git a/src/ao_btm.c b/src/ao_btm.c index aa7a7101..491e4be3 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -21,42 +21,9 @@ uint8_t ao_btm_running; int8_t ao_btm_stdio; __xdata uint8_t ao_btm_connected; -__xdata char ao_btm_buffer[1024]; -int ao_btm_ptr; -char ao_btm_dir; - void ao_btm_putchar(char c); -static void -ao_btm_add_char(char c) -{ - if (ao_btm_ptr < sizeof (ao_btm_buffer)) - ao_btm_buffer[ao_btm_ptr++] = c; -} - -static void -ao_btm_log_char(char c, char dir) -{ - if (dir != ao_btm_dir) { - ao_btm_add_char(dir); - ao_btm_dir = dir; - } - ao_btm_add_char(c); -} - -static void -ao_btm_log_out_char(char c) -{ - ao_btm_log_char(c, '>'); -} - -static void -ao_btm_log_in_char(char c) -{ - ao_btm_log_char(c, '<'); -} - #define AO_BTM_MAX_REPLY 16 __xdata char ao_btm_reply[AO_BTM_MAX_REPLY]; @@ -76,7 +43,6 @@ ao_btm_get_line(void) for (;;) { while ((c = ao_serial_pollchar()) != AO_READ_AGAIN) { - ao_btm_log_in_char(c); if (ao_btm_reply_len < sizeof (ao_btm_reply)) ao_btm_reply[ao_btm_reply_len++] = c; if (c == '\r' || c == '\n') @@ -149,7 +115,6 @@ ao_cmd_filter(void) void ao_btm_putchar(char c) { - ao_btm_log_out_char(c); ao_serial_putchar(c); ao_delay(1); } @@ -274,37 +239,6 @@ ao_btm(void) __xdata struct ao_task ao_btm_task; -/* - * Dump everything received from the bluetooth device during startup - */ -static void -ao_btm_dump(void) -{ - int i; - char c; - - for (i = 0; i < ao_btm_ptr; i++) { - c = ao_btm_buffer[i]; - if (c < ' ' && c != '\n') - printf("\\%03o", ((int) c) & 0xff); - else - putchar(ao_btm_buffer[i]); - } - putchar('\n'); -} - -static void -ao_btm_speed(void) -{ - ao_cmd_decimal(); - if (ao_cmd_lex_u32 == 57600) - ao_serial_set_speed(AO_SERIAL_SPEED_57600); - else if (ao_cmd_lex_u32 == 19200) - ao_serial_set_speed(AO_SERIAL_SPEED_19200); - else - ao_cmd_status = ao_cmd_syntax_error; -} - void ao_btm_check_link() __critical { @@ -327,12 +261,6 @@ ao_btm_isr(void) P2IFG = 0; } -__code struct ao_cmds ao_btm_cmds[] = { - { ao_btm_dump, "d\0Dump btm buffer." }, - { ao_btm_speed, "s <19200,57600>\0Set btm serial speed." }, - { 0, NULL }, -}; - void ao_btm_init (void) { @@ -353,5 +281,4 @@ ao_btm_init (void) PICTL |= PICTL_P2IEN; ao_add_task(&ao_btm_task, ao_btm, "bt"); - ao_cmd_register(&ao_btm_cmds[0]); } -- cgit v1.2.3 From 2ebdb888f6792de70b3132950a988d49752d264e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 Apr 2011 14:01:19 -0700 Subject: altosui: Eliminate ao_cmd_filter hook Disabling status messages means we don't need to filter them out of the input stream. Signed-off-by: Keith Packard --- src/ao_btm.c | 31 ------------------------------- src/ao_cmd.c | 5 ----- src/ao_pins.h | 1 - 3 files changed, 37 deletions(-) (limited to 'src') diff --git a/src/ao_btm.c b/src/ao_btm.c index 491e4be3..db0ff6b0 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -17,13 +17,9 @@ #include "ao.h" -uint8_t ao_btm_running; int8_t ao_btm_stdio; __xdata uint8_t ao_btm_connected; -void -ao_btm_putchar(char c); - #define AO_BTM_MAX_REPLY 16 __xdata char ao_btm_reply[AO_BTM_MAX_REPLY]; @@ -81,32 +77,6 @@ ao_btm_echo(uint8_t echo) ao_stdios[ao_btm_stdio].echo = echo; } -/* - * A command line pre-processor to detect connect/disconnect messages - * and update the internal state - */ - -uint8_t -ao_cmd_filter(void) -{ - if (ao_cur_stdio != ao_btm_stdio) - return 0; - ao_cmd_lex(); - while (ao_cmd_lex_c != '\n') { - if (ao_match_word("CONNECT")) - return 1; - if (ao_match_word("DISCONNECT")) - return 1; - if (ao_match_word("ERROR")) - return 1; - if (ao_match_word("OK")) - return 1; - ao_cmd_lex(); - } - ao_cmd_status = 0; - return 0; -} - /* * Delay between command charaters; the BT module * can't keep up with 57600 baud @@ -226,7 +196,6 @@ ao_btm(void) NULL); ao_btm_echo(0); - ao_btm_running = 1; for (;;) { while (!ao_btm_connected) ao_sleep(&ao_btm_connected); diff --git a/src/ao_cmd.c b/src/ao_cmd.c index c738a3e0..23346c3d 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -274,11 +274,6 @@ ao_cmd(void) for (;;) { readline(); -#if HAS_CMD_FILTER - if (ao_cmd_filter()) - continue; - cmd_i = 0; -#endif ao_cmd_lex(); ao_cmd_white(); c = ao_cmd_lex_c; diff --git a/src/ao_pins.h b/src/ao_pins.h index 1344dcaa..9ee5bdb4 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -224,7 +224,6 @@ #define HAS_BEEP 0 #define HAS_SERIAL_1 1 #define USE_SERIAL_STDIN 1 - #define HAS_CMD_FILTER 1 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 -- cgit v1.2.3 From 214cd69c0e4a1617ed5cde8fc2f46a4cee6ecced Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Apr 2011 22:50:58 -0700 Subject: altos: add telebt-v0.0 Makefile Git doesn't like to add these. Signed-off-by: Keith Packard --- src/telebt-v0.0/Makefile | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/telebt-v0.0/Makefile (limited to 'src') diff --git a/src/telebt-v0.0/Makefile b/src/telebt-v0.0/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telebt-v0.0/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto -- cgit v1.2.3 From c1760cebd47d0f03808f3204c0fcb1183f754e50 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 May 2011 15:44:56 -0700 Subject: altos: Add preliminary telebt v0.1 defines This should make the telebt v0.1 binary that works on the real hardware. Signed-off-by: Keith Packard --- src/Makefile.proto | 8 +++++++- src/ao_log_telem.c | 30 ++++++++++++++++++++++++++++++ src/ao_pins.h | 28 ++++++++++++++++++++++++++++ src/ao_telebt.c | 4 ++++ src/telebt-v0.1/.gitignore | 2 ++ src/telebt-v0.1/.sdcdbrc | 1 + src/telebt-v0.1/Makefile | 1 + src/telebt-v0.1/Makefile.defs | 8 ++++++++ 8 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 src/ao_log_telem.c create mode 100644 src/telebt-v0.1/.gitignore create mode 100644 src/telebt-v0.1/.sdcdbrc create mode 100644 src/telebt-v0.1/Makefile create mode 100644 src/telebt-v0.1/Makefile.defs (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index ca68edbc..04b708b2 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -238,7 +238,7 @@ TNANO_BASE_SRC = \ $(TNANO_MAIN_SRC) # -# Sources for TeleDongle +# Sources for TeleBluetooth # TBT_MAIN_SRC = \ @@ -255,6 +255,12 @@ TBT_BASE_SRC = \ $(DBG_SRC) \ $(TBT_MAIN_SRC) +TBT_V_0_1_SRC = \ + $(TBT_BASE_SRC) \ + $(SPI_DRIVER_SRC) \ + $(M25_DRIVER_SRC) \ + ao_log_telem.c + # # TI Dongle sources # diff --git a/src/ao_log_telem.c b/src/ao_log_telem.c new file mode 100644 index 00000000..1b472efe --- /dev/null +++ b/src/ao_log_telem.c @@ -0,0 +1,30 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +void +ao_log_write_erase(uint8_t pos) +{ + (void) pos; +} + +uint8_t +ao_log_present(void) +{ + return 0; +} diff --git a/src/ao_pins.h b/src/ao_pins.h index 324d7827..bc9bdcb9 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -243,6 +243,34 @@ #define HAS_IGNITE 0 #endif +#if defined(TELEBT_V_0_1) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 1 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_BTM 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 1 + #define AO_LED_GREEN 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x04 /* CS0 is P1_2 */ + #define M25_MAX_CHIPS 1 + #define HAS_ACCEL 0 + #define HAS_IGNITE 0 +#endif + #if DBG_ON_P1 #define DBG_CLOCK (1 << 4) /* mi0 */ diff --git a/src/ao_telebt.c b/src/ao_telebt.c index 295f0cec..34d4432d 100644 --- a/src/ao_telebt.c +++ b/src/ao_telebt.c @@ -27,6 +27,10 @@ main(void) ao_led_on(AO_LED_RED); ao_timer_init(); ao_cmd_init(); +#if HAS_EEPROM + ao_spi_init(); + ao_storage_init(); +#endif ao_usb_init(); ao_monitor_init(AO_LED_GREEN, TRUE); ao_rssi_init(AO_LED_RED); diff --git a/src/telebt-v0.1/.gitignore b/src/telebt-v0.1/.gitignore new file mode 100644 index 00000000..1acfbfcc --- /dev/null +++ b/src/telebt-v0.1/.gitignore @@ -0,0 +1,2 @@ +telebt-* +ao_product.h diff --git a/src/telebt-v0.1/.sdcdbrc b/src/telebt-v0.1/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telebt-v0.1/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telebt-v0.1/Makefile b/src/telebt-v0.1/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telebt-v0.1/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/telebt-v0.1/Makefile.defs b/src/telebt-v0.1/Makefile.defs new file mode 100644 index 00000000..50657c83 --- /dev/null +++ b/src/telebt-v0.1/Makefile.defs @@ -0,0 +1,8 @@ +PROG = telebt-v0.1-$(VERSION).ihx + +SRC = \ + $(TBT_V_0_1_SRC) + +PRODUCT=TeleBT-v0.1 +PRODUCT_DEF=-DTELEBT_V_0_1 +IDPRODUCT=0x000e -- cgit v1.2.3 From d9cc27641fe1778c098b065bf110be7823e6c9f4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 May 2011 16:57:38 -0700 Subject: altos: Add telebt-v0.1 to Makefile Doesn't get built without it. Signed-off-by: Keith Packard --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index d83ec668..3eec3980 100644 --- a/src/Makefile +++ b/src/Makefile @@ -10,7 +10,7 @@ SUBDIRS=\ telemetrum-v1.1 telemetrum-v1.0 \ teledongle-v0.2 teledongle-v0.1 \ telemini-v0.1 telenano-v0.1 \ - telebt-v0.0 \ + telebt-v0.0 telebt-v0.1 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ tidongle test -- cgit v1.2.3 From 19bfa3882a2d95fcade256c2d63ad24f794281e5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 May 2011 20:33:58 -0700 Subject: altos: Use USART configuration 1 with flow control for TBT It's just wired that way. Signed-off-by: Keith Packard --- src/ao_pins.h | 3 +++ src/ao_serial.c | 18 ++++++++++++++++++ src/cc1111.h | 6 ++++++ 3 files changed, 27 insertions(+) (limited to 'src') diff --git a/src/ao_pins.h b/src/ao_pins.h index bc9bdcb9..4c31f755 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -248,6 +248,9 @@ #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 1 + #define HAS_SERIAL_1_ALT_1 1 + #define HAS_SERIAL_1_ALT_2 0 + #define HAS_SERIAL_1_HW_FLOW 1 #define USE_SERIAL_STDIN 1 #define HAS_ADC 0 #define HAS_DBG 1 diff --git a/src/ao_serial.c b/src/ao_serial.c index 9c0b798d..2e7dad7b 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -127,6 +127,18 @@ ao_serial_set_speed(uint8_t speed) void ao_serial_init(void) { +#if HAS_SERIAL_1_ALT_1 + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_1; + + P2DIR = (P2DIR & ~P2DIR_PRIP0_MASK) | P2DIR_PRIP0_USART1_USART0; + + /* Make the USART pins be controlled by the USART */ + P0SEL |= (1 << 5) | (1 << 4); +#if HAS_SERIAL_1_HW_FLOW + P0SEL |= (1 << 3) | (1 << 2); +#endif +#else /* Set up the USART pin assignment */ PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_2; @@ -135,6 +147,8 @@ ao_serial_init(void) /* Make the USART pins be controlled by the USART */ P1SEL |= (1 << 6) | (1 << 7); + P1SEL |= (1 << 5) | (1 << 4); +#endif /* UART mode with receiver enabled */ U1CSR = (UxCSR_MODE_UART | UxCSR_RE); @@ -144,7 +158,11 @@ ao_serial_init(void) /* Reasonable serial parameters */ U1UCR = (UxUCR_FLUSH | +#if HAS_SERIAL_1_HW_FLOW + UxUCR_FLOW_ENABLE | +#else UxUCR_FLOW_DISABLE | +#endif UxUCR_D9_EVEN_PARITY | UxUCR_BIT9_8_BITS | UxUCR_PARITY_DISABLE | diff --git a/src/cc1111.h b/src/cc1111.h index a07490e5..5b018cb5 100644 --- a/src/cc1111.h +++ b/src/cc1111.h @@ -589,6 +589,12 @@ sfr at 0xFD P0DIR; sfr at 0xFE P1DIR; sfr at 0xFF P2DIR; +#define P2DIR_PRIP0_USART0_USART1 (0 << 6) +#define P2DIR_PRIP0_USART1_USART0 (1 << 6) +#define P2DIR_PRIP0_TIMER1_01_USART1 (2 << 6) +#define P2DIR_PRIP0_TIMER1_2_USART0 (3 << 6) +#define P2DIR_PRIP0_MASK (3 << 6) + sfr at 0x8F P0INP; /* Select between tri-state and pull up/down -- cgit v1.2.3 From 3336d0f726afd1d43cf62280940e5fb91dab2e91 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 May 2011 21:13:19 -0700 Subject: altos: Fix BT link status pin for real TBT hardware The prototype used P2_1, while the real hardware uses P1_7. Lots of defines to make this work... Signed-off-by: Keith Packard --- src/ao_btm.c | 50 ++++++++++++++++++++++++++++++++++++++++---------- src/ao_pins.h | 8 ++++++++ 2 files changed, 48 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/ao_btm.c b/src/ao_btm.c index db0ff6b0..355c3ca4 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -208,26 +208,44 @@ ao_btm(void) __xdata struct ao_task ao_btm_task; +#if BT_LINK_ON_P2 +#define BT_PICTL_ICON PICTL_P2ICON +#define BT_PIFG P2IFG +#define BT_PDIR P2DIR +#define BT_PINP P2INP +#define BT_IEN2_PIE IEN2_P2IE +#endif +#if BT_LINK_ON_P1 +#define BT_PICTL_ICON PICTL_P1ICON +#define BT_PIFG P1IFG +#define BT_PDIR P1DIR +#define BT_PINP P1INP +#define BT_IEN2_PIE IEN2_P1IE +#endif + void ao_btm_check_link() __critical { - if (P2_1) { + /* Check the pin and configure the interrupt detector to wait for the + * pin to flip the other way + */ + if (BT_LINK_PIN) { ao_btm_connected = 0; - PICTL |= PICTL_P2ICON; + PICTL |= BT_PICTL_ICON; } else { ao_btm_connected = 1; - PICTL &= ~PICTL_P2ICON; + PICTL &= ~BT_PICTL_ICON; } } void ao_btm_isr(void) { - if (P2IFG & (1 << 1)) { + if (BT_PIFG & (1 << BT_LINK_PIN_INDEX)) { ao_btm_check_link(); ao_wakeup(&ao_btm_connected); } - P2IFG = 0; + BT_PIFG = 0; } void @@ -240,14 +258,26 @@ ao_btm_init (void) * Configure link status line */ - /* Set P2_1 to input, pull-down */ - P2DIR &= ~(1 << 1); - P2INP |= P2INP_MDP2_1_TRISTATE; + /* Set pin to input */ + BT_PDIR &= ~(1 << BT_LINK_PIN_INDEX); + + /* Set pin to tri-state */ + BT_PINP |= (1 << BT_LINK_PIN_INDEX); - /* Enable P2 interrupts */ - IEN2 |= IEN2_P2IE; + /* Enable interrupts */ + IEN2 |= BT_IEN2_PIE; + + /* Check current pin state */ ao_btm_check_link(); + +#if BT_LINK_ON_P2 + /* Eable the pin interrupt */ PICTL |= PICTL_P2IEN; +#endif +#if BT_LINK_ON_P1 + /* Enable pin interrupt */ + P1IEN |= (1 << BT_LINK_PIN_INDEX); +#endif ao_add_task(&ao_btm_task, ao_btm, "bt"); } diff --git a/src/ao_pins.h b/src/ao_pins.h index 4c31f755..21b99027 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -241,6 +241,10 @@ #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 #define HAS_IGNITE 0 + #define BT_LINK_ON_P2 1 + #define BT_LINK_ON_P1 0 + #define BT_LINK_PIN_INDEX 7 + #define BT_LINK_PIN P2_1 #endif #if defined(TELEBT_V_0_1) @@ -272,6 +276,10 @@ #define M25_MAX_CHIPS 1 #define HAS_ACCEL 0 #define HAS_IGNITE 0 + #define BT_LINK_ON_P2 0 + #define BT_LINK_ON_P1 1 + #define BT_LINK_PIN_INDEX 7 + #define BT_LINK_PIN P1_7 #endif #if DBG_ON_P1 -- cgit v1.2.3 From 6d858b64ee0e8c227c149d2af6d2d634536964f4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 May 2011 22:12:31 -0700 Subject: altos: pull TBT v0.1 ser_reset line low This line resets the BT module if held low for three seconds. Signed-off-by: Keith Packard --- src/ao_btm.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/ao_btm.c b/src/ao_btm.c index 355c3ca4..241b3f6a 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -254,6 +254,15 @@ ao_btm_init (void) ao_serial_init(); ao_serial_set_speed(AO_SERIAL_SPEED_19200); +#if BT_LINK_ON_P1 + /* + * Configure ser reset line + */ + + P1_6 = 0; + P1DIR |= (1 << 6); +#endif + /* * Configure link status line */ -- cgit v1.2.3 From 22e3ac0eb014b8255029763ae8180ad3527ba306 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 May 2011 22:42:32 -0700 Subject: altos: Add beeper to TBT v0.1 It's available, let's use it. Signed-off-by: Keith Packard --- src/Makefile.proto | 1 + src/ao_btm.c | 4 ++++ src/ao_pins.h | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index 04b708b2..c86de823 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -259,6 +259,7 @@ TBT_V_0_1_SRC = \ $(TBT_BASE_SRC) \ $(SPI_DRIVER_SRC) \ $(M25_DRIVER_SRC) \ + $(BEEP_DRIVER_SRC) \ ao_log_telem.c # diff --git a/src/ao_btm.c b/src/ao_btm.c index 241b3f6a..4b3c5209 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -166,6 +166,10 @@ ao_btm(void) */ ao_delay(AO_SEC_TO_TICKS(3)); +#if HAS_BEEP + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); +#endif + /* * The first time we connect, the BTM-180 comes up at 19200 baud. * After that, it will remember and come up at 57600 baud. So, see diff --git a/src/ao_pins.h b/src/ao_pins.h index 21b99027..4a03ca50 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -250,7 +250,7 @@ #if defined(TELEBT_V_0_1) #define HAS_FLIGHT 0 #define HAS_USB 1 - #define HAS_BEEP 0 + #define HAS_BEEP 1 #define HAS_SERIAL_1 1 #define HAS_SERIAL_1_ALT_1 1 #define HAS_SERIAL_1_ALT_2 0 -- cgit v1.2.3 From 514348055630edec12224c4b0964240b929759a3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 May 2011 22:42:58 -0700 Subject: altos: Debugging TBT issues -- check pin configuration after boot Make sure the serial pins are configured as peripherals Make sure the ser_reset and bt_link pins are going the right direction. Signed-off-by: Keith Packard --- src/ao_btm.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/ao_btm.c b/src/ao_btm.c index 4b3c5209..490b2667 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -17,6 +17,21 @@ #include "ao.h" +#if BT_LINK_ON_P2 +#define BT_PICTL_ICON PICTL_P2ICON +#define BT_PIFG P2IFG +#define BT_PDIR P2DIR +#define BT_PINP P2INP +#define BT_IEN2_PIE IEN2_P2IE +#endif +#if BT_LINK_ON_P1 +#define BT_PICTL_ICON PICTL_P1ICON +#define BT_PIFG P1IFG +#define BT_PDIR P1DIR +#define BT_PINP P1INP +#define BT_IEN2_PIE IEN2_P1IE +#endif + int8_t ao_btm_stdio; __xdata uint8_t ao_btm_connected; @@ -166,6 +181,15 @@ ao_btm(void) */ ao_delay(AO_SEC_TO_TICKS(3)); +#if BT_LINK_ON_P1 + if ((P1DIR & (1 << 6)) == 0) + ao_panic(AO_PANIC_BT); + if ((P1DIR & (1 << 7)) != 0) + ao_panic(AO_PANIC_BT); + if ((P0SEL & ((1 << 5) | (1 << 4) | (1 << 3) | (1 << 2))) != + ((1 << 5) | (1 << 4) | (1 << 3) | (1 << 2))) + ao_panic(AO_PANIC_BT); +#endif #if HAS_BEEP ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); #endif @@ -212,21 +236,6 @@ ao_btm(void) __xdata struct ao_task ao_btm_task; -#if BT_LINK_ON_P2 -#define BT_PICTL_ICON PICTL_P2ICON -#define BT_PIFG P2IFG -#define BT_PDIR P2DIR -#define BT_PINP P2INP -#define BT_IEN2_PIE IEN2_P2IE -#endif -#if BT_LINK_ON_P1 -#define BT_PICTL_ICON PICTL_P1ICON -#define BT_PIFG P1IFG -#define BT_PDIR P1DIR -#define BT_PINP P1INP -#define BT_IEN2_PIE IEN2_P1IE -#endif - void ao_btm_check_link() __critical { -- cgit v1.2.3 From 23f441b95e55fbee709382b05d325bc021285766 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 May 2011 22:49:54 -0700 Subject: altos: Initialize beeper for telebt Needed to get sounds to come out Signed-off-by: Keith Packard --- src/ao_telebt.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/ao_telebt.c b/src/ao_telebt.c index 34d4432d..8e77c4d9 100644 --- a/src/ao_telebt.c +++ b/src/ao_telebt.c @@ -26,6 +26,9 @@ main(void) ao_led_init(LEDS_AVAILABLE); ao_led_on(AO_LED_RED); ao_timer_init(); +#if HAS_BEEP + ao_beep_init(); +#endif ao_cmd_init(); #if HAS_EEPROM ao_spi_init(); -- cgit v1.2.3 From 8be559baa979c15e78f8dba7879b383dbe3936d3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 May 2011 22:59:15 -0700 Subject: altos: Hook up the P1 ISR for TeleBT v0.1 bt_link line Otherwise, we're heading off into the weeds... Signed-off-by: Keith Packard --- src/ao.h | 12 ++++++++++-- src/ao_btm.c | 3 +++ src/ao_usb.c | 2 ++ 3 files changed, 15 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 226f9a22..600c488a 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1367,9 +1367,17 @@ ao_packet_slave_init(uint8_t enable); /* ao_btm.c */ -/* Shared by USB, so the USB code calls this function */ +/* If bt_link is on P2, this interrupt is shared by USB, so the USB + * code calls this function. Otherwise, it's a regular ISR. + */ + void -ao_btm_isr(void); +ao_btm_isr(void) +#if BT_LINK_ON_P1 + __interrupt 15 +#endif + ; + void ao_btm_init(void); diff --git a/src/ao_btm.c b/src/ao_btm.c index 490b2667..172004e9 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -253,6 +253,9 @@ ao_btm_check_link() __critical void ao_btm_isr(void) +#if BT_LINK_ON_P1 + __interrupt 15 +#endif { if (BT_PIFG & (1 << BT_LINK_PIN_INDEX)) { ao_btm_check_link(); diff --git a/src/ao_usb.c b/src/ao_usb.c index ece6756a..dd752152 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -59,8 +59,10 @@ ao_usb_isr(void) __interrupt 6 if (USBCIF & USBCIF_RSTIF) ao_usb_set_interrupts(); #if HAS_BTM +#if BT_LINK_ON_P2 ao_btm_isr(); #endif +#endif } struct ao_usb_setup { -- cgit v1.2.3 From 66bdf0e066bc0bb7a326a6c2a9c88b69e5c1be66 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 May 2011 23:12:47 -0700 Subject: altos: clear CPU port 1 interrupt flag when handled Signed-off-by: Keith Packard --- src/ao_btm.c | 3 +++ src/ao_usb.c | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_btm.c b/src/ao_btm.c index 172004e9..a9306c10 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -257,6 +257,9 @@ ao_btm_isr(void) __interrupt 15 #endif { +#if BT_LINK_ON_P1 + P1IF = 0; +#endif if (BT_PIFG & (1 << BT_LINK_PIN_INDEX)) { ao_btm_check_link(); ao_wakeup(&ao_btm_connected); diff --git a/src/ao_usb.c b/src/ao_usb.c index dd752152..e4b7938d 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -46,7 +46,6 @@ void ao_usb_isr(void) __interrupt 6 { USBIF = 0; - IRCON2 &= ~IRCON2_USBIF; ao_usb_iif |= USBIIF; if (ao_usb_iif & 1) ao_wakeup(&ao_usb_task); -- cgit v1.2.3 From 479bdffa35d0b8d4e48868c8d20f3cb1549521ab Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 May 2011 23:55:23 -0700 Subject: Revert "altos: Debugging TBT issues -- check pin configuration after boot" This reverts commit 514348055630edec12224c4b0964240b929759a3. Looks like this was never a problem. --- src/ao_btm.c | 39 +++++++++++++++------------------------ 1 file changed, 15 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/ao_btm.c b/src/ao_btm.c index a9306c10..44155ec1 100644 --- a/src/ao_btm.c +++ b/src/ao_btm.c @@ -17,21 +17,6 @@ #include "ao.h" -#if BT_LINK_ON_P2 -#define BT_PICTL_ICON PICTL_P2ICON -#define BT_PIFG P2IFG -#define BT_PDIR P2DIR -#define BT_PINP P2INP -#define BT_IEN2_PIE IEN2_P2IE -#endif -#if BT_LINK_ON_P1 -#define BT_PICTL_ICON PICTL_P1ICON -#define BT_PIFG P1IFG -#define BT_PDIR P1DIR -#define BT_PINP P1INP -#define BT_IEN2_PIE IEN2_P1IE -#endif - int8_t ao_btm_stdio; __xdata uint8_t ao_btm_connected; @@ -181,15 +166,6 @@ ao_btm(void) */ ao_delay(AO_SEC_TO_TICKS(3)); -#if BT_LINK_ON_P1 - if ((P1DIR & (1 << 6)) == 0) - ao_panic(AO_PANIC_BT); - if ((P1DIR & (1 << 7)) != 0) - ao_panic(AO_PANIC_BT); - if ((P0SEL & ((1 << 5) | (1 << 4) | (1 << 3) | (1 << 2))) != - ((1 << 5) | (1 << 4) | (1 << 3) | (1 << 2))) - ao_panic(AO_PANIC_BT); -#endif #if HAS_BEEP ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); #endif @@ -236,6 +212,21 @@ ao_btm(void) __xdata struct ao_task ao_btm_task; +#if BT_LINK_ON_P2 +#define BT_PICTL_ICON PICTL_P2ICON +#define BT_PIFG P2IFG +#define BT_PDIR P2DIR +#define BT_PINP P2INP +#define BT_IEN2_PIE IEN2_P2IE +#endif +#if BT_LINK_ON_P1 +#define BT_PICTL_ICON PICTL_P1ICON +#define BT_PIFG P1IFG +#define BT_PDIR P1DIR +#define BT_PINP P1INP +#define BT_IEN2_PIE IEN2_P1IE +#endif + void ao_btm_check_link() __critical { -- cgit v1.2.3 From 0e67b6890dd3a06665239f8dfd2e69266d055e46 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 22 Jun 2011 12:26:45 -0700 Subject: altos: Rename telemetry to telemetry_orig This makes room to create a new multi-packet telemetry format without changing anything yet. Signed-off-by: Keith Packard --- src/Makefile.proto | 2 +- src/ao.h | 13 +++--- src/ao_monitor.c | 66 ++++++++++++++++-------------- src/ao_radio.c | 3 -- src/ao_telemetrum.c | 2 +- src/ao_telemetry.c | 105 ------------------------------------------------ src/ao_telemetry_orig.c | 105 ++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 149 insertions(+), 147 deletions(-) delete mode 100644 src/ao_telemetry.c create mode 100644 src/ao_telemetry_orig.c (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index c86de823..bc7b3a7f 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -160,7 +160,7 @@ TM_TASK_SRC = \ ao_log.c \ ao_log_big.c \ ao_report.c \ - ao_telemetry.c + ao_telemetry_orig.c TM_MAIN_SRC = \ ao_telemetrum.c diff --git a/src/ao.h b/src/ao.h index 600c488a..b6a987e3 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1079,10 +1079,11 @@ struct ao_telemetry_tiny { /* * ao_radio_recv tacks on rssi and status bytes */ -struct ao_telemetry_recv { - struct ao_telemetry telemetry; - int8_t rssi; - uint8_t status; + +struct ao_telemetry_orig_recv { + struct ao_telemetry_orig telemetry_orig; + int8_t rssi; + uint8_t status; }; struct ao_telemetry_tiny_recv { @@ -1104,7 +1105,7 @@ void ao_rdf_set(uint8_t rdf); void -ao_telemetry_init(void); +ao_telemetry_orig_init(void); void ao_telemetry_tiny_init(void); @@ -1160,7 +1161,7 @@ void ao_monitor(void); #define AO_MONITORING_OFF 0 -#define AO_MONITORING_FULL 1 +#define AO_MONITORING_ORIG 1 #define AO_MONITORING_TINY 2 void diff --git a/src/ao_monitor.c b/src/ao_monitor.c index 8f290071..248857de 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -26,11 +26,12 @@ ao_monitor(void) { __xdata char callsign[AO_MAX_CALLSIGN+1]; __xdata union { - struct ao_telemetry_recv full; + struct ao_telemetry_orig_recv orig; struct ao_telemetry_tiny_recv tiny; } u; -#define recv (u.full) +#define recv_raw (u.raw) +#define recv_orig (u.orig) #define recv_tiny (u.tiny) uint8_t state; @@ -39,18 +40,19 @@ ao_monitor(void) for (;;) { __critical while (!ao_monitoring) ao_sleep(&ao_monitoring); - if (ao_monitoring == AO_MONITORING_FULL) { - if (!ao_radio_recv(&recv, sizeof (struct ao_telemetry_recv))) + switch (ao_monitoring) { + case AO_MONITORING_ORIG: + if (!ao_radio_recv(&recv_orig, sizeof (struct ao_telemetry_orig_recv))) continue; - state = recv.telemetry.flight_state; + state = recv_orig.telemetry_orig.flight_state; /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ - rssi = (int16_t) (recv.rssi >> 1) - 74; - memcpy(callsign, recv.telemetry.callsign, AO_MAX_CALLSIGN); + rssi = (int16_t) (recv_orig.rssi >> 1) - 74; + memcpy(callsign, recv_orig.telemetry_orig.callsign, AO_MAX_CALLSIGN); if (state > ao_flight_invalid) state = ao_flight_invalid; - if (recv.status & PKT_APPEND_STATUS_1_CRC_OK) { + if (recv_orig.status & PKT_APPEND_STATUS_1_CRC_OK) { /* General header fields */ printf(AO_TELEM_VERSION " %d " @@ -62,11 +64,11 @@ ao_monitor(void) AO_TELEM_TICK " %d ", AO_TELEMETRY_VERSION, callsign, - recv.telemetry.serial, - recv.telemetry.flight, + recv_orig.telemetry_orig.serial, + recv_orig.telemetry_orig.flight, rssi, ao_state_names[state], - recv.telemetry.adc.tick); + recv_orig.telemetry_orig.adc.tick); /* Raw sensor values */ printf(AO_TELEM_RAW_ACCEL " %d " @@ -75,48 +77,49 @@ ao_monitor(void) AO_TELEM_RAW_BATT " %d " AO_TELEM_RAW_DROGUE " %d " AO_TELEM_RAW_MAIN " %d ", - recv.telemetry.adc.accel, - recv.telemetry.adc.pres, - recv.telemetry.adc.temp, - recv.telemetry.adc.v_batt, - recv.telemetry.adc.sense_d, - recv.telemetry.adc.sense_m); + recv_orig.telemetry_orig.adc.accel, + recv_orig.telemetry_orig.adc.pres, + recv_orig.telemetry_orig.adc.temp, + recv_orig.telemetry_orig.adc.v_batt, + recv_orig.telemetry_orig.adc.sense_d, + recv_orig.telemetry_orig.adc.sense_m); /* Sensor calibration values */ printf(AO_TELEM_CAL_ACCEL_GROUND " %d " AO_TELEM_CAL_BARO_GROUND " %d " AO_TELEM_CAL_ACCEL_PLUS " %d " AO_TELEM_CAL_ACCEL_MINUS " %d ", - recv.telemetry.ground_accel, - recv.telemetry.ground_pres, - recv.telemetry.accel_plus_g, - recv.telemetry.accel_minus_g); + recv_orig.telemetry_orig.ground_accel, + recv_orig.telemetry_orig.ground_pres, + recv_orig.telemetry_orig.accel_plus_g, + recv_orig.telemetry_orig.accel_minus_g); - if (recv.telemetry.u.k.unused == 0x8000) { + if (recv_orig.telemetry_orig.u.k.unused == 0x8000) { /* Kalman state values */ printf(AO_TELEM_KALMAN_HEIGHT " %d " AO_TELEM_KALMAN_SPEED " %d " AO_TELEM_KALMAN_ACCEL " %d ", - recv.telemetry.height, - recv.telemetry.u.k.speed, - recv.telemetry.accel); + recv_orig.telemetry_orig.height, + recv_orig.telemetry_orig.u.k.speed, + recv_orig.telemetry_orig.accel); } else { /* Ad-hoc flight values */ printf(AO_TELEM_ADHOC_ACCEL " %d " AO_TELEM_ADHOC_SPEED " %ld " AO_TELEM_ADHOC_BARO " %d ", - recv.telemetry.accel, - recv.telemetry.u.flight_vel, - recv.telemetry.height); + recv_orig.telemetry_orig.accel, + recv_orig.telemetry_orig.u.flight_vel, + recv_orig.telemetry_orig.height); } - ao_gps_print(&recv.telemetry.gps); - ao_gps_tracking_print(&recv.telemetry.gps_tracking); + ao_gps_print(&recv_orig.telemetry_orig.gps); + ao_gps_tracking_print(&recv_orig.telemetry_orig.gps_tracking); putchar('\n'); ao_rssi_set(rssi); } else { printf("CRC INVALID RSSI %3d\n", rssi); } - } else { + break; + case AO_MONITORING_TINY: if (!ao_radio_recv(&recv_tiny, sizeof (struct ao_telemetry_tiny_recv))) continue; @@ -181,6 +184,7 @@ ao_monitor(void) } else { printf("CRC INVALID RSSI %3d\n", rssi); } + break; } ao_usb_flush(); ao_led_toggle(ao_monitor_led); diff --git a/src/ao_radio.c b/src/ao_radio.c index b5a67b99..01974ba1 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -161,8 +161,6 @@ static __code uint8_t radio_setup[] = { 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), @@ -233,7 +231,6 @@ static __code uint8_t fixed_pkt_setup[] = { (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), /* max packet length -- now set inline */ - // RF_PKTLEN_OFF, sizeof (struct ao_telemetry), RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| PKTCTRL1_APPEND_STATUS| PKTCTRL1_ADR_CHK_NONE), diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 4ace415c..bede5868 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -57,7 +57,7 @@ main(void) ao_serial_init(); ao_gps_init(); ao_gps_report_init(); - ao_telemetry_init(); + ao_telemetry_orig_init(); ao_radio_init(); ao_packet_slave_init(TRUE); ao_igniter_init(); diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c deleted file mode 100644 index 9a86882f..00000000 --- a/src/ao_telemetry.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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" - -__xdata uint16_t ao_telemetry_interval = 0; -__xdata uint8_t ao_rdf = 0; -__xdata uint16_t ao_rdf_time; - -#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) -#define AO_RDF_LENGTH_MS 500 - -void -ao_telemetry(void) -{ - uint16_t time; - int16_t delay; - static __xdata struct ao_telemetry telemetry; - - ao_config_get(); - while (!ao_flight_number) - ao_sleep(&ao_flight_number); - memcpy(telemetry.callsign, ao_config.callsign, AO_MAX_CALLSIGN); - telemetry.serial = ao_serial_number; - telemetry.flight = ao_log_full() ? 0 : ao_flight_number; - telemetry.accel_plus_g = ao_config.accel_plus_g; - telemetry.accel_minus_g = ao_config.accel_minus_g; - for (;;) { - while (ao_telemetry_interval == 0) - ao_sleep(&ao_telemetry_interval); - time = ao_rdf_time = ao_time(); - while (ao_telemetry_interval) { - telemetry.flight_state = ao_flight_state; - telemetry.height = ao_height; - telemetry.u.k.speed = ao_speed; - telemetry.accel = ao_accel; - telemetry.u.k.unused = 0x8000; -#if HAS_ACCEL - telemetry.ground_accel = ao_ground_accel; -#endif - telemetry.ground_pres = ao_ground_pres; -#if HAS_ADC - ao_adc_get(&telemetry.adc); -#endif -#if HAS_GPS - ao_mutex_get(&ao_gps_mutex); - memcpy(&telemetry.gps, &ao_gps_data, sizeof (struct ao_gps_data)); - memcpy(&telemetry.gps_tracking, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data)); - ao_mutex_put(&ao_gps_mutex); -#endif - ao_radio_send(&telemetry, sizeof (telemetry)); - if (ao_rdf && - (int16_t) (ao_time() - ao_rdf_time) >= 0) - { - ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; - ao_radio_rdf(AO_RDF_LENGTH_MS); - } - time += ao_telemetry_interval; - delay = time - ao_time(); - if (delay > 0) - ao_delay(delay); - else - time = ao_time(); - } - } -} - -void -ao_telemetry_set_interval(uint16_t interval) -{ - ao_telemetry_interval = interval; - ao_wakeup(&ao_telemetry_interval); -} - -void -ao_rdf_set(uint8_t rdf) -{ - ao_rdf = rdf; - if (rdf == 0) - ao_radio_rdf_abort(); - else - ao_rdf_time = ao_time(); -} - -__xdata struct ao_task ao_telemetry_task; - -void -ao_telemetry_init() -{ - ao_add_task(&ao_telemetry_task, ao_telemetry, "telemetry"); -} diff --git a/src/ao_telemetry_orig.c b/src/ao_telemetry_orig.c new file mode 100644 index 00000000..9a86882f --- /dev/null +++ b/src/ao_telemetry_orig.c @@ -0,0 +1,105 @@ +/* + * 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" + +__xdata uint16_t ao_telemetry_interval = 0; +__xdata uint8_t ao_rdf = 0; +__xdata uint16_t ao_rdf_time; + +#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) +#define AO_RDF_LENGTH_MS 500 + +void +ao_telemetry(void) +{ + uint16_t time; + int16_t delay; + static __xdata struct ao_telemetry telemetry; + + ao_config_get(); + while (!ao_flight_number) + ao_sleep(&ao_flight_number); + memcpy(telemetry.callsign, ao_config.callsign, AO_MAX_CALLSIGN); + telemetry.serial = ao_serial_number; + telemetry.flight = ao_log_full() ? 0 : ao_flight_number; + telemetry.accel_plus_g = ao_config.accel_plus_g; + telemetry.accel_minus_g = ao_config.accel_minus_g; + for (;;) { + while (ao_telemetry_interval == 0) + ao_sleep(&ao_telemetry_interval); + time = ao_rdf_time = ao_time(); + while (ao_telemetry_interval) { + telemetry.flight_state = ao_flight_state; + telemetry.height = ao_height; + telemetry.u.k.speed = ao_speed; + telemetry.accel = ao_accel; + telemetry.u.k.unused = 0x8000; +#if HAS_ACCEL + telemetry.ground_accel = ao_ground_accel; +#endif + telemetry.ground_pres = ao_ground_pres; +#if HAS_ADC + ao_adc_get(&telemetry.adc); +#endif +#if HAS_GPS + ao_mutex_get(&ao_gps_mutex); + memcpy(&telemetry.gps, &ao_gps_data, sizeof (struct ao_gps_data)); + memcpy(&telemetry.gps_tracking, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data)); + ao_mutex_put(&ao_gps_mutex); +#endif + ao_radio_send(&telemetry, sizeof (telemetry)); + if (ao_rdf && + (int16_t) (ao_time() - ao_rdf_time) >= 0) + { + ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; + ao_radio_rdf(AO_RDF_LENGTH_MS); + } + time += ao_telemetry_interval; + delay = time - ao_time(); + if (delay > 0) + ao_delay(delay); + else + time = ao_time(); + } + } +} + +void +ao_telemetry_set_interval(uint16_t interval) +{ + ao_telemetry_interval = interval; + ao_wakeup(&ao_telemetry_interval); +} + +void +ao_rdf_set(uint8_t rdf) +{ + ao_rdf = rdf; + if (rdf == 0) + ao_radio_rdf_abort(); + else + ao_rdf_time = ao_time(); +} + +__xdata struct ao_task ao_telemetry_task; + +void +ao_telemetry_init() +{ + ao_add_task(&ao_telemetry_task, ao_telemetry, "telemetry"); +} -- cgit v1.2.3 From 489a68ba8e3bc360e2e8fc887e4c4b840b5a0dd3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 22 Jun 2011 12:27:34 -0700 Subject: altos: Add arbitrary telemetry packet monitoring This adds the ability to monitor arbitrary telemetry packets (up to 128 bytes), moving the telemetry data parsing up to the host. Signed-off-by: Keith Packard --- src/ao.h | 9 +++++++-- src/ao_monitor.c | 10 ++++++++++ src/ao_telemetry_orig.c | 10 +++++----- 3 files changed, 22 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index b6a987e3..f5753703 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1036,12 +1036,13 @@ void ao_gps_report_init(void); /* - * ao_telemetry.c + * ao_telemetry_orig.c */ #define AO_MAX_CALLSIGN 8 +#define AO_MAX_TELEMETRY 128 -struct ao_telemetry { +struct ao_telemetry_orig { uint16_t serial; uint16_t flight; uint8_t flight_state; @@ -1080,6 +1081,10 @@ struct ao_telemetry_tiny { * ao_radio_recv tacks on rssi and status bytes */ +struct ao_telemetry_raw_recv { + uint8_t packet[AO_MAX_TELEMETRY + 2]; +}; + struct ao_telemetry_orig_recv { struct ao_telemetry_orig telemetry_orig; int8_t rssi; diff --git a/src/ao_monitor.c b/src/ao_monitor.c index 248857de..ac1929db 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -26,6 +26,7 @@ ao_monitor(void) { __xdata char callsign[AO_MAX_CALLSIGN+1]; __xdata union { + struct ao_telemetry_raw_recv raw; struct ao_telemetry_orig_recv orig; struct ao_telemetry_tiny_recv tiny; } u; @@ -185,6 +186,15 @@ ao_monitor(void) printf("CRC INVALID RSSI %3d\n", rssi); } break; + default: + if (ao_monitoring > AO_MAX_TELEMETRY) + ao_monitoring = AO_MAX_TELEMETRY; + if (!ao_radio_recv(&recv_raw, ao_monitoring)) + continue; + for (state = 0; state < ao_monitoring + 1; state++) + printf("%02x ", recv_raw.packet[state]); + printf("%02x\n", recv_raw.packet[state]); + break; } ao_usb_flush(); ao_led_toggle(ao_monitor_led); diff --git a/src/ao_telemetry_orig.c b/src/ao_telemetry_orig.c index 9a86882f..4b3a344a 100644 --- a/src/ao_telemetry_orig.c +++ b/src/ao_telemetry_orig.c @@ -25,11 +25,11 @@ __xdata uint16_t ao_rdf_time; #define AO_RDF_LENGTH_MS 500 void -ao_telemetry(void) +ao_telemetry_orig(void) { uint16_t time; int16_t delay; - static __xdata struct ao_telemetry telemetry; + static __xdata struct ao_telemetry_orig telemetry; ao_config_get(); while (!ao_flight_number) @@ -96,10 +96,10 @@ ao_rdf_set(uint8_t rdf) ao_rdf_time = ao_time(); } -__xdata struct ao_task ao_telemetry_task; +__xdata struct ao_task ao_telemetry_orig_task; void -ao_telemetry_init() +ao_telemetry_orig_init() { - ao_add_task(&ao_telemetry_task, ao_telemetry, "telemetry"); + ao_add_task(&ao_telemetry_orig_task, ao_telemetry_orig, "telemetry_orig"); } -- cgit v1.2.3 From 5e111fdf1f23203baeeb490ae1b69402ebd513b8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 24 Jun 2011 08:31:12 -0700 Subject: altos: Add checksum to TELEM output lines Verify the received telemetry lines to protect against OS data loss Signed-off-by: Keith Packard --- src/ao_monitor.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ao_monitor.c b/src/ao_monitor.c index ac1929db..1d083c59 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -36,6 +36,7 @@ ao_monitor(void) #define recv_tiny (u.tiny) uint8_t state; + uint8_t sum, byte; int16_t rssi; for (;;) { @@ -191,9 +192,14 @@ ao_monitor(void) ao_monitoring = AO_MAX_TELEMETRY; if (!ao_radio_recv(&recv_raw, ao_monitoring)) continue; - for (state = 0; state < ao_monitoring + 1; state++) - printf("%02x ", recv_raw.packet[state]); - printf("%02x\n", recv_raw.packet[state]); + printf ("TELEM %02x", ao_monitoring+2); + sum = 0x5a; + for (state = 0; state < ao_monitoring + 2; state++) { + byte = recv_raw.packet[state]; + sum += byte; + printf("%02x", byte); + } + printf("%02x\n", sum); break; } ao_usb_flush(); -- cgit v1.2.3 From 336224a08327cadc95f6e5b564a4ddc64aaad8f8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 24 Jun 2011 08:31:51 -0700 Subject: altos: Start adding new telemetry frame definitions These use the initial 24 bytes per frame plan, which will probably get changed to 32 bytes per frame. Signed-off-by: Keith Packard --- src/ao.h | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index f5753703..4895f016 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1042,6 +1042,95 @@ ao_gps_report_init(void); #define AO_MAX_CALLSIGN 8 #define AO_MAX_TELEMETRY 128 +struct ao_telemetry_generic { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t payload[19]; /* 5 */ + /* 24 */ +}; + +#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 +#define AO_TELEMETRY_SENSOR_TELEMINI 0x02 +#define AO_TELEMETRY_SENSOR_TELENANO 0x03 + +struct ao_telemetry_sensor { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t state; /* 5 flight state */ + int16_t accel; /* 6 accelerometer (TM only) */ + int16_t pres; /* 8 pressure sensor */ + int16_t temp; /* 10 temperature sensor */ + int16_t v_batt; /* 12 battery voltage */ + int16_t sense_d; /* 14 drogue continuity sense (TM/Tm) */ + int16_t sense_m; /* 16 main continuity sense (TM/Tm) */ + + int16_t acceleration; /* 18 m/s² * 16 */ + int16_t speed; /* 20 m/s * 16 */ + int16_t height; /* 22 m */ + /* 24 */ +}; + +#define AO_TELEMETRY_CONSTANT 0x10 + +struct ao_telemetry_constant { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t device; /* 5 device type */ + uint16_t flight; /* 6 flight number */ + int16_t ground_accel; /* 8 average ground accelerometer (TM only) */ + int16_t ground_pres; /* 10 average ground barometer */ + int16_t accel_plus_g; /* 12 +1g accelerometer calibration value (TM only) */ + int16_t accel_minus_g; /* 14 -1g accelermeter calibration value (TM only) */ + char callsign[AO_MAX_CALLSIGN]; /* 16 identity */ + /* 24 */ +}; + +#define AO_TELEMETRY_LOCATION 0x11 + +struct ao_telemetry_location { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t flags; /* 5 Number of sats and other flags */ + int16_t altitude; /* 6 GPS reported altitude (m) */ + int32_t latitude; /* 8 latitude (degrees * 10⁷) */ + int32_t longitude; /* 12 longitude (degrees * 10⁷) */ + uint8_t year; /* 16 (- 2000) */ + uint8_t month; /* 17 (1-12) */ + uint8_t day; /* 18 (1-31) */ + uint8_t hour; /* 19 (0-23) */ + uint8_t minute; /* 20 (0-59) */ + uint8_t second; /* 21 (0-59) */ + uint8_t hdop; /* 22 (m * 5) */ + uint8_t unused; /* 23 */ + /* 24 */ +}; + +#define AO_TELEMETRY_SATELLITE 0x12 + +struct ao_telemetry_satellite { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t channels; /* 5 number of reported sats */ + uint8_t sats_0_1[3]; /* 6 reported sats 0 and 1 */ + uint8_t sats_2_3[3]; + uint8_t sats_4_5[3]; + uint8_t sats_6_7[3]; + uint8_t sats_8_9[3]; + uint8_t sats_10_11[3]; + /* 24 */ +}; + +#define AO_SAT_0_SSID(s) ((s)[0] & 0x3f) +#define AO_SAT_0_C_N_1(s) ((((s)[0] & 0xc0) >> 2) | ((s)[1] & 0x0f)) +#define AO_SAT_1_SSID(s) ((((s)[1] & 0xf0) >> 2) | ((s)[2] & 0x03)) +#define AO_SAT_1_C_N_1(s) (((s)[2] & 0xfc) >> 2) + struct ao_telemetry_orig { uint16_t serial; uint16_t flight; -- cgit v1.2.3 From cb239b7161feea8646425b1f5788c3c82ae24321 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Jun 2011 01:01:08 -0700 Subject: altos: ao_radio_recv needs byte count *including* rssi and status That's two more than the actual packet length. Signed-off-by: Keith Packard --- src/ao_monitor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao_monitor.c b/src/ao_monitor.c index 1d083c59..e5e9159f 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -190,9 +190,9 @@ ao_monitor(void) default: if (ao_monitoring > AO_MAX_TELEMETRY) ao_monitoring = AO_MAX_TELEMETRY; - if (!ao_radio_recv(&recv_raw, ao_monitoring)) + if (!ao_radio_recv(&recv_raw, ao_monitoring + 2)) continue; - printf ("TELEM %02x", ao_monitoring+2); + printf ("TELEM %02x", ao_monitoring + 2); sum = 0x5a; for (state = 0; state < ao_monitoring + 2; state++) { byte = recv_raw.packet[state]; -- cgit v1.2.3 From d3c26e534d8df34cfbf29b70cd1b2692493ce150 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jul 2011 18:03:51 -0700 Subject: altos: teledongle does not need ao_packet_slave.c TeleDongle doesn't provide slave interfaces, so remove ao_packet_slave from the TD build Signed-off-by: Keith Packard --- src/Makefile.proto | 10 ++++++---- src/ao_radio.c | 2 ++ 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index bc7b3a7f..5322df17 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -62,9 +62,7 @@ USB_DRIVER_SRC = \ ao_usb.c TELE_COMMON_SRC = \ - ao_packet.c \ - ao_packet_slave.c \ - ao_state.c + ao_packet.c # # Receiver code @@ -73,6 +71,7 @@ TELE_RECEIVER_SRC =\ ao_monitor.c \ ao_gps_print.c \ ao_packet_master.c \ + ao_state.c \ ao_rssi.c # @@ -107,6 +106,7 @@ TM_DRIVER_SRC = \ ao_adc.c \ ao_gps_report.c \ ao_ignite.c \ + ao_packet_slave.c \ $(BEEP_DRIVER_SRC) \ $(USB_DRIVER_SRC) @@ -160,7 +160,7 @@ TM_TASK_SRC = \ ao_log.c \ ao_log_big.c \ ao_report.c \ - ao_telemetry_orig.c + ao_telemetry.c TM_MAIN_SRC = \ ao_telemetrum.c @@ -185,6 +185,7 @@ TMINI_DRIVER_SRC = \ ao_ignite.c \ ao_config.c \ ao_storage.c \ + ao_packet_slave.c \ ao_intflash.c TMINI_TASK_SRC = \ @@ -214,6 +215,7 @@ TNANO_DRIVER_SRC = \ ao_adc.c \ ao_config.c \ ao_storage.c \ + ao_packet_slave.c \ ao_intflash.c TNANO_TASK_SRC = \ diff --git a/src/ao_radio.c b/src/ao_radio.c index 01974ba1..4c382bb9 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -433,7 +433,9 @@ ao_radio_test(void) mode++; if ((mode & 2) && !radio_on) { ao_set_monitor(0); +#if PACKET_HAS_SLAVE ao_packet_slave_stop(); +#endif ao_radio_get(0xff); RFST = RFST_STX; radio_on = 1; -- cgit v1.2.3 From 06b6f78e22be38a26bfe11ed4d4b659d5b13f00c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jul 2011 18:04:49 -0700 Subject: altos: Shrink const space in ao_config Eliminate separate 'cmd' and 'help' struct entries. Use \0 trick in cmd strings to eliminate whitespace. Edit help text. Signed-off-by: Keith Packard --- src/ao_config.c | 66 ++++++++++++++++++++++++++++----------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/ao_config.c b/src/ao_config.c index 319febb9..c7fc7dd2 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -208,7 +208,7 @@ ao_config_accel_calibrate_auto(char *orientation) __reentrant int32_t accel_total; uint8_t cal_adc_ring; - printf("Orient %s and press a key...", orientation); + printf("Orient antenna %s and press a key...", orientation); flush(); (void) getchar(); puts("\r\n"); flush(); @@ -235,8 +235,8 @@ ao_config_accel_calibrate_set(void) __reentrant if (ao_cmd_status != ao_cmd_success) return; if (ao_cmd_lex_i == 0) { - up = ao_config_accel_calibrate_auto("antenna up"); - down = ao_config_accel_calibrate_auto("antenna down"); + up = ao_config_accel_calibrate_auto("up"); + down = ao_config_accel_calibrate_auto("down"); } else { up = ao_cmd_lex_i; ao_cmd_decimal(); @@ -245,7 +245,7 @@ ao_config_accel_calibrate_set(void) __reentrant down = ao_cmd_lex_i; } if (up >= down) { - printf("Invalid accel calibration: antenna up (%d) should be less than antenna down (%d)\n", + printf("Invalid accel: up (%d) down (%d)\n", up, down); return; } @@ -336,10 +336,9 @@ ao_config_log_set(void) __reentrant #endif /* HAS_EEPROM */ struct ao_config_var { - char cmd; + const char *str; void (*set)(void) __reentrant; void (*show)(void) __reentrant; - const char *help; }; static void @@ -353,35 +352,34 @@ ao_config_write(void) __reentrant; __code struct ao_config_var ao_config_vars[] = { #if HAS_ADC - { 'm', ao_config_main_deploy_set, ao_config_main_deploy_show, - "m Set height above launch for main deploy (in meters)" }, - { 'd', ao_config_apogee_delay_set, ao_config_apogee_delay_show, - "d Set apogee igniter delay (in seconds)" }, + { "m \0Main deploy (in meters)", + ao_config_main_deploy_set, ao_config_main_deploy_show, }, + { "d \0Apogee delay (in seconds)", + ao_config_apogee_delay_set, ao_config_apogee_delay_show }, #endif /* HAS_ADC */ - { 'r', ao_config_radio_channel_set, ao_config_radio_channel_show, - "r Set radio channel (freq = 434.550 + channel * .1)" }, - { 'c', ao_config_callsign_set, ao_config_callsign_show, - "c Set callsign broadcast in each packet (8 char max)" }, + { "r \0Radio channel (freq = 434.550 + chan * .1)", + ao_config_radio_channel_set, ao_config_radio_channel_show }, + { "c \0Callsign (8 char max)", + ao_config_callsign_set, ao_config_callsign_show }, #if HAS_ACCEL - { 'a', ao_config_accel_calibrate_set, ao_config_accel_calibrate_show, - "a <+g> <-g> Set accelerometer calibration (0 for auto)" }, + { "a <+g> <-g>\0Accel calib (0 for auto)", + ao_config_accel_calibrate_set,ao_config_accel_calibrate_show }, #endif /* HAS_ACCEL */ - { 'f', ao_config_radio_cal_set, ao_config_radio_cal_show, - "f Set radio calibration value (cal = rf/(xtal/2^16))" }, + { "f \0Radio calib (cal = rf/(xtal/2^16))", + ao_config_radio_cal_set, ao_config_radio_cal_show }, #if HAS_EEPROM - { 'l', ao_config_log_set, ao_config_log_show, - "l Set flight log size in kB" }, + { "l \0Flight log size in kB", + ao_config_log_set, ao_config_log_show }, #endif - { 's', ao_config_show, ao_config_show, - "s Show current config values" }, + { "s\0Show", + ao_config_show, ao_config_show }, #if HAS_EEPROM - { 'w', ao_config_write, ao_config_write, - "w Write current values to eeprom" }, + { "w\0Write to eeprom", + ao_config_write, ao_config_write }, #endif - { '?', ao_config_help, ao_config_help, - "? Show available config variables" }, - { 0, ao_config_help, ao_config_help, - NULL }, + { "?\0Help", + ao_config_help, ao_config_help }, + { 0, 0, 0 } }; void @@ -395,8 +393,8 @@ ao_config_set(void) c = ao_cmd_lex_c; ao_cmd_lex(); func = 0; - for (cmd = 0; ao_config_vars[cmd].cmd != '\0'; cmd++) - if (ao_config_vars[cmd].cmd == c) { + for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) + if (ao_config_vars[cmd].str[0] == c) { func = ao_config_vars[cmd].set; break; } @@ -410,8 +408,10 @@ static void ao_config_help(void) __reentrant { uint8_t cmd; - for (cmd = 0; ao_config_vars[cmd].cmd != '\0'; cmd++) - puts (ao_config_vars[cmd].help); + for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) + printf("%-20s %s\n", + ao_config_vars[cmd].str, + ao_config_vars[cmd].str+1+strlen(ao_config_vars[cmd].str)); } static void @@ -420,7 +420,7 @@ ao_config_show(void) __reentrant uint8_t cmd; printf("Config version: %d.%d\n", ao_config.major, ao_config.minor); - for (cmd = 0; ao_config_vars[cmd].cmd != '\0'; cmd++) + for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) if (ao_config_vars[cmd].show != ao_config_vars[cmd].set) (*ao_config_vars[cmd].show)(); } -- cgit v1.2.3 From 9e5e4c1ad82d621ceb7286f72c87eeaf5976f9bf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jul 2011 18:06:48 -0700 Subject: altos: Add sat info to GPS report command Plan to use this to report current flight computer state in idle mode. Signed-off-by: Keith Packard --- src/ao_gps_skytraq.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index d286a30a..6099ca96 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -312,9 +312,8 @@ ao_nmea_gsv(void) ao_gps_skip_field(); /* azimuth */ c = ao_gps_decimal(2); /* C/N0 */ if (i < AO_MAX_GPS_TRACKING) { - if (!(ao_gps_tracking_next.sats[i].c_n_1 = c)) - ao_gps_tracking_next.sats[i].svid = 0; - ao_gps_tracking_next.channels = i + 1; + if ((ao_gps_tracking_next.sats[i].c_n_1 = c) != 0) + ao_gps_tracking_next.channels = i + 1; } } if (ao_gps_char == '*') { @@ -461,17 +460,24 @@ __xdata struct ao_task ao_gps_task; static void gps_dump(void) __reentrant { + uint8_t i; ao_mutex_get(&ao_gps_mutex); printf ("Date: %02d/%02d/%02d\n", ao_gps_data.year, ao_gps_data.month, ao_gps_data.day); printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second); printf ("Lat/Lon: %ld %ld\n", ao_gps_data.latitude, ao_gps_data.longitude); printf ("Alt: %d\n", ao_gps_data.altitude); printf ("Flags: 0x%x\n", ao_gps_data.flags); + printf ("Sats: %d", ao_gps_tracking_data.channels); + for (i = 0; i < ao_gps_tracking_data.channels; i++) + printf (" %d %d", + ao_gps_tracking_data.sats[i].svid, + ao_gps_tracking_data.sats[i].c_n_1); + printf ("\ndone\n"); ao_mutex_put(&ao_gps_mutex); } __code struct ao_cmds ao_gps_cmds[] = { - { gps_dump, "g\0Display current GPS values" }, + { gps_dump, "g\0Display GPS" }, { 0, NULL }, }; -- cgit v1.2.3 From b51e5466f7a125db873edd1fa9bd3881d7e98aad Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jul 2011 18:08:19 -0700 Subject: altos: Shrink help text Reduce const space taken by command help text. Signed-off-by: Keith Packard --- src/ao_adc.c | 2 +- src/ao_cmd.c | 12 +++++------- src/ao_dbg.c | 12 ++++++------ src/ao_ignite.c | 2 +- src/ao_log.c | 4 ++-- src/ao_storage.c | 8 ++++---- 6 files changed, 19 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/ao_adc.c b/src/ao_adc.c index 48568383..cbeb6a24 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -162,7 +162,7 @@ ao_adc_dump(void) __reentrant } __code struct ao_cmds ao_adc_cmds[] = { - { ao_adc_dump, "a\0Display current ADC values" }, + { ao_adc_dump, "a\0Current ADC" }, { 0, NULL }, }; diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 23346c3d..3f020dc3 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -221,8 +221,6 @@ version(void) printf("software-version %s\n", ao_version); } -static const char help_txt[] = "All numbers are in hex"; - #define NUM_CMDS 11 static __code struct ao_cmds *__xdata (ao_cmds[NUM_CMDS]); @@ -234,7 +232,7 @@ help(void) __xdata uint8_t cmds; __xdata uint8_t cmd; __code struct ao_cmds * __xdata cs; - puts(help_txt); + for (cmds = 0; cmds < ao_ncmds; cmds++) { cs = ao_cmds[cmds]; for (cmd = 0; cs[cmd].func; cmd++) @@ -302,11 +300,11 @@ ao_cmd(void) __xdata struct ao_task ao_cmd_task; __code struct ao_cmds ao_base_cmds[] = { - { help, "?\0Print this message" }, - { ao_task_info, "T\0Show task states" }, - { echo, "E <0 off, 1 on>\0Set command echo mode" }, + { help, "?\0Help" }, + { ao_task_info, "T\0Show tasks" }, + { echo, "E <0 off, 1 on>\0Set echo mode" }, { ao_reboot, "r eboot\0Reboot" }, - { version, "v\0Show version" }, + { version, "v\0Version" }, { 0, NULL }, }; diff --git a/src/ao_dbg.c b/src/ao_dbg.c index 49371560..14a123a2 100644 --- a/src/ao_dbg.c +++ b/src/ao_dbg.c @@ -348,12 +348,12 @@ debug_output(void) } __code struct ao_cmds ao_dbg_cmds[7] = { - { debug_enable, "D\0Enable debug mode" }, - { debug_get, "G \0Get data from debug port" }, - { debug_input, "I \0Input bytes to target at " }, - { debug_output, "O \0Output bytes to target at " }, - { debug_put, "P ...\0Put data to debug port" }, - { debug_reset, "R\0Reset target" }, + { debug_enable, "D\0Enable debug" }, + { debug_get, "G \0Get data" }, + { debug_input, "I \0Input at " }, + { debug_output, "O \0Output at " }, + { debug_put, "P ...\0Put data" }, + { debug_reset, "R\0Reset" }, { 0, NULL }, }; diff --git a/src/ao_ignite.c b/src/ao_ignite.c index 7874ee01..8ef83da8 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -165,7 +165,7 @@ ao_ignite_test(void) __code struct ao_cmds ao_ignite_cmds[] = { { ao_ignite_manual, "i {main|drogue}\0Fire igniter. is doit with D&I" }, - { ao_ignite_test, "t\0Test igniter continuity" }, + { ao_ignite_test, "t\0Test igniter" }, { 0, NULL }, }; diff --git a/src/ao_log.c b/src/ao_log.c index 433e9c3a..71900490 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -262,8 +262,8 @@ ao_log_delete(void) __reentrant } __code struct ao_cmds ao_log_cmds[] = { - { ao_log_list, "l\0List stored flight logs" }, - { ao_log_delete, "d \0Delete stored flight" }, + { ao_log_list, "l\0List flight logs" }, + { ao_log_delete, "d \0Delete flight" }, { 0, NULL }, }; diff --git a/src/ao_storage.c b/src/ao_storage.c index 69183514..6ffca0e5 100644 --- a/src/ao_storage.c +++ b/src/ao_storage.c @@ -166,13 +166,13 @@ ao_storage_info(void) __reentrant } __code struct ao_cmds ao_storage_cmds[] = { - { ao_storage_info, "f\0Show storage info" }, - { ao_storage_dump, "e \0Dump a block of flash data" }, + { ao_storage_info, "f\0Show storage" }, + { ao_storage_dump, "e \0Dump flash" }, #ifdef HAS_STORAGE_DBG { ao_storage_store, "w ...\0Write data to flash" }, #endif - { ao_storage_zap, "z \0Erase flash containing " }, - { ao_storage_zapall,"Z \0Erase all logs. is doit with D&I" }, + { ao_storage_zap, "z \0Erase " }, + { ao_storage_zapall,"Z \0Erase all. is doit with D&I" }, { 0, NULL }, }; -- cgit v1.2.3 From 359681f23e2f71bc8f4975a4a76ae28c08ecab2e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jul 2011 18:09:03 -0700 Subject: altos: Add split telemetry code This sends every packet every time, which isn't correct, but should be useful for testing. Signed-off-by: Keith Packard --- src/ao.h | 98 +++++++++++++++++++++++------------ src/ao_product.c | 2 +- src/ao_telemetrum.c | 2 +- src/ao_telemetry.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 214 insertions(+), 34 deletions(-) create mode 100644 src/ao_telemetry.c (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 4895f016..4d31f4f5 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1040,14 +1040,15 @@ ao_gps_report_init(void); */ #define AO_MAX_CALLSIGN 8 +#define AO_MAX_VERSION 8 #define AO_MAX_TELEMETRY 128 struct ao_telemetry_generic { uint16_t serial; /* 0 */ uint16_t tick; /* 2 */ uint8_t type; /* 4 */ - uint8_t payload[19]; /* 5 */ - /* 24 */ + uint8_t payload[27]; /* 5 */ + /* 32 */ }; #define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 @@ -1070,31 +1071,46 @@ struct ao_telemetry_sensor { int16_t acceleration; /* 18 m/s² * 16 */ int16_t speed; /* 20 m/s * 16 */ int16_t height; /* 22 m */ - /* 24 */ -}; -#define AO_TELEMETRY_CONSTANT 0x10 + int16_t ground_pres; /* 24 average pres on pad */ + int16_t ground_accel; /* 26 average accel on pad */ + int16_t accel_plus_g; /* 28 accel calibration at +1g */ + int16_t accel_minus_g; /* 30 accel calibration at -1g */ + /* 32 */ +}; -struct ao_telemetry_constant { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t device; /* 5 device type */ - uint16_t flight; /* 6 flight number */ - int16_t ground_accel; /* 8 average ground accelerometer (TM only) */ - int16_t ground_pres; /* 10 average ground barometer */ - int16_t accel_plus_g; /* 12 +1g accelerometer calibration value (TM only) */ - int16_t accel_minus_g; /* 14 -1g accelermeter calibration value (TM only) */ - char callsign[AO_MAX_CALLSIGN]; /* 16 identity */ - /* 24 */ +#define AO_TELEMETRY_CONFIGURATION 0x04 + +struct ao_telemetry_configuration { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t device; /* 5 device type */ + uint16_t flight; /* 6 flight number */ + uint8_t config_major; /* 8 Config major version */ + uint8_t config_minor; /* 9 Config minor version */ + uint16_t main_deploy; /* 10 Main deploy alt in meters */ + uint32_t flight_log_max; /* 12 Maximum flight log size in bytes */ + char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ + char version[AO_MAX_VERSION]; /* 24 Software version */ + /* 32 */ }; -#define AO_TELEMETRY_LOCATION 0x11 +#define AO_TELEMETRY_LOCATION 0x05 + +#define AO_GPS_MODE_NOT_VALID 'N' +#define AO_GPS_MODE_AUTONOMOUS 'A' +#define AO_GPS_MODE_DIFFERENTIAL 'D' +#define AO_GPS_MODE_ESTIMATED 'E' +#define AO_GPS_MODE_MANUAL 'M' +#define AO_GPS_MODE_SIMULATED 'S' struct ao_telemetry_location { uint16_t serial; /* 0 */ uint16_t tick; /* 2 */ uint8_t type; /* 4 */ + uint8_t flags; /* 5 Number of sats and other flags */ int16_t altitude; /* 6 GPS reported altitude (m) */ int32_t latitude; /* 8 latitude (degrees * 10⁷) */ @@ -1105,25 +1121,40 @@ struct ao_telemetry_location { uint8_t hour; /* 19 (0-23) */ uint8_t minute; /* 20 (0-59) */ uint8_t second; /* 21 (0-59) */ - uint8_t hdop; /* 22 (m * 5) */ - uint8_t unused; /* 23 */ - /* 24 */ + uint8_t pdop; /* 22 (m * 5) */ + uint8_t hdop; /* 23 (m * 5) */ + uint8_t vdop; /* 24 (m * 5) */ + uint8_t mode; /* 25 */ + uint16_t ground_speed; /* 26 cm/s */ + uint8_t course; /* 28 degrees / 2 */ + uint8_t unused[3]; /* 29 */ + /* 32 */ }; #define AO_TELEMETRY_SATELLITE 0x12 +struct ao_telemetry_satellite_info { + uint8_t svid; + uint8_t c_n_1; +}; + struct ao_telemetry_satellite { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t channels; /* 5 number of reported sats */ - uint8_t sats_0_1[3]; /* 6 reported sats 0 and 1 */ - uint8_t sats_2_3[3]; - uint8_t sats_4_5[3]; - uint8_t sats_6_7[3]; - uint8_t sats_8_9[3]; - uint8_t sats_10_11[3]; - /* 24 */ + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t channels; /* 5 number of reported sats */ + + struct ao_telemetry_satellite_info sats[12]; /* 6 */ + uint8_t unused[2]; /* 30 */ + /* 32 */ +}; + +union ao_telemetry_all { + struct ao_telemetry_generic generic; + struct ao_telemetry_sensor sensor; + struct ao_telemetry_configuration configuration; + struct ao_telemetry_location location; + struct ao_telemetry_satellite satellite; }; #define AO_SAT_0_SSID(s) ((s)[0] & 0x3f) @@ -1198,6 +1229,9 @@ ao_telemetry_set_interval(uint16_t interval); void ao_rdf_set(uint8_t rdf); +void +ao_telemetry_init(void); + void ao_telemetry_orig_init(void); diff --git a/src/ao_product.c b/src/ao_product.c index 54ba2a14..bb42e92c 100644 --- a/src/ao_product.c +++ b/src/ao_product.c @@ -20,7 +20,7 @@ /* Defines which mark this particular AltOS product */ -const char ao_version[] = AO_iVersion_STRING; +const char ao_version[AO_MAX_VERSION] = AO_iVersion_STRING; const char ao_manufacturer[] = AO_iManufacturer_STRING; const char ao_product[] = AO_iProduct_STRING; diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index bede5868..4ace415c 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -57,7 +57,7 @@ main(void) ao_serial_init(); ao_gps_init(); ao_gps_report_init(); - ao_telemetry_orig_init(); + ao_telemetry_init(); ao_radio_init(); ao_packet_slave_init(TRUE); ao_igniter_init(); diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c new file mode 100644 index 00000000..024ac6f8 --- /dev/null +++ b/src/ao_telemetry.c @@ -0,0 +1,146 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_product.h" + +__xdata uint16_t ao_telemetry_interval = 0; +__xdata uint8_t ao_rdf = 0; +__xdata uint16_t ao_rdf_time; + +#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) +#define AO_RDF_LENGTH_MS 500 + +#if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) +#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMETRUM +#endif + +#if defined(TELEMINI_V_0_1) +#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMINI +#endif + +#if defined(TELENANO_V_0_1) +#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELENANO +#endif + +void +ao_telemetry(void) +{ + uint16_t time; + int16_t delay; + static __xdata union ao_telemetry_all telemetry; + uint8_t sample; + + ao_config_get(); + while (!ao_flight_number) + ao_sleep(&ao_flight_number); + + telemetry.generic.serial = ao_serial_number; + for (;;) { + while (ao_telemetry_interval == 0) + ao_sleep(&ao_telemetry_interval); + time = ao_rdf_time = ao_time(); + while (ao_telemetry_interval) { + + /* Send sensor packet */ + sample = ao_sample_adc; + + telemetry.generic.tick = ao_adc_ring[sample].tick; + telemetry.generic.type = AO_TELEMETRY_SENSOR; + + telemetry.sensor.state = ao_flight_state; +#if HAS_ACCEL + telemetry.sensor.accel = ao_adc_ring[sample].accel; +#else + telemetry.sensor.accel = 0; +#endif + telemetry.sensor.pres = ao_adc_ring[sample].pres; + telemetry.sensor.temp = ao_adc_ring[sample].temp; + telemetry.sensor.v_batt = ao_adc_ring[sample].v_batt; +#if HAS_IGNITE + telemetry.sensor.sense_d = ao_adc_ring[sample].sense_d; + telemetry.sensor.sense_m = ao_adc_ring[sample].sense_m; +#else + telemetry.sensor.sense_d = 0; + telemetry.sensor.sense_m = 0; +#endif + + telemetry.sensor.acceleration = ao_accel; + telemetry.sensor.speed = ao_speed; + telemetry.sensor.height = ao_height; + + telemetry.sensor.ground_pres = ao_ground_pres; + telemetry.sensor.ground_accel = ao_ground_accel; + telemetry.sensor.accel_plus_g = ao_config.accel_plus_g; + telemetry.sensor.accel_minus_g = ao_config.accel_minus_g; + + ao_radio_send(&telemetry, sizeof (telemetry)); + + telemetry.generic.type = AO_TELEMETRY_CONFIGURATION; + telemetry.configuration.device = AO_idProduct_NUMBER; + telemetry.configuration.flight = ao_flight_number; + telemetry.configuration.config_major = AO_CONFIG_MAJOR; + telemetry.configuration.config_minor = AO_CONFIG_MINOR; + telemetry.configuration.main_deploy = ao_config.main_deploy; + telemetry.configuration.flight_log_max = ao_config.flight_log_max; + memcpy (telemetry.configuration.callsign, + ao_config.callsign, + AO_MAX_CALLSIGN); + memcpy (telemetry.configuration.version, + ao_version, + AO_MAX_VERSION); + + if (ao_rdf && + (int16_t) (ao_time() - ao_rdf_time) >= 0) + { + ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; + ao_radio_rdf(AO_RDF_LENGTH_MS); + } + time += ao_telemetry_interval; + delay = time - ao_time(); + if (delay > 0) + ao_delay(delay); + else + time = ao_time(); + } + } +} + +void +ao_telemetry_set_interval(uint16_t interval) +{ + ao_telemetry_interval = interval; + ao_wakeup(&ao_telemetry_interval); +} + +void +ao_rdf_set(uint8_t rdf) +{ + ao_rdf = rdf; + if (rdf == 0) + ao_radio_rdf_abort(); + else + ao_rdf_time = ao_time(); +} + +__xdata struct ao_task ao_telemetry_task; + +void +ao_telemetry_init() +{ + ao_add_task(&ao_telemetry_task, ao_telemetry, "telemetry"); +} -- cgit v1.2.3 From ef3ce687d73c1274ce5368432f4d449b063ce5c0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jul 2011 23:39:21 -0700 Subject: altos: Complete new telemetry switchover This involved rewriting the GPS code to use the telemetry structures directly so that a memcpy could be used to transfer the data to the telemetry packets, saving a bunch of code space, along with fixing up the gps testing programs to deal with the structure changes. In addition, the teledongle code needed to have the monitoring code split into separate radio receiver and USB writer threads as the packets are now back-to-back, and hence come too fast to wait for the USB data to be sent to the host after each one. Signed-off-by: Keith Packard --- src/ao.h | 162 ++++++++++++++++++++++--------------------- src/ao_gps_print.c | 6 +- src/ao_gps_report.c | 12 ++-- src/ao_gps_sirf.c | 6 +- src/ao_gps_skytraq.c | 10 +-- src/ao_gps_test.c | 12 ++-- src/ao_gps_test_skytraq.c | 13 ++-- src/ao_monitor.c | 81 +++++++++++++++------- src/ao_telemetry.c | 170 +++++++++++++++++++++++++++++++++------------- 9 files changed, 292 insertions(+), 180 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 4d31f4f5..08f45275 100644 --- a/src/ao.h +++ b/src/ao.h @@ -965,80 +965,8 @@ void ao_spi_init(void); /* - * ao_gps.c + * ao_telemetry.c */ - -#define AO_GPS_NUM_SAT_MASK (0xf << 0) -#define AO_GPS_NUM_SAT_SHIFT (0) - -#define AO_GPS_VALID (1 << 4) -#define AO_GPS_RUNNING (1 << 5) -#define AO_GPS_DATE_VALID (1 << 6) -#define AO_GPS_COURSE_VALID (1 << 7) - -extern __xdata uint16_t ao_gps_tick; - -struct ao_gps_data { - uint8_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint8_t second; - uint8_t flags; - int32_t latitude; /* degrees * 10⁷ */ - int32_t longitude; /* degrees * 10⁷ */ - int16_t altitude; /* m */ - uint16_t ground_speed; /* cm/s */ - uint8_t course; /* degrees / 2 */ - uint8_t hdop; /* * 5 */ - int16_t climb_rate; /* cm/s */ - uint16_t h_error; /* m */ - uint16_t v_error; /* m */ -}; - -struct ao_gps_sat_data { - uint8_t svid; - uint8_t c_n_1; -}; - -#define AO_MAX_GPS_TRACKING 12 - -struct ao_gps_tracking_data { - uint8_t channels; - struct ao_gps_sat_data sats[AO_MAX_GPS_TRACKING]; -}; - -extern __xdata uint8_t ao_gps_mutex; -extern __xdata struct ao_gps_data ao_gps_data; -extern __xdata struct ao_gps_tracking_data ao_gps_tracking_data; - -void -ao_gps(void); - -void -ao_gps_print(__xdata struct ao_gps_data *gps_data); - -void -ao_gps_tracking_print(__xdata struct ao_gps_tracking_data *gps_tracking_data); - -void -ao_gps_init(void); - -/* - * ao_gps_report.c - */ - -void -ao_gps_report(void); - -void -ao_gps_report_init(void); - -/* - * ao_telemetry_orig.c - */ - #define AO_MAX_CALLSIGN 8 #define AO_MAX_VERSION 8 #define AO_MAX_TELEMETRY 128 @@ -1126,12 +1054,13 @@ struct ao_telemetry_location { uint8_t vdop; /* 24 (m * 5) */ uint8_t mode; /* 25 */ uint16_t ground_speed; /* 26 cm/s */ - uint8_t course; /* 28 degrees / 2 */ - uint8_t unused[3]; /* 29 */ + int16_t climb_rate; /* 28 cm/s */ + uint8_t course; /* 30 degrees / 2 */ + uint8_t unused[1]; /* 31 */ /* 32 */ }; -#define AO_TELEMETRY_SATELLITE 0x12 +#define AO_TELEMETRY_SATELLITE 0x06 struct ao_telemetry_satellite_info { uint8_t svid; @@ -1157,10 +1086,79 @@ union ao_telemetry_all { struct ao_telemetry_satellite satellite; }; -#define AO_SAT_0_SSID(s) ((s)[0] & 0x3f) -#define AO_SAT_0_C_N_1(s) ((((s)[0] & 0xc0) >> 2) | ((s)[1] & 0x0f)) -#define AO_SAT_1_SSID(s) ((((s)[1] & 0xf0) >> 2) | ((s)[2] & 0x03)) -#define AO_SAT_1_C_N_1(s) (((s)[2] & 0xfc) >> 2) +/* + * ao_gps.c + */ + +#define AO_GPS_NUM_SAT_MASK (0xf << 0) +#define AO_GPS_NUM_SAT_SHIFT (0) + +#define AO_GPS_VALID (1 << 4) +#define AO_GPS_RUNNING (1 << 5) +#define AO_GPS_DATE_VALID (1 << 6) +#define AO_GPS_COURSE_VALID (1 << 7) + +extern __xdata uint16_t ao_gps_tick; +extern __xdata uint8_t ao_gps_mutex; +extern __xdata struct ao_telemetry_location ao_gps_data; +extern __xdata struct ao_telemetry_satellite ao_gps_tracking_data; + +struct ao_gps_orig { + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t flags; + int32_t latitude; /* degrees * 10⁷ */ + int32_t longitude; /* degrees * 10⁷ */ + int16_t altitude; /* m */ + uint16_t ground_speed; /* cm/s */ + uint8_t course; /* degrees / 2 */ + uint8_t hdop; /* * 5 */ + int16_t climb_rate; /* cm/s */ + uint16_t h_error; /* m */ + uint16_t v_error; /* m */ +}; + +struct ao_gps_sat_orig { + uint8_t svid; + uint8_t c_n_1; +}; + +#define AO_MAX_GPS_TRACKING 12 + +struct ao_gps_tracking_orig { + uint8_t channels; + struct ao_gps_sat_orig sats[AO_MAX_GPS_TRACKING]; +}; + +void +ao_gps(void); + +void +ao_gps_print(__xdata struct ao_gps_orig *gps_data); + +void +ao_gps_tracking_print(__xdata struct ao_gps_tracking_orig *gps_tracking_data); + +void +ao_gps_init(void); + +/* + * ao_gps_report.c + */ + +void +ao_gps_report(void); + +void +ao_gps_report_init(void); + +/* + * ao_telemetry_orig.c + */ struct ao_telemetry_orig { uint16_t serial; @@ -1180,9 +1178,9 @@ struct ao_telemetry_orig { int16_t accel_plus_g; int16_t accel_minus_g; struct ao_adc adc; - struct ao_gps_data gps; + struct ao_gps_orig gps; char callsign[AO_MAX_CALLSIGN]; - struct ao_gps_tracking_data gps_tracking; + struct ao_gps_tracking_orig gps_tracking; }; struct ao_telemetry_tiny { diff --git a/src/ao_gps_print.c b/src/ao_gps_print.c index ca071b42..fcdedd30 100644 --- a/src/ao_gps_print.c +++ b/src/ao_gps_print.c @@ -21,7 +21,7 @@ #include "ao_telem.h" void -ao_gps_print(__xdata struct ao_gps_data *gps_data) __reentrant +ao_gps_print(__xdata struct ao_gps_orig *gps_data) __reentrant { char state; @@ -77,10 +77,10 @@ ao_gps_print(__xdata struct ao_gps_data *gps_data) __reentrant } void -ao_gps_tracking_print(__xdata struct ao_gps_tracking_data *gps_tracking_data) __reentrant +ao_gps_tracking_print(__xdata struct ao_gps_tracking_orig *gps_tracking_data) __reentrant { uint8_t c, n, v; - __xdata struct ao_gps_sat_data *sat; + __xdata struct ao_gps_sat_orig *sat; n = gps_tracking_data->channels; if (n == 0) diff --git a/src/ao_gps_report.c b/src/ao_gps_report.c index 7abc93f5..e57f8744 100644 --- a/src/ao_gps_report.c +++ b/src/ao_gps_report.c @@ -20,14 +20,14 @@ void ao_gps_report(void) { - static __xdata struct ao_log_record gps_log; - static __xdata struct ao_gps_data gps_data; + static __xdata struct ao_log_record gps_log; + static __xdata struct ao_telemetry_location gps_data; uint8_t date_reported = 0; for (;;) { ao_sleep(&ao_gps_data); ao_mutex_get(&ao_gps_mutex); - memcpy(&gps_data, &ao_gps_data, sizeof (struct ao_gps_data)); + memcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); ao_mutex_put(&ao_gps_mutex); if (!(gps_data.flags & AO_GPS_VALID)) @@ -64,15 +64,15 @@ ao_gps_report(void) void ao_gps_tracking_report(void) { - static __xdata struct ao_log_record gps_log; - static __xdata struct ao_gps_tracking_data gps_tracking_data; + static __xdata struct ao_log_record gps_log; + static __xdata struct ao_telemetry_satellite gps_tracking_data; uint8_t c, n; for (;;) { ao_sleep(&ao_gps_tracking_data); ao_mutex_get(&ao_gps_mutex); gps_log.tick = ao_gps_tick; - memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data)); + memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); ao_mutex_put(&ao_gps_mutex); if (!(n = gps_tracking_data.channels)) diff --git a/src/ao_gps_sirf.c b/src/ao_gps_sirf.c index 87b1d69c..5827c687 100644 --- a/src/ao_gps_sirf.c +++ b/src/ao_gps_sirf.c @@ -21,8 +21,8 @@ __xdata uint8_t ao_gps_mutex; __xdata uint16_t ao_gps_tick; -__xdata struct ao_gps_data ao_gps_data; -__xdata struct ao_gps_tracking_data ao_gps_tracking_data; +__xdata struct ao_telemetry_location ao_gps_data; +__xdata struct ao_telemetry_satellite ao_gps_tracking_data; static const char ao_gps_set_nmea[] = "\r\n$PSRF100,0,57600,8,1,0*37\r\n"; @@ -406,6 +406,7 @@ ao_gps(void) __reentrant ao_gps_data.hdop = ao_sirf_data.hdop; ao_gps_data.climb_rate = ao_sirf_data.climb_rate; ao_gps_data.flags |= AO_GPS_COURSE_VALID; +#if 0 if (ao_sirf_data.h_error > 6553500) ao_gps_data.h_error = 65535; else @@ -414,6 +415,7 @@ ao_gps(void) __reentrant ao_gps_data.v_error = 65535; else ao_gps_data.v_error = ao_sirf_data.v_error / 100; +#endif ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_data); break; diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index 6099ca96..84743ff5 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -29,13 +29,13 @@ static __xdata uint8_t ao_gps_cksum; static __xdata uint8_t ao_gps_error; __xdata uint16_t ao_gps_tick; -__xdata struct ao_gps_data ao_gps_data; -__xdata struct ao_gps_tracking_data ao_gps_tracking_data; +__xdata struct ao_telemetry_location ao_gps_data; +__xdata struct ao_telemetry_satellite ao_gps_tracking_data; static __xdata uint16_t ao_gps_next_tick; -static __xdata struct ao_gps_data ao_gps_next; +static __xdata struct ao_telemetry_location ao_gps_next; static __xdata uint8_t ao_gps_date_flags; -static __xdata struct ao_gps_tracking_data ao_gps_tracking_next; +static __xdata struct ao_telemetry_satellite ao_gps_tracking_next; #define STQ_S 0xa0, 0xa1 #define STQ_E 0x0d, 0x0a @@ -265,7 +265,7 @@ ao_nmea_gga() if (!ao_gps_error) { ao_mutex_get(&ao_gps_mutex); ao_gps_tick = ao_gps_next_tick; - memcpy(&ao_gps_data, &ao_gps_next, sizeof (struct ao_gps_data)); + memcpy(&ao_gps_data, &ao_gps_next, sizeof (ao_gps_data)); ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_data); } diff --git a/src/ao_gps_test.c b/src/ao_gps_test.c index 44efb50c..93d7a9ab 100644 --- a/src/ao_gps_test.c +++ b/src/ao_gps_test.c @@ -30,7 +30,7 @@ #define AO_GPS_DATE_VALID (1 << 6) #define AO_GPS_COURSE_VALID (1 << 7) -struct ao_gps_data { +struct ao_gps_orig { uint8_t year; uint8_t month; uint8_t day; @@ -58,18 +58,22 @@ struct ao_gps_data { #define SIRF_SAT_ACQUISITION_FAILED (1 << 6) #define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) -struct ao_gps_sat_data { +struct ao_gps_sat_orig { uint8_t svid; uint8_t c_n_1; }; #define AO_MAX_GPS_TRACKING 12 -struct ao_gps_tracking_data { +struct ao_gps_tracking_orig { uint8_t channels; - struct ao_gps_sat_data sats[AO_MAX_GPS_TRACKING]; + struct ao_gps_sat_orig sats[AO_MAX_GPS_TRACKING]; }; +#define ao_telemetry_location ao_gps_orig +#define ao_telemetry_satellite ao_gps_tracking_orig +#define ao_telemetry_satellite_info ao_gps_sat_orig + void ao_mutex_get(uint8_t *mutex) { diff --git a/src/ao_gps_test_skytraq.c b/src/ao_gps_test_skytraq.c index b94e9bd2..a78fae0f 100644 --- a/src/ao_gps_test_skytraq.c +++ b/src/ao_gps_test_skytraq.c @@ -30,7 +30,7 @@ #define AO_GPS_DATE_VALID (1 << 6) #define AO_GPS_COURSE_VALID (1 << 7) -struct ao_gps_data { +struct ao_gps_orig { uint8_t year; uint8_t month; uint8_t day; @@ -58,19 +58,22 @@ struct ao_gps_data { #define SIRF_SAT_ACQUISITION_FAILED (1 << 6) #define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) -struct ao_gps_sat_data { +struct ao_gps_sat_orig { uint8_t svid; - uint8_t state; uint8_t c_n_1; }; #define AO_MAX_GPS_TRACKING 12 -struct ao_gps_tracking_data { +struct ao_gps_tracking_orig { uint8_t channels; - struct ao_gps_sat_data sats[AO_MAX_GPS_TRACKING]; + struct ao_gps_sat_orig sats[AO_MAX_GPS_TRACKING]; }; +#define ao_telemetry_location ao_gps_orig +#define ao_telemetry_satellite ao_gps_tracking_orig +#define ao_telemetry_satellite_info ao_gps_sat_orig + void ao_mutex_get(uint8_t *mutex) { diff --git a/src/ao_monitor.c b/src/ao_monitor.c index e5e9159f..8f1b9e12 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -21,32 +21,71 @@ __xdata uint8_t ao_monitoring; __pdata uint8_t ao_monitor_led; -void -ao_monitor(void) -{ - __xdata char callsign[AO_MAX_CALLSIGN+1]; - __xdata union { +#define AO_MONITOR_RING 8 + +__xdata union ao_monitor { struct ao_telemetry_raw_recv raw; struct ao_telemetry_orig_recv orig; struct ao_telemetry_tiny_recv tiny; - } u; +} ao_monitor_ring[AO_MONITOR_RING]; + +#define ao_monitor_ring_next(n) (((n) + 1) & (AO_MONITOR_RING - 1)) -#define recv_raw (u.raw) -#define recv_orig (u.orig) -#define recv_tiny (u.tiny) +__data uint8_t ao_monitor_head; +void +ao_monitor_get(void) +{ + uint8_t size; + + for (;;) { + switch (ao_monitoring) { + case 0: + ao_sleep(&ao_monitoring); + continue; + case AO_MONITORING_ORIG: + size = sizeof (struct ao_telemetry_orig_recv); + break; + case AO_MONITORING_TINY: + size = sizeof (struct ao_telemetry_tiny_recv); + break; + default: + if (ao_monitoring > AO_MAX_TELEMETRY) + ao_monitoring = AO_MAX_TELEMETRY; + size = ao_monitoring; + break; + } + if (!ao_radio_recv(&ao_monitor_ring[ao_monitor_head], size + 2)) + continue; + ao_monitor_head = ao_monitor_ring_next(ao_monitor_head); + ao_wakeup(DATA_TO_XDATA(&ao_monitor_head)); + ao_led_toggle(ao_monitor_led); + } +} + +void +ao_monitor_put(void) +{ + __xdata char callsign[AO_MAX_CALLSIGN+1]; + + uint8_t ao_monitor_tail; uint8_t state; uint8_t sum, byte; int16_t rssi; + __xdata union ao_monitor *m; + +#define recv_raw ((m->raw)) +#define recv_orig ((m->orig)) +#define recv_tiny ((m->tiny)) + ao_monitor_tail = ao_monitor_head; for (;;) { - __critical while (!ao_monitoring) - ao_sleep(&ao_monitoring); + while (ao_monitor_tail == ao_monitor_head) + ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); + m = &ao_monitor_ring[ao_monitor_tail]; + ao_monitor_tail = ao_monitor_ring_next(ao_monitor_tail); switch (ao_monitoring) { case AO_MONITORING_ORIG: - if (!ao_radio_recv(&recv_orig, sizeof (struct ao_telemetry_orig_recv))) - continue; - state = recv_orig.telemetry_orig.flight_state; /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ @@ -122,9 +161,6 @@ ao_monitor(void) } break; case AO_MONITORING_TINY: - if (!ao_radio_recv(&recv_tiny, sizeof (struct ao_telemetry_tiny_recv))) - continue; - state = recv_tiny.telemetry_tiny.flight_state; /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ @@ -188,10 +224,6 @@ ao_monitor(void) } break; default: - if (ao_monitoring > AO_MAX_TELEMETRY) - ao_monitoring = AO_MAX_TELEMETRY; - if (!ao_radio_recv(&recv_raw, ao_monitoring + 2)) - continue; printf ("TELEM %02x", ao_monitoring + 2); sum = 0x5a; for (state = 0; state < ao_monitoring + 2; state++) { @@ -203,11 +235,11 @@ ao_monitor(void) break; } ao_usb_flush(); - ao_led_toggle(ao_monitor_led); } } -__xdata struct ao_task ao_monitor_task; +__xdata struct ao_task ao_monitor_get_task; +__xdata struct ao_task ao_monitor_put_task; void ao_set_monitor(uint8_t monitoring) @@ -236,5 +268,6 @@ ao_monitor_init(uint8_t monitor_led, uint8_t monitoring) __reentrant ao_monitor_led = monitor_led; ao_monitoring = monitoring; ao_cmd_register(&ao_monitor_cmds[0]); - ao_add_task(&ao_monitor_task, ao_monitor, "monitor"); + ao_add_task(&ao_monitor_get_task, ao_monitor_get, "monitor_get"); + ao_add_task(&ao_monitor_put_task, ao_monitor_put, "monitor_put"); } diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 024ac6f8..94ea0b22 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -18,7 +18,13 @@ #include "ao.h" #include "ao_product.h" -__xdata uint16_t ao_telemetry_interval = 0; +__xdata uint16_t ao_telemetry_interval; +__xdata int8_t ao_telemetry_config_max; +__xdata int8_t ao_telemetry_config_cur; +#if HAS_GPS +__xdata int8_t ao_telemetry_loc_cur; +__xdata int8_t ao_telemetry_sat_cur; +#endif __xdata uint8_t ao_rdf = 0; __xdata uint16_t ao_rdf_time; @@ -37,13 +43,110 @@ __xdata uint16_t ao_rdf_time; #define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELENANO #endif +static __xdata union ao_telemetry_all telemetry; + +/* Send sensor packet */ +static void +ao_send_sensor(void) +{ + uint8_t sample; + sample = ao_sample_adc; + + telemetry.generic.tick = ao_adc_ring[sample].tick; + telemetry.generic.type = AO_TELEMETRY_SENSOR; + + telemetry.sensor.state = ao_flight_state; +#if HAS_ACCEL + telemetry.sensor.accel = ao_adc_ring[sample].accel; +#else + telemetry.sensor.accel = 0; +#endif + telemetry.sensor.pres = ao_adc_ring[sample].pres; + telemetry.sensor.temp = ao_adc_ring[sample].temp; + telemetry.sensor.v_batt = ao_adc_ring[sample].v_batt; +#if HAS_IGNITE + telemetry.sensor.sense_d = ao_adc_ring[sample].sense_d; + telemetry.sensor.sense_m = ao_adc_ring[sample].sense_m; +#else + telemetry.sensor.sense_d = 0; + telemetry.sensor.sense_m = 0; +#endif + + telemetry.sensor.acceleration = ao_accel; + telemetry.sensor.speed = ao_speed; + telemetry.sensor.height = ao_height; + + telemetry.sensor.ground_pres = ao_ground_pres; + telemetry.sensor.ground_accel = ao_ground_accel; + telemetry.sensor.accel_plus_g = ao_config.accel_plus_g; + telemetry.sensor.accel_minus_g = ao_config.accel_minus_g; + + ao_radio_send(&telemetry, sizeof (telemetry)); +} + +static void +ao_send_configuration(void) +{ + if (--ao_telemetry_config_cur <= 0) + { + telemetry.generic.type = AO_TELEMETRY_CONFIGURATION; + telemetry.configuration.device = AO_idProduct_NUMBER; + telemetry.configuration.flight = ao_flight_number; + telemetry.configuration.config_major = AO_CONFIG_MAJOR; + telemetry.configuration.config_minor = AO_CONFIG_MINOR; + telemetry.configuration.main_deploy = ao_config.main_deploy; + telemetry.configuration.flight_log_max = ao_config.flight_log_max; + memcpy (telemetry.configuration.callsign, + ao_config.callsign, + AO_MAX_CALLSIGN); + memcpy (telemetry.configuration.version, + ao_version, + AO_MAX_VERSION); + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_config_cur = ao_telemetry_config_max; + } +} + +#if HAS_GPS +static void +ao_send_location(void) +{ + if (--ao_telemetry_loc_cur <= 0) + { + telemetry.generic.type = AO_TELEMETRY_LOCATION; + ao_mutex_get(&ao_gps_mutex); + memcpy(&telemetry.location.flags, + &ao_gps_data.flags, + 26); + ao_mutex_put(&ao_gps_mutex); + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_loc_cur = ao_telemetry_config_max; + } +} + +static void +ao_send_satellite(void) +{ + if (--ao_telemetry_sat_cur <= 0) + { + telemetry.generic.type = AO_TELEMETRY_SATELLITE; + ao_mutex_get(&ao_gps_mutex); + telemetry.satellite.channels = ao_gps_tracking_data.channels; + memcpy(&telemetry.satellite.sats, + &ao_gps_tracking_data.sats, + AO_MAX_GPS_TRACKING * sizeof (struct ao_telemetry_satellite_info)); + ao_mutex_put(&ao_gps_mutex); + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_sat_cur = ao_telemetry_config_max; + } +} +#endif + void ao_telemetry(void) { uint16_t time; int16_t delay; - static __xdata union ao_telemetry_all telemetry; - uint8_t sample; ao_config_get(); while (!ao_flight_number) @@ -56,54 +159,13 @@ ao_telemetry(void) time = ao_rdf_time = ao_time(); while (ao_telemetry_interval) { - /* Send sensor packet */ - sample = ao_sample_adc; - - telemetry.generic.tick = ao_adc_ring[sample].tick; - telemetry.generic.type = AO_TELEMETRY_SENSOR; - telemetry.sensor.state = ao_flight_state; -#if HAS_ACCEL - telemetry.sensor.accel = ao_adc_ring[sample].accel; -#else - telemetry.sensor.accel = 0; -#endif - telemetry.sensor.pres = ao_adc_ring[sample].pres; - telemetry.sensor.temp = ao_adc_ring[sample].temp; - telemetry.sensor.v_batt = ao_adc_ring[sample].v_batt; -#if HAS_IGNITE - telemetry.sensor.sense_d = ao_adc_ring[sample].sense_d; - telemetry.sensor.sense_m = ao_adc_ring[sample].sense_m; -#else - telemetry.sensor.sense_d = 0; - telemetry.sensor.sense_m = 0; + ao_send_sensor(); + ao_send_configuration(); +#if HAS_GPS + ao_send_location(); + ao_send_satellite(); #endif - - telemetry.sensor.acceleration = ao_accel; - telemetry.sensor.speed = ao_speed; - telemetry.sensor.height = ao_height; - - telemetry.sensor.ground_pres = ao_ground_pres; - telemetry.sensor.ground_accel = ao_ground_accel; - telemetry.sensor.accel_plus_g = ao_config.accel_plus_g; - telemetry.sensor.accel_minus_g = ao_config.accel_minus_g; - - ao_radio_send(&telemetry, sizeof (telemetry)); - - telemetry.generic.type = AO_TELEMETRY_CONFIGURATION; - telemetry.configuration.device = AO_idProduct_NUMBER; - telemetry.configuration.flight = ao_flight_number; - telemetry.configuration.config_major = AO_CONFIG_MAJOR; - telemetry.configuration.config_minor = AO_CONFIG_MINOR; - telemetry.configuration.main_deploy = ao_config.main_deploy; - telemetry.configuration.flight_log_max = ao_config.flight_log_max; - memcpy (telemetry.configuration.callsign, - ao_config.callsign, - AO_MAX_CALLSIGN); - memcpy (telemetry.configuration.version, - ao_version, - AO_MAX_VERSION); - if (ao_rdf && (int16_t) (ao_time() - ao_rdf_time) >= 0) { @@ -124,6 +186,16 @@ void ao_telemetry_set_interval(uint16_t interval) { ao_telemetry_interval = interval; + ao_telemetry_config_max = AO_SEC_TO_TICKS(1) / interval; + ao_telemetry_config_cur = 0; +#if HAS_GPS + ao_telemetry_loc_cur = 0; + if (ao_telemetry_config_max - 1 > ao_telemetry_loc_cur) + ao_telemetry_loc_cur++; + ao_telemetry_sat_cur = ao_telemetry_loc_cur; + if (ao_telemetry_config_max - 1 > ao_telemetry_sat_cur) + ao_telemetry_sat_cur++; +#endif ao_wakeup(&ao_telemetry_interval); } -- cgit v1.2.3 From edf6252450e06fd42fa6dde3acd127baa8fa6d36 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 5 Jul 2011 21:44:53 -0700 Subject: altos: Adapt to changes in telemetry Configuration packet Apogee delay added. flight_log_max changed to two bytes (in kB now). Signed-off-by: Keith Packard --- src/ao.h | 5 +++-- src/ao_telemetry.c | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 08f45275..9a986479 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1018,8 +1018,9 @@ struct ao_telemetry_configuration { uint16_t flight; /* 6 flight number */ uint8_t config_major; /* 8 Config major version */ uint8_t config_minor; /* 9 Config minor version */ - uint16_t main_deploy; /* 10 Main deploy alt in meters */ - uint32_t flight_log_max; /* 12 Maximum flight log size in bytes */ + uint16_t apogee_delay; /* 10 Apogee deploy delay in seconds */ + uint16_t main_deploy; /* 12 Main deploy alt in meters */ + uint16_t flight_log_max; /* 14 Maximum flight log size in kB */ char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ char version[AO_MAX_VERSION]; /* 24 Software version */ /* 32 */ diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 94ea0b22..f45d2ab4 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -94,8 +94,9 @@ ao_send_configuration(void) telemetry.configuration.flight = ao_flight_number; telemetry.configuration.config_major = AO_CONFIG_MAJOR; telemetry.configuration.config_minor = AO_CONFIG_MINOR; + telemetry.configuration.apogee_delay = ao_config.apogee_delay; telemetry.configuration.main_deploy = ao_config.main_deploy; - telemetry.configuration.flight_log_max = ao_config.flight_log_max; + telemetry.configuration.flight_log_max = ao_config.flight_log_max >> 10; memcpy (telemetry.configuration.callsign, ao_config.callsign, AO_MAX_CALLSIGN); -- cgit v1.2.3 From 41c230cac359b4459ca93196d08704b7d35447c7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 12:38:11 -0700 Subject: altos: Shrink ao_cmd_put16, ao_cmd_hex and ao_cmd No functional changes, just reduces code size. Signed-off-by: Keith Packard --- src/ao_cmd.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 3f020dc3..60f10716 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -110,9 +110,8 @@ putnibble(uint8_t v) void ao_cmd_put16(uint16_t v) { - int8_t i; - for (i = 3; i >= 0; i--) - putnibble((v >> (i << 2)) & 0xf); + ao_cmd_put8(v >> 8); + ao_cmd_put8(v); } void @@ -133,18 +132,20 @@ void ao_cmd_hex(void) { __xdata uint8_t r = ao_cmd_lex_error; + uint8_t n; ao_cmd_lex_i = 0; ao_cmd_white(); for(;;) { 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'); + n = (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); + n = (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); + n = (ao_cmd_lex_c - 'A' + 10); else break; + ao_cmd_lex_i = (ao_cmd_lex_i << 4) | n; r = ao_cmd_success; ao_cmd_lex(); } @@ -265,8 +266,8 @@ ao_cmd_register(__code struct ao_cmds *cmds) void ao_cmd(void) { - __xdata char c; - __xdata uint8_t cmd, cmds; + char c; + uint8_t cmd, cmds; __code struct ao_cmds * __xdata cs; void (*__xdata func)(void); -- cgit v1.2.3 From 480b48837db31987b947e4d32248965d4a16be03 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 13:21:25 -0700 Subject: altos: Shrink ao_config_callsign_set Replacing a hand-coded memset with a function call, using static space instead of stack space for an array. Signed-off-by: Keith Packard --- src/ao_config.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ao_config.c b/src/ao_config.c index c7fc7dd2..2434bc6c 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -116,8 +116,9 @@ void ao_config_callsign_set(void) __reentrant { uint8_t c; - char callsign[AO_MAX_CALLSIGN + 1]; + static __xdata char callsign[AO_MAX_CALLSIGN + 1]; + memset(callsign, '\0', sizeof callsign); ao_cmd_white(); c = 0; while (ao_cmd_lex_c != '\n') { @@ -131,8 +132,6 @@ ao_config_callsign_set(void) __reentrant return; ao_mutex_get(&ao_config_mutex); _ao_config_get(); - while (c < AO_MAX_CALLSIGN + 1) - callsign[c++] = '\0'; memcpy(&ao_config.callsign, &callsign, AO_MAX_CALLSIGN + 1); ao_config_dirty = 1; -- cgit v1.2.3 From 64860be02b3efa6f784a259249cfa6d14545fbd3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 13:49:05 -0700 Subject: altos: Shrink ao_add_task by rolling up a memset loop This has a dramatic effect. By pulling the 'stack' variable into registers it reduces the size of this function from 550 to 231 bytes. Signed-off-by: Keith Packard --- src/ao_task.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/ao_task.c b/src/ao_task.c index 35f34b49..7e34ed61 100644 --- a/src/ao_task.c +++ b/src/ao_task.c @@ -48,26 +48,31 @@ ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *nam */ stack = task->stack; - *stack++ = ((uint16_t) start); - *stack++ = ((uint16_t) start) >> 8; + *stack++ = ((uint16_t) start); /* 0 */ + *stack++ = ((uint16_t) start) >> 8; /* 1 */ /* and the stuff saved by ao_switch */ - *stack++ = 0; /* acc */ - *stack++ = 0x80; /* IE */ - *stack++ = 0; /* DPL */ - *stack++ = 0; /* DPH */ - *stack++ = 0; /* B */ - *stack++ = 0; /* R2 */ - *stack++ = 0; /* R3 */ - *stack++ = 0; /* R4 */ - *stack++ = 0; /* R5 */ - *stack++ = 0; /* R6 */ - *stack++ = 0; /* R7 */ - *stack++ = 0; /* R0 */ - *stack++ = 0; /* R1 */ - *stack++ = 0; /* PSW */ - *stack++ = 0; /* BP */ - task->stack_count = stack - task->stack; + *stack++ = 0; /* 2 acc */ + *stack++ = 0x80; /* 3 IE */ + + /* 4 DPL + * 5 DPH + * 6 B + * 7 R2 + * 8 R3 + * 9 R4 + * 10 R5 + * 11 R6 + * 12 R7 + * 13 R0 + * 14 R1 + * 15 PSW + * 16 BP + */ + for (t = 0; t < 13; t++) + *stack++ = 0; + + task->stack_count = 17; task->wchan = NULL; } -- cgit v1.2.3 From 92047ff86c79c2b18ef565a4560b06fe00d6f159 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:31:53 -0700 Subject: altos: Switch ao_gps_skytraq and ao_gps_sirf __xdata to __pdata Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_gps_sirf.c | 2 +- src/ao_gps_skytraq.c | 31 ++++++++++++++++--------------- 3 files changed, 18 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 9a986479..40466123 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1099,7 +1099,7 @@ union ao_telemetry_all { #define AO_GPS_DATE_VALID (1 << 6) #define AO_GPS_COURSE_VALID (1 << 7) -extern __xdata uint16_t ao_gps_tick; +extern __pdata uint16_t ao_gps_tick; extern __xdata uint8_t ao_gps_mutex; extern __xdata struct ao_telemetry_location ao_gps_data; extern __xdata struct ao_telemetry_satellite ao_gps_tracking_data; diff --git a/src/ao_gps_sirf.c b/src/ao_gps_sirf.c index 5827c687..f2abbf84 100644 --- a/src/ao_gps_sirf.c +++ b/src/ao_gps_sirf.c @@ -20,7 +20,7 @@ #endif __xdata uint8_t ao_gps_mutex; -__xdata uint16_t ao_gps_tick; +__pdata uint16_t ao_gps_tick; __xdata struct ao_telemetry_location ao_gps_data; __xdata struct ao_telemetry_satellite ao_gps_tracking_data; diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index 84743ff5..e7d1d2ef 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -21,20 +21,20 @@ #define AO_GPS_LEADER 2 -static const char ao_gps_header[] = "GP"; +static __code char ao_gps_header[] = "GP"; __xdata uint8_t ao_gps_mutex; -static __xdata char ao_gps_char; -static __xdata uint8_t ao_gps_cksum; -static __xdata uint8_t ao_gps_error; +static __pdata char ao_gps_char; +static __pdata uint8_t ao_gps_cksum; +static __pdata uint8_t ao_gps_error; -__xdata uint16_t ao_gps_tick; +__pdata uint16_t ao_gps_tick; __xdata struct ao_telemetry_location ao_gps_data; __xdata struct ao_telemetry_satellite ao_gps_tracking_data; -static __xdata uint16_t ao_gps_next_tick; +static __pdata uint16_t ao_gps_next_tick; static __xdata struct ao_telemetry_location ao_gps_next; -static __xdata uint8_t ao_gps_date_flags; +static __pdata uint8_t ao_gps_date_flags; static __xdata struct ao_telemetry_satellite ao_gps_tracking_next; #define STQ_S 0xa0, 0xa1 @@ -49,7 +49,7 @@ static __xdata struct ao_telemetry_satellite ao_gps_tracking_next; STQ_S, 0,15, id, a,b,c,d,e,f,g,h,i,j,k,l,m,n, \ (id^a^b^c^d^e^f^g^h^i^j^k^l^m^n), STQ_E -static const uint8_t ao_gps_config[] = { +static __code uint8_t ao_gps_config[] = { SKYTRAQ_MSG_8(0x08, 1, 1, 1, 1, 1, 1, 1, 0), /* configure nmea */ /* gga interval */ /* gsa interval */ @@ -89,13 +89,13 @@ ao_gps_skip_sep(void) ao_gps_lexchar(); } -__xdata static uint8_t ao_gps_num_width; +__pdata static uint8_t ao_gps_num_width; static int16_t ao_gps_decimal(uint8_t max_width) { int16_t v; - __xdata uint8_t neg = 0; + __pdata uint8_t neg = 0; ao_gps_skip_sep(); if (ao_gps_char == '-') { @@ -390,15 +390,16 @@ ao_nmea_rmc(void) } } -#define ao_skytraq_sendstruct(s) ao_skytraq_sendbytes((s), (s)+sizeof(s)) +#define ao_skytraq_sendstruct(s) ao_skytraq_sendbytes((s), sizeof(s)) static void -ao_skytraq_sendbytes(const uint8_t *b, const uint8_t *e) +ao_skytraq_sendbytes(__code uint8_t *b, uint8_t l) { - while (b != e) { - if (*b == 0xa0) + while (l--) { + uint8_t c = *b++; + if (c == 0xa0) ao_delay(AO_MS_TO_TICKS(500)); - ao_serial_putchar(*b++); + ao_serial_putchar(c); } } -- cgit v1.2.3 From 62267144d189967fcd0724b6dfbdbab3cb6fb414 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:33:52 -0700 Subject: altos: Switch ao_ignite and ao_gps_sirf __xdata to __pdata Signed-off-by: Keith Packard --- src/ao_ignite.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ao_ignite.c b/src/ao_ignite.c index 8ef83da8..e1b91bea 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -58,8 +58,8 @@ enum ao_igniter_status ao_igniter_status(enum ao_igniter igniter) { __xdata struct ao_adc adc; - __xdata int16_t value; - __xdata uint8_t request, firing, fired; + __pdata int16_t value; + __pdata uint8_t request, firing, fired; __critical { ao_adc_get(&adc); @@ -143,7 +143,7 @@ ao_ignite_manual(void) } } -static __code char *igniter_status_names[] = { +static __code char * __code igniter_status_names[] = { "unknown", "ready", "active", "open" }; -- cgit v1.2.3 From 5203ddaac692bfd82a01368da9fb66c25e9e14c1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:36:45 -0700 Subject: altos: Switch ao_log.c and ao_log_big.c __xdata to __pdata Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_log.c | 2 +- src/ao_log_big.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 40466123..c9a6970e 100644 --- a/src/ao.h +++ b/src/ao.h @@ -535,7 +535,7 @@ extern __pdata uint32_t ao_log_current_pos; extern __pdata uint32_t ao_log_end_pos; extern __pdata uint32_t ao_log_start_pos; extern __xdata uint8_t ao_log_running; -extern __xdata enum flight_state ao_log_state; +extern __pdata enum flight_state ao_log_state; /* required functions from the underlying log system */ diff --git a/src/ao_log.c b/src/ao_log.c index 71900490..80d7243d 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -21,7 +21,7 @@ __pdata uint32_t ao_log_current_pos; __pdata uint32_t ao_log_end_pos; __pdata uint32_t ao_log_start_pos; __xdata uint8_t ao_log_running; -__xdata enum flight_state ao_log_state; +__pdata enum flight_state ao_log_state; __xdata uint16_t ao_flight_number; void diff --git a/src/ao_log_big.c b/src/ao_log_big.c index 0c6cff85..74d94c4b 100644 --- a/src/ao_log_big.c +++ b/src/ao_log_big.c @@ -60,7 +60,7 @@ ao_log_dump_check_data(void) return 1; } -static __xdata uint8_t ao_log_adc_pos; +static __data uint8_t ao_log_adc_pos; /* a hack to make sure that ao_log_records fill the eeprom block in even units */ typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; @@ -72,7 +72,7 @@ typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; void ao_log(void) { - uint16_t next_sensor, next_other; + __pdata uint16_t next_sensor, next_other; ao_storage_setup(); -- cgit v1.2.3 From 002f167fc2709aaf1a4984aaa0a3519a97749d5f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:37:15 -0700 Subject: altos: Switch ao_report.c __xdata to __pdata Signed-off-by: Keith Packard --- src/ao_report.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ao_report.c b/src/ao_report.c index b9dc5bb4..3cf558e1 100644 --- a/src/ao_report.c +++ b/src/ao_report.c @@ -48,7 +48,7 @@ static const uint8_t flight_reports[] = { #endif #define pause(time) ao_delay(time) -static __xdata enum ao_flight_state ao_report_state; +static __pdata enum ao_flight_state ao_report_state; static void ao_report_beep(void) __reentrant @@ -87,9 +87,9 @@ ao_report_digit(uint8_t digit) __reentrant static void ao_report_altitude(void) { - __xdata int16_t agl = ao_max_height; + __pdata int16_t agl = ao_max_height; __xdata uint8_t digits[10]; - __xdata uint8_t ndigits, i; + __pdata uint8_t ndigits, i; if (agl < 0) agl = 0; -- cgit v1.2.3 From 803bf106caf5d6b5ac12eb00a941647c7325edd1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:37:34 -0700 Subject: altos: Switch ao_rssi.c __xdata to __pdata Signed-off-by: Keith Packard --- src/ao_rssi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao_rssi.c b/src/ao_rssi.c index 6912b9a2..e3964d2d 100644 --- a/src/ao_rssi.c +++ b/src/ao_rssi.c @@ -18,8 +18,8 @@ #include "ao.h" static __xdata volatile uint16_t ao_rssi_time; -static __xdata volatile uint16_t ao_rssi_delay; -static __xdata uint8_t ao_rssi_led; +static __pdata volatile uint16_t ao_rssi_delay; +static __pdata uint8_t ao_rssi_led; void ao_rssi(void) -- cgit v1.2.3 From 86b41d4c2b8a9fa4507cdb75302e0cedebb103cb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:38:29 -0700 Subject: altos: Switch ao_sample.c __xdata to __pdata Signed-off-by: Keith Packard --- src/ao.h | 10 +++++----- src/ao_sample.c | 18 +++++++++--------- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index c9a6970e..1919a259 100644 --- a/src/ao.h +++ b/src/ao.h @@ -803,13 +803,13 @@ extern __data uint8_t ao_sample_adc; /* Ring position of last processed sample extern __pdata int16_t ao_sample_accel; /* most recent accel sensor reading */ #endif -extern __xdata int16_t ao_ground_pres; /* startup pressure */ -extern __xdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ +extern __pdata int16_t ao_ground_pres; /* startup pressure */ +extern __pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ #if HAS_ACCEL -extern __xdata int16_t ao_ground_accel; /* startup acceleration */ -extern __xdata int16_t ao_accel_2g; /* factory accel calibration */ -extern __xdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +extern __pdata int16_t ao_ground_accel; /* startup acceleration */ +extern __pdata int16_t ao_accel_2g; /* factory accel calibration */ +extern __pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ #endif void ao_sample_init(void); diff --git a/src/ao_sample.c b/src/ao_sample.c index 84cf1e00..ac156646 100644 --- a/src/ao_sample.c +++ b/src/ao_sample.c @@ -37,21 +37,21 @@ __data uint8_t ao_sample_adc; * Sensor calibration values */ -__xdata int16_t ao_ground_pres; /* startup pressure */ -__xdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ +__pdata int16_t ao_ground_pres; /* startup pressure */ +__pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ #if HAS_ACCEL -__xdata int16_t ao_ground_accel; /* startup acceleration */ -__xdata int16_t ao_accel_2g; /* factory accel calibration */ -__xdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +__pdata int16_t ao_ground_accel; /* startup acceleration */ +__pdata int16_t ao_accel_2g; /* factory accel calibration */ +__pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ #endif -static __xdata uint8_t ao_preflight; /* in preflight mode */ +static __pdata uint8_t ao_preflight; /* in preflight mode */ -static __xdata uint16_t nsamples; -__xdata int32_t ao_sample_pres_sum; +static __pdata uint16_t nsamples; +__pdata int32_t ao_sample_pres_sum; #if HAS_ACCEL -__xdata int32_t ao_sample_accel_sum; +__pdata int32_t ao_sample_accel_sum; #endif static void -- cgit v1.2.3 From 9ba0da9247ea424a7a147aa85daae0d5e6316b81 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:38:46 -0700 Subject: altos: Switch ao_serial.c __xdata to __pdata Signed-off-by: Keith Packard --- src/ao_serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_serial.c b/src/ao_serial.c index 2e7dad7b..82370c64 100644 --- a/src/ao_serial.c +++ b/src/ao_serial.c @@ -91,7 +91,7 @@ ao_serial_drain(void) __critical ao_sleep(&ao_usart1_tx_fifo); } -static const struct { +static __code struct { uint8_t baud; uint8_t gcr; } ao_serial_speeds[] = { -- cgit v1.2.3 From f2f8ade6994aa3a69fd08f19c4403ceb8cea295d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:39:44 -0700 Subject: altos: Switch ao_stdio.c __data to __pdata Signed-off-by: Keith Packard --- src/ao.h | 4 ++-- src/ao_stdio.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 1919a259..dade99bf 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1311,8 +1311,8 @@ struct ao_stdio { }; extern __xdata struct ao_stdio ao_stdios[]; -extern __data int8_t ao_cur_stdio; -extern __data int8_t ao_num_stdios; +extern __pdata int8_t ao_cur_stdio; +extern __pdata int8_t ao_num_stdios; void flush(void); diff --git a/src/ao_stdio.c b/src/ao_stdio.c index 6b890832..c0138a30 100644 --- a/src/ao_stdio.c +++ b/src/ao_stdio.c @@ -24,8 +24,8 @@ #define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) __xdata struct ao_stdio ao_stdios[AO_NUM_STDIOS]; -__data int8_t ao_cur_stdio; -__data int8_t ao_num_stdios; +__pdata int8_t ao_cur_stdio; +__pdata int8_t ao_num_stdios; void putchar(char c) -- cgit v1.2.3 From 359baab005c274a0841268c615c23b3ffef813cf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:41:06 -0700 Subject: altos: Switch ao_telemetry.c __xdata to __pdata Signed-off-by: Keith Packard --- src/ao_telemetry.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index f45d2ab4..dcd0ff62 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -18,15 +18,15 @@ #include "ao.h" #include "ao_product.h" -__xdata uint16_t ao_telemetry_interval; -__xdata int8_t ao_telemetry_config_max; -__xdata int8_t ao_telemetry_config_cur; +static __pdata uint16_t ao_telemetry_interval; +static __pdata int8_t ao_telemetry_config_max; +static __pdata int8_t ao_telemetry_config_cur; #if HAS_GPS -__xdata int8_t ao_telemetry_loc_cur; -__xdata int8_t ao_telemetry_sat_cur; +static __pdata int8_t ao_telemetry_loc_cur; +static __pdata int8_t ao_telemetry_sat_cur; #endif -__xdata uint8_t ao_rdf = 0; -__xdata uint16_t ao_rdf_time; +static __pdata uint8_t ao_rdf = 0; +static __pdata uint16_t ao_rdf_time; #define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) #define AO_RDF_LENGTH_MS 500 @@ -156,7 +156,7 @@ ao_telemetry(void) telemetry.generic.serial = ao_serial_number; for (;;) { while (ao_telemetry_interval == 0) - ao_sleep(&ao_telemetry_interval); + ao_sleep(&telemetry); time = ao_rdf_time = ao_time(); while (ao_telemetry_interval) { @@ -197,7 +197,7 @@ ao_telemetry_set_interval(uint16_t interval) if (ao_telemetry_config_max - 1 > ao_telemetry_sat_cur) ao_telemetry_sat_cur++; #endif - ao_wakeup(&ao_telemetry_interval); + ao_wakeup(&telemetry); } void -- cgit v1.2.3 From 355db71f4511adff8abcb2caded61c12fe8b7ee9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:41:32 -0700 Subject: altos: Switch ao_usb.c __xdata to __pdata Signed-off-by: Keith Packard --- src/ao_usb.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/ao_usb.c b/src/ao_usb.c index e4b7938d..08cb7390 100644 --- a/src/ao_usb.c +++ b/src/ao_usb.c @@ -21,10 +21,10 @@ struct ao_task __xdata ao_usb_task; static __xdata uint16_t ao_usb_in_bytes; -static __xdata uint16_t ao_usb_in_bytes_last; +static __pdata uint16_t ao_usb_in_bytes_last; static __xdata uint16_t ao_usb_out_bytes; -static __xdata uint8_t ao_usb_iif; -static __xdata uint8_t ao_usb_running; +static __pdata uint8_t ao_usb_iif; +static __pdata uint8_t ao_usb_running; static void ao_usb_set_interrupts(void) @@ -72,20 +72,20 @@ struct ao_usb_setup { uint16_t length; } __xdata ao_usb_setup; -__xdata uint8_t ao_usb_ep0_state; -uint8_t * __xdata ao_usb_ep0_in_data; -__xdata uint8_t ao_usb_ep0_in_len; -__xdata uint8_t ao_usb_ep0_in_buf[2]; -__xdata uint8_t ao_usb_ep0_out_len; -__xdata uint8_t *__xdata ao_usb_ep0_out_data; -__xdata uint8_t ao_usb_configuration; +__pdata uint8_t ao_usb_ep0_state; +uint8_t * __pdata ao_usb_ep0_in_data; +__pdata uint8_t ao_usb_ep0_in_len; +__pdata uint8_t ao_usb_ep0_in_buf[2]; +__pdata uint8_t ao_usb_ep0_out_len; +__xdata uint8_t *__pdata ao_usb_ep0_out_data; +__pdata uint8_t ao_usb_configuration; /* Send an IN data packet */ static void ao_usb_ep0_flush(void) { - __xdata uint8_t this_len; - __xdata uint8_t cs0; + __pdata uint8_t this_len; + __pdata uint8_t cs0; /* If the IN packet hasn't been picked up, just return */ USBINDEX = 0; @@ -115,9 +115,9 @@ __xdata static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; static void ao_usb_get_descriptor(uint16_t value) { - const uint8_t *__xdata descriptor; - __xdata uint8_t type = value >> 8; - __xdata uint8_t index = value; + __code uint8_t *__pdata descriptor; + __pdata uint8_t type = value >> 8; + __pdata uint8_t index = value; descriptor = ao_usb_descriptors; while (descriptor[0] != 0) { @@ -138,7 +138,7 @@ ao_usb_get_descriptor(uint16_t value) static void ao_usb_ep0_fill(void) { - __xdata uint8_t len; + __pdata uint8_t len; USBINDEX = 0; len = USBCNT0; @@ -282,7 +282,7 @@ ao_usb_ep0_setup(void) static void ao_usb_ep0(void) { - __xdata uint8_t cs0; + __pdata uint8_t cs0; ao_usb_ep0_state = AO_USB_EP0_IDLE; for (;;) { -- cgit v1.2.3 From 2ec986f08ce8d4635f4435bb0042b405d93edc40 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:45:04 -0700 Subject: altos: Switch const for __code in struct ao_cmds This saves quite a bit of code space when accessing these values. Signed-off-by: Keith Packard --- src/ao.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index dade99bf..bb384611 100644 --- a/src/ao.h +++ b/src/ao.h @@ -395,7 +395,7 @@ ao_match_word(__code char *word); struct ao_cmds { void (*func)(void); - const char *help; + __code char *help; }; void -- cgit v1.2.3 From 6893752900385ee51cc4cf75e1b672202de7578a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:26:09 -0700 Subject: altos: switch ao_cmd __xdata to __pdata Saves code space Signed-off-by: Keith Packard --- src/ao.h | 8 ++++---- src/ao_cmd.c | 30 +++++++++++++++--------------- 2 files changed, 19 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index bb384611..8836a286 100644 --- a/src/ao.h +++ b/src/ao.h @@ -367,10 +367,10 @@ enum ao_cmd_status { ao_cmd_syntax_error = 2, }; -extern __xdata uint16_t ao_cmd_lex_i; -extern __xdata uint32_t ao_cmd_lex_u32; -extern __xdata char ao_cmd_lex_c; -extern __xdata enum ao_cmd_status ao_cmd_status; +extern __pdata uint16_t ao_cmd_lex_i; +extern __pdata uint32_t ao_cmd_lex_u32; +extern __pdata char ao_cmd_lex_c; +extern __pdata enum ao_cmd_status ao_cmd_status; void ao_cmd_lex(void); diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 60f10716..6d3ae38d 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -17,21 +17,21 @@ #include "ao.h" -__xdata uint16_t ao_cmd_lex_i; -__xdata uint32_t ao_cmd_lex_u32; -__xdata char ao_cmd_lex_c; -__xdata enum ao_cmd_status ao_cmd_status; +__pdata uint16_t ao_cmd_lex_i; +__pdata uint32_t ao_cmd_lex_u32; +__pdata char ao_cmd_lex_c; +__pdata enum ao_cmd_status ao_cmd_status; #define CMD_LEN 32 static __xdata char cmd_line[CMD_LEN]; -static __xdata uint8_t cmd_len; -static __xdata uint8_t cmd_i; +static __pdata uint8_t cmd_len; +static __pdata uint8_t cmd_i; static void -put_string(char *s) +put_string(__code char *s) { - __xdata char c; + char c; while (c = *s++) putchar(c); } @@ -39,7 +39,7 @@ put_string(char *s) static void readline(void) { - __xdata char c; + __pdata char c; if (ao_echo()) put_string("> "); cmd_len = 0; @@ -131,7 +131,7 @@ ao_cmd_white(void) void ao_cmd_hex(void) { - __xdata uint8_t r = ao_cmd_lex_error; + __pdata uint8_t r = ao_cmd_lex_error; uint8_t n; ao_cmd_lex_i = 0; @@ -156,7 +156,7 @@ ao_cmd_hex(void) void ao_cmd_decimal(void) { - __xdata uint8_t r = ao_cmd_lex_error; + __pdata uint8_t r = ao_cmd_lex_error; ao_cmd_lex_u32 = 0; ao_cmd_white(); @@ -225,14 +225,14 @@ version(void) #define NUM_CMDS 11 static __code struct ao_cmds *__xdata (ao_cmds[NUM_CMDS]); -static __xdata uint8_t ao_ncmds; +static __pdata uint8_t ao_ncmds; static void help(void) { - __xdata uint8_t cmds; - __xdata uint8_t cmd; - __code struct ao_cmds * __xdata cs; + register uint8_t cmds; + register uint8_t cmd; + register __code struct ao_cmds * cs; for (cmds = 0; cmds < ao_ncmds; cmds++) { cs = ao_cmds[cmds]; -- cgit v1.2.3 From 6903b6464db7eb803de8bf9b897c45431f7a1d63 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:27:32 -0700 Subject: altos: Switch ao_config.c __xdata to __pdata Signed-off-by: Keith Packard --- src/ao_config.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ao_config.c b/src/ao_config.c index 2434bc6c..813164ea 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -18,8 +18,8 @@ #include "ao.h" __xdata struct ao_config ao_config; -__xdata uint8_t ao_config_loaded; -__xdata uint8_t ao_config_dirty; +__pdata uint8_t ao_config_loaded; +__pdata uint8_t ao_config_dirty; __xdata uint8_t ao_config_mutex; #define AO_CONFIG_DEFAULT_MAIN_DEPLOY 250 @@ -335,7 +335,7 @@ ao_config_log_set(void) __reentrant #endif /* HAS_EEPROM */ struct ao_config_var { - const char *str; + __code char *str; void (*set)(void) __reentrant; void (*show)(void) __reentrant; }; -- cgit v1.2.3 From 3742b36a528f114c3b1873caa4f39581145b76da Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:28:01 -0700 Subject: altos: Switch ao_dbg.c __xdata to __pdata Signed-off-by: Keith Packard --- src/ao_dbg.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/ao_dbg.c b/src/ao_dbg.c index 14a123a2..d4c9567f 100644 --- a/src/ao_dbg.c +++ b/src/ao_dbg.c @@ -31,7 +31,7 @@ ao_dbg_send_bits(uint8_t msk, uint8_t val) __reentrant void ao_dbg_send_byte(uint8_t byte) { - __xdata uint8_t b, d; + __pdata uint8_t b, d; DBG_PORT |= DBG_DATA; DBG_PORT_DIR |= DBG_DATA; @@ -49,7 +49,7 @@ ao_dbg_send_byte(uint8_t byte) uint8_t ao_dbg_recv_byte(void) { - __xdata uint8_t byte, b; + __pdata uint8_t byte, b; byte = 0; for (b = 0; b < 8; b++) { @@ -89,12 +89,12 @@ ao_dbg_recv_byte(void) #define SFR_DPL1 0x84 #define SFR_DPH1 0x85 -__xdata uint8_t save_acc; -__xdata uint8_t save_psw; -__xdata uint8_t save_dpl0; -__xdata uint8_t save_dph0; -__xdata uint8_t save_dpl1; -__xdata uint8_t save_dph1; +__pdata uint8_t save_acc; +__pdata uint8_t save_psw; +__pdata uint8_t save_dpl0; +__pdata uint8_t save_dph0; +__pdata uint8_t save_dpl1; +__pdata uint8_t save_dph1; static uint8_t ao_dbg_inst1(uint8_t a) __reentrant @@ -260,9 +260,9 @@ debug_put(void) static void debug_get(void) { - __xdata uint16_t count; - __xdata uint16_t i; - __xdata uint8_t byte; + __pdata uint16_t count; + __pdata uint16_t i; + __pdata uint8_t byte; ao_cmd_hex(); if (ao_cmd_status != ao_cmd_success) return; @@ -284,7 +284,7 @@ debug_get(void) static uint8_t getnibble(void) { - __xdata char c; + __pdata char c; c = getchar(); if ('0' <= c && c <= '9') @@ -300,10 +300,10 @@ getnibble(void) static void debug_input(void) { - __xdata uint16_t count; - __xdata uint16_t addr; - __xdata uint8_t b; - __xdata uint8_t i; + __pdata uint16_t count; + __pdata uint16_t addr; + __pdata uint8_t b; + __pdata uint8_t i; ao_cmd_hex(); count = ao_cmd_lex_i; @@ -326,9 +326,9 @@ debug_input(void) static void debug_output(void) { - __xdata uint16_t count; - __xdata uint16_t addr; - __xdata uint8_t b; + __pdata uint16_t count; + __pdata uint16_t addr; + __pdata uint8_t b; ao_cmd_hex(); count = ao_cmd_lex_i; -- cgit v1.2.3 From 038d7b25ba833da4be458409670d3f95e8aaf17b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:51:52 -0700 Subject: altos: Switch ao_flight and ao_flight_nano __xdata to __pdata Signed-off-by: Keith Packard --- src/ao.h | 2 +- src/ao_flight.c | 5 +---- src/ao_flight_nano.c | 2 +- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 8836a286..ac5615bb 100644 --- a/src/ao.h +++ b/src/ao.h @@ -707,7 +707,7 @@ enum ao_flight_state { extern __pdata enum ao_flight_state ao_flight_state; extern __pdata uint16_t ao_launch_time; -extern __xdata uint8_t ao_flight_force_idle; +extern __pdata uint8_t ao_flight_force_idle; /* Flight thread */ void diff --git a/src/ao_flight.c b/src/ao_flight.c index c6cbbf7c..f1b60d69 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -44,7 +44,7 @@ __pdata uint16_t ao_interval_end; __pdata int16_t ao_interval_min_height; __pdata int16_t ao_interval_max_height; -__xdata uint8_t ao_flight_force_idle; +__pdata uint8_t ao_flight_force_idle; /* We also have a clock, which can be used to sanity check things in * case of other failures @@ -170,7 +170,6 @@ ao_flight(void) #endif ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - break; } break; case ao_flight_boost: @@ -194,7 +193,6 @@ ao_flight(void) ao_flight_state = ao_flight_coast; #endif ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - break; } break; #if HAS_ACCEL @@ -208,7 +206,6 @@ ao_flight(void) { ao_flight_state = ao_flight_coast; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - break; } break; #endif diff --git a/src/ao_flight_nano.c b/src/ao_flight_nano.c index 32770227..2e332b12 100644 --- a/src/ao_flight_nano.c +++ b/src/ao_flight_nano.c @@ -30,7 +30,7 @@ __pdata uint16_t ao_interval_end; __pdata int16_t ao_interval_min_height; __pdata int16_t ao_interval_max_height; -__xdata uint8_t ao_flight_force_idle; +__pdata uint8_t ao_flight_force_idle; /* Landing is detected by getting constant readings from both pressure and accelerometer * for a fairly long time (AO_INTERVAL_TICKS) -- cgit v1.2.3 From b65140a0139075adeddaccf0f4d5c7a75fac4757 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 15:52:25 -0700 Subject: altos: Switch flash drivers __xdata to __pdata Signed-off-by: Keith Packard --- src/ao.h | 8 ++++---- src/ao_ee.c | 8 ++++---- src/ao_flash.c | 8 ++++---- src/ao_intflash.c | 8 ++++---- src/ao_m25.c | 8 ++++---- 5 files changed, 20 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index ac5615bb..e52a2198 100644 --- a/src/ao.h +++ b/src/ao.h @@ -464,16 +464,16 @@ ao_mutex_put(__xdata uint8_t *ao_mutex) __reentrant; */ /* Total bytes of available storage */ -extern __xdata uint32_t ao_storage_total; +extern __pdata uint32_t ao_storage_total; /* Block size - device is erased in these units. At least 256 bytes */ -extern __xdata uint32_t ao_storage_block; +extern __pdata uint32_t ao_storage_block; /* Byte offset of config block. Will be ao_storage_block bytes long */ -extern __xdata uint32_t ao_storage_config; +extern __pdata uint32_t ao_storage_config; /* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ -extern __xdata uint16_t ao_storage_unit; +extern __pdata uint16_t ao_storage_unit; #define AO_STORAGE_ERASE_LOG (ao_storage_config + AO_CONFIG_MAX_SIZE) diff --git a/src/ao_ee.c b/src/ao_ee.c index e3b41103..83863af5 100644 --- a/src/ao_ee.c +++ b/src/ao_ee.c @@ -23,16 +23,16 @@ #define EE_DEVICE_SIZE ((uint32_t) 128 * (uint32_t) 1024) /* Total bytes of available storage */ -__xdata uint32_t ao_storage_total; +__pdata uint32_t ao_storage_total; /* Block size - device is erased in these units. At least 256 bytes */ -__xdata uint32_t ao_storage_block; +__pdata uint32_t ao_storage_block; /* Byte offset of config block. Will be ao_storage_block bytes long */ -__xdata uint32_t ao_storage_config; +__pdata uint32_t ao_storage_config; /* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ -__xdata uint16_t ao_storage_unit; +__pdata uint16_t ao_storage_unit; /* * Using SPI on USART 0, with P1_2 as the chip select diff --git a/src/ao_flash.c b/src/ao_flash.c index d323926f..00e96398 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -19,16 +19,16 @@ #include "at45db161d.h" /* Total bytes of available storage */ -__xdata uint32_t ao_storage_total; +__pdata uint32_t ao_storage_total; /* Block size - device is erased in these units. At least 256 bytes */ -__xdata uint32_t ao_storage_block; +__pdata uint32_t ao_storage_block; /* Byte offset of config block. Will be ao_storage_block bytes long */ -__xdata uint32_t ao_storage_config; +__pdata uint32_t ao_storage_config; /* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ -__xdata uint16_t ao_storage_unit; +__pdata uint16_t ao_storage_unit; #define FLASH_CS P1_1 #define FLASH_CS_INDEX 1 diff --git a/src/ao_intflash.c b/src/ao_intflash.c index 88d1f7f6..d76d954e 100644 --- a/src/ao_intflash.c +++ b/src/ao_intflash.c @@ -47,16 +47,16 @@ __xdata __at(AO_INTFLASH_LOCATION) uint8_t ao_intflash[AO_INTFLASH_SIZE]; /* Total bytes of available storage */ -__xdata uint32_t ao_storage_total = sizeof(ao_intflash); +__pdata uint32_t ao_storage_total = sizeof(ao_intflash); /* Block size - device is erased in these units. */ -__xdata uint32_t ao_storage_block = AO_INTFLASH_BLOCK; +__pdata uint32_t ao_storage_block = AO_INTFLASH_BLOCK; /* Byte offset of config block. Will be ao_storage_block bytes long */ -__xdata uint32_t ao_storage_config = sizeof(ao_intflash) - AO_INTFLASH_BLOCK; +__pdata uint32_t ao_storage_config = sizeof(ao_intflash) - AO_INTFLASH_BLOCK; /* Storage unit size - device reads and writes must be within blocks of this size. */ -__xdata uint16_t ao_storage_unit = AO_INTFLASH_BLOCK; +__pdata uint16_t ao_storage_unit = AO_INTFLASH_BLOCK; __xdata static uint8_t ao_intflash_dma_done; static uint8_t ao_intflash_dma; diff --git a/src/ao_m25.c b/src/ao_m25.c index afd5df76..208c69ba 100644 --- a/src/ao_m25.c +++ b/src/ao_m25.c @@ -18,16 +18,16 @@ #include "ao.h" /* Total bytes of available storage */ -__xdata uint32_t ao_storage_total; +__pdata uint32_t ao_storage_total; /* Block size - device is erased in these units. At least 256 bytes */ -__xdata uint32_t ao_storage_block; +__pdata uint32_t ao_storage_block; /* Byte offset of config block. Will be ao_storage_block bytes long */ -__xdata uint32_t ao_storage_config; +__pdata uint32_t ao_storage_config; /* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ -__xdata uint16_t ao_storage_unit; +__pdata uint16_t ao_storage_unit; /* * Each flash chip is arranged in 64kB sectors; the -- cgit v1.2.3 From 0154d13756bcb09f009981ee5e4bd27fd04b8788 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 16:19:22 -0700 Subject: altos: Switch Tm and Tn to common telemetry code Signed-off-by: Keith Packard --- src/Makefile.proto | 4 ++-- src/ao_telemetry.c | 6 ++++++ src/ao_telemini.c | 2 +- src/ao_telenano.c | 2 +- 4 files changed, 10 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index 5322df17..309fd75d 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -195,7 +195,7 @@ TMINI_TASK_SRC = \ ao_log.c \ ao_log_tiny.c \ ao_report.c \ - ao_telemetry_tiny.c + ao_telemetry.c TMINI_MAIN_SRC = \ ao_telemini.c @@ -225,7 +225,7 @@ TNANO_TASK_SRC = \ ao_log.c \ ao_log_tiny.c \ ao_report.c \ - ao_telemetry_tiny.c + ao_telemetry.c TNANO_MAIN_SRC = \ ao_telenano.c diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index dcd0ff62..603a6791 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -77,9 +77,15 @@ ao_send_sensor(void) telemetry.sensor.height = ao_height; telemetry.sensor.ground_pres = ao_ground_pres; +#if HAS_ACCEL telemetry.sensor.ground_accel = ao_ground_accel; telemetry.sensor.accel_plus_g = ao_config.accel_plus_g; telemetry.sensor.accel_minus_g = ao_config.accel_minus_g; +#else + telemetry.sensor.ground_accel = 0; + telemetry.sensor.accel_plus_g = 0; + telemetry.sensor.accel_minus_g = 0; +#endif ao_radio_send(&telemetry, sizeof (telemetry)); } diff --git a/src/ao_telemini.c b/src/ao_telemini.c index dbc3b74c..19d03692 100644 --- a/src/ao_telemini.c +++ b/src/ao_telemini.c @@ -42,7 +42,7 @@ main(void) ao_flight_init(); ao_log_init(); ao_report_init(); - ao_telemetry_tiny_init(); + ao_telemetry_init(); ao_radio_init(); ao_packet_slave_init(TRUE); ao_igniter_init(); diff --git a/src/ao_telenano.c b/src/ao_telenano.c index 47b7b3c3..40822b6e 100644 --- a/src/ao_telenano.c +++ b/src/ao_telenano.c @@ -42,7 +42,7 @@ main(void) ao_flight_nano_init(); ao_log_init(); ao_report_init(); - ao_telemetry_tiny_init(); + ao_telemetry_init(); ao_radio_init(); ao_packet_slave_init(TRUE); ao_config_init(); -- cgit v1.2.3 From 5ca6400fd8a360b64d8f96f50d5595a7fd17762d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 16:18:54 -0700 Subject: altos: Remove ao_telemetry_orig.c and ao_telemetry_tiny.c All products use the common ao_telemetry.c code now Signed-off-by: Keith Packard --- src/ao_telemetry_orig.c | 105 ------------------------------------------------ src/ao_telemetry_tiny.c | 91 ----------------------------------------- 2 files changed, 196 deletions(-) delete mode 100644 src/ao_telemetry_orig.c delete mode 100644 src/ao_telemetry_tiny.c (limited to 'src') diff --git a/src/ao_telemetry_orig.c b/src/ao_telemetry_orig.c deleted file mode 100644 index 4b3a344a..00000000 --- a/src/ao_telemetry_orig.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * 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" - -__xdata uint16_t ao_telemetry_interval = 0; -__xdata uint8_t ao_rdf = 0; -__xdata uint16_t ao_rdf_time; - -#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) -#define AO_RDF_LENGTH_MS 500 - -void -ao_telemetry_orig(void) -{ - uint16_t time; - int16_t delay; - static __xdata struct ao_telemetry_orig telemetry; - - ao_config_get(); - while (!ao_flight_number) - ao_sleep(&ao_flight_number); - memcpy(telemetry.callsign, ao_config.callsign, AO_MAX_CALLSIGN); - telemetry.serial = ao_serial_number; - telemetry.flight = ao_log_full() ? 0 : ao_flight_number; - telemetry.accel_plus_g = ao_config.accel_plus_g; - telemetry.accel_minus_g = ao_config.accel_minus_g; - for (;;) { - while (ao_telemetry_interval == 0) - ao_sleep(&ao_telemetry_interval); - time = ao_rdf_time = ao_time(); - while (ao_telemetry_interval) { - telemetry.flight_state = ao_flight_state; - telemetry.height = ao_height; - telemetry.u.k.speed = ao_speed; - telemetry.accel = ao_accel; - telemetry.u.k.unused = 0x8000; -#if HAS_ACCEL - telemetry.ground_accel = ao_ground_accel; -#endif - telemetry.ground_pres = ao_ground_pres; -#if HAS_ADC - ao_adc_get(&telemetry.adc); -#endif -#if HAS_GPS - ao_mutex_get(&ao_gps_mutex); - memcpy(&telemetry.gps, &ao_gps_data, sizeof (struct ao_gps_data)); - memcpy(&telemetry.gps_tracking, &ao_gps_tracking_data, sizeof (struct ao_gps_tracking_data)); - ao_mutex_put(&ao_gps_mutex); -#endif - ao_radio_send(&telemetry, sizeof (telemetry)); - if (ao_rdf && - (int16_t) (ao_time() - ao_rdf_time) >= 0) - { - ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; - ao_radio_rdf(AO_RDF_LENGTH_MS); - } - time += ao_telemetry_interval; - delay = time - ao_time(); - if (delay > 0) - ao_delay(delay); - else - time = ao_time(); - } - } -} - -void -ao_telemetry_set_interval(uint16_t interval) -{ - ao_telemetry_interval = interval; - ao_wakeup(&ao_telemetry_interval); -} - -void -ao_rdf_set(uint8_t rdf) -{ - ao_rdf = rdf; - if (rdf == 0) - ao_radio_rdf_abort(); - else - ao_rdf_time = ao_time(); -} - -__xdata struct ao_task ao_telemetry_orig_task; - -void -ao_telemetry_orig_init() -{ - ao_add_task(&ao_telemetry_orig_task, ao_telemetry_orig, "telemetry_orig"); -} diff --git a/src/ao_telemetry_tiny.c b/src/ao_telemetry_tiny.c deleted file mode 100644 index 6f2ddda1..00000000 --- a/src/ao_telemetry_tiny.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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" - -__xdata uint8_t ao_rdf = 0; -__xdata uint16_t ao_rdf_time; -__xdata uint16_t ao_telemetry_tiny_interval = 0; - -#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) -#define AO_RDF_LENGTH_MS 500 - -void -ao_telemetry_tiny(void) -{ - uint16_t time; - int16_t delay; - static __xdata struct ao_telemetry_tiny telemetry_tiny; - - ao_config_get(); - while (!ao_flight_number) - ao_sleep(&ao_flight_number); - memcpy(telemetry_tiny.callsign, ao_config.callsign, AO_MAX_CALLSIGN); - telemetry_tiny.serial = ao_serial_number; - telemetry_tiny.flight = ao_log_full() ? 0 : ao_flight_number; - for (;;) { - while (ao_telemetry_tiny_interval == 0) - ao_sleep(&ao_telemetry_tiny_interval); - time = ao_rdf_time = ao_time(); - while (ao_telemetry_tiny_interval) { - telemetry_tiny.flight_state = ao_flight_state; - telemetry_tiny.height = ao_height; - telemetry_tiny.speed = ao_speed; - telemetry_tiny.accel = ao_accel; - telemetry_tiny.ground_pres = ao_ground_pres; - ao_adc_get(&telemetry_tiny.adc); - ao_radio_send(&telemetry_tiny, sizeof (telemetry_tiny)); - if (ao_rdf && - (int16_t) (ao_time() - ao_rdf_time) >= 0) - { - ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; - ao_radio_rdf(AO_RDF_LENGTH_MS); - } - time += ao_telemetry_tiny_interval; - delay = time - ao_time(); - if (delay > 0) - ao_delay(delay); - else - time = ao_time(); - } - } -} - -void -ao_telemetry_set_interval(uint16_t interval) -{ - ao_telemetry_tiny_interval = interval; - ao_wakeup(&ao_telemetry_tiny_interval); -} - -void -ao_rdf_set(uint8_t rdf) -{ - ao_rdf = rdf; - if (rdf == 0) - ao_radio_rdf_abort(); - else - ao_rdf_time = ao_time(); -} - -__xdata struct ao_task ao_telemetry_tiny_task; - -void -ao_telemetry_tiny_init() -{ - ao_add_task(&ao_telemetry_tiny_task, ao_telemetry_tiny, "telemetry_tiny"); -} -- cgit v1.2.3 From 81cf2e833bedbc1ace8fd310e9e94bfb7673d428 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 16:43:17 -0700 Subject: altos: Ensure low-rate telem packets interleave with sensor telem packets To avoid over-committing the radio link, we want to send only one low rate packet after each sensor packet. However, the initializations for this were incorrect, causing the configuration and location packets to be sent at the same time. Signed-off-by: Keith Packard --- src/ao_telemetry.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 603a6791..172b6f17 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -194,13 +194,13 @@ ao_telemetry_set_interval(uint16_t interval) { ao_telemetry_interval = interval; ao_telemetry_config_max = AO_SEC_TO_TICKS(1) / interval; - ao_telemetry_config_cur = 0; + ao_telemetry_config_cur = 1; #if HAS_GPS - ao_telemetry_loc_cur = 0; - if (ao_telemetry_config_max - 1 > ao_telemetry_loc_cur) + ao_telemetry_loc_cur = 1; + if (ao_telemetry_config_max > ao_telemetry_loc_cur) ao_telemetry_loc_cur++; ao_telemetry_sat_cur = ao_telemetry_loc_cur; - if (ao_telemetry_config_max - 1 > ao_telemetry_sat_cur) + if (ao_telemetry_config_max > ao_telemetry_sat_cur) ao_telemetry_sat_cur++; #endif ao_wakeup(&telemetry); -- cgit v1.2.3 From 504ab7ab355652d5d01094c927089029596a0753 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 6 Jul 2011 17:49:01 -0700 Subject: altos: product defines are always in ao_product.h When all products were built in a single directory, each one had a separate version of ao_product.h. Now that they all reside in sub-directories, each directory has its own ao_product.h This change is needed so that other modules in the system can use the product defines; otherwise, ao_product.h was not built at the right time. Signed-off-by: Keith Packard --- configure.ac | 2 +- src/Makefile.proto | 3 +-- src/ao_product.c | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/configure.ac b/configure.ac index 187af4fb..78f5adbb 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 0.9.4.1) +AC_INIT([altos], 0.9.4.2) AC_CONFIG_SRCDIR([src/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE diff --git a/src/Makefile.proto b/src/Makefile.proto index 309fd75d..d4a8c4ea 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -359,8 +359,7 @@ all: ../$(PROG) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ -ao_product.rel: ao_product.c ao_product.h - $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< +$(REL): ao_product.h distclean: clean diff --git a/src/ao_product.c b/src/ao_product.c index bb42e92c..fb59580b 100644 --- a/src/ao_product.c +++ b/src/ao_product.c @@ -16,7 +16,7 @@ */ #include "ao.h" -#include PRODUCT_DEFS +#include "ao_product.h" /* Defines which mark this particular AltOS product */ -- cgit v1.2.3 From 0d0cf6f9a1b14a1b66aee3845964cd33d1f035c2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jul 2011 13:09:57 -0700 Subject: altos: new versions of sdcc require __ prefixes for custom keywords Fortunately, 2.9.1 appears to accept either, so we can switch now and prepare for sdcc 3.0.0. Signed-off-by: Keith Packard --- src/ao_task.c | 2 +- src/cc1111.h | 148 +++++++++++++++++++++++++++++----------------------------- 2 files changed, 75 insertions(+), 75 deletions(-) (limited to 'src') diff --git a/src/ao_task.c b/src/ao_task.c index 7e34ed61..f5850fa4 100644 --- a/src/ao_task.c +++ b/src/ao_task.c @@ -78,7 +78,7 @@ ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *nam /* Task switching function. This must not use any stack variables */ void -ao_yield(void) _naked +ao_yield(void) __naked { /* Save current context */ diff --git a/src/cc1111.h b/src/cc1111.h index 5b018cb5..e52aa79f 100644 --- a/src/cc1111.h +++ b/src/cc1111.h @@ -40,7 +40,7 @@ #include #include -sfr __at 0xA8 IEN0; /* Interrupt Enable 0 Register */ +__sfr __at 0xA8 IEN0; /* Interrupt Enable 0 Register */ sbit __at 0xA8 RFTXRXIE; /* RF TX/RX done interrupt enable */ sbit __at 0xA9 ADCIE; /* ADC interrupt enable */ @@ -60,7 +60,7 @@ sbit __at 0xAF EA; /* Enable All */ #define IEN0_ADCIE (1 << 1) #define IEN0_RFTXRXIE (1 << 0) -sfr __at 0xB8 IEN1; /* Interrupt Enable 1 Register */ +__sfr __at 0xB8 IEN1; /* Interrupt Enable 1 Register */ #define IEN1_P0IE (1 << 5) /* Port 0 interrupt enable */ #define IEN1_T4IE (1 << 4) /* Timer 4 interrupt enable */ @@ -70,7 +70,7 @@ sfr __at 0xB8 IEN1; /* Interrupt Enable 1 Register */ #define IEN1_DMAIE (1 << 0) /* DMA transfer interrupt enable */ /* IEN2 */ -sfr __at 0x9A IEN2; /* Interrupt Enable 2 Register */ +__sfr __at 0x9A IEN2; /* Interrupt Enable 2 Register */ #define IEN2_WDTIE (1 << 5) /* Watchdog timer interrupt enable */ #define IEN2_P1IE (1 << 4) /* Port 1 interrupt enable */ @@ -82,7 +82,7 @@ sfr __at 0x9A IEN2; /* Interrupt Enable 2 Register */ #define IEN2_RFIE (1 << 0) /* RF general interrupt enable */ /* CLKCON 0xC6 */ -sfr __at 0xC6 CLKCON; /* Clock Control */ +__sfr __at 0xC6 CLKCON; /* Clock Control */ #define CLKCON_OSC32K_RC (1 << 7) #define CLKCON_OSC32K_XTAL (0 << 7) @@ -126,14 +126,14 @@ sfr __at 0xC6 CLKCON; /* Clock Control */ #define SLEEP_MODE_MASK (3 << 0) /* PCON 0x87 */ -sfr __at 0x87 PCON; /* Power Mode Control Register */ +__sfr __at 0x87 PCON; /* Power Mode Control Register */ #define PCON_IDLE (1 << 0) /* * TCON */ -sfr __at 0x88 TCON; /* CPU Interrupt Flag 1 */ +__sfr __at 0x88 TCON; /* CPU Interrupt Flag 1 */ sbit __at 0x8F URX1IF; /* USART1 RX interrupt flag. Automatically cleared */ sbit __at 0x8F I2SRXIF; /* I2S RX interrupt flag. Automatically cleared */ @@ -150,7 +150,7 @@ sbit __at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically clea /* * S0CON */ -sfr __at 0x98 S0CON; /* CPU Interrupt Flag 2 */ +__sfr __at 0x98 S0CON; /* CPU Interrupt Flag 2 */ sbit __at 0x98 ENCIF_0; /* AES interrupt 0. */ sbit __at 0x99 ENCIF_1; /* AES interrupt 1. */ @@ -161,7 +161,7 @@ sbit __at 0x99 ENCIF_1; /* AES interrupt 1. */ /* * S1CON */ -sfr __at 0x9B S1CON; /* CPU Interrupt Flag 3 */ +__sfr __at 0x9B S1CON; /* CPU Interrupt Flag 3 */ #define S1CON_RFIF_1 (1 << 1) #define S1CON_RFIF_0 (1 << 0) @@ -169,7 +169,7 @@ sfr __at 0x9B S1CON; /* CPU Interrupt Flag 3 */ /* * IRCON */ -sfr __at 0xC0 IRCON; /* CPU Interrupt Flag 4 */ +__sfr __at 0xC0 IRCON; /* CPU Interrupt Flag 4 */ sbit __at 0xC0 DMAIF; /* DMA complete interrupt flag */ sbit __at 0xC1 T1IF; /* Timer 1 interrupt flag. Automatically cleared */ @@ -190,7 +190,7 @@ sbit __at 0xC7 STIF; /* Sleep Timer interrupt flag */ /* * IRCON2 */ -sfr __at 0xE8 IRCON2; /* CPU Interrupt Flag 5 */ +__sfr __at 0xE8 IRCON2; /* CPU Interrupt Flag 5 */ sbit __at 0xE8 USBIF; /* USB interrupt flag (shared with Port2) */ sbit __at 0xE8 P2IF; /* Port2 interrupt flag (shared with USB) */ @@ -225,8 +225,8 @@ sbit __at 0xEC WDTIF; /* Watchdog timer interrupt flag */ * Priority = (IP1 << 1) | IP0. Higher priority interrupts served first */ -sfr __at 0xB9 IP1; /* Interrupt Priority 1 */ -sfr __at 0xA9 IP0; /* Interrupt Priority 0 */ +__sfr __at 0xB9 IP1; /* Interrupt Priority 1 */ +__sfr __at 0xA9 IP0; /* Interrupt Priority 0 */ #define IP1_IPG5 (1 << 5) #define IP1_IPG4 (1 << 4) @@ -286,13 +286,13 @@ sfr __at 0xA9 IP0; /* Interrupt Priority 0 */ */ /* Timer count */ -sfr __at 0xCA T3CNT; -sfr __at 0xEA T4CNT; +__sfr __at 0xCA T3CNT; +__sfr __at 0xEA T4CNT; /* Timer control */ -sfr __at 0xCB T3CTL; -sfr __at 0xEB T4CTL; +__sfr __at 0xCB T3CTL; +__sfr __at 0xEB T4CTL; #define TxCTL_DIV_1 (0 << 5) #define TxCTL_DIV_2 (1 << 5) @@ -312,10 +312,10 @@ sfr __at 0xEB T4CTL; /* Timer 4 channel 0 compare control */ -sfr __at 0xCC T3CCTL0; -sfr __at 0xCE T3CCTL1; -sfr __at 0xEC T4CCTL0; -sfr __at 0xEE T4CCTL1; +__sfr __at 0xCC T3CCTL0; +__sfr __at 0xCE T3CCTL1; +__sfr __at 0xEC T4CCTL0; +__sfr __at 0xEE T4CCTL1; #define TxCCTLy_IM (1 << 6) #define TxCCTLy_CMP_SET (0 << 3) @@ -328,16 +328,16 @@ sfr __at 0xEE T4CCTL1; #define TxCCTLy_CMP_MODE_ENABLE (1 << 2) /* Timer compare value */ -sfr __at 0xCD T3CC0; -sfr __at 0xCF T3CC1; -sfr __at 0xED T4CC0; -sfr __at 0xEF T4CC1; +__sfr __at 0xCD T3CC0; +__sfr __at 0xCF T3CC1; +__sfr __at 0xED T4CC0; +__sfr __at 0xEF T4CC1; /* * Peripheral control */ -sfr __at 0xf1 PERCFG; +__sfr __at 0xf1 PERCFG; #define PERCFG_T1CFG_ALT_1 (0 << 6) #define PERCFG_T1CFG_ALT_2 (1 << 6) #define PERCFG_T1CFG_ALT_MASK (1 << 6) @@ -442,12 +442,12 @@ __xdata __at (0xde17) volatile uint8_t USBCNTH; __xdata __at (0xde20) volatile uint8_t USBFIFO[12]; /* ADC Data register, low and high */ -sfr at 0xBA ADCL; -sfr at 0xBB ADCH; +__sfr at 0xBA ADCL; +__sfr at 0xBB ADCH; __xdata __at (0xDFBA) volatile uint16_t ADCXDATA; /* ADC Control Register 1 */ -sfr at 0xB4 ADCCON1; +__sfr at 0xB4 ADCCON1; # define ADCCON1_EOC (1 << 7) /* conversion complete */ # define ADCCON1_ST (1 << 6) /* start conversion */ @@ -463,7 +463,7 @@ sfr at 0xB4 ADCCON1; # define ADCCON1_RCTRL_CLOCK_LFSR (1 << 2) /* Clock the LFSR once */ /* ADC Control Register 2 */ -sfr at 0xB5 ADCCON2; +__sfr at 0xB5 ADCCON2; # define ADCCON2_SREF_MASK (3 << 6) /* reference voltage */ # define ADCCON2_SREF_1_25V (0 << 6) /* internal 1.25V */ @@ -498,7 +498,7 @@ sfr at 0xB5 ADCCON2; /* ADC Control Register 3 */ -sfr at 0xB6 ADCCON3; +__sfr at 0xB6 ADCCON3; # define ADCCON3_EREF_MASK (3 << 6) /* extra conversion reference */ # define ADCCON3_EREF_1_25 (0 << 6) /* internal 1.25V */ @@ -533,13 +533,13 @@ sfr at 0xB6 ADCCON3; * ADC configuration register, this selects which * GPIO pins are to be used as ADC inputs */ -sfr at 0xF2 ADCCFG; +__sfr at 0xF2 ADCCFG; /* * Watchdog timer */ -sfr at 0xc9 WDCTL; +__sfr at 0xc9 WDCTL; #define WDCTL_CLEAR_FIRST (0xa << 4) #define WDCTL_CLEAR_SECOND (0x5 << 4) @@ -556,9 +556,9 @@ sfr at 0xc9 WDCTL; * Pin selectors, these set which pins are * using their peripheral function */ -sfr at 0xF3 P0SEL; -sfr at 0xF4 P1SEL; -sfr at 0xF5 P2SEL; +__sfr at 0xF3 P0SEL; +__sfr at 0xF4 P1SEL; +__sfr at 0xF5 P2SEL; #define P2SEL_PRI3P1_USART0 (0 << 6) #define P2SEL_PRI3P1_USART1 (1 << 6) @@ -585,9 +585,9 @@ sfr at 0xF5 P2SEL; /* * For pins used as GPIOs, these set which are used as outputs */ -sfr at 0xFD P0DIR; -sfr at 0xFE P1DIR; -sfr at 0xFF P2DIR; +__sfr at 0xFD P0DIR; +__sfr at 0xFE P1DIR; +__sfr at 0xFF P2DIR; #define P2DIR_PRIP0_USART0_USART1 (0 << 6) #define P2DIR_PRIP0_USART1_USART0 (1 << 6) @@ -595,7 +595,7 @@ sfr at 0xFF P2DIR; #define P2DIR_PRIP0_TIMER1_2_USART0 (3 << 6) #define P2DIR_PRIP0_MASK (3 << 6) -sfr at 0x8F P0INP; +__sfr at 0x8F P0INP; /* Select between tri-state and pull up/down * for pins P0_0 - P0_7. @@ -617,7 +617,7 @@ sfr at 0x8F P0INP; #define P0INP_MDP0_0_PULL (0 << 0) #define P0INP_MDP0_0_TRISTATE (1 << 0) -sfr at 0xF6 P1INP; +__sfr at 0xF6 P1INP; /* Select between tri-state and pull up/down * for pins P1_2 - P1_7. Pins P1_0 and P1_1 are @@ -636,7 +636,7 @@ sfr at 0xF6 P1INP; #define P1INP_MDP1_2_PULL (0 << 2) #define P1INP_MDP1_2_TRISTATE (1 << 2) -sfr at 0xF7 P2INP; +__sfr at 0xF7 P2INP; /* P2INP has three extra bits which are used to choose * between pull-up and pull-down when they are not tri-stated */ @@ -662,13 +662,13 @@ sfr at 0xF7 P2INP; #define P2INP_MDP2_0_TRISTATE (1 << 0) /* GPIO interrupt status flags */ -sfr at 0x89 P0IFG; -sfr at 0x8A P1IFG; -sfr at 0x8B P2IFG; +__sfr at 0x89 P0IFG; +__sfr at 0x8A P1IFG; +__sfr at 0x8B P2IFG; #define P0IFG_USB_RESUME (1 << 7) -sfr at 0x8C PICTL; +__sfr at 0x8C PICTL; #define PICTL_P2IEN (1 << 5) #define PICTL_P0IENH (1 << 4) #define PICTL_P0IENL (1 << 3) @@ -677,7 +677,7 @@ sfr at 0x8C PICTL; #define PICTL_P0ICON (1 << 0) /* GPIO pins */ -sfr at 0x80 P0; +__sfr at 0x80 P0; sbit at 0x80 P0_0; sbit at 0x81 P0_1; @@ -688,7 +688,7 @@ sbit at 0x85 P0_5; sbit at 0x86 P0_6; sbit at 0x87 P0_7; -sfr at 0x90 P1; +__sfr at 0x90 P1; sbit at 0x90 P1_0; sbit at 0x91 P1_1; @@ -699,7 +699,7 @@ sbit at 0x95 P1_5; sbit at 0x96 P1_6; sbit at 0x97 P1_7; -sfr at 0xa0 P2; +__sfr at 0xa0 P2; sbit at 0xa0 P2_0; sbit at 0xa1 P2_1; @@ -794,7 +794,7 @@ struct cc_dma_channel { * DMAARM - DMA Channel Arm */ -sfr at 0xD6 DMAARM; +__sfr at 0xD6 DMAARM; # define DMAARM_ABORT (1 << 7) # define DMAARM_DMAARM4 (1 << 4) @@ -807,7 +807,7 @@ sfr at 0xD6 DMAARM; * DMAREQ - DMA Channel Start Request and Status */ -sfr at 0xD7 DMAREQ; +__sfr at 0xD7 DMAREQ; # define DMAREQ_DMAREQ4 (1 << 4) # define DMAREQ_DMAREQ3 (1 << 3) @@ -819,21 +819,21 @@ sfr at 0xD7 DMAREQ; * DMA configuration 0 address */ -sfr at 0xD5 DMA0CFGH; -sfr at 0xD4 DMA0CFGL; +__sfr at 0xD5 DMA0CFGH; +__sfr at 0xD4 DMA0CFGL; /* * DMA configuration 1-4 address */ -sfr at 0xD3 DMA1CFGH; -sfr at 0xD2 DMA1CFGL; +__sfr at 0xD3 DMA1CFGH; +__sfr at 0xD2 DMA1CFGL; /* * DMAIRQ - DMA Interrupt Flag */ -sfr at 0xD1 DMAIRQ; +__sfr at 0xD1 DMAIRQ; # define DMAIRQ_DMAIF4 (1 << 4) # define DMAIRQ_DMAIF3 (1 << 3) @@ -846,8 +846,8 @@ sfr at 0xD1 DMAIRQ; */ /* USART config/status registers */ -sfr at 0x86 U0CSR; -sfr at 0xF8 U1CSR; +__sfr at 0x86 U0CSR; +__sfr at 0xF8 U1CSR; # define UxCSR_MODE_UART (1 << 7) # define UxCSR_MODE_SPI (0 << 7) @@ -861,8 +861,8 @@ sfr at 0xF8 U1CSR; # define UxCSR_ACTIVE (1 << 0) /* UART configuration registers */ -sfr at 0xc4 U0UCR; -sfr at 0xfb U1UCR; +__sfr at 0xc4 U0UCR; +__sfr at 0xfb U1UCR; # define UxUCR_FLUSH (1 << 7) # define UxUCR_FLOW_DISABLE (0 << 6) @@ -881,8 +881,8 @@ sfr at 0xfb U1UCR; # define UxUCR_START_HIGH (1 << 0) /* USART General configuration registers (mostly SPI) */ -sfr at 0xc5 U0GCR; -sfr at 0xfc U1GCR; +__sfr at 0xc5 U0GCR; +__sfr at 0xfc U1GCR; # define UxGCR_CPOL_NEGATIVE (0 << 7) # define UxGCR_CPOL_POSITIVE (1 << 7) @@ -894,18 +894,18 @@ sfr at 0xfc U1GCR; # define UxGCR_BAUD_E_SHIFT 0 /* USART data registers */ -sfr at 0xc1 U0DBUF; +__sfr at 0xc1 U0DBUF; __xdata __at (0xDFC1) volatile uint8_t U0DBUFXADDR; -sfr at 0xf9 U1DBUF; +__sfr at 0xf9 U1DBUF; __xdata __at (0xDFF9) volatile uint8_t U1DBUFXADDR; /* USART baud rate registers, M value */ -sfr at 0xc2 U0BAUD; -sfr at 0xfa U1BAUD; +__sfr at 0xc2 U0BAUD; +__sfr at 0xfa U1BAUD; /* Flash controller */ -sfr at 0xAE FCTL; +__sfr at 0xAE FCTL; #define FCTL_BUSY (1 << 7) #define FCTL_SWBSY (1 << 6) #define FCTL_CONTRD_ENABLE (1 << 4) @@ -913,22 +913,22 @@ sfr at 0xAE FCTL; #define FCTL_ERASE (1 << 0) /* Flash write data. Write two bytes here */ -sfr at 0xAF FWDATA; +__sfr at 0xAF FWDATA; __xdata __at (0xDFAF) volatile uint8_t FWDATAXADDR; /* Flash write/erase address */ -sfr at 0xAD FADDRH; -sfr at 0xAC FADDRL; +__sfr at 0xAD FADDRH; +__sfr at 0xAC FADDRL; /* Flash timing */ -sfr at 0xAB FWT; +__sfr at 0xAB FWT; /* Radio */ -sfr at 0xD9 RFD; +__sfr at 0xD9 RFD; __xdata at (0xDFD9) volatile uint8_t RFDXADDR; -sfr at 0xE9 RFIF; +__sfr at 0xE9 RFIF; #define RFIF_IM_TXUNF (1 << 7) #define RFIF_IM_RXOVF (1 << 6) #define RFIF_IM_TIMEOUT (1 << 5) @@ -938,7 +938,7 @@ sfr at 0xE9 RFIF; #define RFIF_IM_CCA (1 << 1) #define RFIF_IM_SFD (1 << 0) -sfr at 0x91 RFIM; +__sfr at 0x91 RFIM; #define RFIM_IM_TXUNF (1 << 7) #define RFIM_IM_RXOVF (1 << 6) #define RFIM_IM_TIMEOUT (1 << 5) @@ -948,7 +948,7 @@ sfr at 0x91 RFIM; #define RFIM_IM_CCA (1 << 1) #define RFIM_IM_SFD (1 << 0) -sfr at 0xE1 RFST; +__sfr at 0xE1 RFST; #define RFST_SFSTXON 0x00 #define RFST_SCAL 0x01 -- cgit v1.2.3 From 51796e2f1ebce3ee8dc1ac90648381410c1379ee Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 23 May 2011 11:32:29 -0700 Subject: altos, altosui: Add igniter mode (dual, apogee, main) This provides for redundant charges for either apogee or main. Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 7 ++++++ altosui/AltosConfigData.java | 2 ++ altosui/AltosConfigUI.java | 54 ++++++++++++++++++++++++++++++++++++++++---- src/ao.h | 7 +++++- src/ao_config.c | 31 +++++++++++++++++++++++++ src/ao_ignite.c | 50 ++++++++++++++++++++++++++++++++-------- 6 files changed, 136 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index c5de83f2..e3c30d4d 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -70,6 +70,7 @@ public class AltosConfig implements ActionListener { int_ref radio_channel; int_ref radio_calibration; int_ref flight_log_max; + int_ref ignite_mode; string_ref version; string_ref product; string_ref callsign; @@ -130,6 +131,7 @@ public class AltosConfig implements ActionListener { config_ui.set_radio_channel(radio_channel.get()); config_ui.set_radio_calibration(radio_calibration.get()); config_ui.set_flight_log_max(flight_log_max.get()); + config_ui.set_ignite_mode(ignite_mode.get()); config_ui.set_callsign(callsign.get()); config_ui.set_clean(); config_ui.make_visible(); @@ -153,6 +155,7 @@ public class AltosConfig implements ActionListener { get_int(line, "Radio channel:", radio_channel); get_int(line, "Radio cal:", radio_calibration); get_int(line, "Max flight log:", flight_log_max); + get_int(line, "Ignite mode:", ignite_mode); get_string(line, "Callsign:", callsign); get_string(line,"software-version", version); get_string(line,"product", product); @@ -224,6 +227,8 @@ public class AltosConfig implements ActionListener { serial_line.printf("c c %s\n", callsign.get()); if (flight_log_max.get() != 0) serial_line.printf("c l %d\n", flight_log_max.get()); + if (ignite_mode.get() >= 0) + serial_line.printf("c i %d\n", ignite_mode.get()); serial_line.printf("c w\n"); } catch (InterruptedException ie) { } finally { @@ -306,6 +311,7 @@ public class AltosConfig implements ActionListener { radio_channel.set(config_ui.radio_channel()); radio_calibration.set(config_ui.radio_calibration()); flight_log_max.set(config_ui.flight_log_max()); + ignite_mode.set(config_ui.ignite_mode()); callsign.set(config_ui.callsign()); run_serial_thread(serial_mode_save); } @@ -340,6 +346,7 @@ public class AltosConfig implements ActionListener { radio_channel = new int_ref(0); radio_calibration = new int_ref(1186611); flight_log_max = new int_ref(0); + ignite_mode = new int_ref(-1); callsign = new string_ref("N0CALL"); version = new string_ref("unknown"); product = new string_ref("unknown"); diff --git a/altosui/AltosConfigData.java b/altosui/AltosConfigData.java index 8c32ed86..3f0e9af3 100644 --- a/altosui/AltosConfigData.java +++ b/altosui/AltosConfigData.java @@ -51,6 +51,7 @@ public class AltosConfigData implements Iterable { int accel_cal_plus, accel_cal_minus; int radio_calibration; int flight_log_max; + int ignite_mode; static String get_string(String line, String label) throws ParseException { @@ -96,6 +97,7 @@ public class AltosConfigData implements Iterable { try { radio_channel = get_int(line, "Radio channel:"); } catch (Exception e) {} try { radio_calibration = get_int(line, "Radio cal:"); } catch (Exception e) {} try { flight_log_max = get_int(line, "Max flight log:"); } catch (Exception e) {} + try { ignite_mode = get_int(line, "Ignite mode:"); } catch (Exception e) {} try { callsign = get_string(line, "Callsign:"); } catch (Exception e) {} try { version = get_string(line,"software-version"); } catch (Exception e) {} try { product = get_string(line,"product"); } catch (Exception e) {} diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index f835ee2e..6f635b9d 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -46,6 +46,7 @@ public class AltosConfigUI JLabel radio_channel_label; JLabel radio_calibration_label; JLabel flight_log_max_label; + JLabel ignite_mode_label; JLabel callsign_label; public boolean dirty; @@ -59,6 +60,7 @@ public class AltosConfigUI JComboBox radio_channel_value; JTextField radio_calibration_value; JComboBox flight_log_max_value; + JComboBox ignite_mode_value; JTextField callsign_value; JButton save; @@ -83,6 +85,12 @@ public class AltosConfigUI "704", "768", "832", "896", "960", }; + static String[] ignite_mode_values = { + "Dual Deploy", + "Redundant Apogee", + "Redundant Main", + }; + static String[] radio_channel_values = new String[10]; { for (int i = 0; i <= 9; i++) @@ -326,9 +334,33 @@ public class AltosConfigUI flight_log_max_value.addItemListener(this); pane.add(flight_log_max_value, c); - /* Buttons */ + /* Ignite mode */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = 9; + c.gridwidth = 4; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; + ignite_mode_label = new JLabel("Igniter Firing Mode:"); + pane.add(ignite_mode_label, c); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = 9; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + ignite_mode_value = new JComboBox(ignite_mode_values); + ignite_mode_value.setEditable(false); + ignite_mode_value.addItemListener(this); + pane.add(ignite_mode_value, c); + + /* Buttons */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 10; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -339,7 +371,7 @@ public class AltosConfigUI save.setActionCommand("Save"); c = new GridBagConstraints(); - c.gridx = 2; c.gridy = 9; + c.gridx = 2; c.gridy = 10; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; @@ -350,7 +382,7 @@ public class AltosConfigUI reset.setActionCommand("Reset"); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 9; + c.gridx = 4; c.gridy = 10; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; @@ -361,7 +393,7 @@ public class AltosConfigUI reboot.setActionCommand("Reboot"); c = new GridBagConstraints(); - c.gridx = 6; c.gridy = 9; + c.gridx = 6; c.gridy = 10; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_END; @@ -499,6 +531,20 @@ public class AltosConfigUI return Integer.parseInt(flight_log_max_value.getSelectedItem().toString()); } + public void set_ignite_mode(int new_ignite_mode) { + if (new_ignite_mode < 0) { + ignite_mode_value.setEnabled(false); + new_ignite_mode = 0; + } else { + ignite_mode_value.setEnabled(true); + } + ignite_mode_value.setSelectedItem(Integer.toString(new_ignite_mode)); + } + + public int ignite_mode() { + return ignite_mode_value.getSelectedIndex(); + } + public void set_clean() { dirty = false; } diff --git a/src/ao.h b/src/ao.h index e52a2198..d3e588b6 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1357,7 +1357,7 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 4 +#define AO_CONFIG_MINOR 5 struct ao_config { uint8_t major; @@ -1370,8 +1370,13 @@ struct ao_config { int16_t accel_minus_g; /* minor version 2 */ uint32_t radio_cal; /* minor version 3 */ uint32_t flight_log_max; /* minor version 4 */ + uint8_t ignite_mode; /* minor version 5 */ }; +#define AO_IGNITE_MODE_DUAL 0 +#define AO_IGNITE_MODE_APOGEE 1 +#define AO_IGNITE_MODE_MAIN 2 + extern __xdata struct ao_config ao_config; #define AO_CONFIG_MAX_SIZE 128 diff --git a/src/ao_config.c b/src/ao_config.c index 813164ea..48349886 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -27,6 +27,7 @@ __xdata uint8_t ao_config_mutex; #define AO_CONFIG_DEFAULT_CALLSIGN "N0CALL" #define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000 #define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 +#define AO_CONFIG_DEFAULT_IGNITE_MODE AO_IGNITE_MODE_DUAL #if USE_INTERNAL_EEPROM #define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_config #else @@ -75,6 +76,7 @@ _ao_config_get(void) ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; ao_config.radio_cal = ao_radio_cal; ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; + ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { @@ -92,6 +94,9 @@ _ao_config_get(void) /* Fixups for minor version 4 */ if (ao_config.minor < 4) ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; + /* Fixupes for minor version 5 */ + if (ao_config.minor < 5) + ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -334,6 +339,28 @@ ao_config_log_set(void) __reentrant } #endif /* HAS_EEPROM */ +#if HAS_IGNITE +void +ao_config_ignite_mode_show(void) __reentrant +{ + printf("Ignite mode: %d\n", ao_config.ignite_mode); +} + +void +ao_config_ignite_mode_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_mutex_get(&ao_config_mutex); + _ao_config_get(); + ao_config.ignite_mode = ao_cmd_lex_i; + ao_config_dirty = 1; + ao_mutex_put(&ao_config_mutex); + ao_config_log_show(); +} +#endif + struct ao_config_var { __code char *str; void (*set)(void) __reentrant; @@ -369,6 +396,10 @@ __code struct ao_config_var ao_config_vars[] = { #if HAS_EEPROM { "l \0Flight log size in kB", ao_config_log_set, ao_config_log_show }, +#endif +#if HAS_IGNITE + { "i <0 dual, 1 apogee, 2 main>\0Set igniter mode", + ao_config_ignite_mode_set, ao_config_ignite_mode_show }, #endif { "s\0Show", ao_config_show, ao_config_show }, diff --git a/src/ao_ignite.c b/src/ao_ignite.c index e1b91bea..512ec622 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -51,7 +51,7 @@ void ao_ignite(enum ao_igniter igniter) __critical { ao_ignition[igniter].request = 1; - ao_wakeup(&ao_ignition[0]); + ao_wakeup(&ao_ignition); } enum ao_igniter_status @@ -91,16 +91,46 @@ void ao_igniter_fire(enum ao_igniter igniter) __critical { ao_ignition[igniter].firing = 1; - switch (igniter) { - case ao_igniter_drogue: - AO_IGNITER_DROGUE = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_DROGUE = 0; + switch(ao_config.ignite_mode) { + case AO_IGNITE_MODE_DUAL: + switch (igniter) { + case ao_igniter_drogue: + AO_IGNITER_DROGUE = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_DROGUE = 0; + break; + case ao_igniter_main: + AO_IGNITER_MAIN = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_MAIN = 0; + break; + } break; - case ao_igniter_main: - AO_IGNITER_MAIN = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_MAIN = 0; + case AO_IGNITE_MODE_APOGEE: + switch (igniter) { + case ao_igniter_drogue: + AO_IGNITER_DROGUE = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_DROGUE = 0; + ao_delay(AO_IGNITER_CHARGE_TIME); + AO_IGNITER_MAIN = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_MAIN = 0; + break; + } + break; + case AO_IGNITE_MODE_MAIN: + switch (igniter) { + case ao_igniter_main: + AO_IGNITER_DROGUE = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_DROGUE = 0; + ao_delay(AO_IGNITER_CHARGE_TIME); + AO_IGNITER_MAIN = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_MAIN = 0; + break; + } break; } ao_ignition[igniter].firing = 0; -- cgit v1.2.3 From 146a0ab223e8d9b376125d1e59f597f6d7851a9b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jul 2011 18:49:55 -0700 Subject: altos: Add ability to read new TELEM files to ao_flight_test Not that telem files are currently very useful as the kalman filter gets completly confused by the variable steps caused by missing data, but... Signed-off-by: Keith Packard --- src/ao_flight_test.c | 209 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/ao_kalman.c | 37 +++++++++ src/make-kalman | 3 + 3 files changed, 249 insertions(+) (limited to 'src') diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 57785442..72ad1450 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -298,6 +298,139 @@ ao_insert(void) } } +#define AO_MAX_CALLSIGN 8 +#define AO_MAX_VERSION 8 +#define AO_MAX_TELEMETRY 128 + +struct ao_telemetry_generic { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t payload[27]; /* 5 */ + /* 32 */ +}; + +#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 +#define AO_TELEMETRY_SENSOR_TELEMINI 0x02 +#define AO_TELEMETRY_SENSOR_TELENANO 0x03 + +struct ao_telemetry_sensor { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t state; /* 5 flight state */ + int16_t accel; /* 6 accelerometer (TM only) */ + int16_t pres; /* 8 pressure sensor */ + int16_t temp; /* 10 temperature sensor */ + int16_t v_batt; /* 12 battery voltage */ + int16_t sense_d; /* 14 drogue continuity sense (TM/Tm) */ + int16_t sense_m; /* 16 main continuity sense (TM/Tm) */ + + int16_t acceleration; /* 18 m/s² * 16 */ + int16_t speed; /* 20 m/s * 16 */ + int16_t height; /* 22 m */ + + int16_t ground_pres; /* 24 average pres on pad */ + int16_t ground_accel; /* 26 average accel on pad */ + int16_t accel_plus_g; /* 28 accel calibration at +1g */ + int16_t accel_minus_g; /* 30 accel calibration at -1g */ + /* 32 */ +}; + +#define AO_TELEMETRY_CONFIGURATION 0x04 + +struct ao_telemetry_configuration { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t device; /* 5 device type */ + uint16_t flight; /* 6 flight number */ + uint8_t config_major; /* 8 Config major version */ + uint8_t config_minor; /* 9 Config minor version */ + uint16_t apogee_delay; /* 10 Apogee deploy delay in seconds */ + uint16_t main_deploy; /* 12 Main deploy alt in meters */ + uint16_t flight_log_max; /* 14 Maximum flight log size in kB */ + char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ + char version[AO_MAX_VERSION]; /* 24 Software version */ + /* 32 */ +}; + +#define AO_TELEMETRY_LOCATION 0x05 + +#define AO_GPS_MODE_NOT_VALID 'N' +#define AO_GPS_MODE_AUTONOMOUS 'A' +#define AO_GPS_MODE_DIFFERENTIAL 'D' +#define AO_GPS_MODE_ESTIMATED 'E' +#define AO_GPS_MODE_MANUAL 'M' +#define AO_GPS_MODE_SIMULATED 'S' + +struct ao_telemetry_location { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t flags; /* 5 Number of sats and other flags */ + int16_t altitude; /* 6 GPS reported altitude (m) */ + int32_t latitude; /* 8 latitude (degrees * 10⁷) */ + int32_t longitude; /* 12 longitude (degrees * 10⁷) */ + uint8_t year; /* 16 (- 2000) */ + uint8_t month; /* 17 (1-12) */ + uint8_t day; /* 18 (1-31) */ + uint8_t hour; /* 19 (0-23) */ + uint8_t minute; /* 20 (0-59) */ + uint8_t second; /* 21 (0-59) */ + uint8_t pdop; /* 22 (m * 5) */ + uint8_t hdop; /* 23 (m * 5) */ + uint8_t vdop; /* 24 (m * 5) */ + uint8_t mode; /* 25 */ + uint16_t ground_speed; /* 26 cm/s */ + int16_t climb_rate; /* 28 cm/s */ + uint8_t course; /* 30 degrees / 2 */ + uint8_t unused[1]; /* 31 */ + /* 32 */ +}; + +#define AO_TELEMETRY_SATELLITE 0x06 + +struct ao_telemetry_satellite_info { + uint8_t svid; + uint8_t c_n_1; +}; + +struct ao_telemetry_satellite { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t channels; /* 5 number of reported sats */ + + struct ao_telemetry_satellite_info sats[12]; /* 6 */ + uint8_t unused[2]; /* 30 */ + /* 32 */ +}; + +union ao_telemetry_all { + struct ao_telemetry_generic generic; + struct ao_telemetry_sensor sensor; + struct ao_telemetry_configuration configuration; + struct ao_telemetry_location location; + struct ao_telemetry_satellite satellite; +}; + +uint16_t +uint16(uint8_t *bytes, int off) +{ + off++; + return (uint16_t) bytes[off] | (((uint16_t) bytes[off+1]) << 8); +} + +int16_t +int16(uint8_t *bytes, int off) +{ + return (int16_t) uint16(bytes, off); +} + void ao_sleep(void *wchan) { @@ -306,6 +439,8 @@ ao_sleep(void *wchan) uint16_t tick; uint16_t a, b; int ret; + uint8_t bytes[1024]; + union ao_telemetry_all telem; char line[1024]; char *saveptr; char *l; @@ -342,6 +477,8 @@ ao_sleep(void *wchan) tick = strtoul(words[1], NULL, 16); a = strtoul(words[2], NULL, 16); b = strtoul(words[3], NULL, 16); + if (type == 'P') + type = 'A'; } else if (nword >= 6 && strcmp(words[0], "Accel") == 0) { ao_config.accel_plus_g = atoi(words[3]); ao_config.accel_minus_g = atoi(words[5]); @@ -358,6 +495,78 @@ ao_sleep(void *wchan) a = atoi(words[12]); b = atoi(words[14]); } + } else if (nword == 2 && strcmp(words[0], "TELEM") == 0) { + char *hex = words[1]; + char elt[3]; + int i, len; + uint8_t sum; + + len = strlen(hex); + if (len > sizeof (bytes) * 2) { + len = sizeof (bytes)*2; + hex[len] = '\0'; + } + for (i = 0; i < len; i += 2) { + elt[0] = hex[i]; + elt[1] = hex[i+1]; + elt[2] = '\0'; + bytes[i/2] = (uint8_t) strtol(elt, NULL, 16); + } + len = i/2; + if (bytes[0] != len - 2) { + printf ("bad length %d != %d\n", bytes[0], len - 2); + continue; + } + sum = 0x5a; + for (i = 1; i < len-1; i++) + sum += bytes[i]; + if (sum != bytes[len-1]) { + printf ("bad checksum\n"); + continue; + } + if ((bytes[len-2] & 0x80) == 0) { + continue; + } + if (len == 36) { + memcpy(&telem, bytes + 1, 32); + tick = telem.generic.tick; + switch (telem.generic.type) { + case AO_TELEMETRY_SENSOR_TELEMETRUM: + case AO_TELEMETRY_SENSOR_TELEMINI: + case AO_TELEMETRY_SENSOR_TELENANO: + if (!ao_flight_started) { + ao_flight_ground_accel = telem.sensor.ground_accel; + ao_config.accel_plus_g = telem.sensor.accel_plus_g; + ao_config.accel_minus_g = telem.sensor.accel_minus_g; + ao_flight_started = 1; + } + type = 'A'; + a = telem.sensor.accel; + b = telem.sensor.pres; + break; + } + } else if (len == 99) { + ao_flight_started = 1; + tick = uint16(bytes, 21); + ao_flight_ground_accel = int16(bytes, 7); + ao_config.accel_plus_g = int16(bytes, 17); + ao_config.accel_minus_g = int16(bytes, 19); + type = 'A'; + a = int16(bytes, 23); + b = int16(bytes, 25); + } else if (len == 98) { + ao_flight_started = 1; + tick = uint16(bytes, 20); + ao_flight_ground_accel = int16(bytes, 6); + ao_config.accel_plus_g = int16(bytes, 16); + ao_config.accel_minus_g = int16(bytes, 18); + type = 'A'; + a = int16(bytes, 22); + b = int16(bytes, 24); + } else { + printf("unknown len %d\n", len); + continue; + } } if (type != 'F' && !ao_flight_started) continue; diff --git a/src/ao_kalman.c b/src/ao_kalman.c index fb75fba9..4e6cbb06 100644 --- a/src/ao_kalman.c +++ b/src/ao_kalman.c @@ -31,6 +31,9 @@ static __pdata int32_t ao_k_accel; #define AO_K_STEP_10 to_fix16(0.1) #define AO_K_STEP_2_2_10 to_fix16(0.005) +#define AO_K_STEP_1 to_fix16(1) +#define AO_K_STEP_2_2_1 to_fix16(0.5) + __pdata int16_t ao_height; __pdata int16_t ao_speed; __pdata int16_t ao_accel; @@ -47,6 +50,13 @@ static void ao_kalman_predict(void) { #ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 50) { + ao_k_height += ((int32_t) ao_speed * AO_K_STEP_1 + + (int32_t) ao_accel * AO_K_STEP_2_2_1) >> 4; + ao_k_speed += (int32_t) ao_accel * AO_K_STEP_1; + + return; + } if (ao_sample_tick - ao_sample_prev_tick > 5) { ao_k_height += ((int32_t) ao_speed * AO_K_STEP_10 + (int32_t) ao_accel * AO_K_STEP_2_2_10) >> 4; @@ -126,6 +136,12 @@ ao_kalman_correct_baro(void) { ao_kalman_err_height(); #ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 50) { + ao_k_height += (int32_t) AO_BARO_K0_1 * ao_error_h; + ao_k_speed += (int32_t) AO_BARO_K1_1 * ao_error_h; + ao_k_accel += (int32_t) AO_BARO_K2_1 * ao_error_h; + return; + } if (ao_sample_tick - ao_sample_prev_tick > 5) { ao_k_height += (int32_t) AO_BARO_K0_10 * ao_error_h; ao_k_speed += (int32_t) AO_BARO_K1_10 * ao_error_h; @@ -158,6 +174,27 @@ ao_kalman_correct_both(void) ao_kalman_err_accel(); #ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 50) { + if (ao_flight_debug) { + printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), + (double) ao_error_h, AO_BOTH_K10_1 / 65536.0, + (double) ao_error_a, AO_BOTH_K11_1 / 65536.0, + (ao_k_speed + + (int32_t) AO_BOTH_K10_1 * ao_error_h + + (int32_t) AO_BOTH_K11_1 * ao_error_a) / (65536.0 * 16.0)); + } + ao_k_height += + (int32_t) AO_BOTH_K00_1 * ao_error_h + + (int32_t) AO_BOTH_K01_1 * ao_error_a; + ao_k_speed += + (int32_t) AO_BOTH_K10_1 * ao_error_h + + (int32_t) AO_BOTH_K11_1 * ao_error_a; + ao_k_accel += + (int32_t) AO_BOTH_K20_1 * ao_error_h + + (int32_t) AO_BOTH_K21_1 * ao_error_a; + return; + } if (ao_sample_tick - ao_sample_prev_tick > 5) { if (ao_flight_debug) { printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", diff --git a/src/make-kalman b/src/make-kalman index 5a25e1ec..9ac35134 100644 --- a/src/make-kalman +++ b/src/make-kalman @@ -8,9 +8,12 @@ SIGMA_ACCEL="-M 2 -H 4 -A 4" nickle kalman.5c -p AO_BOTH -c both -t 0.01 $SIGMA_BOTH nickle kalman.5c -p AO_BOTH -c both -t 0.1 $SIGMA_BOTH +nickle kalman.5c -p AO_BOTH -c both -t 1 $SIGMA_BOTH nickle kalman.5c -p AO_ACCEL -c accel -t 0.01 $SIGMA_ACCEL nickle kalman.5c -p AO_ACCEL -c accel -t 0.1 $SIGMA_ACCEL +nickle kalman.5c -p AO_ACCEL -c accel -t 1 $SIGMA_ACCEL nickle kalman.5c -p AO_BARO -c baro -t 0.01 $SIGMA_BARO nickle kalman.5c -p AO_BARO -c baro -t 0.1 $SIGMA_BARO +nickle kalman.5c -p AO_BARO -c baro -t 1 $SIGMA_BARO -- cgit v1.2.3 From e19a117b99e8374ca0e8e35948e23bc672ad1a32 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 1 Aug 2011 22:33:38 -0700 Subject: altos: Average height values for landing detection Instead of using the direct output of the kalman filter and hoping that is quiet enough to detect landing, filter that with a long exponential decay filter and then check to make sure that doesn't change more than 2m in 5 seconds as a trigger for landing detection. Tested with existing telemetrum flight logs and it correctly detects landing in all cases. Signed-off-by: Keith Packard --- src/ao.h | 1 + src/ao_flight.c | 15 +++++++------- src/ao_flight_test.c | 58 ++++++++++++++++++++++++++++++++++++++++++++-------- src/ao_kalman.c | 14 +++++++++++++ 4 files changed, 72 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index d3e588b6..9cde9cba 100644 --- a/src/ao.h +++ b/src/ao.h @@ -829,6 +829,7 @@ extern __pdata int16_t ao_height; /* meters */ extern __pdata int16_t ao_speed; /* m/s * 16 */ extern __pdata int16_t ao_accel; /* m/s² * 16 */ extern __pdata int16_t ao_max_height; /* max of ao_height */ +extern __pdata int16_t ao_avg_height; /* running average of height */ extern __pdata int16_t ao_error_h; extern __pdata int16_t ao_error_h_sq_avg; diff --git a/src/ao_flight.c b/src/ao_flight.c index f1b60d69..a8760ff0 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -43,7 +43,6 @@ __pdata uint16_t ao_launch_tick; /* time of launch detect */ __pdata uint16_t ao_interval_end; __pdata int16_t ao_interval_min_height; __pdata int16_t ao_interval_max_height; - __pdata uint8_t ao_flight_force_idle; /* We also have a clock, which can be used to sanity check things in @@ -242,7 +241,7 @@ ao_flight(void) /* initialize interval values */ ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; - ao_interval_min_height = ao_interval_max_height = ao_height; + ao_interval_min_height = ao_interval_max_height = ao_avg_height; /* and enter drogue state */ ao_flight_state = ao_flight_drogue; @@ -279,14 +278,14 @@ ao_flight(void) * barometer: altitude stable and within 1000m of the launch altitude */ - if (ao_height < ao_interval_min_height) - ao_interval_min_height = ao_height; - if (ao_height > ao_interval_max_height) - ao_interval_max_height = ao_height; + if (ao_avg_height < ao_interval_min_height) + ao_interval_min_height = ao_avg_height; + if (ao_avg_height > ao_interval_max_height) + ao_interval_max_height = ao_avg_height; if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { if (ao_height < AO_M_TO_HEIGHT(1000) && - ao_interval_max_height - ao_interval_min_height < AO_M_TO_HEIGHT(5)) + ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(2)) { ao_flight_state = ao_flight_landed; @@ -295,7 +294,7 @@ ao_flight(void) ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } - ao_interval_min_height = ao_interval_max_height = ao_height; + ao_interval_min_height = ao_interval_max_height = ao_avg_height; ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; } break; diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index 72ad1450..e55d5ade 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -155,6 +155,7 @@ FILE *emulator_in; char *emulator_app; char *emulator_name; double emulator_error_max = 4; +double emulator_height_error_max = 20; /* noise in the baro sensor */ void ao_dump_state(void); @@ -224,12 +225,20 @@ static int ao_test_max_height; static double ao_test_max_height_time; static int ao_test_main_height; static double ao_test_main_height_time; +static double ao_test_landed_time; +static double ao_test_landed_height; +static double ao_test_landed_time; +static int landed_set; +static double landed_time; +static double landed_height; void ao_test_exit(void) { double drogue_error; double main_error; + double landed_error; + double landed_time_error; if (!ao_test_main_height_time) { ao_test_main_height_time = ao_test_max_height_time; @@ -237,16 +246,23 @@ ao_test_exit(void) } drogue_error = fabs(ao_test_max_height_time - drogue_time); main_error = fabs(ao_test_main_height_time - main_time); - if (drogue_error > emulator_error_max || main_error > emulator_error_max) { + landed_error = fabs(ao_test_landed_height - landed_height); + landed_time_error = ao_test_landed_time - landed_time; + if (drogue_error > emulator_error_max || main_error > emulator_error_max || + landed_time_error > emulator_error_max || landed_error > emulator_height_error_max) { printf ("%s %s\n", emulator_app, emulator_name); printf ("\tApogee error %g\n", drogue_error); printf ("\tMain error %g\n", main_error); - printf ("\tActual: apogee: %d at %7.2f main: %d at %7.2f\n", + printf ("\tLanded height error %g\n", landed_error); + printf ("\tLanded time error %g\n", landed_time_error); + printf ("\tActual: apogee: %d at %7.2f main: %d at %7.2f landed %7.2f at %7.2f\n", ao_test_max_height, ao_test_max_height_time, - ao_test_main_height, ao_test_main_height_time); - printf ("\tComputed: apogee: %d at %7.2f main: %d at %7.2f\n", - drogue_height, drogue_time, main_height, main_time); + ao_test_main_height, ao_test_main_height_time, + ao_test_landed_height, ao_test_landed_time); + printf ("\tComputed: apogee: %d at %7.2f main: %d at %7.2f landed %7.2f at %7.2f\n", + drogue_height, drogue_time, main_height, main_time, + landed_height, landed_time); exit (1); } exit(0); @@ -274,14 +290,27 @@ ao_insert(void) if (ao_test_max_height < height) { ao_test_max_height = height; ao_test_max_height_time = time; + ao_test_landed_height = height; + ao_test_landed_time = time; } if (height > ao_config.main_deploy) { ao_test_main_height_time = time; ao_test_main_height = height; } + if (ao_test_landed_height > height) { + ao_test_landed_height = height; + ao_test_landed_time = time; + } + + if (ao_flight_state == ao_flight_landed && !landed_set) { + landed_set = 1; + landed_time = time; + landed_height = height; + } + if (!ao_summary) { - printf("%7.2f height %g accel %g state %s k_height %g k_speed %g k_accel %g drogue %d main %d error %d\n", + printf("%7.2f height %8.2f accel %8.3f state %-8.8s k_height %8.2f k_speed %8.3f k_accel %8.3f avg_height %5d drogue %4d main %4d error %5d\n", time, height, accel, @@ -289,11 +318,13 @@ ao_insert(void) ao_k_height / 65536.0, ao_k_speed / 65536.0 / 16.0, ao_k_accel / 65536.0 / 16.0, + ao_avg_height, drogue_height, main_height, ao_error_h_sq_avg); - if (ao_flight_state == ao_flight_landed) - ao_test_exit(); + +// if (ao_flight_state == ao_flight_landed) +// ao_test_exit(); } } } @@ -495,6 +526,17 @@ ao_sleep(void *wchan) a = atoi(words[12]); b = atoi(words[14]); } + } else if (nword == 3 && strcmp(words[0], "BARO") == 0) { + tick = strtol(words[1], NULL, 16); + a = 16384 - 328; + b = strtol(words[2], NULL, 10); + type = 'A'; + if (!ao_flight_started) { + ao_flight_ground_accel = 16384 - 328; + ao_config.accel_plus_g = 16384 - 328; + ao_config.accel_minus_g = 16384 + 328; + ao_flight_started = 1; + } } else if (nword == 2 && strcmp(words[0], "TELEM") == 0) { char *hex = words[1]; char elt[3]; diff --git a/src/ao_kalman.c b/src/ao_kalman.c index 4e6cbb06..ab97fc34 100644 --- a/src/ao_kalman.c +++ b/src/ao_kalman.c @@ -38,6 +38,8 @@ __pdata int16_t ao_height; __pdata int16_t ao_speed; __pdata int16_t ao_accel; __pdata int16_t ao_max_height; +static __pdata int32_t ao_avg_height_scaled; +__pdata int16_t ao_avg_height; __pdata int16_t ao_error_h; __pdata int16_t ao_error_h_sq_avg; @@ -275,6 +277,18 @@ ao_kalman(void) ao_accel = from_fix(ao_k_accel); if (ao_height > ao_max_height) ao_max_height = ao_height; +#ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 50) { + ao_avg_height = ao_height; + } else if (ao_sample_tick - ao_sample_prev_tick > 5) { + ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_height; + ao_avg_height = (ao_avg_height_scaled + 3) >> 2; + } else +#endif + { + ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_height; + ao_avg_height = (ao_avg_height_scaled + 15) >> 5; + } #ifdef AO_FLIGHT_TEST ao_sample_prev_tick = ao_sample_tick; #endif -- cgit v1.2.3 From 6c55bf35b11ae3ddae152795072d69e98184bac1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 2 Aug 2011 01:49:35 -0700 Subject: altos: Reduce height averaging filter time constant Using the longer time constant could lead to false landing detection just after apogee, which is definitely not a good idea. Signed-off-by: Keith Packard --- src/ao_kalman.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/ao_kalman.c b/src/ao_kalman.c index ab97fc34..203d727a 100644 --- a/src/ao_kalman.c +++ b/src/ao_kalman.c @@ -277,18 +277,15 @@ ao_kalman(void) ao_accel = from_fix(ao_k_accel); if (ao_height > ao_max_height) ao_max_height = ao_height; + ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_height; #ifdef AO_FLIGHT_TEST - if (ao_sample_tick - ao_sample_prev_tick > 50) { - ao_avg_height = ao_height; - } else if (ao_sample_tick - ao_sample_prev_tick > 5) { - ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_height; - ao_avg_height = (ao_avg_height_scaled + 3) >> 2; - } else + if (ao_sample_tick - ao_sample_prev_tick > 50) + ao_avg_height = (ao_avg_height_scaled + 1) >> 1; + else if (ao_sample_tick - ao_sample_prev_tick > 5) + ao_avg_height = (ao_avg_height_scaled + 7) >> 4; + else #endif - { - ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_height; - ao_avg_height = (ao_avg_height_scaled + 15) >> 5; - } + ao_avg_height = (ao_avg_height_scaled + 63) >> 7; #ifdef AO_FLIGHT_TEST ao_sample_prev_tick = ao_sample_tick; #endif -- cgit v1.2.3 From 82e04a0e3a3296288a524ec582785a36fd644331 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 2 Aug 2011 02:09:23 -0700 Subject: altos: Require sequencing through 'main' state before landing The old version of the code would permit the flight to go straight from 'drogue' to 'landed' without passing through 'main' at all. This meant that a false landing detection would leave the main charge unfired, potentially causing the airframe to land on drogue alone. Requiring that the flight sequence pass through main ensures that the main charge will get fired at the right time, although if the airframe lands higher than that altitude, it will not go to 'landed' mode ever. Signed-off-by: Keith Packard --- src/ao_flight.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index a8760ff0..af3d6bfa 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -233,16 +233,6 @@ ao_flight(void) /* Turn the RDF beacon back on */ ao_rdf_set(1); - /* - * Start recording min/max height - * to figure out when the rocket has landed - */ - - /* initialize interval values */ - ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; - - ao_interval_min_height = ao_interval_max_height = ao_avg_height; - /* and enter drogue state */ ao_flight_state = ao_flight_drogue; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); @@ -266,16 +256,28 @@ ao_flight(void) if (ao_height <= ao_config.main_deploy) { ao_ignite(ao_igniter_main); + + /* + * Start recording min/max height + * to figure out when the rocket has landed + */ + + /* initialize interval values */ + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + + ao_interval_min_height = ao_interval_max_height = ao_avg_height; + ao_flight_state = ao_flight_main; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } + break; /* fall through... */ case ao_flight_main: - /* drogue/main to land: + /* main to land: * - * barometer: altitude stable and within 1000m of the launch altitude + * barometer: altitude stable */ if (ao_avg_height < ao_interval_min_height) @@ -284,8 +286,7 @@ ao_flight(void) ao_interval_max_height = ao_avg_height; if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { - if (ao_height < AO_M_TO_HEIGHT(1000) && - ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(2)) + if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(2)) { ao_flight_state = ao_flight_landed; -- cgit v1.2.3 From 6492218fc316f8cf6214a577807a8dd0a80a9b6a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 2 Aug 2011 19:07:56 -0700 Subject: altos/altosui: Add pad orientation configure option Allow TeleMetrum to be operated with the antenna pointing downwards on the pad. This provides some additional flexibility when designing an ebay. The accelerometer calibration levels are flipped around to match, so no re-calibration should be required. Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 9 ++++++-- altosui/AltosConfigUI.java | 56 +++++++++++++++++++++++++++++++++++++++++----- altosui/AltosSerial.java | 1 - src/ao.h | 6 ++++- src/ao_config.c | 39 +++++++++++++++++++++++++++++++- src/ao_flight_test.c | 4 ++++ src/ao_sample.c | 2 ++ 7 files changed, 107 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index e3c30d4d..04d75528 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -71,6 +71,7 @@ public class AltosConfig implements ActionListener { int_ref radio_calibration; int_ref flight_log_max; int_ref ignite_mode; + int_ref pad_orientation; string_ref version; string_ref product; string_ref callsign; @@ -132,6 +133,7 @@ public class AltosConfig implements ActionListener { config_ui.set_radio_calibration(radio_calibration.get()); config_ui.set_flight_log_max(flight_log_max.get()); config_ui.set_ignite_mode(ignite_mode.get()); + config_ui.set_pad_orientation(pad_orientation.get()); config_ui.set_callsign(callsign.get()); config_ui.set_clean(); config_ui.make_visible(); @@ -139,12 +141,10 @@ public class AltosConfig implements ActionListener { void process_line(String line) { if (line == null) { - System.out.printf("timeout\n"); abort(); return; } if (line.equals("done")) { - System.out.printf("done\n"); if (serial_line != null) update_ui(); return; @@ -156,6 +156,7 @@ public class AltosConfig implements ActionListener { get_int(line, "Radio cal:", radio_calibration); get_int(line, "Max flight log:", flight_log_max); get_int(line, "Ignite mode:", ignite_mode); + get_int(line, "Pad orientation:", pad_orientation); get_string(line, "Callsign:", callsign); get_string(line,"software-version", version); get_string(line,"product", product); @@ -229,6 +230,8 @@ public class AltosConfig implements ActionListener { serial_line.printf("c l %d\n", flight_log_max.get()); if (ignite_mode.get() >= 0) serial_line.printf("c i %d\n", ignite_mode.get()); + if (pad_orientation.get() >= 0) + serial_line.printf("c o %d\n", pad_orientation.get()); serial_line.printf("c w\n"); } catch (InterruptedException ie) { } finally { @@ -312,6 +315,7 @@ public class AltosConfig implements ActionListener { radio_calibration.set(config_ui.radio_calibration()); flight_log_max.set(config_ui.flight_log_max()); ignite_mode.set(config_ui.ignite_mode()); + pad_orientation.set(config_ui.pad_orientation()); callsign.set(config_ui.callsign()); run_serial_thread(serial_mode_save); } @@ -347,6 +351,7 @@ public class AltosConfig implements ActionListener { radio_calibration = new int_ref(1186611); flight_log_max = new int_ref(0); ignite_mode = new int_ref(-1); + pad_orientation = new int_ref(-1); callsign = new string_ref("N0CALL"); version = new string_ref("unknown"); product = new string_ref("unknown"); diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index 6f635b9d..1a48c1d3 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -47,6 +47,7 @@ public class AltosConfigUI JLabel radio_calibration_label; JLabel flight_log_max_label; JLabel ignite_mode_label; + JLabel pad_orientation_label; JLabel callsign_label; public boolean dirty; @@ -61,6 +62,7 @@ public class AltosConfigUI JTextField radio_calibration_value; JComboBox flight_log_max_value; JComboBox ignite_mode_value; + JComboBox pad_orientation_value; JTextField callsign_value; JButton save; @@ -91,6 +93,11 @@ public class AltosConfigUI "Redundant Main", }; + static String[] pad_orientation_values = { + "Antenna Up", + "Antenna Down", + }; + static String[] radio_channel_values = new String[10]; { for (int i = 0; i <= 9; i++) @@ -358,9 +365,33 @@ public class AltosConfigUI ignite_mode_value.addItemListener(this); pane.add(ignite_mode_value, c); - /* Buttons */ + /* Pad orientation */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = 10; + c.gridwidth = 4; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; + pad_orientation_label = new JLabel("Pad Orientation:"); + pane.add(pad_orientation_label, c); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = 10; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + pad_orientation_value = new JComboBox(pad_orientation_values); + pad_orientation_value.setEditable(false); + pad_orientation_value.addItemListener(this); + pane.add(pad_orientation_value, c); + + /* Buttons */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 11; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -371,7 +402,7 @@ public class AltosConfigUI save.setActionCommand("Save"); c = new GridBagConstraints(); - c.gridx = 2; c.gridy = 10; + c.gridx = 2; c.gridy = 11; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; @@ -382,7 +413,7 @@ public class AltosConfigUI reset.setActionCommand("Reset"); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 10; + c.gridx = 4; c.gridy = 11; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; @@ -393,7 +424,7 @@ public class AltosConfigUI reboot.setActionCommand("Reboot"); c = new GridBagConstraints(); - c.gridx = 6; c.gridy = 10; + c.gridx = 6; c.gridy = 11; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_END; @@ -538,13 +569,28 @@ public class AltosConfigUI } else { ignite_mode_value.setEnabled(true); } - ignite_mode_value.setSelectedItem(Integer.toString(new_ignite_mode)); + ignite_mode_value.setSelectedIndex(new_ignite_mode); } public int ignite_mode() { return ignite_mode_value.getSelectedIndex(); } + + public void set_pad_orientation(int new_pad_orientation) { + if (new_pad_orientation < 0) { + pad_orientation_value.setEnabled(false); + new_pad_orientation = 0; + } else { + pad_orientation_value.setEnabled(true); + } + pad_orientation_value.setSelectedIndex(new_pad_orientation); + } + + public int pad_orientation() { + return pad_orientation_value.getSelectedIndex(); + } + public void set_clean() { dirty = false; } diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java index cb82a574..f45aa18b 100644 --- a/altosui/AltosSerial.java +++ b/altosui/AltosSerial.java @@ -233,7 +233,6 @@ public class AltosSerial implements Runnable { abort = false; timeout_started = false; for (;;) { - System.out.printf("timeout %d\n", timeout); AltosLine line = reply_queue.poll(timeout, TimeUnit.MILLISECONDS); if (line != null) { stop_timeout_dialog(); diff --git a/src/ao.h b/src/ao.h index 9cde9cba..b315af7a 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1358,7 +1358,7 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 5 +#define AO_CONFIG_MINOR 6 struct ao_config { uint8_t major; @@ -1372,12 +1372,16 @@ struct ao_config { uint32_t radio_cal; /* minor version 3 */ uint32_t flight_log_max; /* minor version 4 */ uint8_t ignite_mode; /* minor version 5 */ + uint8_t pad_orientation; /* minor version 6 */ }; #define AO_IGNITE_MODE_DUAL 0 #define AO_IGNITE_MODE_APOGEE 1 #define AO_IGNITE_MODE_MAIN 2 +#define AO_PAD_ORIENTATION_ANTENNA_UP 0 +#define AO_PAD_ORIENTATION_ANTENNA_DOWN 1 + extern __xdata struct ao_config ao_config; #define AO_CONFIG_MAX_SIZE 128 diff --git a/src/ao_config.c b/src/ao_config.c index 48349886..215dda92 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -28,6 +28,7 @@ __xdata uint8_t ao_config_mutex; #define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000 #define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 #define AO_CONFIG_DEFAULT_IGNITE_MODE AO_IGNITE_MODE_DUAL +#define AO_CONFIG_DEFAULT_PAD_ORIENTATION AO_PAD_ORIENTATION_ANTENNA_UP #if USE_INTERNAL_EEPROM #define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_config #else @@ -77,6 +78,7 @@ _ao_config_get(void) ao_config.radio_cal = ao_radio_cal; ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; + ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { @@ -97,6 +99,8 @@ _ao_config_get(void) /* Fixupes for minor version 5 */ if (ao_config.minor < 5) ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; + if (ao_config.minor < 6) + ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -357,7 +361,36 @@ ao_config_ignite_mode_set(void) __reentrant ao_config.ignite_mode = ao_cmd_lex_i; ao_config_dirty = 1; ao_mutex_put(&ao_config_mutex); - ao_config_log_show(); + ao_config_ignite_mode_show(); +} +#endif + +#if HAS_IGNITE +void +ao_config_pad_orientation_show(void) __reentrant +{ + printf("Pad orientation: %d\n", ao_config.pad_orientation); +} + +void +ao_config_pad_orientation_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_mutex_get(&ao_config_mutex); + _ao_config_get(); + ao_cmd_lex_i &= 1; + if (ao_config.pad_orientation != ao_cmd_lex_i) { + uint16_t t; + t = ao_config.accel_plus_g; + ao_config.accel_plus_g = 0x7fff - ao_config.accel_minus_g; + ao_config.accel_minus_g = 0x7fff - t; + } + ao_config.pad_orientation = ao_cmd_lex_i; + ao_config_dirty = 1; + ao_mutex_put(&ao_config_mutex); + ao_config_pad_orientation_show(); } #endif @@ -400,6 +433,10 @@ __code struct ao_config_var ao_config_vars[] = { #if HAS_IGNITE { "i <0 dual, 1 apogee, 2 main>\0Set igniter mode", ao_config_ignite_mode_set, ao_config_ignite_mode_show }, +#endif +#if HAS_ACCEL + { "o <0 antenna up, 1 antenna down>\0Set pad orientation", + ao_config_pad_orientation_set,ao_config_pad_orientation_show }, #endif { "s\0Show", ao_config_show, ao_config_show }, diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c index e55d5ade..56733c89 100644 --- a/src/ao_flight_test.c +++ b/src/ao_flight_test.c @@ -179,8 +179,12 @@ struct ao_config { uint16_t main_deploy; int16_t accel_plus_g; int16_t accel_minus_g; + uint8_t pad_orientation; }; +#define AO_PAD_ORIENTATION_ANTENNA_UP 0 +#define AO_PAD_ORIENTATION_ANTENNA_DOWN 1 + #define ao_config_get() struct ao_config ao_config; diff --git a/src/ao_sample.c b/src/ao_sample.c index ac156646..88ba58c5 100644 --- a/src/ao_sample.c +++ b/src/ao_sample.c @@ -179,6 +179,8 @@ ao_sample(void) * just dropped a bit of noise off the low end. */ ao_sample_accel = (uint16_t) ((((uint32_t) ao_sample_accel << 16) / (ao_accel_ref[ao_sample_adc] << 1))) >> 1; + if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) + ao_sample_accel = 0x7fff - ao_sample_accel; ao_adc->accel = ao_sample_accel; #endif #endif -- cgit v1.2.3 From 30670732ca3f5a34025ab4bc4c69afa45637b4d6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 11:58:23 -0700 Subject: altos: Correct flight log max on Tm to 5k Was using the wrong #define name to check for Tm/Tn devices that use internal flash for data storage. Signed-off-by: Keith Packard --- src/ao_config.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_config.c b/src/ao_config.c index 215dda92..c4d80890 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -29,7 +29,12 @@ __xdata uint8_t ao_config_mutex; #define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 #define AO_CONFIG_DEFAULT_IGNITE_MODE AO_IGNITE_MODE_DUAL #define AO_CONFIG_DEFAULT_PAD_ORIENTATION AO_PAD_ORIENTATION_ANTENNA_UP -#if USE_INTERNAL_EEPROM +#if HAS_EEPROM +#ifndef USE_INTERNAL_FLASH +#error Please define USE_INTERNAL_FLASH +#endif +#endif +#if USE_INTERNAL_FLASH #define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_config #else #define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 192 * (uint32_t) 1024) -- cgit v1.2.3 From e1e5c9b3e24670e9f58c6f7389eafb3338efdb40 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 12:08:45 -0700 Subject: altos: Remove pad_orientation functions from non-accel devices Anything without an accelerometer can't detect pad orientation. Signed-off-by: Keith Packard --- src/ao_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_config.c b/src/ao_config.c index c4d80890..5e80d55d 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -370,7 +370,7 @@ ao_config_ignite_mode_set(void) __reentrant } #endif -#if HAS_IGNITE +#if HAS_ACCEL void ao_config_pad_orientation_show(void) __reentrant { -- cgit v1.2.3 From ba5dc35388d28c5769eaabc970c4d4b8c2c2ff9c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 3 Aug 2011 23:07:53 -0700 Subject: altos: Add ability to set arbitrary radio frequency This adds a separate config parameter to control the raw radio frequency setting, allowing the user to select an arbitrary frequency instead of being forced to choose one of the 10 pre-defined 'channels'. Signed-off-by: Keith Packard --- src/ao.h | 1 + src/ao_config.c | 28 +++++++++++++++++++++++++++- src/ao_radio.c | 6 +++--- 3 files changed, 31 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index b315af7a..bb3c80ec 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1373,6 +1373,7 @@ struct ao_config { uint32_t flight_log_max; /* minor version 4 */ uint8_t ignite_mode; /* minor version 5 */ uint8_t pad_orientation; /* minor version 6 */ + uint32_t radio_setting; /* minor version 7 */ }; #define AO_IGNITE_MODE_DUAL 0 diff --git a/src/ao_config.c b/src/ao_config.c index 5e80d55d..a5796b03 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -84,6 +84,7 @@ _ao_config_get(void) ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; + ao_config.radio_setting = ao_radio_cal; ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { @@ -106,6 +107,8 @@ _ao_config_get(void) ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; if (ao_config.minor < 6) ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; + if (ao_config.minor < 7) + ao_config.radio_setting = ao_config.radio_cal; ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -309,7 +312,7 @@ ao_config_radio_cal_set(void) __reentrant return; ao_mutex_get(&ao_config_mutex); _ao_config_get(); - ao_config.radio_cal = ao_cmd_lex_u32; + ao_config.radio_setting = ao_config.radio_cal = ao_cmd_lex_u32; ao_config_dirty = 1; ao_mutex_put(&ao_config_mutex); ao_config_radio_cal_show(); @@ -399,6 +402,27 @@ ao_config_pad_orientation_set(void) __reentrant } #endif +void +ao_config_radio_setting_show(void) __reentrant +{ + printf("Radio setting: %ld\n", ao_config.radio_setting); +} + +void +ao_config_radio_setting_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_mutex_get(&ao_config_mutex); + _ao_config_get(); + ao_config.radio_setting = ao_cmd_lex_u32; + ao_config_dirty = 1; + ao_mutex_put(&ao_config_mutex); + ao_config_radio_setting_show(); + ao_radio_recv_abort(); +} + struct ao_config_var { __code char *str; void (*set)(void) __reentrant; @@ -443,6 +467,8 @@ __code struct ao_config_var ao_config_vars[] = { { "o <0 antenna up, 1 antenna down>\0Set pad orientation", ao_config_pad_orientation_set,ao_config_pad_orientation_show }, #endif + { "R \0Radio freq control (freq = 434.550 * setting/cal)", + ao_config_radio_setting_set, ao_config_radio_setting_show }, { "s\0Show", ao_config_show, ao_config_show }, #if HAS_EEPROM diff --git a/src/ao_radio.c b/src/ao_radio.c index 4c382bb9..1fb0eea6 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -287,9 +287,9 @@ ao_radio_get(uint8_t len) ao_mutex_get(&ao_radio_mutex); ao_radio_idle(); RF_CHANNR = ao_config.radio_channel; - RF_FREQ2 = (uint8_t) (ao_config.radio_cal >> 16); - RF_FREQ1 = (uint8_t) (ao_config.radio_cal >> 8); - RF_FREQ0 = (uint8_t) (ao_config.radio_cal); + RF_FREQ2 = (uint8_t) (ao_config.radio_setting >> 16); + RF_FREQ1 = (uint8_t) (ao_config.radio_setting >> 8); + RF_FREQ0 = (uint8_t) (ao_config.radio_setting); RF_PKTLEN = len; } -- cgit v1.2.3 From 40544dbfe09c64f7764a5f0686415805611fab25 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 8 Aug 2011 17:46:04 -0700 Subject: altos: minor type in comment about accel correction Kurt Roeckx found a typo in the equations describing how the accelerometer is corrected by the 5V reference measurement. Signed-off-by: Keith Packard --- src/ao_sample.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_sample.c b/src/ao_sample.c index 88ba58c5..b2b8e9f6 100644 --- a/src/ao_sample.c +++ b/src/ao_sample.c @@ -139,7 +139,7 @@ ao_sample(void) * * ao_sample_accel 32767 * = ------------ * ------------ - * 32737 ao_accel_ref + * 32767 ao_accel_ref * * Multiply through by 32767: * -- cgit v1.2.3 From 81ad44d4b6d9ad2f6b91d0906e8543da82da424f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 9 Aug 2011 14:26:43 -0700 Subject: altos: Switch telemini from v0.1 to v1.0 TeleMini production boards are firmware compatible with the v0.1 design, so instead of creating another product, just rename the existing one. Signed-off-by: Keith Packard --- src/Makefile | 2 +- src/ao_adc.c | 2 +- src/ao_pins.h | 2 +- src/ao_telemetry.c | 2 +- src/telemini-v0.1/.gitignore | 2 -- src/telemini-v0.1/.sdcdbrc | 1 - src/telemini-v0.1/Makefile | 1 - src/telemini-v0.1/Makefile.defs | 9 --------- src/telemini-v1.0/.gitignore | 2 ++ src/telemini-v1.0/.sdcdbrc | 1 + src/telemini-v1.0/Makefile | 1 + src/telemini-v1.0/Makefile.defs | 9 +++++++++ 12 files changed, 17 insertions(+), 17 deletions(-) delete mode 100644 src/telemini-v0.1/.gitignore delete mode 100644 src/telemini-v0.1/.sdcdbrc delete mode 100644 src/telemini-v0.1/Makefile delete mode 100644 src/telemini-v0.1/Makefile.defs create mode 100644 src/telemini-v1.0/.gitignore create mode 100644 src/telemini-v1.0/.sdcdbrc create mode 100644 src/telemini-v1.0/Makefile create mode 100644 src/telemini-v1.0/Makefile.defs (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 3eec3980..018f0c5c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -9,7 +9,7 @@ include Version SUBDIRS=\ telemetrum-v1.1 telemetrum-v1.0 \ teledongle-v0.2 teledongle-v0.1 \ - telemini-v0.1 telenano-v0.1 \ + telemini-v1.0 telenano-v0.1 \ telebt-v0.0 telebt-v0.1 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ tidongle test diff --git a/src/ao_adc.c b/src/ao_adc.c index cbeb6a24..786dfd11 100644 --- a/src/ao_adc.c +++ b/src/ao_adc.c @@ -84,7 +84,7 @@ ao_adc_isr(void) __interrupt 1 #if IGNITE_ON_P0 /* TeleMini readings */ a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].pres); -#ifdef TELEMINI_V_0_1 +#ifdef TELEMINI_V_1_0 switch (sequence) { case 0: /* pressure */ diff --git a/src/ao_pins.h b/src/ao_pins.h index 4a03ca50..bc07ad54 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -97,7 +97,7 @@ #define HAS_IGNITE 0 #endif -#if defined(TELEMINI_V_0_1) +#if defined(TELEMINI_V_1_0) #define HAS_FLIGHT 1 #define HAS_USB 0 #define HAS_BEEP 0 diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 172b6f17..52f818ed 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -35,7 +35,7 @@ static __pdata uint16_t ao_rdf_time; #define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMETRUM #endif -#if defined(TELEMINI_V_0_1) +#if defined(TELEMINI_V_1_0) #define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMINI #endif diff --git a/src/telemini-v0.1/.gitignore b/src/telemini-v0.1/.gitignore deleted file mode 100644 index 82868aac..00000000 --- a/src/telemini-v0.1/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -telemini-* -ao_product.h diff --git a/src/telemini-v0.1/.sdcdbrc b/src/telemini-v0.1/.sdcdbrc deleted file mode 100644 index 710b4a2f..00000000 --- a/src/telemini-v0.1/.sdcdbrc +++ /dev/null @@ -1 +0,0 @@ ---directory=.. diff --git a/src/telemini-v0.1/Makefile b/src/telemini-v0.1/Makefile deleted file mode 100644 index d8867b19..00000000 --- a/src/telemini-v0.1/Makefile +++ /dev/null @@ -1 +0,0 @@ -include ../Makefile.proto diff --git a/src/telemini-v0.1/Makefile.defs b/src/telemini-v0.1/Makefile.defs deleted file mode 100644 index 94ac1268..00000000 --- a/src/telemini-v0.1/Makefile.defs +++ /dev/null @@ -1,9 +0,0 @@ -PROG = telemini-v0.1-$(VERSION).ihx - -SRC = \ - $(TMINI_BASE_SRC) - -PRODUCT=TeleMini-v0.1 -PRODUCT_DEF=-DTELEMINI_V_0_1 -IDPRODUCT=0x000a -CODESIZE=0x6700 diff --git a/src/telemini-v1.0/.gitignore b/src/telemini-v1.0/.gitignore new file mode 100644 index 00000000..82868aac --- /dev/null +++ b/src/telemini-v1.0/.gitignore @@ -0,0 +1,2 @@ +telemini-* +ao_product.h diff --git a/src/telemini-v1.0/.sdcdbrc b/src/telemini-v1.0/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telemini-v1.0/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telemini-v1.0/Makefile b/src/telemini-v1.0/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telemini-v1.0/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/telemini-v1.0/Makefile.defs b/src/telemini-v1.0/Makefile.defs new file mode 100644 index 00000000..0e91f2fc --- /dev/null +++ b/src/telemini-v1.0/Makefile.defs @@ -0,0 +1,9 @@ +PROG = telemini-v1.0-$(VERSION).ihx + +SRC = \ + $(TMINI_BASE_SRC) + +PRODUCT=TeleMini-v1.0 +PRODUCT_DEF=-DTELEMINI_V_1_0 +IDPRODUCT=0x000a +CODESIZE=0x6700 -- cgit v1.2.3 From b520c32bcddabd42c07ceafa827694a3ae23a76f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 11 Aug 2011 15:57:58 -0700 Subject: altos: Pull igniter pins low as soon as possible at boot time This reduces the pulse width on the igniter circuit caused by the default cc1111 pin configuration at powerup time. Signed-off-by: Keith Packard --- src/ao.h | 3 +++ src/ao_ignite.c | 8 +++++++- src/ao_telemetrum.c | 7 ++++++- 3 files changed, 16 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index bb3c80ec..0699fc2c 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1350,6 +1350,9 @@ enum ao_igniter_status { enum ao_igniter_status ao_igniter_status(enum ao_igniter igniter); +void +ao_ignite_set_pins(void); + void ao_igniter_init(void); diff --git a/src/ao_ignite.c b/src/ao_ignite.c index 512ec622..5238beb4 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -202,11 +202,17 @@ __code struct ao_cmds ao_ignite_cmds[] = { __xdata struct ao_task ao_igniter_task; void -ao_igniter_init(void) +ao_ignite_set_pins(void) { AO_IGNITER_DROGUE = 0; AO_IGNITER_MAIN = 0; AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; +} + +void +ao_igniter_init(void) +{ + ao_ignite_set_pins(); ao_cmd_register(&ao_ignite_cmds[0]); ao_add_task(&ao_igniter_task, ao_igniter, "igniter"); } diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 4ace415c..d9ea1fc8 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -28,8 +28,13 @@ ao_set_monitor(uint8_t monitoring) void main(void) { - ao_clock_init(); + /* + * Reduce the transient on the ignite pins at startup by + * pulling the pins low as soon as possible at power up + */ + ao_ignite_set_pins(); + ao_clock_init(); /* Turn on the red LED until the system is stable */ ao_led_init(LEDS_AVAILABLE); -- cgit v1.2.3 From 1d13460412046c53f36466193329caaa657bb278 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 11 Aug 2011 15:59:47 -0700 Subject: altos: Apply igniter boot pulse-width reduction to telemini TeleMini needs the same fix as TeleMetrum to reduce startup igniter pulses. Signed-off-by: Keith Packard --- src/ao_telemini.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_telemini.c b/src/ao_telemini.c index 19d03692..6c612481 100644 --- a/src/ao_telemini.c +++ b/src/ao_telemini.c @@ -28,8 +28,13 @@ ao_set_monitor(uint8_t monitoring) void main(void) { - ao_clock_init(); + /* + * Reduce the transient on the ignite pins at startup by + * pulling the pins low as soon as possible at power up + */ + ao_ignite_set_pins(); + ao_clock_init(); /* Turn on the red LED until the system is stable */ ao_led_init(LEDS_AVAILABLE); -- cgit v1.2.3 From 640422c028a2be898aa3a9048a0f6fad2e43dd8d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 11 Aug 2011 16:11:34 -0700 Subject: altos: remove monitor disable stubs from altimeter code Monitor mode in the ground-station boards must be disabled when the radio is going to be used for another purpose, or the radio parameters changed. That places monitor-mode disable calls in other parts of the system which are shared with the altimeter code. Elide the ao_set_monitor calls for builds which do not include any monitoring code. Signed-off-by: Keith Packard --- src/ao_monitor.c | 4 ++++ src/ao_packet_master.c | 2 ++ src/ao_pins.h | 13 +++++++++++++ src/ao_radio.c | 2 ++ src/ao_telemetrum.c | 7 ------- src/ao_telemini.c | 7 ------- src/ao_telenano.c | 7 ------- 7 files changed, 21 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/ao_monitor.c b/src/ao_monitor.c index 8f1b9e12..69eb58e8 100644 --- a/src/ao_monitor.c +++ b/src/ao_monitor.c @@ -18,6 +18,10 @@ #include "ao.h" #include "ao_telem.h" +#if !HAS_MONITOR +#error Must define HAS_MONITOR to 1 +#endif + __xdata uint8_t ao_monitoring; __pdata uint8_t ao_monitor_led; diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c index e721ffba..b0fdf5a8 100644 --- a/src/ao_packet_master.c +++ b/src/ao_packet_master.c @@ -109,7 +109,9 @@ ao_packet_forward(void) __reentrant ao_cmd_white(); flush(); +#if HAS_MONITOR ao_set_monitor(0); +#endif ao_add_task(&ao_packet_task, ao_packet_master, "master"); ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); while ((c = getchar()) != '~') { diff --git a/src/ao_pins.h b/src/ao_pins.h index bc07ad54..89907b9c 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -42,6 +42,7 @@ #define HAS_ACCEL_REF 0 #define HAS_ACCEL 1 #define HAS_IGNITE 1 + #define HAS_MONITOR 0 #endif #if defined(TELEMETRUM_V_1_1) @@ -72,6 +73,7 @@ #define M25_MAX_CHIPS 1 #define HAS_ACCEL 1 #define HAS_IGNITE 1 + #define HAS_MONITOR 0 #endif #if defined(TELEDONGLE_V_0_2) @@ -95,6 +97,7 @@ #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 #define HAS_IGNITE 0 + #define HAS_MONITOR 1 #endif #if defined(TELEMINI_V_1_0) @@ -120,6 +123,7 @@ #define HAS_EXTERNAL_TEMP 0 #define HAS_ACCEL 0 #define HAS_IGNITE 1 + #define HAS_MONITOR 0 #endif #if defined(TELENANO_V_0_1) @@ -144,6 +148,7 @@ #define HAS_EXTERNAL_TEMP 0 #define HAS_ACCEL 0 #define HAS_IGNITE 0 + #define HAS_MONITOR 0 #endif #if defined(TELEMETRUM_V_0_1) @@ -172,6 +177,7 @@ #define SPI_CS_ON_P0 0 #define HAS_ACCEL 1 #define HAS_IGNITE 1 + #define HAS_MONITOR 0 #endif #if defined(TELEDONGLE_V_0_1) @@ -195,6 +201,7 @@ #define SPI_CS_ON_P1 0 #define SPI_CS_ON_P0 1 #define HAS_IGNITE 0 + #define HAS_MONITOR 1 #endif #if defined(TIDONGLE) @@ -217,6 +224,7 @@ #define SPI_CS_ON_P1 0 #define SPI_CS_ON_P0 1 #define HAS_IGNITE 0 + #define HAS_MONITOR 1 #endif #if defined(TELEBT_V_0_0) @@ -245,6 +253,7 @@ #define BT_LINK_ON_P1 0 #define BT_LINK_PIN_INDEX 7 #define BT_LINK_PIN P2_1 + #define HAS_MONITOR 1 #endif #if defined(TELEBT_V_0_1) @@ -280,6 +289,7 @@ #define BT_LINK_ON_P1 1 #define BT_LINK_PIN_INDEX 7 #define BT_LINK_PIN P1_7 + #define HAS_MONITOR 1 #endif #if DBG_ON_P1 @@ -376,4 +386,7 @@ #error Please define PACKET_HAS_SLAVE #endif +#ifndef HAS_MONITOR +#error Please define HAS_MONITOR +#endif #endif /* _AO_PINS_H_ */ diff --git a/src/ao_radio.c b/src/ao_radio.c index 1fb0eea6..00816b33 100644 --- a/src/ao_radio.c +++ b/src/ao_radio.c @@ -432,7 +432,9 @@ ao_radio_test(void) } mode++; if ((mode & 2) && !radio_on) { +#if HAS_MONITOR ao_set_monitor(0); +#endif #if PACKET_HAS_SLAVE ao_packet_slave_stop(); #endif diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index d9ea1fc8..6fa70b3a 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -18,13 +18,6 @@ #include "ao.h" #include "ao_pins.h" -/* stub so as telemetrum doesn't have monitor mode */ -void -ao_set_monitor(uint8_t monitoring) -{ - (void) monitoring; -} - void main(void) { diff --git a/src/ao_telemini.c b/src/ao_telemini.c index 6c612481..fa23de01 100644 --- a/src/ao_telemini.c +++ b/src/ao_telemini.c @@ -18,13 +18,6 @@ #include "ao.h" #include "ao_pins.h" -/* stub so as telemini doesn't have monitor mode */ -void -ao_set_monitor(uint8_t monitoring) -{ - (void) monitoring; -} - void main(void) { diff --git a/src/ao_telenano.c b/src/ao_telenano.c index 40822b6e..d91983d0 100644 --- a/src/ao_telenano.c +++ b/src/ao_telenano.c @@ -18,13 +18,6 @@ #include "ao.h" #include "ao_pins.h" -/* stub so as telemini doesn't have monitor mode */ -void -ao_set_monitor(uint8_t monitoring) -{ - (void) monitoring; -} - void main(void) { -- cgit v1.2.3 From 7bcf25606cd5892d58295649f3d475d284494ee8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Aug 2011 05:26:09 -0700 Subject: altos: shrink text space from ao_config.c Eliminate redundant config initializers by setting minor to zero and letting upgrade code handle all of the new values. Stop computing (fake) frequency when showing radio channel Stop computing feet when showing main deploy height Signed-off-by: Keith Packard --- src/ao_config.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/ao_config.c b/src/ao_config.c index a5796b03..36bd47c4 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -71,21 +71,11 @@ _ao_config_get(void) #endif if (ao_config.major != AO_CONFIG_MAJOR) { ao_config.major = AO_CONFIG_MAJOR; - ao_config.minor = AO_CONFIG_MINOR; + ao_config.minor = 0; ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; - ao_config.accel_plus_g = 0; - ao_config.accel_minus_g = 0; - memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); - ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; - ao_config.radio_cal = ao_radio_cal; - ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; - ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; - ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; - ao_config.radio_setting = ao_radio_cal; - ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { /* Fixups for minor version 1 */ @@ -159,12 +149,8 @@ ao_config_callsign_set(void) __reentrant void ao_config_radio_channel_show(void) __reentrant { - uint32_t freq = 434550L + ao_config.radio_channel * 100L; - uint16_t mhz = freq / 1000L; - uint16_t khz = freq % 1000L; - - printf("Radio channel: %d (%d.%03dMHz)\n", - ao_config.radio_channel, mhz, khz); + printf("Radio channel: %d\n", + ao_config.radio_channel); } void @@ -187,9 +173,8 @@ ao_config_radio_channel_set(void) __reentrant void ao_config_main_deploy_show(void) __reentrant { - printf("Main deploy: %d meters (%d feet)\n", - ao_config.main_deploy, - (int16_t) ((int32_t) ao_config.main_deploy * 328 / 100)); + printf("Main deploy: %d meters\n", + ao_config.main_deploy); } void -- cgit v1.2.3 From c2f2f519dbc8ce233ab36222088c1be6b1362f01 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Aug 2011 18:28:38 -0700 Subject: altos: re-write a bit of GPS parsing code to reduce size Use a local variable while computing hdop. Place the next incoming character in data instead of pdata. Saved a surprising amount of memory. Signed-off-by: Keith Packard --- src/ao_gps_skytraq.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c index e7d1d2ef..7ac26946 100644 --- a/src/ao_gps_skytraq.c +++ b/src/ao_gps_skytraq.c @@ -24,7 +24,7 @@ static __code char ao_gps_header[] = "GP"; __xdata uint8_t ao_gps_mutex; -static __pdata char ao_gps_char; +static __data char ao_gps_char; static __pdata uint8_t ao_gps_cksum; static __pdata uint8_t ao_gps_error; @@ -238,14 +238,14 @@ ao_nmea_gga() ao_gps_next.flags |= i; ao_gps_lexchar(); - ao_gps_next.hdop = ao_gps_decimal(0xff); - if (ao_gps_next.hdop <= 50) { - ao_gps_next.hdop = (uint8_t) 5 * ao_gps_next.hdop; + i = ao_gps_decimal(0xff); + if (i <= 50) { + i = (uint8_t) 5 * i; if (ao_gps_char == '.') - ao_gps_next.hdop = (ao_gps_next.hdop + - ((uint8_t) ao_gps_decimal(1) >> 1)); + i = (i + ((uint8_t) ao_gps_decimal(1) >> 1)); } else - ao_gps_next.hdop = 255; + i = 255; + ao_gps_next.hdop = i; ao_gps_skip_field(); ao_gps_next.altitude = ao_gps_decimal(0xff); -- cgit v1.2.3 From bf06af154e232d4caa1585a1d6d5279a075292e4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Aug 2011 21:43:56 -0700 Subject: altos/altosui: Report log format in the version command This will make it easier to figure out what the contents of the flash should look like from altosui; the current 'guessing' mechanism will not scale to many more formats. Signed-off-by: Keith Packard --- altosui/Altos.java | 32 ++++++++++++++++++++++++++++++++ altosui/AltosConfig.java | 3 +++ altosui/AltosConfigData.java | 2 ++ altosui/AltosEepromDownload.java | 26 +++++++++++++------------- altosui/AltosEepromRecord.java | 3 +++ src/ao.h | 9 +++++++++ src/ao_cmd.c | 3 +++ src/ao_log.c | 2 ++ src/ao_log_tiny.c | 2 ++ src/ao_telebt.c | 2 ++ 10 files changed, 71 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/altosui/Altos.java b/altosui/Altos.java index 73dc7468..416d9328 100644 --- a/altosui/Altos.java +++ b/altosui/Altos.java @@ -51,6 +51,7 @@ public class Altos { static final int AO_LOG_MANUFACTURER = 2000; static final int AO_LOG_PRODUCT = 2001; static final int AO_LOG_SERIAL_NUMBER = 2002; + static final int AO_LOG_LOG_FORMAT = 2003; static final int AO_LOG_SOFTWARE_VERSION = 9999; /* Added to flag invalid records */ @@ -177,6 +178,13 @@ public class Altos { static final int AO_GPS_NUM_SAT_SHIFT = 0; static final int AO_GPS_NUM_SAT_MASK = 0xf; + static final int AO_LOG_FORMAT_UNKNOWN = 0; + static final int AO_LOG_FORMAT_FULL = 1; + static final int AO_LOG_FORMAT_TINY = 2; + static final int AO_LOG_FORMAT_TELEMETRY = 3; + static final int AO_LOG_FORMAT_TELESCIENCE = 4; + static final int AO_LOG_FORMAT_NONE = 127; + static boolean isspace(int c) { switch (c) { case ' ': @@ -404,12 +412,36 @@ public class Altos { return 0x000e; } + static int usb_product_telelaunch() { + load_library(); + return 0x000f; + } + + static int usb_product_telelco() { + load_library(); + return 0x0010; + } + + static int usb_product_telescience() { + load_library(); + return 0x0011; + } + + static int usb_product_telepyro() { + load_library(); + return 0x0012; + } + public final static int vendor_altusmetrum = usb_vendor_altusmetrum(); public final static int product_altusmetrum = usb_product_altusmetrum(); public final static int product_telemetrum = usb_product_telemetrum(); public final static int product_teledongle = usb_product_teledongle(); public final static int product_teleterra = usb_product_teleterra(); public final static int product_telebt = usb_product_telebt(); + public final static int product_telelaunch = usb_product_telelaunch(); + public final static int product_tele10 = usb_product_telelco(); + public final static int product_telescience = usb_product_telescience(); + public final static int product_telepyro = usb_product_telepyro(); public final static int product_altusmetrum_min = usb_product_altusmetrum_min(); public final static int product_altusmetrum_max = usb_product_altusmetrum_max(); diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 7312ea6c..ffabe209 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -67,6 +67,7 @@ public class AltosConfig implements ActionListener { AltosConfigData remote_config_data; double remote_frequency; int_ref serial; + int_ref log_format; int_ref main_deploy; int_ref apogee_delay; int_ref radio_channel; @@ -153,6 +154,7 @@ public class AltosConfig implements ActionListener { return; } get_int(line, "serial-number", serial); + get_int(line, "log-format", log_format); get_int(line, "Main deploy:", main_deploy); get_int(line, "Apogee delay:", apogee_delay); get_int(line, "Radio channel:", radio_channel); @@ -374,6 +376,7 @@ public class AltosConfig implements ActionListener { owner = given_owner; serial = new int_ref(0); + log_format = new int_ref(Altos.AO_LOG_FORMAT_UNKNOWN); main_deploy = new int_ref(250); apogee_delay = new int_ref(0); radio_channel = new int_ref(0); diff --git a/altosui/AltosConfigData.java b/altosui/AltosConfigData.java index 016033a3..710231d7 100644 --- a/altosui/AltosConfigData.java +++ b/altosui/AltosConfigData.java @@ -36,6 +36,7 @@ public class AltosConfigData implements Iterable { String manufacturer; String product; String version; + int log_format; int serial; /* Strings returned */ @@ -94,6 +95,7 @@ public class AltosConfigData implements Iterable { continue; lines.add(line); try { serial = get_int(line, "serial-number"); } catch (Exception e) {} + try { log_format = get_int(line, "log-format"); } catch (Exception e) {} try { main_deploy = get_int(line, "Main deploy:"); } catch (Exception e) {} try { apogee_delay = get_int(line, "Apogee delay:"); } catch (Exception e) {} try { radio_channel = get_int(line, "Radio channel:"); } catch (Exception e) {} diff --git a/altosui/AltosEepromDownload.java b/altosui/AltosEepromDownload.java index 64dcdff7..417aab00 100644 --- a/altosui/AltosEepromDownload.java +++ b/altosui/AltosEepromDownload.java @@ -89,9 +89,6 @@ public class AltosEepromDownload implements Runnable { } } - static final int log_full = 1; - static final int log_tiny = 2; - boolean done; int state; @@ -186,7 +183,7 @@ public class AltosEepromDownload implements Runnable { void CaptureLog(AltosEepromLog log) throws IOException, InterruptedException, TimeoutException { int block, state_block = 0; - int log_style = 0; + int log_format = flights.config_data.log_format; state = 0; done = false; @@ -215,21 +212,24 @@ public class AltosEepromDownload implements Runnable { AltosEepromChunk eechunk = new AltosEepromChunk(serial_line, block); /* - * Figure out what kind of data is there + * Guess what kind of data is there if the device + * didn't tell us */ - if (block == log.start_block) { - if (eechunk.data(0) == Altos.AO_LOG_FLIGHT) - log_style = log_full; - else - log_style = log_tiny; + if (log_format == Altos.AO_LOG_FORMAT_UNKNOWN) { + if (block == log.start_block) { + if (eechunk.data(0) == Altos.AO_LOG_FLIGHT) + log_format = Altos.AO_LOG_FORMAT_FULL; + else + log_format = Altos.AO_LOG_FORMAT_TINY; + } } - switch (log_style) { - case log_full: + switch (log_format) { + case Altos.AO_LOG_FORMAT_FULL: CaptureFull(eechunk); break; - case log_tiny: + case Altos.AO_LOG_FORMAT_TINY: CaptureTiny(eechunk); break; } diff --git a/altosui/AltosEepromRecord.java b/altosui/AltosEepromRecord.java index 52acb435..c0f97035 100644 --- a/altosui/AltosEepromRecord.java +++ b/altosui/AltosEepromRecord.java @@ -143,6 +143,9 @@ public class AltosEepromRecord { } else if (tokens[0].equals("serial-number")) { cmd = Altos.AO_LOG_SERIAL_NUMBER; a = Integer.parseInt(tokens[1]); + } else if (tokens[0].equals("log-format")) { + cmd = Altos.AO_LOG_LOG_FORMAT; + a = Integer.parseInt(tokens[1]); } else if (tokens[0].equals("software-version")) { cmd = Altos.AO_LOG_SOFTWARE_VERSION; data = tokens[1]; diff --git a/src/ao.h b/src/ao.h index 0699fc2c..1c8f5bbf 100644 --- a/src/ao.h +++ b/src/ao.h @@ -539,6 +539,15 @@ extern __pdata enum flight_state ao_log_state; /* required functions from the underlying log system */ +#define AO_LOG_FORMAT_UNKNOWN 0 /* unknown; altosui will have to guess */ +#define AO_LOG_FORMAT_FULL 1 /* 8 byte typed log records */ +#define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */ +#define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */ +#define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ +#define AO_LOG_FORMAT_NONE 127 /* No log at all */ + +extern __code uint8_t ao_log_format; + /* Return the flight number from the given log slot, 0 if none */ uint16_t ao_log_flight(uint8_t slot); diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 6d3ae38d..1442ebea 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -219,6 +219,9 @@ version(void) printf("manufacturer %s\n", ao_manufacturer); printf("product %s\n", ao_product); printf("serial-number %u\n", ao_serial_number); +#if HAS_EEPROM + printf("log-format %u\n", ao_log_format); +#endif printf("software-version %s\n", ao_version); } diff --git a/src/ao_log.c b/src/ao_log.c index 80d7243d..6d3ad535 100644 --- a/src/ao_log.c +++ b/src/ao_log.c @@ -24,6 +24,8 @@ __xdata uint8_t ao_log_running; __pdata enum flight_state ao_log_state; __xdata uint16_t ao_flight_number; +__code uint8_t ao_log_format = AO_LOG_FORMAT_FULL; + void ao_log_flush(void) { diff --git a/src/ao_log_tiny.c b/src/ao_log_tiny.c index d26e0080..d5a3b99f 100644 --- a/src/ao_log_tiny.c +++ b/src/ao_log_tiny.c @@ -28,6 +28,8 @@ static __data uint16_t ao_log_tiny_interval; #define AO_PAD_RING 2 #endif +__code uint8_t ao_log_format = AO_LOG_FORMAT_TINY; + void ao_log_tiny_set_interval(uint16_t ticks) { diff --git a/src/ao_telebt.c b/src/ao_telebt.c index 8e77c4d9..85565172 100644 --- a/src/ao_telebt.c +++ b/src/ao_telebt.c @@ -17,6 +17,8 @@ #include "ao.h" +__code uint8_t ao_log_format = AO_LOG_FORMAT_NONE; /* until we actually log stuff */ + void main(void) { -- cgit v1.2.3 From 30abbdc7ffcfc809b4a3fc31486fe968161ea225 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 9 Jul 2011 16:59:16 -0700 Subject: altos: Add SPI-based companion board support This sends current flight state information and retrieves companion data to include in telemetry. Signed-off-by: Keith Packard --- src/Makefile.proto | 6 +++ src/ao.h | 72 ++++++++++++++++++++++++++++- src/ao_companion.c | 96 +++++++++++++++++++++++++++++++++++++++ src/ao_ee.c | 14 +----- src/ao_flash.c | 14 +----- src/ao_m25.c | 4 +- src/ao_pins.h | 16 +++++++ src/ao_spi.c | 8 ++-- src/ao_telemetrum.c | 3 ++ src/ao_telemetry.c | 45 +++++++++++++++++- src/telemetrum-v1.0/Makefile.defs | 1 + src/telemetrum-v1.1/Makefile.defs | 1 + 12 files changed, 248 insertions(+), 32 deletions(-) create mode 100644 src/ao_companion.c (limited to 'src') diff --git a/src/Makefile.proto b/src/Makefile.proto index d4a8c4ea..8f98d354 100644 --- a/src/Makefile.proto +++ b/src/Makefile.proto @@ -150,6 +150,12 @@ SKY_DRIVER_SRC = \ BTM_DRIVER_SRC = \ ao_btm.c +# +# Companion port driver source +# +COMPANION_SRC = \ + ao_companion.c + # # Tasks run on TeleMetrum # diff --git a/src/ao.h b/src/ao.h index 1c8f5bbf..de47f3df 100644 --- a/src/ao.h +++ b/src/ao.h @@ -965,6 +965,34 @@ ao_serial_init(void); * ao_spi.c */ +extern __xdata uint8_t ao_spi_mutex; + +#define ao_spi_get_mask(reg,mask) do {\ + ao_mutex_get(&ao_spi_mutex); \ + (reg) &= ~(mask); \ + } while (0) + +#define ao_spi_put_mask(reg,mask) do { \ + (reg) |= (mask); \ + ao_mutex_put(&ao_spi_mutex); \ + } while (0) + +#define ao_spi_get_bit(bit) do {\ + ao_mutex_get(&ao_spi_mutex); \ + (bit) = 0; \ + } while (0) + +#define ao_spi_put_bit(bit) do { \ + (bit) = 1; \ + ao_mutex_put(&ao_spi_mutex); \ + } while (0) + +/* + * The SPI mutex must be held to call either of these + * functions -- this mutex covers the entire SPI operation, + * from chip select low to chip select high + */ + void ao_spi_send(void __xdata *block, uint16_t len) __reentrant; @@ -1089,12 +1117,29 @@ struct ao_telemetry_satellite { /* 32 */ }; +#define AO_TELEMETRY_COMPANION 0x07 + +#define AO_COMPANION_MAX_CHANNELS 12 + +struct ao_telemetry_companion { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t board_id; /* 5 */ + + uint8_t update_period; /* 6 */ + uint8_t channels; /* 7 */ + uint16_t companion_data[AO_COMPANION_MAX_CHANNELS]; /* 8 */ + /* 32 */ +}; + union ao_telemetry_all { struct ao_telemetry_generic generic; struct ao_telemetry_sensor sensor; struct ao_telemetry_configuration configuration; struct ao_telemetry_location location; struct ao_telemetry_satellite satellite; + struct ao_telemetry_companion companion; }; /* @@ -1529,8 +1574,33 @@ ao_btm_isr(void) #endif ; - void ao_btm_init(void); +/* ao_companion.c */ + +#define AO_COMPANION_SETUP 1 +#define AO_COMPANION_FETCH 2 + +struct ao_companion_command { + uint8_t command; + uint8_t flight_state; + uint16_t tick; +}; + +struct ao_companion_setup { + uint16_t board_id; + uint16_t board_id_inverse; + uint8_t update_period; + uint8_t channels; +}; + +extern __pdata uint8_t ao_companion_running; +extern __xdata struct ao_companion_setup ao_companion_setup; +extern __xdata uint8_t ao_companion_mutex; +extern __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; + +void +ao_companion_init(void); + #endif /* _AO_H_ */ diff --git a/src/ao_companion.c b/src/ao_companion.c new file mode 100644 index 00000000..8db3273e --- /dev/null +++ b/src/ao_companion.c @@ -0,0 +1,96 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +#define COMPANION_SELECT() ao_spi_get_bit(COMPANION_CS) +#define COMPANION_DESELECT() ao_spi_put_bit(COMPANION_CS) + +static __xdata struct ao_companion_command ao_companion_command; +__xdata struct ao_companion_setup ao_companion_setup; + +__xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; +__pdata uint8_t ao_companion_running; +__xdata uint8_t ao_companion_mutex; + +static void +ao_companion_send_command(uint8_t command) +{ + ao_companion_command.command = command; + ao_companion_command.flight_state = ao_flight_state; + ao_companion_command.tick = ao_time(); + ao_spi_send(&ao_companion_command, sizeof (ao_companion_command)); +} + +static uint8_t +ao_companion_get_setup(void) +{ + COMPANION_SELECT(); + ao_companion_send_command(AO_COMPANION_SETUP); + ao_spi_recv(&ao_companion_setup, sizeof (ao_companion_setup)); + COMPANION_DESELECT(); + if (ao_companion_setup.board_id != ~ao_companion_setup.board_id) + return 0; + return 1; +} + +static void +ao_companion_get_data(void) +{ + COMPANION_SELECT(); + ao_companion_send_command(AO_COMPANION_FETCH); + ao_mutex_get(&ao_companion_mutex); + ao_spi_recv(&ao_companion_data, ao_companion_setup.channels * 2); + ao_mutex_put(&ao_companion_mutex); + COMPANION_DESELECT(); +} + +void +ao_companion(void) +{ + if (!ao_companion_get_setup()) + ao_exit(); + ao_companion_running = 1; + for (;;) { + ao_delay(ao_companion_setup.update_period); + ao_companion_get_data(); + } +} + +void +ao_companion_status(void) __reentrant +{ +} + +__code struct ao_cmds ao_companion_cmds[] = { + { ao_companion_status, "L\0Companion link status" }, + { 0, NULL }, +}; + +static __xdata struct ao_task ao_companion_task; + +void +ao_companion_init(void) +{ + COMPANION_CS_PORT |= COMPANION_CS_MASK; /* raise all CS pins */ + COMPANION_CS_DIR |= COMPANION_CS_MASK; /* set CS pins as outputs */ + COMPANION_CS_SEL &= ~COMPANION_CS_MASK; /* set CS pins as GPIO */ + + ao_cmd_register(&ao_companion_cmds[0]); + + ao_add_task(&ao_companion_task, ao_companion, "companion"); +} diff --git a/src/ao_ee.c b/src/ao_ee.c index 83863af5..a2fe8dc1 100644 --- a/src/ao_ee.c +++ b/src/ao_ee.c @@ -49,19 +49,9 @@ static __xdata uint8_t ao_ee_mutex; _asm nop _endasm; \ } while(0) -static void ao_ee_cs_low(void) -{ - ao_ee_delay(); - EE_CS = 0; - ao_ee_delay(); -} +#define ao_ee_cs_low() ao_spi_get_bit(EE_CS) -static void ao_ee_cs_high(void) -{ - ao_ee_delay(); - EE_CS = 1; - ao_ee_delay(); -} +#define ao_ee_cs_high() ao_spi_put_bit(EE_CS) struct ao_ee_instruction { uint8_t instruction; diff --git a/src/ao_flash.c b/src/ao_flash.c index 00e96398..bb40f6f7 100644 --- a/src/ao_flash.c +++ b/src/ao_flash.c @@ -43,19 +43,9 @@ __xdata uint8_t ao_flash_mutex; _asm nop _endasm; \ } while(0) -void ao_flash_cs_low(void) -{ - ao_flash_delay(); - FLASH_CS = 0; - ao_flash_delay(); -} +#define ao_flash_cs_low() ao_spi_get_bit(FLASH_CS) -void ao_flash_cs_high(void) -{ - ao_flash_delay(); - FLASH_CS = 1; - ao_flash_delay(); -} +#define ao_flash_cs_high() ao_spi_put_bit(FLASH_CS) struct ao_flash_instruction { uint8_t instruction; diff --git a/src/ao_m25.c b/src/ao_m25.c index 208c69ba..d7208273 100644 --- a/src/ao_m25.c +++ b/src/ao_m25.c @@ -99,8 +99,8 @@ static __xdata uint8_t ao_m25_mutex; static __xdata uint8_t ao_m25_instruction[4]; -#define M25_SELECT(cs) (SPI_CS_PORT &= ~(cs)) -#define M25_DESELECT(cs) (SPI_CS_PORT |= (cs)) +#define M25_SELECT(cs) ao_spi_get_mask(SPI_CS_PORT,cs) +#define M25_DESELECT(cs) ao_spi_put_mask(SPI_CS_PORT,cs) #define M25_BLOCK_SHIFT 16 #define M25_BLOCK 65536L diff --git a/src/ao_pins.h b/src/ao_pins.h index 89907b9c..e1f5459f 100644 --- a/src/ao_pins.h +++ b/src/ao_pins.h @@ -36,6 +36,11 @@ #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 + #define HAS_COMPANION 1 + #define COMPANION_CS_ON_P1 1 + #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ + #define COMPANION_CS P1_2 + #define AO_LED_RED 1 #define LEDS_AVAILABLE (AO_LED_RED) #define HAS_EXTERNAL_TEMP 0 @@ -63,6 +68,11 @@ #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 + #define HAS_COMPANION 1 + #define COMPANION_CS_ON_P1 1 + #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ + #define COMPANION_CS P1_2 + #define AO_LED_RED 1 #define LEDS_AVAILABLE (AO_LED_RED) #define HAS_EXTERNAL_TEMP 0 @@ -328,6 +338,12 @@ #endif /* DBG_ON_P0 */ +#if COMPANION_CS_ON_P1 + #define COMPANION_CS_PORT P1 + #define COMPANION_CS_SEL P1SEL + #define COMPANION_CS_DIR P1DIR +#endif + #if SPI_CS_ON_P1 #define SPI_CS_PORT P1 #define SPI_CS_SEL P1SEL diff --git a/src/ao_spi.c b/src/ao_spi.c index bd52a0d4..fbe613c7 100644 --- a/src/ao_spi.c +++ b/src/ao_spi.c @@ -17,6 +17,10 @@ #include "ao.h" +/* Shared mutex to protect SPI bus, must cover the entire + * operation, from CS low to CS high. This means that any SPI + * user must protect the SPI bus with this mutex + */ __xdata uint8_t ao_spi_mutex; __xdata uint8_t ao_spi_dma_in_done; __xdata uint8_t ao_spi_dma_out_done; @@ -36,7 +40,6 @@ static __xdata uint8_t ao_spi_const = 0xff; void ao_spi_send(void __xdata *block, uint16_t len) __reentrant { - ao_mutex_get(&ao_spi_mutex); ao_dma_set_transfer(ao_spi_dma_in_id, &U0DBUFXADDR, &ao_spi_const, @@ -64,7 +67,6 @@ ao_spi_send(void __xdata *block, uint16_t len) __reentrant ao_dma_trigger(ao_spi_dma_out_id); __critical while (!ao_spi_dma_in_done) ao_sleep(&ao_spi_dma_in_done); - ao_mutex_put(&ao_spi_mutex); } /* Receive bytes over SPI. @@ -76,7 +78,6 @@ ao_spi_send(void __xdata *block, uint16_t len) __reentrant void ao_spi_recv(void __xdata *block, uint16_t len) __reentrant { - ao_mutex_get(&ao_spi_mutex); ao_dma_set_transfer(ao_spi_dma_in_id, &U0DBUFXADDR, block, @@ -104,7 +105,6 @@ ao_spi_recv(void __xdata *block, uint16_t len) __reentrant ao_dma_trigger(ao_spi_dma_out_id); __critical while (!ao_spi_dma_in_done) ao_sleep(&ao_spi_dma_in_done); - ao_mutex_put(&ao_spi_mutex); } /* diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index 6fa70b3a..f560740a 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -61,6 +61,9 @@ main(void) ao_igniter_init(); #if HAS_DBG ao_dbg_init(); +#endif +#if HAS_COMPANION + ao_companion_init(); #endif ao_config_init(); ao_start_scheduler(); diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 52f818ed..15ba4302 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -25,6 +25,10 @@ static __pdata int8_t ao_telemetry_config_cur; static __pdata int8_t ao_telemetry_loc_cur; static __pdata int8_t ao_telemetry_sat_cur; #endif +#if HAS_COMPANION +static __pdata int8_t ao_telemetry_companion_max; +static __pdata int8_t ao_telemetry_companion_cur; +#endif static __pdata uint8_t ao_rdf = 0; static __pdata uint16_t ao_rdf_time; @@ -149,6 +153,26 @@ ao_send_satellite(void) } #endif +#if HAS_COMPANION +static void +ao_send_companion(void) +{ + if (--ao_telemetry_companion_cur <= 0) { + telemetry.generic.type = AO_TELEMETRY_COMPANION; + telemetry.companion.board_id = ao_companion_setup.board_id; + telemetry.companion.update_period = ao_companion_setup.update_period; + telemetry.companion.channels = ao_companion_setup.channels; + ao_mutex_get(&ao_companion_mutex); + memcpy(&telemetry.companion.companion_data, + ao_companion_data, + ao_companion_setup.channels * 2); + ao_mutex_put(&ao_companion_mutex); + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_companion_cur = ao_telemetry_companion_max; + } +} +#endif + void ao_telemetry(void) { @@ -168,6 +192,10 @@ ao_telemetry(void) ao_send_sensor(); +#if HAS_COMPANION + if (ao_companion_running) + ao_send_companion(); +#endif ao_send_configuration(); #if HAS_GPS ao_send_location(); @@ -193,10 +221,25 @@ void ao_telemetry_set_interval(uint16_t interval) { ao_telemetry_interval = interval; + +#if HAS_COMPANION + if (!ao_companion_setup.update_period) + ao_companion_setup.update_period = AO_SEC_TO_TICKS(1); + ao_telemetry_companion_max = ao_companion_setup.update_period / interval; + ao_telemetry_companion_cur = 1; +#endif + ao_telemetry_config_max = AO_SEC_TO_TICKS(1) / interval; +#if HAS_COMPANION + ao_telemetry_config_cur = ao_telemetry_companion_cur; + if (ao_telemetry_config_max > ao_telemetry_config_cur) + ao_telemetry_config_cur++; +#else ao_telemetry_config_cur = 1; +#endif + #if HAS_GPS - ao_telemetry_loc_cur = 1; + ao_telemetry_loc_cur = ao_telemetry_config_cur; if (ao_telemetry_config_max > ao_telemetry_loc_cur) ao_telemetry_loc_cur++; ao_telemetry_sat_cur = ao_telemetry_loc_cur; diff --git a/src/telemetrum-v1.0/Makefile.defs b/src/telemetrum-v1.0/Makefile.defs index a60a501a..5eefc392 100644 --- a/src/telemetrum-v1.0/Makefile.defs +++ b/src/telemetrum-v1.0/Makefile.defs @@ -5,6 +5,7 @@ SRC = \ $(SPI_DRIVER_SRC) \ $(FLASH_DRIVER_SRC) \ $(SKY_DRIVER_SRC) \ + $(COMPANION_SRC) \ $(DBG_SRC) PRODUCT=TeleMetrum-v1.0 diff --git a/src/telemetrum-v1.1/Makefile.defs b/src/telemetrum-v1.1/Makefile.defs index f38226c6..3c8b8793 100644 --- a/src/telemetrum-v1.1/Makefile.defs +++ b/src/telemetrum-v1.1/Makefile.defs @@ -5,6 +5,7 @@ SRC = \ $(SPI_DRIVER_SRC) \ $(M25_DRIVER_SRC) \ $(SKY_DRIVER_SRC) \ + $(COMPANION_SRC) \ $(DBG_SRC) PRODUCT=TeleMetrum-v1.1 -- cgit v1.2.3 From ebe2ffb29944abc4d6a35889c7b5f3d9f2871077 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Aug 2011 05:38:16 -0700 Subject: altos: Put SPI in slower mode when talking to companion board The AVR CPU on the other side just can't go very fast. This reduces the SPI clock by a factor of 16, just under 200kHz. As the companion commands are reasonably short, this shouldn't have a huge effect on overall SPI utilization. Signed-off-by: Keith Packard --- src/ao_companion.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao_companion.c b/src/ao_companion.c index 8db3273e..556ce044 100644 --- a/src/ao_companion.c +++ b/src/ao_companion.c @@ -17,8 +17,18 @@ #include "ao.h" -#define COMPANION_SELECT() ao_spi_get_bit(COMPANION_CS) -#define COMPANION_DESELECT() ao_spi_put_bit(COMPANION_CS) +#define ao_spi_slow() (U0GCR = (UxGCR_CPOL_NEGATIVE | \ + UxGCR_CPHA_FIRST_EDGE | \ + UxGCR_ORDER_MSB | \ + (13 << UxGCR_BAUD_E_SHIFT))) + +#define ao_spi_fast() (U0GCR = (UxGCR_CPOL_NEGATIVE | \ + UxGCR_CPHA_FIRST_EDGE | \ + UxGCR_ORDER_MSB | \ + (17 << UxGCR_BAUD_E_SHIFT))) + +#define COMPANION_SELECT() do { ao_spi_get_bit(COMPANION_CS); ao_spi_slow(); } while (0) +#define COMPANION_DESELECT() do { ao_spi_fast(); ao_spi_put_bit(COMPANION_CS); } while (0) static __xdata struct ao_companion_command ao_companion_command; __xdata struct ao_companion_setup ao_companion_setup; -- cgit v1.2.3 From f87f0787fa5aa528674f3f4919eb22646c87c25a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Aug 2011 05:41:15 -0700 Subject: altos: Make sure companion task exits cleanly when done Signed-off-by: Keith Packard --- src/ao_companion.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/ao_companion.c b/src/ao_companion.c index 556ce044..e2e6d05a 100644 --- a/src/ao_companion.c +++ b/src/ao_companion.c @@ -79,6 +79,7 @@ ao_companion(void) ao_delay(ao_companion_setup.update_period); ao_companion_get_data(); } + ao_exit(); } void -- cgit v1.2.3 From aa642cf55c43188e9a21198d828d7ea90ff54280 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Aug 2011 05:42:05 -0700 Subject: altos: add the 'L' command to show the status of a linked companion board This prints out whether there is a board connected, along with the various values fetched from it. Signed-off-by: Keith Packard --- src/ao_companion.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_companion.c b/src/ao_companion.c index e2e6d05a..b424dd89 100644 --- a/src/ao_companion.c +++ b/src/ao_companion.c @@ -85,6 +85,15 @@ ao_companion(void) void ao_companion_status(void) __reentrant { + uint8_t i; + printf("Companion running: %d\n", ao_companion_running); + printf("device: %d\n", ao_companion_setup.board_id); + printf("update period: %d\n", ao_companion_setup.update_period); + printf("channels: %d\n", ao_companion_setup.channels); + printf("data:"); + for(i = 0; i < ao_companion_setup.channels; i++) + printf(" %5u", ao_companion_data[i]); + printf("\n"); } __code struct ao_cmds ao_companion_cmds[] = { @@ -102,6 +111,5 @@ ao_companion_init(void) COMPANION_CS_SEL &= ~COMPANION_CS_MASK; /* set CS pins as GPIO */ ao_cmd_register(&ao_companion_cmds[0]); - ao_add_task(&ao_companion_task, ao_companion, "companion"); } -- cgit v1.2.3 From 18369c58e62bc64b969a7cf8be3103aa33c6d4aa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Aug 2011 06:29:13 -0700 Subject: altos: Check for companion init packet validity was busted Was using board_id == ~board_id instead of board_id == ~board_id_inverse. Signed-off-by: Keith Packard --- src/ao_companion.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/ao_companion.c b/src/ao_companion.c index b424dd89..f54f5251 100644 --- a/src/ao_companion.c +++ b/src/ao_companion.c @@ -53,9 +53,8 @@ ao_companion_get_setup(void) ao_companion_send_command(AO_COMPANION_SETUP); ao_spi_recv(&ao_companion_setup, sizeof (ao_companion_setup)); COMPANION_DESELECT(); - if (ao_companion_setup.board_id != ~ao_companion_setup.board_id) - return 0; - return 1; + return (ao_companion_setup.board_id == + ~ao_companion_setup.board_id_inverse); } static void @@ -72,10 +71,8 @@ ao_companion_get_data(void) void ao_companion(void) { - if (!ao_companion_get_setup()) - ao_exit(); - ao_companion_running = 1; - for (;;) { + ao_companion_running = ao_companion_get_setup(); + while (ao_companion_running) { ao_delay(ao_companion_setup.update_period); ao_companion_get_data(); } -- cgit v1.2.3 From fa7dd04741bf3fd9cedc59ed3b45b69ef9312609 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 12 Aug 2011 21:41:25 -0700 Subject: altos: Send SPI message at flight state changes Get the companion board starting its data logging as soon as possible after boost starts. Signed-off-by: Keith Packard --- src/ao.h | 1 + src/ao_companion.c | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index de47f3df..b14b65f2 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1581,6 +1581,7 @@ ao_btm_init(void); #define AO_COMPANION_SETUP 1 #define AO_COMPANION_FETCH 2 +#define AO_COMPANION_NOTIFY 3 struct ao_companion_command { uint8_t command; diff --git a/src/ao_companion.c b/src/ao_companion.c index f54f5251..f0ce3f12 100644 --- a/src/ao_companion.c +++ b/src/ao_companion.c @@ -68,13 +68,24 @@ ao_companion_get_data(void) COMPANION_DESELECT(); } +static void +ao_companion_notify(void) +{ + COMPANION_SELECT(); + ao_companion_send_command(AO_COMPANION_NOTIFY); + COMPANION_DESELECT(); +} + void ao_companion(void) { ao_companion_running = ao_companion_get_setup(); while (ao_companion_running) { - ao_delay(ao_companion_setup.update_period); - ao_companion_get_data(); + ao_alarm(ao_companion_setup.update_period); + if (ao_sleep(DATA_TO_XDATA(&ao_flight_state))) + ao_companion_get_data(); + else + ao_companion_notify(); } ao_exit(); } -- cgit v1.2.3 From 41e5be32819d305c8268e6f992be91411ea13435 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Aug 2011 18:30:00 -0700 Subject: altos: Send serial/flight to companion board Lets the companion log them for later matching with TeleMetrum log Signed-off-by: Keith Packard --- src/ao.h | 2 ++ src/ao_companion.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index b14b65f2..6a4da31e 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1587,6 +1587,8 @@ struct ao_companion_command { uint8_t command; uint8_t flight_state; uint16_t tick; + uint16_t serial; + uint16_t flight; }; struct ao_companion_setup { diff --git a/src/ao_companion.c b/src/ao_companion.c index f0ce3f12..8f23ba25 100644 --- a/src/ao_companion.c +++ b/src/ao_companion.c @@ -43,6 +43,8 @@ ao_companion_send_command(uint8_t command) ao_companion_command.command = command; ao_companion_command.flight_state = ao_flight_state; ao_companion_command.tick = ao_time(); + ao_companion_command.serial = ao_serial_number; + ao_companion_command.flight = ao_flight_number; ao_spi_send(&ao_companion_command, sizeof (ao_companion_command)); } -- cgit v1.2.3 From b0ec30de37aa822ba66d25ceaa8cf8dc967b4371 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Aug 2011 18:31:08 -0700 Subject: altos: wait 10s for companion to boot In case the companion is delayed while booting, retry the setup 10 times with a 1s delay between tries. Signed-off-by: Keith Packard --- src/ao_companion.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_companion.c b/src/ao_companion.c index 8f23ba25..4c8f4269 100644 --- a/src/ao_companion.c +++ b/src/ao_companion.c @@ -81,7 +81,14 @@ ao_companion_notify(void) void ao_companion(void) { - ao_companion_running = ao_companion_get_setup(); + uint8_t i; + while (!ao_flight_number) + ao_sleep(&ao_flight_number); + for (i = 0; i < 10; i++) { + ao_delay(AO_SEC_TO_TICKS(1)); + if ((ao_companion_running = ao_companion_get_setup())) + break; + } while (ao_companion_running) { ao_alarm(ao_companion_setup.update_period); if (ao_sleep(DATA_TO_XDATA(&ao_flight_state))) -- cgit v1.2.3 From 7f74761051f2a5ab45b82c4dd79a8569376bbe2e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Aug 2011 23:56:06 -0700 Subject: altos: Correct AO_CONFIG_MINOR from 6 to 7 Forgot to bump this when adding radio setting. Signed-off-by: Keith Packard --- src/ao.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao.h b/src/ao.h index 6a4da31e..79452862 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1415,7 +1415,7 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 6 +#define AO_CONFIG_MINOR 7 struct ao_config { uint8_t major; -- cgit v1.2.3 From aa71c2cdcb417eba2a2d30792ece9a47b8b3fc82 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Aug 2011 23:56:55 -0700 Subject: altos: Reset radio channel to zero when using radio setting Otherwise, it's hard to set the frequency over the radio link. Signed-off-by: Keith Packard --- src/ao_config.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/ao_config.c b/src/ao_config.c index 36bd47c4..331509e2 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -402,6 +402,7 @@ ao_config_radio_setting_set(void) __reentrant ao_mutex_get(&ao_config_mutex); _ao_config_get(); ao_config.radio_setting = ao_cmd_lex_u32; + ao_config.radio_channel = 0; ao_config_dirty = 1; ao_mutex_put(&ao_config_mutex); ao_config_radio_setting_show(); -- cgit v1.2.3 From 709485f20fb039f8dd087c8491c5f5a76718ae53 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 13 Aug 2011 23:58:03 -0700 Subject: altos: use raw height while waiting for landing This avoids any noise introduced by the kalman filter, making landing detection much more reliable. This patch also changes the interval to 10s so that the height bounds can be increased to 4m. Signed-off-by: Keith Packard --- src/ao_flight.c | 4 ++-- src/ao_kalman.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index af3d6bfa..85c1825b 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -54,7 +54,7 @@ __pdata uint8_t ao_flight_force_idle; /* Landing is detected by getting constant readings from both pressure and accelerometer * for a fairly long time (AO_INTERVAL_TICKS) */ -#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(5) +#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(10) #define abs(a) ((a) < 0 ? -(a) : (a)) @@ -286,7 +286,7 @@ ao_flight(void) ao_interval_max_height = ao_avg_height; if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { - if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(2)) + if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4)) { ao_flight_state = ao_flight_landed; diff --git a/src/ao_kalman.c b/src/ao_kalman.c index 203d727a..ee01949e 100644 --- a/src/ao_kalman.c +++ b/src/ao_kalman.c @@ -277,7 +277,7 @@ ao_kalman(void) ao_accel = from_fix(ao_k_accel); if (ao_height > ao_max_height) ao_max_height = ao_height; - ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_height; + ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_sample_height; #ifdef AO_FLIGHT_TEST if (ao_sample_tick - ao_sample_prev_tick > 50) ao_avg_height = (ao_avg_height_scaled + 1) >> 1; -- cgit v1.2.3 From 4f64d66295a8f76680af8cfda4650aa4c4f8576d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 14 Aug 2011 19:19:50 -0700 Subject: altos: Lost change that reported flight 0 when log memory was full commit 52ac83fedbfd380d14d4df2e79992bbdfba3552a added coded to check for a full flight log and complain with a special tone. It also reported flight 0 over telemetry, and that part of the patch got lost when moving to the new telemetry format. This patch resurrects that piece. Signed-off-by: Keith Packard --- src/ao_telemetry.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 15ba4302..8a18ba07 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -101,7 +101,7 @@ ao_send_configuration(void) { telemetry.generic.type = AO_TELEMETRY_CONFIGURATION; telemetry.configuration.device = AO_idProduct_NUMBER; - telemetry.configuration.flight = ao_flight_number; + telemetry.configuration.flight = ao_log_full() ? 0 : ao_flight_number; telemetry.configuration.config_major = AO_CONFIG_MAJOR; telemetry.configuration.config_minor = AO_CONFIG_MINOR; telemetry.configuration.apogee_delay = ao_config.apogee_delay; -- cgit v1.2.3 From f2b0900f8b83fcb3085f3d042ffd961ffd758d5d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 20 Aug 2011 11:28:53 -0700 Subject: altos: Merge common config code in ao_config.c This shuffles code around in ao_config.c to share some common code segments for starting and committing config changes. This also stops printing out changes as they are made which aren't needed by the UI code. Signed-off-by: Keith Packard --- src/ao_config.c | 104 +++++++++++++++++++++++--------------------------------- 1 file changed, 42 insertions(+), 62 deletions(-) (limited to 'src') diff --git a/src/ao_config.c b/src/ao_config.c index 331509e2..e0eae78e 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -105,11 +105,24 @@ _ao_config_get(void) ao_config_loaded = 1; } -void -ao_config_get(void) +static void +_ao_config_edit_start(void) { ao_mutex_get(&ao_config_mutex); _ao_config_get(); +} + +static void +_ao_config_edit_finish(void) +{ + ao_config_dirty = 1; + ao_mutex_put(&ao_config_mutex); +} + +void +ao_config_get(void) +{ + _ao_config_edit_start(); ao_mutex_put(&ao_config_mutex); } @@ -137,13 +150,10 @@ ao_config_callsign_set(void) __reentrant } if (ao_cmd_status != ao_cmd_success) return; - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); + _ao_config_edit_start(); memcpy(&ao_config.callsign, &callsign, AO_MAX_CALLSIGN + 1); - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); - ao_config_callsign_show(); + _ao_config_edit_finish(); } void @@ -159,12 +169,9 @@ ao_config_radio_channel_set(void) __reentrant ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); + _ao_config_edit_start(); ao_config.radio_channel = ao_cmd_lex_i; - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); - ao_config_radio_channel_show(); + _ao_config_edit_finish(); ao_radio_recv_abort(); } @@ -183,12 +190,9 @@ ao_config_main_deploy_set(void) __reentrant ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); + _ao_config_edit_start(); ao_config.main_deploy = ao_cmd_lex_i; - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); - ao_config_main_deploy_show(); + _ao_config_edit_finish(); } #if HAS_ACCEL @@ -250,13 +254,10 @@ ao_config_accel_calibrate_set(void) __reentrant up, down); return; } - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); + _ao_config_edit_start(); ao_config.accel_plus_g = up; ao_config.accel_minus_g = down; - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); - ao_config_accel_calibrate_show(); + _ao_config_edit_finish(); } #endif /* HAS_ACCEL */ @@ -273,12 +274,9 @@ ao_config_apogee_delay_set(void) __reentrant ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); + _ao_config_edit_start(); ao_config.apogee_delay = ao_cmd_lex_i; - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); - ao_config_apogee_delay_show(); + _ao_config_edit_finish(); } #endif /* HAS_ADC */ @@ -295,12 +293,9 @@ ao_config_radio_cal_set(void) __reentrant ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); + _ao_config_edit_start(); ao_config.radio_setting = ao_config.radio_cal = ao_cmd_lex_u32; - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); - ao_config_radio_cal_show(); + _ao_config_edit_finish(); } #if HAS_EEPROM @@ -326,12 +321,9 @@ ao_config_log_set(void) __reentrant else if (ao_cmd_lex_i > config) printf("Flight log max %d kB\n", config); else { - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); + _ao_config_edit_start(); ao_config.flight_log_max = (uint32_t) ao_cmd_lex_i << 10; - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); - ao_config_log_show(); + _ao_config_edit_finish(); } } #endif /* HAS_EEPROM */ @@ -349,12 +341,9 @@ ao_config_ignite_mode_set(void) __reentrant ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); + _ao_config_edit_start(); ao_config.ignite_mode = ao_cmd_lex_i; - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); - ao_config_ignite_mode_show(); + _ao_config_edit_finish(); } #endif @@ -371,8 +360,7 @@ ao_config_pad_orientation_set(void) __reentrant ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); + _ao_config_edit_start(); ao_cmd_lex_i &= 1; if (ao_config.pad_orientation != ao_cmd_lex_i) { uint16_t t; @@ -381,9 +369,7 @@ ao_config_pad_orientation_set(void) __reentrant ao_config.accel_minus_g = 0x7fff - t; } ao_config.pad_orientation = ao_cmd_lex_i; - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); - ao_config_pad_orientation_show(); + _ao_config_edit_finish(); } #endif @@ -399,13 +385,10 @@ ao_config_radio_setting_set(void) __reentrant ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); + _ao_config_edit_start(); ao_config.radio_setting = ao_cmd_lex_u32; ao_config.radio_channel = 0; - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); - ao_config_radio_setting_show(); + _ao_config_edit_finish(); ao_radio_recv_abort(); } @@ -456,13 +439,13 @@ __code struct ao_config_var ao_config_vars[] = { { "R \0Radio freq control (freq = 434.550 * setting/cal)", ao_config_radio_setting_set, ao_config_radio_setting_show }, { "s\0Show", - ao_config_show, ao_config_show }, + ao_config_show, 0 }, #if HAS_EEPROM { "w\0Write to eeprom", - ao_config_write, ao_config_write }, + ao_config_write, 0 }, #endif { "?\0Help", - ao_config_help, ao_config_help }, + ao_config_help, 0 }, { 0, 0, 0 } }; @@ -479,13 +462,10 @@ ao_config_set(void) func = 0; for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) if (ao_config_vars[cmd].str[0] == c) { - func = ao_config_vars[cmd].set; - break; + (*ao_config_vars[cmd].set)(); + return; } - if (func) - (*func)(); - else - ao_cmd_status = ao_cmd_syntax_error; + ao_cmd_status = ao_cmd_syntax_error; } static void @@ -505,7 +485,7 @@ ao_config_show(void) __reentrant printf("Config version: %d.%d\n", ao_config.major, ao_config.minor); for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) - if (ao_config_vars[cmd].show != ao_config_vars[cmd].set) + if (ao_config_vars[cmd].show) (*ao_config_vars[cmd].show)(); } -- cgit v1.2.3 From 6823ad5e48fc0a19791d96f886b5689f88c4311b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 18 Aug 2011 18:02:02 -0700 Subject: altos/altosui: Add ability to disable telemetry/rdf completely This turns off the telemetry system so that it never transmits telemetry or RDF tones. In idle mode, it will still accept packet mode connections. Signed-off-by: Keith Packard --- altosui/AltosConfig.java | 8 ++++++ altosui/AltosConfigUI.java | 65 +++++++++++++++++++++++++++++++++++++--------- src/ao.h | 3 ++- src/ao_config.c | 25 ++++++++++++++++-- src/ao_telemetry.c | 2 ++ 5 files changed, 88 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/altosui/AltosConfig.java b/altosui/AltosConfig.java index 84c8a4a3..b1e6bc12 100644 --- a/altosui/AltosConfig.java +++ b/altosui/AltosConfig.java @@ -79,6 +79,7 @@ public class AltosConfig implements ActionListener { int_ref storage_size; int_ref storage_erase_unit; int_ref stored_flight; + int_ref radio_enable; string_ref version; string_ref product; string_ref callsign; @@ -148,6 +149,7 @@ public class AltosConfig implements ActionListener { config_ui.set_radio_calibration(radio_calibration.get()); config_ui.set_radio_frequency(frequency()); config_ui.set_flight_log_max_enabled(stored_flight.get() < 0); + config_ui.set_radio_enable(radio_enable.get()); config_ui.set_flight_log_max_limit(log_limit()); config_ui.set_flight_log_max(flight_log_max.get()); config_ui.set_ignite_mode(ignite_mode.get()); @@ -177,6 +179,7 @@ public class AltosConfig implements ActionListener { get_int(line, "Ignite mode:", ignite_mode); get_int(line, "Pad orientation:", pad_orientation); get_int(line, "Radio setting:", radio_setting); + get_int(line, "Radio enable:", radio_enable); get_int(line, "Storage size:", storage_size); get_int(line, "Storage erase unit:", storage_erase_unit); get_int(line, "flight", stored_flight); @@ -255,6 +258,8 @@ public class AltosConfig implements ActionListener { serial_line.printf("c c %s\n", callsign.get()); if (flight_log_max.get() != 0) serial_line.printf("c l %d\n", flight_log_max.get()); + if (radio_enable.get() >= 0) + serial_line.printf("c e %d\n", radio_enable.get()); if (ignite_mode.get() >= 0) serial_line.printf("c i %d\n", ignite_mode.get()); if (pad_orientation.get() >= 0) @@ -373,6 +378,8 @@ public class AltosConfig implements ActionListener { radio_calibration.set(config_ui.radio_calibration()); set_frequency(config_ui.radio_frequency()); flight_log_max.set(config_ui.flight_log_max()); + if (radio_enable.get() >= 0) + radio_enable.set(config_ui.radio_enable()); if (ignite_mode.get() >= 0) ignite_mode.set(config_ui.ignite_mode()); if (pad_orientation.get() >= 0) @@ -412,6 +419,7 @@ public class AltosConfig implements ActionListener { radio_channel = new int_ref(0); radio_setting = new int_ref(0); radio_calibration = new int_ref(1186611); + radio_enable = new int_ref(-1); flight_log_max = new int_ref(0); ignite_mode = new int_ref(-1); pad_orientation = new int_ref(-1); diff --git a/altosui/AltosConfigUI.java b/altosui/AltosConfigUI.java index 69afd691..bb9e1cd2 100644 --- a/altosui/AltosConfigUI.java +++ b/altosui/AltosConfigUI.java @@ -46,6 +46,7 @@ public class AltosConfigUI JLabel frequency_label; JLabel radio_calibration_label; JLabel radio_frequency_label; + JLabel radio_enable_label; JLabel flight_log_max_label; JLabel ignite_mode_label; JLabel pad_orientation_label; @@ -61,6 +62,7 @@ public class AltosConfigUI JComboBox apogee_delay_value; AltosFreqList radio_frequency_value; JTextField radio_calibration_value; + JRadioButton radio_enable_value; JComboBox flight_log_max_value; JComboBox ignite_mode_value; JComboBox pad_orientation_value; @@ -287,7 +289,7 @@ public class AltosConfigUI radio_calibration_value.setEnabled(false); pane.add(radio_calibration_value, c); - /* Callsign */ + /* Radio Enable */ c = new GridBagConstraints(); c.gridx = 0; c.gridy = 7; c.gridwidth = 4; @@ -295,11 +297,34 @@ public class AltosConfigUI c.anchor = GridBagConstraints.LINE_START; c.insets = il; c.ipady = 5; + radio_enable_label = new JLabel("Telemetry/RDF Enable:"); + pane.add(radio_enable_label, c); + + c = new GridBagConstraints(); + c.gridx = 4; c.gridy = 7; + c.gridwidth = 4; + c.fill = GridBagConstraints.HORIZONTAL; + c.weightx = 1; + c.anchor = GridBagConstraints.LINE_START; + c.insets = ir; + c.ipady = 5; + radio_enable_value = new JRadioButton("Enabled"); + radio_enable_value.addItemListener(this); + pane.add(radio_enable_value, c); + + /* Callsign */ + c = new GridBagConstraints(); + c.gridx = 0; c.gridy = 8; + c.gridwidth = 4; + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.LINE_START; + c.insets = il; + c.ipady = 5; callsign_label = new JLabel("Callsign:"); pane.add(callsign_label, c); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 7; + c.gridx = 4; c.gridy = 8; c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; @@ -312,7 +337,7 @@ public class AltosConfigUI /* Flight log max */ c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 8; + c.gridx = 0; c.gridy = 9; c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -322,7 +347,7 @@ public class AltosConfigUI pane.add(flight_log_max_label, c); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 8; + c.gridx = 4; c.gridy = 9; c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; @@ -336,7 +361,7 @@ public class AltosConfigUI /* Ignite mode */ c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 9; + c.gridx = 0; c.gridy = 10; c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -346,7 +371,7 @@ public class AltosConfigUI pane.add(ignite_mode_label, c); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 9; + c.gridx = 4; c.gridy = 10; c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; @@ -360,7 +385,7 @@ public class AltosConfigUI /* Pad orientation */ c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 10; + c.gridx = 0; c.gridy = 11; c.gridwidth = 4; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -370,7 +395,7 @@ public class AltosConfigUI pane.add(pad_orientation_label, c); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 10; + c.gridx = 4; c.gridy = 11; c.gridwidth = 4; c.fill = GridBagConstraints.HORIZONTAL; c.weightx = 1; @@ -384,7 +409,7 @@ public class AltosConfigUI /* Buttons */ c = new GridBagConstraints(); - c.gridx = 0; c.gridy = 11; + c.gridx = 0; c.gridy = 12; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_START; @@ -395,7 +420,7 @@ public class AltosConfigUI save.setActionCommand("Save"); c = new GridBagConstraints(); - c.gridx = 2; c.gridy = 11; + c.gridx = 2; c.gridy = 12; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; @@ -406,7 +431,7 @@ public class AltosConfigUI reset.setActionCommand("Reset"); c = new GridBagConstraints(); - c.gridx = 4; c.gridy = 11; + c.gridx = 4; c.gridy = 12; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.CENTER; @@ -417,7 +442,7 @@ public class AltosConfigUI reboot.setActionCommand("Reboot"); c = new GridBagConstraints(); - c.gridx = 6; c.gridy = 11; + c.gridx = 6; c.gridy = 12; c.gridwidth = 2; c.fill = GridBagConstraints.NONE; c.anchor = GridBagConstraints.LINE_END; @@ -559,6 +584,22 @@ public class AltosConfigUI return Integer.parseInt(radio_calibration_value.getText()); } + public void set_radio_enable(int new_radio_enable) { + if (new_radio_enable >= 0) + radio_enable_value.setSelected(new_radio_enable > 0); + else { + radio_enable_value.setSelected(true); + radio_enable_value.setEnabled(false); + } + } + + public int radio_enable() { + if (radio_enable_value.isEnabled()) + return radio_enable_value.isSelected() ? 1 : 0; + else + return -1; + } + public void set_callsign(String new_callsign) { callsign_value.setText(new_callsign); } diff --git a/src/ao.h b/src/ao.h index 79452862..8ac9ac3d 100644 --- a/src/ao.h +++ b/src/ao.h @@ -1415,7 +1415,7 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 7 +#define AO_CONFIG_MINOR 8 struct ao_config { uint8_t major; @@ -1431,6 +1431,7 @@ struct ao_config { uint8_t ignite_mode; /* minor version 5 */ uint8_t pad_orientation; /* minor version 6 */ uint32_t radio_setting; /* minor version 7 */ + uint8_t radio_enable; /* minor version 8 */ }; #define AO_IGNITE_MODE_DUAL 0 diff --git a/src/ao_config.c b/src/ao_config.c index e0eae78e..eb1eea3f 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -99,6 +99,8 @@ _ao_config_get(void) ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; if (ao_config.minor < 7) ao_config.radio_setting = ao_config.radio_cal; + if (ao_config.minor < 8) + ao_config.radio_enable = TRUE; ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -392,6 +394,23 @@ ao_config_radio_setting_set(void) __reentrant ao_radio_recv_abort(); } +void +ao_config_radio_enable_show(void) __reentrant +{ + printf("Radio enable: %d\n", ao_config.radio_enable); +} + +void +ao_config_radio_enable_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.radio_enable = ao_cmd_lex_i; + _ao_config_edit_finish(); +} + struct ao_config_var { __code char *str; void (*set)(void) __reentrant; @@ -418,6 +437,10 @@ __code struct ao_config_var ao_config_vars[] = { ao_config_radio_channel_set, ao_config_radio_channel_show }, { "c \0Callsign (8 char max)", ao_config_callsign_set, ao_config_callsign_show }, + { "R \0Radio freq control (freq = 434.550 * setting/cal)", + ao_config_radio_setting_set, ao_config_radio_setting_show }, + { "e <0 disable, 1 enable>\0Enable telemetry and RDF", + ao_config_radio_enable_set, ao_config_radio_enable_show }, #if HAS_ACCEL { "a <+g> <-g>\0Accel calib (0 for auto)", ao_config_accel_calibrate_set,ao_config_accel_calibrate_show }, @@ -436,8 +459,6 @@ __code struct ao_config_var ao_config_vars[] = { { "o <0 antenna up, 1 antenna down>\0Set pad orientation", ao_config_pad_orientation_set,ao_config_pad_orientation_show }, #endif - { "R \0Radio freq control (freq = 434.550 * setting/cal)", - ao_config_radio_setting_set, ao_config_radio_setting_show }, { "s\0Show", ao_config_show, 0 }, #if HAS_EEPROM diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index 8a18ba07..c7338a58 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -180,6 +180,8 @@ ao_telemetry(void) int16_t delay; ao_config_get(); + if (!ao_config.radio_enable) + ao_exit(); while (!ao_flight_number) ao_sleep(&ao_flight_number); -- cgit v1.2.3 From 3bfe8df44b575ca430ffaa051e20faa955a06c03 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Aug 2011 18:02:45 -0700 Subject: altos: Clear callsign on initial config load Before being written the first time, ao_config will get set to 0xff when the config storage is read. This leaves the tail of the callsign filled with invalid bytes. Zero the whole thing before loading the default callsign to make sure any extra bytes are set correctly. Signed-off-by: Keith Packard --- src/ao_config.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/ao_config.c b/src/ao_config.c index eb1eea3f..0c10e608 100644 --- a/src/ao_config.c +++ b/src/ao_config.c @@ -74,6 +74,7 @@ _ao_config_get(void) ao_config.minor = 0; ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; + memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); } -- cgit v1.2.3 From 9513be7f9d3d0b0ec29f6487fa9dc8f1ac24d0de Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Aug 2011 20:43:44 -0700 Subject: altos: Restructure altos build to prepare for multi-arch support Split out sources into separate directories: core: architecture and product independent bits cc1111: cc1111-specific code drivers: architecture independent drivers product: product-specific sources and Makefile fragments util: scripts for building stuff This should have no effect on the built products, but testing is encouraged Signed-off-by: Keith Packard --- configure.ac | 2 +- src/25lc1024.h | 41 - src/Makefile | 25 +- src/Makefile.proto | 380 -------- src/_bp.c | 26 - src/altitude.h | 132 --- src/ao-make-product.5c | 103 -- src/ao.h | 1610 -------------------------------- src/ao_adc.c | 196 ---- src/ao_adc_fake.c | 27 - src/ao_beep.c | 52 -- src/ao_btm.c | 302 ------ src/ao_cmd.c | 320 ------- src/ao_companion.c | 132 --- src/ao_config.c | 542 ----------- src/ao_convert.c | 85 -- src/ao_convert_test.c | 75 -- src/ao_dbg.c | 364 -------- src/ao_dma.c | 131 --- src/ao_ee.c | 241 ----- src/ao_ee_fake.c | 37 - src/ao_flash.c | 318 ------- src/ao_flight.c | 315 ------- src/ao_flight_nano.c | 120 --- src/ao_flight_test.c | 716 -------------- src/ao_gps_print.c | 112 --- src/ao_gps_report.c | 99 -- src/ao_gps_sirf.c | 442 --------- src/ao_gps_skytraq.c | 490 ---------- src/ao_gps_test.c | 508 ---------- src/ao_gps_test_skytraq.c | 490 ---------- src/ao_host.h | 127 --- src/ao_ignite.c | 218 ----- src/ao_intflash.c | 209 ----- src/ao_kalman.c | 292 ------ src/ao_led.c | 61 -- src/ao_log.c | 284 ------ src/ao_log_big.c | 158 ---- src/ao_log_telem.c | 30 - src/ao_log_tiny.c | 161 ---- src/ao_m25.c | 380 -------- src/ao_main.c | 43 - src/ao_monitor.c | 277 ------ src/ao_mutex.c | 41 - src/ao_packet.c | 148 --- src/ao_packet_master.c | 144 --- src/ao_packet_slave.c | 64 -- src/ao_panic.c | 66 -- src/ao_pins.h | 408 -------- src/ao_product.c | 155 --- src/ao_radio.c | 475 ---------- src/ao_reboot.c | 28 - src/ao_report.c | 180 ---- src/ao_romconfig.c | 32 - src/ao_rssi.c | 53 -- src/ao_sample.c | 209 ----- src/ao_serial.c | 175 ---- src/ao_spi.c | 157 ---- src/ao_state.c | 23 - src/ao_stdio.c | 84 -- src/ao_storage.c | 184 ---- src/ao_task.c | 275 ------ src/ao_telebt.c | 50 - src/ao_teledongle.c | 40 - src/ao_telem.h | 172 ---- src/ao_telemetrum.c | 70 -- src/ao_telemetry.c | 270 ------ src/ao_telemini.c | 49 - src/ao_telenano.c | 43 - src/ao_teleterra.c | 38 - src/ao_test.c | 117 --- src/ao_tidongle.c | 42 - src/ao_timer.c | 111 --- src/ao_usb.c | 460 --------- src/ao_usb.h | 100 -- src/at45db161d.h | 45 - src/cc1111.h | 1306 -------------------------- src/cc1111/Makefile.cc1111 | 27 + src/cc1111/_bp.c | 26 + src/cc1111/ao_adc.c | 196 ++++ src/cc1111/ao_beep.c | 52 ++ src/cc1111/ao_dbg.c | 364 ++++++++ src/cc1111/ao_dma.c | 131 +++ src/cc1111/ao_ignite.c | 218 +++++ src/cc1111/ao_intflash.c | 209 +++++ src/cc1111/ao_led.c | 61 ++ src/cc1111/ao_packet.c | 148 +++ src/cc1111/ao_packet_master.c | 144 +++ src/cc1111/ao_packet_slave.c | 64 ++ src/cc1111/ao_radio.c | 475 ++++++++++ src/cc1111/ao_reboot.c | 28 + src/cc1111/ao_romconfig.c | 32 + src/cc1111/ao_serial.c | 175 ++++ src/cc1111/ao_spi.c | 157 ++++ src/cc1111/ao_timer.c | 111 +++ src/cc1111/ao_usb.c | 460 +++++++++ src/cc1111/ao_usb.h | 100 ++ src/cc1111/cc1111.h | 1306 ++++++++++++++++++++++++++ src/check-stack | 13 - src/core/altitude.h | 132 +++ src/core/ao.h | 1610 ++++++++++++++++++++++++++++++++ src/core/ao_cmd.c | 320 +++++++ src/core/ao_config.c | 542 +++++++++++ src/core/ao_convert.c | 85 ++ src/core/ao_convert_test.c | 75 ++ src/core/ao_ee_fake.c | 37 + src/core/ao_flight.c | 315 +++++++ src/core/ao_flight_nano.c | 120 +++ src/core/ao_gps_print.c | 112 +++ src/core/ao_gps_report.c | 99 ++ src/core/ao_host.h | 127 +++ src/core/ao_kalman.c | 292 ++++++ src/core/ao_log.c | 284 ++++++ src/core/ao_log_big.c | 158 ++++ src/core/ao_log_telem.c | 30 + src/core/ao_log_tiny.c | 161 ++++ src/core/ao_monitor.c | 277 ++++++ src/core/ao_mutex.c | 41 + src/core/ao_panic.c | 66 ++ src/core/ao_pins.h | 408 ++++++++ src/core/ao_product.c | 155 +++ src/core/ao_report.c | 180 ++++ src/core/ao_rssi.c | 53 ++ src/core/ao_sample.c | 209 +++++ src/core/ao_state.c | 23 + src/core/ao_stdio.c | 84 ++ src/core/ao_storage.c | 184 ++++ src/core/ao_task.c | 275 ++++++ src/core/ao_telem.h | 172 ++++ src/core/ao_telemetry.c | 270 ++++++ src/drivers/ao_25lc1024.c | 241 +++++ src/drivers/ao_25lc1024.h | 41 + src/drivers/ao_at45db161d.c | 318 +++++++ src/drivers/ao_at45db161d.h | 45 + src/drivers/ao_btm.c | 302 ++++++ src/drivers/ao_companion.c | 132 +++ src/drivers/ao_gps_sirf.c | 442 +++++++++ src/drivers/ao_gps_skytraq.c | 490 ++++++++++ src/drivers/ao_m25.c | 380 ++++++++ src/gps-cksum | 17 - src/make-altitude | 283 ------ src/make-kalman | 19 - src/product/Makefile.telebt | 97 ++ src/product/Makefile.teledongle | 96 ++ src/product/Makefile.telemetrum | 111 +++ src/product/Makefile.telemini | 100 ++ src/product/Makefile.telenano | 99 ++ src/product/ao_telebt.c | 50 + src/product/ao_teledongle.c | 40 + src/product/ao_telemetrum.c | 70 ++ src/product/ao_telemini.c | 49 + src/product/ao_telenano.c | 43 + src/product/ao_teleterra.c | 38 + src/product/ao_test.c | 117 +++ src/product/ao_tidongle.c | 42 + src/sirf-cksum | 44 - src/skytraq-cksum | 44 - src/telebt-v0.0/Makefile | 10 +- src/telebt-v0.0/Makefile.defs | 8 - src/telebt-v0.1/Makefile | 20 +- src/telebt-v0.1/Makefile.defs | 8 - src/teledongle-v0.1/Makefile | 9 +- src/teledongle-v0.1/Makefile.defs | 9 - src/teledongle-v0.2/Makefile | 9 +- src/teledongle-v0.2/Makefile.defs | 9 - src/telemetrum-v0.1-sirf/Makefile | 17 +- src/telemetrum-v0.1-sirf/Makefile.defs | 12 - src/telemetrum-v0.1-sky/Makefile | 17 +- src/telemetrum-v0.1-sky/Makefile.defs | 12 - src/telemetrum-v1.0/Makefile | 17 +- src/telemetrum-v1.0/Makefile.defs | 13 - src/telemetrum-v1.1/Makefile | 17 +- src/telemetrum-v1.1/Makefile.defs | 13 - src/telemini-v1.0/Makefile | 9 +- src/telemini-v1.0/Makefile.defs | 9 - src/telenano-v0.1/Makefile | 10 +- src/telenano-v0.1/Makefile.defs | 9 - src/test/Makefile | 20 +- src/test/ao_flight_test.c | 716 ++++++++++++++ src/test/ao_gps_test.c | 508 ++++++++++ src/test/ao_gps_test_skytraq.c | 490 ++++++++++ src/tidongle/Makefile | 93 +- src/tidongle/Makefile.defs | 9 - src/util/ao-make-product.5c | 103 ++ src/util/check-stack | 13 + src/util/gps-cksum | 17 + src/util/make-altitude | 283 ++++++ src/util/make-kalman | 19 + src/util/sirf-cksum | 44 + src/util/skytraq-cksum | 44 + 190 files changed, 17208 insertions(+), 17018 deletions(-) delete mode 100644 src/25lc1024.h delete mode 100644 src/Makefile.proto delete mode 100644 src/_bp.c delete mode 100644 src/altitude.h delete mode 100644 src/ao-make-product.5c delete mode 100644 src/ao.h delete mode 100644 src/ao_adc.c delete mode 100644 src/ao_adc_fake.c delete mode 100644 src/ao_beep.c delete mode 100644 src/ao_btm.c delete mode 100644 src/ao_cmd.c delete mode 100644 src/ao_companion.c delete mode 100644 src/ao_config.c delete mode 100644 src/ao_convert.c delete mode 100644 src/ao_convert_test.c delete mode 100644 src/ao_dbg.c delete mode 100644 src/ao_dma.c delete mode 100644 src/ao_ee.c delete mode 100644 src/ao_ee_fake.c delete mode 100644 src/ao_flash.c delete mode 100644 src/ao_flight.c delete mode 100644 src/ao_flight_nano.c delete mode 100644 src/ao_flight_test.c delete mode 100644 src/ao_gps_print.c delete mode 100644 src/ao_gps_report.c delete mode 100644 src/ao_gps_sirf.c delete mode 100644 src/ao_gps_skytraq.c delete mode 100644 src/ao_gps_test.c delete mode 100644 src/ao_gps_test_skytraq.c delete mode 100644 src/ao_host.h delete mode 100644 src/ao_ignite.c delete mode 100644 src/ao_intflash.c delete mode 100644 src/ao_kalman.c delete mode 100644 src/ao_led.c delete mode 100644 src/ao_log.c delete mode 100644 src/ao_log_big.c delete mode 100644 src/ao_log_telem.c delete mode 100644 src/ao_log_tiny.c delete mode 100644 src/ao_m25.c delete mode 100644 src/ao_main.c delete mode 100644 src/ao_monitor.c delete mode 100644 src/ao_mutex.c delete mode 100644 src/ao_packet.c delete mode 100644 src/ao_packet_master.c delete mode 100644 src/ao_packet_slave.c delete mode 100644 src/ao_panic.c delete mode 100644 src/ao_pins.h delete mode 100644 src/ao_product.c delete mode 100644 src/ao_radio.c delete mode 100644 src/ao_reboot.c delete mode 100644 src/ao_report.c delete mode 100644 src/ao_romconfig.c delete mode 100644 src/ao_rssi.c delete mode 100644 src/ao_sample.c delete mode 100644 src/ao_serial.c delete mode 100644 src/ao_spi.c delete mode 100644 src/ao_state.c delete mode 100644 src/ao_stdio.c delete mode 100644 src/ao_storage.c delete mode 100644 src/ao_task.c delete mode 100644 src/ao_telebt.c delete mode 100644 src/ao_teledongle.c delete mode 100644 src/ao_telem.h delete mode 100644 src/ao_telemetrum.c delete mode 100644 src/ao_telemetry.c delete mode 100644 src/ao_telemini.c delete mode 100644 src/ao_telenano.c delete mode 100644 src/ao_teleterra.c delete mode 100644 src/ao_test.c delete mode 100644 src/ao_tidongle.c delete mode 100644 src/ao_timer.c delete mode 100644 src/ao_usb.c delete mode 100644 src/ao_usb.h delete mode 100644 src/at45db161d.h delete mode 100644 src/cc1111.h create mode 100644 src/cc1111/Makefile.cc1111 create mode 100644 src/cc1111/_bp.c create mode 100644 src/cc1111/ao_adc.c create mode 100644 src/cc1111/ao_beep.c create mode 100644 src/cc1111/ao_dbg.c create mode 100644 src/cc1111/ao_dma.c create mode 100644 src/cc1111/ao_ignite.c create mode 100644 src/cc1111/ao_intflash.c create mode 100644 src/cc1111/ao_led.c create mode 100644 src/cc1111/ao_packet.c create mode 100644 src/cc1111/ao_packet_master.c create mode 100644 src/cc1111/ao_packet_slave.c create mode 100644 src/cc1111/ao_radio.c create mode 100644 src/cc1111/ao_reboot.c create mode 100644 src/cc1111/ao_romconfig.c create mode 100644 src/cc1111/ao_serial.c create mode 100644 src/cc1111/ao_spi.c create mode 100644 src/cc1111/ao_timer.c create mode 100644 src/cc1111/ao_usb.c create mode 100644 src/cc1111/ao_usb.h create mode 100644 src/cc1111/cc1111.h delete mode 100755 src/check-stack create mode 100644 src/core/altitude.h create mode 100644 src/core/ao.h create mode 100644 src/core/ao_cmd.c create mode 100644 src/core/ao_config.c create mode 100644 src/core/ao_convert.c create mode 100644 src/core/ao_convert_test.c create mode 100644 src/core/ao_ee_fake.c create mode 100644 src/core/ao_flight.c create mode 100644 src/core/ao_flight_nano.c create mode 100644 src/core/ao_gps_print.c create mode 100644 src/core/ao_gps_report.c create mode 100644 src/core/ao_host.h create mode 100644 src/core/ao_kalman.c create mode 100644 src/core/ao_log.c create mode 100644 src/core/ao_log_big.c create mode 100644 src/core/ao_log_telem.c create mode 100644 src/core/ao_log_tiny.c create mode 100644 src/core/ao_monitor.c create mode 100644 src/core/ao_mutex.c create mode 100644 src/core/ao_panic.c create mode 100644 src/core/ao_pins.h create mode 100644 src/core/ao_product.c create mode 100644 src/core/ao_report.c create mode 100644 src/core/ao_rssi.c create mode 100644 src/core/ao_sample.c create mode 100644 src/core/ao_state.c create mode 100644 src/core/ao_stdio.c create mode 100644 src/core/ao_storage.c create mode 100644 src/core/ao_task.c create mode 100644 src/core/ao_telem.h create mode 100644 src/core/ao_telemetry.c create mode 100644 src/drivers/ao_25lc1024.c create mode 100644 src/drivers/ao_25lc1024.h create mode 100644 src/drivers/ao_at45db161d.c create mode 100644 src/drivers/ao_at45db161d.h create mode 100644 src/drivers/ao_btm.c create mode 100644 src/drivers/ao_companion.c create mode 100644 src/drivers/ao_gps_sirf.c create mode 100644 src/drivers/ao_gps_skytraq.c create mode 100644 src/drivers/ao_m25.c delete mode 100755 src/gps-cksum delete mode 100644 src/make-altitude delete mode 100644 src/make-kalman create mode 100644 src/product/Makefile.telebt create mode 100644 src/product/Makefile.teledongle create mode 100644 src/product/Makefile.telemetrum create mode 100644 src/product/Makefile.telemini create mode 100644 src/product/Makefile.telenano create mode 100644 src/product/ao_telebt.c create mode 100644 src/product/ao_teledongle.c create mode 100644 src/product/ao_telemetrum.c create mode 100644 src/product/ao_telemini.c create mode 100644 src/product/ao_telenano.c create mode 100644 src/product/ao_teleterra.c create mode 100644 src/product/ao_test.c create mode 100644 src/product/ao_tidongle.c delete mode 100755 src/sirf-cksum delete mode 100644 src/skytraq-cksum delete mode 100644 src/telebt-v0.0/Makefile.defs delete mode 100644 src/telebt-v0.1/Makefile.defs delete mode 100644 src/teledongle-v0.1/Makefile.defs delete mode 100644 src/teledongle-v0.2/Makefile.defs delete mode 100644 src/telemetrum-v0.1-sirf/Makefile.defs delete mode 100644 src/telemetrum-v0.1-sky/Makefile.defs delete mode 100644 src/telemetrum-v1.0/Makefile.defs delete mode 100644 src/telemetrum-v1.1/Makefile.defs delete mode 100644 src/telemini-v1.0/Makefile.defs delete mode 100644 src/telenano-v0.1/Makefile.defs create mode 100644 src/test/ao_flight_test.c create mode 100644 src/test/ao_gps_test.c create mode 100644 src/test/ao_gps_test_skytraq.c delete mode 100644 src/tidongle/Makefile.defs create mode 100644 src/util/ao-make-product.5c create mode 100755 src/util/check-stack create mode 100755 src/util/gps-cksum create mode 100644 src/util/make-altitude create mode 100644 src/util/make-kalman create mode 100755 src/util/sirf-cksum create mode 100644 src/util/skytraq-cksum (limited to 'src') diff --git a/configure.ac b/configure.ac index f9002508..da9d9991 100644 --- a/configure.ac +++ b/configure.ac @@ -19,7 +19,7 @@ dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) AC_INIT([altos], 1.0) -AC_CONFIG_SRCDIR([src/ao.h]) +AC_CONFIG_SRCDIR([src/core/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE diff --git a/src/25lc1024.h b/src/25lc1024.h deleted file mode 100644 index 44e52387..00000000 --- a/src/25lc1024.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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. - */ - -/* Defines for the 25LC1024 1Mbit SPI Bus Serial EEPROM */ - -#ifndef _25LC1024_H_ -#define _25LC1024_H_ - -#define EE_READ 0x03 -#define EE_WRITE 0x02 -#define EE_WREN 0x06 -#define EE_WRDI 0x04 -#define EE_RDSR 0x05 -#define EE_WRSR 0x01 -#define EE_PE 0x42 -#define EE_SE 0xd8 -#define EE_CE 0xc7 -#define EE_RDID 0xab -#define EE_DPD 0xb9 - -#define EE_STATUS_WIP (1 << 0) -#define EE_STATUS_WEL (1 << 1) -#define EE_STATUS_BP0 (1 << 2) -#define EE_STATUS_BP1 (1 << 3) -#define EE_STATUS_WPEN (1 << 7) - -#endif /* _25LC1024_H_ */ diff --git a/src/Makefile b/src/Makefile index 018f0c5c..4e40c2bf 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,7 +2,13 @@ # AltOS build # # -CC=sdcc + +vpath make-altitude util +vpath make-kalman util +vpath kalman.5c kalman +vpath kalman_filter.5c kalman +vpath load_csv.5c kalman +vpath matrix.5c kalman include Version @@ -14,7 +20,7 @@ SUBDIRS=\ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ tidongle test -all: all-recursive +all: all-local all-recursive RECURSIVE_TARGETS = all-recursive clean-recursive install-recursive @@ -27,8 +33,21 @@ $(RECURSIVE_TARGETS): distclean: clean -clean: clean-recursive +clean: clean-local clean-recursive install: install-recursive uninstall: + +all-recursive: all-local + +all-local: altitude.h ao_kalman.h + +altitude.h: make-altitude + nickle $< > $@ + +ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c + sh $< kalman > $@ + +clean-local: + rm -f altitude.h ao_kalman.h \ No newline at end of file diff --git a/src/Makefile.proto b/src/Makefile.proto deleted file mode 100644 index 8f98d354..00000000 --- a/src/Makefile.proto +++ /dev/null @@ -1,380 +0,0 @@ -# -# AltOS build -# -# -vpath %.c .. -vpath %.h .. -vpath make-altitude .. -vpath make-kalman .. -vpath kalman.5c ../kalman -vpath kalman_filter.5c ../kalman -vpath load_csv.5c ../kalman -vpath matrix.5c ../kalman -vpath ao-make-product.5c .. - -CC=sdcc - -ifndef VERSION -include ../Version -endif - -CFLAGS=--model-small --debug --opt-code-speed -DCODESIZE=$(CODESIZE) - -CODESIZE ?= 0x8000 - -LDFLAGS=--out-fmt-ihx --code-loc 0x0000 --code-size $(CODESIZE) \ - --xram-loc 0xf000 --xram-size 0xda2 --iram-size 0xff - -INC = \ - ao.h \ - ao_pins.h \ - cc1111.h \ - altitude.h \ - ao_kalman.h \ - 25lc1024.h - -# -# Common AltOS sources -# -ALTOS_SRC = \ - ao_cmd.c \ - ao_dma.c \ - ao_mutex.c \ - ao_panic.c \ - ao_task.c \ - ao_timer.c \ - ao_romconfig.c \ - _bp.c - -# -# Shared AltOS drivers -# -ALTOS_DRIVER_SRC = \ - ao_config.c \ - ao_led.c \ - ao_radio.c \ - ao_stdio.c - -BEEP_DRIVER_SRC = \ - ao_beep.c - -USB_DRIVER_SRC = \ - ao_usb.c - -TELE_COMMON_SRC = \ - ao_packet.c - -# -# Receiver code -# -TELE_RECEIVER_SRC =\ - ao_monitor.c \ - ao_gps_print.c \ - ao_packet_master.c \ - ao_state.c \ - ao_rssi.c - -# -# Shared Tele drivers (on TeleMetrum, TeleTerra, TeleDongle) -# - -TELE_DRIVER_SRC = \ - ao_convert.c - -# -# Serial port driver -# -SERIAL_DRIVER_SRC = \ - ao_serial.c - -# -# Spi bus driver -# -SPI_DRIVER_SRC = \ - ao_spi.c - -# -# Debug dongle driver (only on TI) -# -DBG_SRC = \ - ao_dbg.c - -# -# Drivers only on TeleMetrum -# -TM_DRIVER_SRC = \ - ao_adc.c \ - ao_gps_report.c \ - ao_ignite.c \ - ao_packet_slave.c \ - $(BEEP_DRIVER_SRC) \ - $(USB_DRIVER_SRC) - -# -# 25LC1024 driver source -EE_DRIVER_SRC = \ - ao_storage.c \ - ao_ee.c - -# -# AT45DB161D driver source - -FLASH_DRIVER_SRC = \ - ao_storage.c \ - ao_flash.c - -# -# Numonyx M25P80 driver source -# - -M25_DRIVER_SRC = \ - ao_storage.c \ - ao_m25.c - -# -# SiRF driver source -# -SIRF_DRIVER_SRC = \ - ao_gps_sirf.c - -# -# Skytraq driver source -# -SKY_DRIVER_SRC = \ - ao_gps_skytraq.c - - -# -# BTM-182 driver source -# -BTM_DRIVER_SRC = \ - ao_btm.c - -# -# Companion port driver source -# -COMPANION_SRC = \ - ao_companion.c - -# -# Tasks run on TeleMetrum -# -TM_TASK_SRC = \ - ao_flight.c \ - ao_sample.c \ - ao_kalman.c \ - ao_log.c \ - ao_log_big.c \ - ao_report.c \ - ao_telemetry.c - -TM_MAIN_SRC = \ - ao_telemetrum.c - -# -# Base sources for TeleMetrum -# -TM_BASE_SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_DRIVER_SRC) \ - $(SERIAL_DRIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(TM_DRIVER_SRC) \ - $(TM_TASK_SRC) \ - $(TM_MAIN_SRC) - -# -# Sources for TeleMini -TMINI_DRIVER_SRC = \ - ao_adc.c \ - ao_ignite.c \ - ao_config.c \ - ao_storage.c \ - ao_packet_slave.c \ - ao_intflash.c - -TMINI_TASK_SRC = \ - ao_flight.c \ - ao_sample.c \ - ao_kalman.c \ - ao_log.c \ - ao_log_tiny.c \ - ao_report.c \ - ao_telemetry.c - -TMINI_MAIN_SRC = \ - ao_telemini.c - -TMINI_BASE_SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_DRIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(TMINI_DRIVER_SRC) \ - $(TMINI_TASK_SRC) \ - $(TMINI_MAIN_SRC) - -# -# Sources for TeleNano -TNANO_DRIVER_SRC = \ - ao_adc.c \ - ao_config.c \ - ao_storage.c \ - ao_packet_slave.c \ - ao_intflash.c - -TNANO_TASK_SRC = \ - ao_flight_nano.c \ - ao_sample.c \ - ao_kalman.c \ - ao_log.c \ - ao_log_tiny.c \ - ao_report.c \ - ao_telemetry.c - -TNANO_MAIN_SRC = \ - ao_telenano.c - -TNANO_BASE_SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_DRIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(TNANO_DRIVER_SRC) \ - $(TNANO_TASK_SRC) \ - $(TNANO_MAIN_SRC) - -# -# Sources for TeleBluetooth -# - -TBT_MAIN_SRC = \ - ao_telebt.c - -TBT_BASE_SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_RECEIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(SERIAL_DRIVER_SRC) \ - $(USB_DRIVER_SRC) \ - $(BTM_DRIVER_SRC) \ - $(DBG_SRC) \ - $(TBT_MAIN_SRC) - -TBT_V_0_1_SRC = \ - $(TBT_BASE_SRC) \ - $(SPI_DRIVER_SRC) \ - $(M25_DRIVER_SRC) \ - $(BEEP_DRIVER_SRC) \ - ao_log_telem.c - -# -# TI Dongle sources -# -TI_MAIN_SRC = \ - ao_tidongle.c - -# -# All sources for the TI debug dongle -# -TI_SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_RECEIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(USB_DRIVER_SRC) \ - $(TI_MAIN_SRC) \ - $(DBG_SRC) - -TT_MAIN_SRC = \ - ao_teleterra.c -# -# All sources for TeleTerra -# -TT_SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_RECEIVER_SRC) \ - $(TELE_DRIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(USB_DRIVER_SRC) \ - $(TT_MAIN_SRC) - - -# -# Sources for TeleDongle -# - -TD_MAIN_SRC = \ - ao_teledongle.c - -TD_SRC = \ - $(ALTOS_SRC) \ - $(ALTOS_DRIVER_SRC) \ - $(TELE_RECEIVER_SRC) \ - $(TELE_COMMON_SRC) \ - $(USB_DRIVER_SRC) \ - $(TD_MAIN_SRC) - -include Makefile.defs - -CFLAGS += $(PRODUCT_DEF) -I. - -NICKLE=nickle -CHECK_STACK=sh ../check-stack - -REL=$(SRC:.c=.rel) ao_product.rel -ADB=$(REL:.rel=.adb) -ASM=$(REL:.rel=.asm) -LNK=$(REL:.rel=.lnk) -LST=$(REL:.rel=.lst) -RST=$(REL:.rel=.rst) -SYM=$(REL:.rel=.sym) - -PCDB=$(PROG:.ihx=.cdb) -PLNK=$(PROG:.ihx=.lnk) -PMAP=$(PROG:.ihx=.map) -PMEM=$(PROG:.ihx=.mem) -PAOM=$(PROG:.ihx=) - -V=0 -# The user has explicitly enabled quiet compilation. -ifeq ($(V),0) -quiet = @printf " $1 $2 $@\n"; $($1) -endif -# Otherwise, print the full command line. -quiet ?= $($1) - -%.rel : %.c $(INC) - $(call quiet,CC,$(PRODUCT_DEF)) $(CFLAGS) -c -o$@ $< - -all: ../$(PROG) - -../$(PROG): $(REL) Makefile Makefile.defs ../Makefile.proto - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../ao.h $(PMEM) - -../altitude.h: make-altitude - nickle $< > $@ - -../ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c - sh $< > $@ - -ao_product.h: ao-make-product.5c ../Version - $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ - -$(REL): ao_product.h - -distclean: clean - -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f ao_product.h - rm -f ../$(PROG) - -install: - -uninstall: diff --git a/src/_bp.c b/src/_bp.c deleted file mode 100644 index 6bf135bc..00000000 --- a/src/_bp.c +++ /dev/null @@ -1,26 +0,0 @@ -/*------------------------------------------------------------------------- - - _bp.c :- just declares bp as a variable - - Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999) - - This library is free software; you can redistribute it and/or modify it - under the terms of the GNU Library General Public License as published by the - Free Software Foundation; either version 2, or (at your option) any - later version. - - This library 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 Library General Public License for more details. - - You should have received a copy of the GNU Library General Public License - along with this program; if not, write to the Free Software - Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - In other words, you are welcome to use, share and improve this program. - You are forbidden to forbid anyone else to use, share and improve - what you give them. Help stamp out software-hoarding! --------------------------------------------------------------------------*/ - -__data unsigned char bp ; diff --git a/src/altitude.h b/src/altitude.h deleted file mode 100644 index a278bbc6..00000000 --- a/src/altitude.h +++ /dev/null @@ -1,132 +0,0 @@ -/*max error 3.197865153490684 at 0.782%. Average error 0.260150920474668*/ -#define NALT 129 -#define ALT_FRAC_BITS 8 - 15835, /* 10.56 kPa 0.000% */ - 15332, /* 11.42 kPa 0.781% */ - 14868, /* 12.29 kPa 1.563% */ - 14435, /* 13.16 kPa 2.344% */ - 14030, /* 14.02 kPa 3.125% */ - 13649, /* 14.90 kPa 3.906% */ - 13290, /* 15.76 kPa 4.688% */ - 12950, /* 16.63 kPa 5.469% */ - 12627, /* 17.50 kPa 6.250% */ - 12320, /* 18.37 kPa 7.031% */ - 12027, /* 19.24 kPa 7.813% */ - 11747, /* 20.10 kPa 8.594% */ - 11479, /* 20.97 kPa 9.375% */ - 11222, /* 21.84 kPa 10.156% */ - 10975, /* 22.71 kPa 10.938% */ - 10736, /* 23.58 kPa 11.719% */ - 10504, /* 24.44 kPa 12.500% */ - 10278, /* 25.31 kPa 13.281% */ - 10059, /* 26.18 kPa 14.063% */ - 9846, /* 27.05 kPa 14.844% */ - 9638, /* 27.91 kPa 15.625% */ - 9435, /* 28.78 kPa 16.406% */ - 9237, /* 29.65 kPa 17.188% */ - 9044, /* 30.52 kPa 17.969% */ - 8855, /* 31.39 kPa 18.750% */ - 8670, /* 32.26 kPa 19.531% */ - 8490, /* 33.13 kPa 20.313% */ - 8313, /* 33.99 kPa 21.094% */ - 8140, /* 34.86 kPa 21.875% */ - 7970, /* 35.73 kPa 22.656% */ - 7803, /* 36.60 kPa 23.438% */ - 7640, /* 37.47 kPa 24.219% */ - 7480, /* 38.33 kPa 25.000% */ - 7322, /* 39.20 kPa 25.781% */ - 7168, /* 40.07 kPa 26.563% */ - 7016, /* 40.94 kPa 27.344% */ - 6867, /* 41.80 kPa 28.125% */ - 6720, /* 42.67 kPa 28.906% */ - 6575, /* 43.54 kPa 29.688% */ - 6433, /* 44.41 kPa 30.469% */ - 6294, /* 45.28 kPa 31.250% */ - 6156, /* 46.15 kPa 32.031% */ - 6020, /* 47.01 kPa 32.813% */ - 5887, /* 47.88 kPa 33.594% */ - 5755, /* 48.75 kPa 34.375% */ - 5625, /* 49.62 kPa 35.156% */ - 5497, /* 50.49 kPa 35.938% */ - 5371, /* 51.35 kPa 36.719% */ - 5247, /* 52.22 kPa 37.500% */ - 5124, /* 53.09 kPa 38.281% */ - 5003, /* 53.96 kPa 39.063% */ - 4883, /* 54.83 kPa 39.844% */ - 4765, /* 55.69 kPa 40.625% */ - 4648, /* 56.56 kPa 41.406% */ - 4533, /* 57.43 kPa 42.188% */ - 4419, /* 58.30 kPa 42.969% */ - 4307, /* 59.17 kPa 43.750% */ - 4196, /* 60.03 kPa 44.531% */ - 4086, /* 60.90 kPa 45.313% */ - 3977, /* 61.77 kPa 46.094% */ - 3870, /* 62.63 kPa 46.875% */ - 3764, /* 63.51 kPa 47.656% */ - 3659, /* 64.38 kPa 48.438% */ - 3555, /* 65.24 kPa 49.219% */ - 3453, /* 66.11 kPa 50.000% */ - 3351, /* 66.98 kPa 50.781% */ - 3250, /* 67.85 kPa 51.563% */ - 3151, /* 68.72 kPa 52.344% */ - 3052, /* 69.58 kPa 53.125% */ - 2955, /* 70.45 kPa 53.906% */ - 2858, /* 71.32 kPa 54.688% */ - 2763, /* 72.19 kPa 55.469% */ - 2668, /* 73.06 kPa 56.250% */ - 2574, /* 73.92 kPa 57.031% */ - 2482, /* 74.79 kPa 57.813% */ - 2390, /* 75.66 kPa 58.594% */ - 2298, /* 76.52 kPa 59.375% */ - 2208, /* 77.40 kPa 60.156% */ - 2119, /* 78.26 kPa 60.938% */ - 2030, /* 79.13 kPa 61.719% */ - 1942, /* 80.00 kPa 62.500% */ - 1855, /* 80.87 kPa 63.281% */ - 1769, /* 81.74 kPa 64.063% */ - 1683, /* 82.60 kPa 64.844% */ - 1598, /* 83.47 kPa 65.625% */ - 1514, /* 84.34 kPa 66.406% */ - 1430, /* 85.21 kPa 67.188% */ - 1347, /* 86.08 kPa 67.969% */ - 1265, /* 86.94 kPa 68.750% */ - 1184, /* 87.81 kPa 69.531% */ - 1103, /* 88.68 kPa 70.313% */ - 1023, /* 89.55 kPa 71.094% */ - 943, /* 90.41 kPa 71.875% */ - 864, /* 91.28 kPa 72.656% */ - 786, /* 92.15 kPa 73.438% */ - 708, /* 93.02 kPa 74.219% */ - 631, /* 93.89 kPa 75.000% */ - 554, /* 94.76 kPa 75.781% */ - 478, /* 95.63 kPa 76.563% */ - 403, /* 96.49 kPa 77.344% */ - 328, /* 97.36 kPa 78.125% */ - 254, /* 98.23 kPa 78.906% */ - 180, /* 99.10 kPa 79.688% */ - 106, /* 99.97 kPa 80.469% */ - 34, /* 100.83 kPa 81.250% */ - -39, /* 101.70 kPa 82.031% */ - -111, /* 102.57 kPa 82.813% */ - -182, /* 103.44 kPa 83.594% */ - -253, /* 104.30 kPa 84.375% */ - -323, /* 105.17 kPa 85.156% */ - -393, /* 106.04 kPa 85.938% */ - -462, /* 106.91 kPa 86.719% */ - -531, /* 107.78 kPa 87.500% */ - -600, /* 108.65 kPa 88.281% */ - -668, /* 109.51 kPa 89.063% */ - -736, /* 110.38 kPa 89.844% */ - -803, /* 111.25 kPa 90.625% */ - -870, /* 112.12 kPa 91.406% */ - -936, /* 112.99 kPa 92.188% */ - -1002, /* 113.85 kPa 92.969% */ - -1068, /* 114.72 kPa 93.750% */ - -1133, /* 115.59 kPa 94.531% */ - -1198, /* 116.46 kPa 95.313% */ - -1262, /* 117.33 kPa 96.094% */ - -1326, /* 118.19 kPa 96.875% */ - -1389, /* 119.06 kPa 97.656% */ - -1453, /* 119.93 kPa 98.438% */ - -1516, /* 120.80 kPa 99.219% */ - -1578, /* 121.67 kPa 100.000% */ diff --git a/src/ao-make-product.5c b/src/ao-make-product.5c deleted file mode 100644 index 5f2eb8e8..00000000 --- a/src/ao-make-product.5c +++ /dev/null @@ -1,103 +0,0 @@ -#!/bin/sh - -autoimport ParseArgs; - -void -write_ucs2(string a, string description) -{ - int len = String::length(a); - - printf("/* %s */\n", description); - printf("#define AO_%s_LEN 0x%02x\n", description, len * 2 + 2); - printf("#define AO_%s_STRING \"%s\"\n", description, a); - printf("#define AO_%s_UCS2", description); - for (int i = 0; i < len; i++) { - int c = a[i]; - if (i > 0) - printf(","); - if (0x20 <= c && c < 128) - printf(" '%c', 0", c); - else - printf(" LE_WORD(0x%04x),", c); - } - printf("\n\n"); -} - -void -write_string(string a, string description) -{ - printf ("/* %s */\n", description); - printf ("#define AO_%s_STRING \"%s\"\n", description, a); -} - -void -write_int(int a, string description) -{ - printf ("/* %s */\n", description); - printf ("#define AO_%s_NUMBER %d\n\n", description, a); -} - -void -write_hex(int a, string description) -{ - printf ("/* %s */\n", description); - printf ("#define AO_%s_NUMBER 0x%04x\n\n", description, a); -} - -string manufacturer = "altusmetrum.org"; -string product = "TeleMetrum"; -string version = "0.0"; -int serial = 1; -int user_argind = 0; -int id_product = 0x000a; - -argdesc argd = { - .args = { - { - .var = { .arg_string = &manufacturer }, - .abbr = 'm', - .name = "manufacturer", - .expr_name = "manf", - .desc = "Manufacturer name." }, - { - .var = { .arg_string = &product }, - .abbr = 'p', - .name = "product", - .expr_name = "prod", - .desc = "Product name." }, - { - .var = { .arg_int = &id_product }, - .abbr = 'i', - .name = "id_product", - .expr_name = "id_p", - .desc = "Product ID." }, - { - .var = { .arg_int = &serial }, - .abbr = 's', - .name = "serial", - .expr_name = "number", - .desc = "Serial number." }, - { - .var = { .arg_string = &version }, - .abbr = 'v', - .name = "version", - .expr_name = "string", - .desc = "Program version." }, - }, - .prog_name = "usb descriptors", -}; - -void -main() -{ - string[dim(argv)-1] nargv = {[n] = argv[n+1]}; - parseargs(&argd, &nargv); - write_ucs2(manufacturer, "iManufacturer"); - write_ucs2(product, "iProduct"); - write_ucs2(sprintf("%06d", serial), "iSerial"); - write_int(serial, "iSerial"); - write_hex(id_product, "idProduct"); - write_string(version, "iVersion"); -} - -main(); diff --git a/src/ao.h b/src/ao.h deleted file mode 100644 index 8ac9ac3d..00000000 --- a/src/ao.h +++ /dev/null @@ -1,1610 +0,0 @@ -/* - * 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. - */ - -#ifndef _AO_H_ -#define _AO_H_ - -#include -#include -#include -#include -#include "cc1111.h" -#include "ao_pins.h" - -#define TRUE 1 -#define FALSE 0 - -/* Convert a __data pointer into an __xdata pointer */ -#define DATA_TO_XDATA(a) ((void __xdata *) ((uint8_t) (a) | 0xff00)) - -/* 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 0x90 -#define AO_STACK_END 0xfe -#define AO_STACK_SIZE (AO_STACK_END - AO_STACK_START + 1) - -/* An AltOS task */ -struct ao_task { - __xdata void *wchan; /* current wait channel (NULL if running) */ - uint16_t alarm; /* abort ao_sleep time */ - uint8_t stack_count; /* amount of saved stack */ - uint8_t task_id; /* unique id */ - __code char *name; /* task name */ - uint8_t stack[AO_STACK_SIZE]; /* saved stack */ -}; - -extern __xdata struct ao_task *__data ao_cur_task; - -#define AO_NUM_TASKS 16 /* maximum number of tasks */ -#define AO_NO_TASK 0 /* no task id */ - -/* - ao_task.c - */ - -/* Suspend the current task until wchan is awoken. - * returns: - * 0 on normal wake - * 1 on alarm - */ -uint8_t -ao_sleep(__xdata void *wchan); - -/* Wake all tasks sleeping on wchan */ -void -ao_wakeup(__xdata void *wchan); - -/* set an alarm to go off in 'delay' ticks */ -void -ao_alarm(uint16_t delay); - -/* Yield the processor to another task */ -void -ao_yield(void) __naked; - -/* Add a task to the run queue */ -void -ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant; - -/* Terminate the current task */ -void -ao_exit(void); - -/* Dump task info to console */ -void -ao_task_info(void); - -/* Start the scheduler. This will not return */ -void -ao_start_scheduler(void); - -/* - * ao_panic.c - */ - -#define AO_PANIC_NO_TASK 1 /* AO_NUM_TASKS is not large enough */ -#define AO_PANIC_DMA 2 /* Attempt to start DMA while active */ -#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 */ -#define AO_PANIC_STDIO 7 /* Too many stdio handlers registered */ -#define AO_PANIC_REBOOT 8 /* Reboot failed */ -#define AO_PANIC_FLASH 9 /* Invalid flash part (or wrong blocksize) */ -#define AO_PANIC_USB 10 /* Trying to send USB packet while busy */ -#define AO_PANIC_BT 11 /* Communications with bluetooth device failed */ - -/* Stop the operating system, beeping and blinking the reason */ -void -ao_panic(uint8_t reason); - -/* - * ao_timer.c - */ - -/* Our timer runs at 100Hz */ -#define AO_HERTZ 100 -#define AO_MS_TO_TICKS(ms) ((ms) / (1000 / AO_HERTZ)) -#define AO_SEC_TO_TICKS(s) ((s) * AO_HERTZ) - -/* Returns the current time in ticks */ -uint16_t -ao_time(void); - -/* Suspend the current task until ticks time has passed */ -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; - -/* Initialize the timer */ -void -ao_timer_init(void); - -/* Initialize the hardware clock. Must be called first */ -void -ao_clock_init(void); - -/* - * One set of samples read from the A/D converter or telemetry - */ -struct ao_adc { - uint16_t tick; /* tick when the sample was read */ - int16_t accel; /* accelerometer */ - int16_t pres; /* pressure sensor */ - int16_t temp; /* temperature sensor */ - int16_t v_batt; /* battery voltage */ - int16_t sense_d; /* drogue continuity sense */ - int16_t sense_m; /* main continuity sense */ -}; - -#ifndef HAS_ADC -#error Please define HAS_ADC -#endif - -#if HAS_ADC - -#if HAS_ACCEL -#ifndef HAS_ACCEL_REF -#error Please define HAS_ACCEL_REF -#endif -#else -#define HAS_ACCEL_REF 0 -#endif - -/* - * ao_adc.c - */ - -#define AO_ADC_RING 32 -#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) -#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) - - -/* - * A/D data is stored in a ring, with the next sample to be written - * at ao_adc_head - */ -extern volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; -extern volatile __data uint8_t ao_adc_head; -#if HAS_ACCEL_REF -extern volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; -#endif - -/* Trigger a conversion sequence (called from the timer interrupt) */ -void -ao_adc_poll(void); - -/* Suspend the current task until another A/D sample is converted */ -void -ao_adc_sleep(void); - -/* Get a copy of the last complete A/D sample set */ -void -ao_adc_get(__xdata struct ao_adc *packet); - -/* The A/D interrupt handler */ - -void -ao_adc_isr(void) __interrupt 1; - -/* Initialize the A/D converter */ -void -ao_adc_init(void); - -#endif /* HAS_ADC */ - -/* - * ao_beep.c - */ - -/* - * Various pre-defined beep frequencies - * - * frequency = 1/2 (24e6/32) / beep - */ - -#define AO_BEEP_LOW 150 /* 2500Hz */ -#define AO_BEEP_MID 94 /* 3989Hz */ -#define AO_BEEP_HIGH 75 /* 5000Hz */ -#define AO_BEEP_OFF 0 /* off */ - -#define AO_BEEP_g 240 /* 1562.5Hz */ -#define AO_BEEP_gs 227 /* 1652Hz (1655Hz) */ -#define AO_BEEP_aa 214 /* 1752Hz (1754Hz) */ -#define AO_BEEP_bbf 202 /* 1856Hz (1858Hz) */ -#define AO_BEEP_bb 190 /* 1974Hz (1969Hz) */ -#define AO_BEEP_cc 180 /* 2083Hz (2086Hz) */ -#define AO_BEEP_ccs 170 /* 2205Hz (2210Hz) */ -#define AO_BEEP_dd 160 /* 2344Hz (2341Hz) */ -#define AO_BEEP_eef 151 /* 2483Hz (2480Hz) */ -#define AO_BEEP_ee 143 /* 2622Hz (2628Hz) */ -#define AO_BEEP_ff 135 /* 2778Hz (2784Hz) */ -#define AO_BEEP_ffs 127 /* 2953Hz (2950Hz) */ -#define AO_BEEP_gg 120 /* 3125Hz */ -#define AO_BEEP_ggs 113 /* 3319Hz (3311Hz) */ -#define AO_BEEP_aaa 107 /* 3504Hz (3508Hz) */ -#define AO_BEEP_bbbf 101 /* 3713Hz (3716Hz) */ -#define AO_BEEP_bbb 95 /* 3947Hz (3937Hz) */ -#define AO_BEEP_ccc 90 /* 4167Hz (4171Hz) */ -#define AO_BEEP_cccs 85 /* 4412Hz (4419Hz) */ -#define AO_BEEP_ddd 80 /* 4688Hz (4682Hz) */ -#define AO_BEEP_eeef 76 /* 4934Hz (4961Hz) */ -#define AO_BEEP_eee 71 /* 5282Hz (5256Hz) */ -#define AO_BEEP_fff 67 /* 5597Hz (5568Hz) */ -#define AO_BEEP_fffs 64 /* 5859Hz (5899Hz) */ -#define AO_BEEP_ggg 60 /* 6250Hz */ - -/* Set the beeper to the specified tone */ -void -ao_beep(uint8_t beep); - -/* Turn on the beeper for the specified time */ -void -ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant; - -/* Initialize the beeper */ -void -ao_beep_init(void); - -/* - * ao_led.c - */ - -#define AO_LED_NONE 0 - -/* Turn on the specified LEDs */ -void -ao_led_on(uint8_t colors); - -/* Turn off the specified LEDs */ -void -ao_led_off(uint8_t colors); - -/* Set all of the LEDs to the specified state */ -void -ao_led_set(uint8_t colors); - -/* Toggle the specified LEDs */ -void -ao_led_toggle(uint8_t colors); - -/* Turn on the specified LEDs for the indicated interval */ -void -ao_led_for(uint8_t colors, uint16_t ticks) __reentrant; - -/* Initialize the LEDs */ -void -ao_led_init(uint8_t enable); - -/* - * ao_romconfig.c - */ - -#define AO_ROMCONFIG_VERSION 2 - -extern __code __at (0x00a0) uint16_t ao_romconfig_version; -extern __code __at (0x00a2) uint16_t ao_romconfig_check; -extern __code __at (0x00a4) uint16_t ao_serial_number; -extern __code __at (0x00a6) uint32_t ao_radio_cal; - -#ifndef HAS_USB -#error Please define HAS_USB -#endif - -#if HAS_USB -extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; -#endif - -/* - * ao_usb.c - */ - -/* Put one character to the USB output queue */ -void -ao_usb_putchar(char c); - -/* Get one character from the USB input queue */ -char -ao_usb_getchar(void); - -/* Poll for a charcter on the USB input queue. - * returns AO_READ_AGAIN if none are available - */ -char -ao_usb_pollchar(void); - -/* Flush the USB output queue */ -void -ao_usb_flush(void); - -#if HAS_USB -/* USB interrupt handler */ -void -ao_usb_isr(void) __interrupt 6; -#endif - -/* Enable the USB controller */ -void -ao_usb_enable(void); - -/* Disable the USB controller */ -void -ao_usb_disable(void); - -/* Initialize the USB system */ -void -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 __pdata uint16_t ao_cmd_lex_i; -extern __pdata uint32_t ao_cmd_lex_u32; -extern __pdata char ao_cmd_lex_c; -extern __pdata 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); - -void -ao_cmd_decimal(void); - -uint8_t -ao_match_word(__code char *word); - -struct ao_cmds { - void (*func)(void); - __code char *help; -}; - -void -ao_cmd_register(__code struct ao_cmds *cmds); - -void -ao_cmd_init(void); - -#if HAS_CMD_FILTER -/* - * Provided by an external module to filter raw command lines - */ -uint8_t -ao_cmd_filter(void); -#endif - -/* - * ao_dma.c - */ - -/* Allocate a DMA channel. the 'done' parameter will be set when the - * dma is finished and will be used to wakeup any waiters - */ - -uint8_t -ao_dma_alloc(__xdata uint8_t * done); - -/* Setup a DMA channel */ -void -ao_dma_set_transfer(uint8_t id, - void __xdata *srcaddr, - void __xdata *dstaddr, - uint16_t count, - uint8_t cfg0, - uint8_t cfg1); - -/* Start a DMA channel */ -void -ao_dma_start(uint8_t id); - -/* Manually trigger a DMA channel */ -void -ao_dma_trigger(uint8_t id); - -/* Abort a running DMA transfer */ -void -ao_dma_abort(uint8_t id); - -/* DMA interrupt routine */ -void -ao_dma_isr(void) __interrupt 8; - -/* - * ao_mutex.c - */ - -void -ao_mutex_get(__xdata uint8_t *ao_mutex) __reentrant; - -void -ao_mutex_put(__xdata uint8_t *ao_mutex) __reentrant; - -/* - * Storage interface, provided by one of the eeprom or flash - * drivers - */ - -/* Total bytes of available storage */ -extern __pdata uint32_t ao_storage_total; - -/* Block size - device is erased in these units. At least 256 bytes */ -extern __pdata uint32_t ao_storage_block; - -/* Byte offset of config block. Will be ao_storage_block bytes long */ -extern __pdata uint32_t ao_storage_config; - -/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ -extern __pdata uint16_t ao_storage_unit; - -#define AO_STORAGE_ERASE_LOG (ao_storage_config + AO_CONFIG_MAX_SIZE) - -/* Initialize above values. Can only be called once the OS is running */ -void -ao_storage_setup(void) __reentrant; - -/* Write data. Returns 0 on failure, 1 on success */ -uint8_t -ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; - -/* Read data. Returns 0 on failure, 1 on success */ -uint8_t -ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; - -/* Erase a block of storage. This always clears ao_storage_block bytes */ -uint8_t -ao_storage_erase(uint32_t pos) __reentrant; - -/* Flush any pending writes to stable storage */ -void -ao_storage_flush(void) __reentrant; - -/* Initialize the storage code */ -void -ao_storage_init(void); - -/* - * Low-level functions wrapped by ao_storage.c - */ - -/* Read data within a storage unit */ -uint8_t -ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; - -/* Write data within a storage unit */ -uint8_t -ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; - -/* Initialize low-level device bits */ -void -ao_storage_device_init(void); - -/* Print out information about flash chips */ -void -ao_storage_device_info(void) __reentrant; - -/* - * ao_log.c - */ - -/* We record flight numbers in the first record of - * the log. Tasks may wait for this to be initialized - * by sleeping on this variable. - */ -extern __xdata uint16_t ao_flight_number; - -extern __pdata uint32_t ao_log_current_pos; -extern __pdata uint32_t ao_log_end_pos; -extern __pdata uint32_t ao_log_start_pos; -extern __xdata uint8_t ao_log_running; -extern __pdata enum flight_state ao_log_state; - -/* required functions from the underlying log system */ - -#define AO_LOG_FORMAT_UNKNOWN 0 /* unknown; altosui will have to guess */ -#define AO_LOG_FORMAT_FULL 1 /* 8 byte typed log records */ -#define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */ -#define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */ -#define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ -#define AO_LOG_FORMAT_NONE 127 /* No log at all */ - -extern __code uint8_t ao_log_format; - -/* Return the flight number from the given log slot, 0 if none */ -uint16_t -ao_log_flight(uint8_t slot); - -/* Flush the log */ -void -ao_log_flush(void); - -/* Logging thread main routine */ -void -ao_log(void); - -/* functions provided in ao_log.c */ - -/* Figure out the current flight number */ -void -ao_log_scan(void) __reentrant; - -/* Return the position of the start of the given log slot */ -uint32_t -ao_log_pos(uint8_t slot); - -/* Start logging to eeprom */ -void -ao_log_start(void); - -/* Stop logging */ -void -ao_log_stop(void); - -/* Initialize the logging system */ -void -ao_log_init(void); - -/* Write out the current flight number to the erase log */ -void -ao_log_write_erase(uint8_t pos); - -/* Returns true if there are any logs stored in eeprom */ -uint8_t -ao_log_present(void); - -/* Returns true if there is no more storage space available */ -uint8_t -ao_log_full(void); - -/* - * ao_log_big.c - */ - -/* - * The data log is recorded in the eeprom as a sequence - * of data packets. - * - * Each packet starts with a 4-byte header that has the - * packet type, the packet checksum and the tick count. Then - * they all contain 2 16 bit values which hold packet-specific - * data. - * - * For each flight, the first packet - * is FLIGHT packet, indicating the serial number of the - * device and a unique number marking the number of flights - * recorded by this device. - * - * During flight, data from the accelerometer and barometer - * are recorded in SENSOR packets, using the raw 16-bit values - * read from the A/D converter. - * - * Also during flight, but at a lower rate, the deployment - * sensors are recorded in DEPLOY packets. The goal here is to - * detect failure in the deployment circuits. - * - * STATE packets hold state transitions as the flight computer - * transitions through different stages of the flight. - */ -#define AO_LOG_FLIGHT 'F' -#define AO_LOG_SENSOR 'A' -#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_GPS_SAT 'V' -#define AO_LOG_GPS_DATE 'Y' - -#define AO_LOG_POS_NONE (~0UL) - -struct ao_log_record { - char type; - uint8_t csum; - uint16_t tick; - union { - struct { - int16_t ground_accel; - uint16_t flight; - } flight; - struct { - int16_t accel; - int16_t pres; - } sensor; - struct { - int16_t temp; - int16_t v_batt; - } temp_volt; - struct { - int16_t drogue; - int16_t main; - } deploy; - struct { - uint16_t state; - uint16_t reason; - } state; - struct { - uint8_t hour; - uint8_t minute; - uint8_t second; - uint8_t flags; - } gps_time; - int32_t gps_latitude; - int32_t gps_longitude; - struct { - int16_t altitude; - uint16_t unused; - } gps_altitude; - struct { - uint16_t svid; - uint8_t unused; - uint8_t c_n; - } gps_sat; - struct { - uint8_t year; - uint8_t month; - uint8_t day; - uint8_t extra; - } gps_date; - struct { - uint16_t d0; - uint16_t d1; - } anon; - } u; -}; - -/* Write a record to the eeprom log */ -uint8_t -ao_log_data(__xdata struct ao_log_record *log) __reentrant; - -/* - * ao_flight.c - */ - -enum ao_flight_state { - ao_flight_startup = 0, - ao_flight_idle = 1, - ao_flight_pad = 2, - ao_flight_boost = 3, - ao_flight_fast = 4, - ao_flight_coast = 5, - ao_flight_drogue = 6, - ao_flight_main = 7, - ao_flight_landed = 8, - ao_flight_invalid = 9 -}; - -extern __pdata enum ao_flight_state ao_flight_state; - -extern __pdata uint16_t ao_launch_time; -extern __pdata uint8_t ao_flight_force_idle; - -/* Flight thread */ -void -ao_flight(void); - -/* Initialize flight thread */ -void -ao_flight_init(void); - -/* - * ao_flight_nano.c - */ - -void -ao_flight_nano_init(void); - -/* - * ao_sample.c - */ - -/* - * Barometer calibration - * - * We directly sample the barometer. The specs say: - * - * Pressure range: 15-115 kPa - * Voltage at 115kPa: 2.82 - * Output scale: 27mV/kPa - * - * If we want to detect launch with the barometer, we need - * a large enough bump to not be fooled by noise. At typical - * launch elevations (0-2000m), a 200Pa pressure change cooresponds - * to about a 20m elevation change. This is 5.4mV, or about 3LSB. - * As all of our calculations are done in 16 bits, we'll actually see a change - * of 16 times this though - * - * 27 mV/kPa * 32767 / 3300 counts/mV = 268.1 counts/kPa - */ - -/* Accelerometer calibration - * - * We're sampling the accelerometer through a resistor divider which - * consists of 5k and 10k resistors. This multiplies the values by 2/3. - * That goes into the cc1111 A/D converter, which is running at 11 bits - * of precision with the bits in the MSB of the 16 bit value. Only positive - * values are used, so values should range from 0-32752 for 0-3.3V. The - * specs say we should see 40mV/g (uncalibrated), multiply by 2/3 for what - * the A/D converter sees (26.67 mV/g). We should see 32752/3300 counts/mV, - * for a final computation of: - * - * 26.67 mV/g * 32767/3300 counts/mV = 264.8 counts/g - * - * Zero g was measured at 16000 (we would expect 16384). - * Note that this value is only require to tell if the - * rocket is standing upright. Once that is determined, - * the value of the accelerometer is averaged for 100 samples - * to find the resting accelerometer value, which is used - * for all further flight computations - */ - -#define GRAVITY 9.80665 - -/* - * Above this height, the baro sensor doesn't work - */ -#define AO_MAX_BARO_HEIGHT 12000 - -/* - * Above this speed, baro measurements are unreliable - */ -#define AO_MAX_BARO_SPEED 200 - -#define ACCEL_NOSE_UP (ao_accel_2g >> 2) - -/* - * Speed and acceleration are scaled by 16 to provide a bit more - * resolution while still having reasonable range. Note that this - * limits speed to 2047m/s (around mach 6) and acceleration to - * 2047m/s² (over 200g) - */ - -#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) -#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) -#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) - -extern __pdata uint16_t ao_sample_tick; /* time of last data */ -extern __pdata int16_t ao_sample_pres; /* most recent pressure sensor reading */ -extern __pdata int16_t ao_sample_alt; /* MSL of ao_sample_pres */ -extern __pdata int16_t ao_sample_height; /* AGL of ao_sample_pres */ -extern __data uint8_t ao_sample_adc; /* Ring position of last processed sample */ - -#if HAS_ACCEL -extern __pdata int16_t ao_sample_accel; /* most recent accel sensor reading */ -#endif - -extern __pdata int16_t ao_ground_pres; /* startup pressure */ -extern __pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ - -#if HAS_ACCEL -extern __pdata int16_t ao_ground_accel; /* startup acceleration */ -extern __pdata int16_t ao_accel_2g; /* factory accel calibration */ -extern __pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ -#endif - -void ao_sample_init(void); - -/* returns FALSE in preflight mode, TRUE in flight mode */ -uint8_t ao_sample(void); - -/* - * ao_kalman.c - */ - -#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) -#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) -#define from_fix(x) ((x) >> 16) - -extern __pdata int16_t ao_height; /* meters */ -extern __pdata int16_t ao_speed; /* m/s * 16 */ -extern __pdata int16_t ao_accel; /* m/s² * 16 */ -extern __pdata int16_t ao_max_height; /* max of ao_height */ -extern __pdata int16_t ao_avg_height; /* running average of height */ - -extern __pdata int16_t ao_error_h; -extern __pdata int16_t ao_error_h_sq_avg; - -#if HAS_ACCEL -extern __pdata int16_t ao_error_a; -#endif - -void ao_kalman(void); - -/* - * ao_report.c - */ - -void -ao_report_init(void); - -/* - * ao_convert.c - * - * Given raw data, convert to SI units - */ - -/* pressure from the sensor to altitude in meters */ -int16_t -ao_pres_to_altitude(int16_t pres) __reentrant; - -int16_t -ao_altitude_to_pres(int16_t alt) __reentrant; - -int16_t -ao_temp_to_dC(int16_t temp) __reentrant; - -/* - * ao_dbg.c - * - * debug another telemetrum board - */ - -/* Send a byte to the dbg target */ -void -ao_dbg_send_byte(uint8_t byte); - -/* Receive a byte from the dbg target */ -uint8_t -ao_dbg_recv_byte(void); - -/* Start a bulk transfer to/from dbg target memory */ -void -ao_dbg_start_transfer(uint16_t addr); - -/* End a bulk transfer to/from dbg target memory */ -void -ao_dbg_end_transfer(void); - -/* Write a byte to dbg target memory */ -void -ao_dbg_write_byte(uint8_t byte); - -/* Read a byte from dbg target memory */ -uint8_t -ao_dbg_read_byte(void); - -/* Enable dbg mode, switching use of the pins */ -void -ao_dbg_debug_mode(void); - -/* Reset the dbg target */ -void -ao_dbg_reset(void); - -void -ao_dbg_init(void); - -/* - * ao_serial.c - */ - -#ifndef HAS_SERIAL_1 -#error Please define HAS_SERIAL_1 -#endif - -#if HAS_SERIAL_1 -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - -void -ao_serial_rx1_isr(void) __interrupt 3; - -void -ao_serial_tx1_isr(void) __interrupt 14; - -char -ao_serial_getchar(void) __critical; - -#if USE_SERIAL_STDIN -char -ao_serial_pollchar(void) __critical; - -void -ao_serial_set_stdin(uint8_t stdin); -#endif - -void -ao_serial_putchar(char c) __critical; - -void -ao_serial_drain(void) __critical; - -#define AO_SERIAL_SPEED_4800 0 -#define AO_SERIAL_SPEED_9600 1 -#define AO_SERIAL_SPEED_19200 2 -#define AO_SERIAL_SPEED_57600 3 - -void -ao_serial_set_speed(uint8_t speed); - -void -ao_serial_init(void); -#endif - -/* - * ao_spi.c - */ - -extern __xdata uint8_t ao_spi_mutex; - -#define ao_spi_get_mask(reg,mask) do {\ - ao_mutex_get(&ao_spi_mutex); \ - (reg) &= ~(mask); \ - } while (0) - -#define ao_spi_put_mask(reg,mask) do { \ - (reg) |= (mask); \ - ao_mutex_put(&ao_spi_mutex); \ - } while (0) - -#define ao_spi_get_bit(bit) do {\ - ao_mutex_get(&ao_spi_mutex); \ - (bit) = 0; \ - } while (0) - -#define ao_spi_put_bit(bit) do { \ - (bit) = 1; \ - ao_mutex_put(&ao_spi_mutex); \ - } while (0) - -/* - * The SPI mutex must be held to call either of these - * functions -- this mutex covers the entire SPI operation, - * from chip select low to chip select high - */ - -void -ao_spi_send(void __xdata *block, uint16_t len) __reentrant; - -void -ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; - -void -ao_spi_init(void); - -/* - * ao_telemetry.c - */ -#define AO_MAX_CALLSIGN 8 -#define AO_MAX_VERSION 8 -#define AO_MAX_TELEMETRY 128 - -struct ao_telemetry_generic { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t payload[27]; /* 5 */ - /* 32 */ -}; - -#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 -#define AO_TELEMETRY_SENSOR_TELEMINI 0x02 -#define AO_TELEMETRY_SENSOR_TELENANO 0x03 - -struct ao_telemetry_sensor { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t state; /* 5 flight state */ - int16_t accel; /* 6 accelerometer (TM only) */ - int16_t pres; /* 8 pressure sensor */ - int16_t temp; /* 10 temperature sensor */ - int16_t v_batt; /* 12 battery voltage */ - int16_t sense_d; /* 14 drogue continuity sense (TM/Tm) */ - int16_t sense_m; /* 16 main continuity sense (TM/Tm) */ - - int16_t acceleration; /* 18 m/s² * 16 */ - int16_t speed; /* 20 m/s * 16 */ - int16_t height; /* 22 m */ - - int16_t ground_pres; /* 24 average pres on pad */ - int16_t ground_accel; /* 26 average accel on pad */ - int16_t accel_plus_g; /* 28 accel calibration at +1g */ - int16_t accel_minus_g; /* 30 accel calibration at -1g */ - /* 32 */ -}; - -#define AO_TELEMETRY_CONFIGURATION 0x04 - -struct ao_telemetry_configuration { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t device; /* 5 device type */ - uint16_t flight; /* 6 flight number */ - uint8_t config_major; /* 8 Config major version */ - uint8_t config_minor; /* 9 Config minor version */ - uint16_t apogee_delay; /* 10 Apogee deploy delay in seconds */ - uint16_t main_deploy; /* 12 Main deploy alt in meters */ - uint16_t flight_log_max; /* 14 Maximum flight log size in kB */ - char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ - char version[AO_MAX_VERSION]; /* 24 Software version */ - /* 32 */ -}; - -#define AO_TELEMETRY_LOCATION 0x05 - -#define AO_GPS_MODE_NOT_VALID 'N' -#define AO_GPS_MODE_AUTONOMOUS 'A' -#define AO_GPS_MODE_DIFFERENTIAL 'D' -#define AO_GPS_MODE_ESTIMATED 'E' -#define AO_GPS_MODE_MANUAL 'M' -#define AO_GPS_MODE_SIMULATED 'S' - -struct ao_telemetry_location { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t flags; /* 5 Number of sats and other flags */ - int16_t altitude; /* 6 GPS reported altitude (m) */ - int32_t latitude; /* 8 latitude (degrees * 10⁷) */ - int32_t longitude; /* 12 longitude (degrees * 10⁷) */ - uint8_t year; /* 16 (- 2000) */ - uint8_t month; /* 17 (1-12) */ - uint8_t day; /* 18 (1-31) */ - uint8_t hour; /* 19 (0-23) */ - uint8_t minute; /* 20 (0-59) */ - uint8_t second; /* 21 (0-59) */ - uint8_t pdop; /* 22 (m * 5) */ - uint8_t hdop; /* 23 (m * 5) */ - uint8_t vdop; /* 24 (m * 5) */ - uint8_t mode; /* 25 */ - uint16_t ground_speed; /* 26 cm/s */ - int16_t climb_rate; /* 28 cm/s */ - uint8_t course; /* 30 degrees / 2 */ - uint8_t unused[1]; /* 31 */ - /* 32 */ -}; - -#define AO_TELEMETRY_SATELLITE 0x06 - -struct ao_telemetry_satellite_info { - uint8_t svid; - uint8_t c_n_1; -}; - -struct ao_telemetry_satellite { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t channels; /* 5 number of reported sats */ - - struct ao_telemetry_satellite_info sats[12]; /* 6 */ - uint8_t unused[2]; /* 30 */ - /* 32 */ -}; - -#define AO_TELEMETRY_COMPANION 0x07 - -#define AO_COMPANION_MAX_CHANNELS 12 - -struct ao_telemetry_companion { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t board_id; /* 5 */ - - uint8_t update_period; /* 6 */ - uint8_t channels; /* 7 */ - uint16_t companion_data[AO_COMPANION_MAX_CHANNELS]; /* 8 */ - /* 32 */ -}; - -union ao_telemetry_all { - struct ao_telemetry_generic generic; - struct ao_telemetry_sensor sensor; - struct ao_telemetry_configuration configuration; - struct ao_telemetry_location location; - struct ao_telemetry_satellite satellite; - struct ao_telemetry_companion companion; -}; - -/* - * ao_gps.c - */ - -#define AO_GPS_NUM_SAT_MASK (0xf << 0) -#define AO_GPS_NUM_SAT_SHIFT (0) - -#define AO_GPS_VALID (1 << 4) -#define AO_GPS_RUNNING (1 << 5) -#define AO_GPS_DATE_VALID (1 << 6) -#define AO_GPS_COURSE_VALID (1 << 7) - -extern __pdata uint16_t ao_gps_tick; -extern __xdata uint8_t ao_gps_mutex; -extern __xdata struct ao_telemetry_location ao_gps_data; -extern __xdata struct ao_telemetry_satellite ao_gps_tracking_data; - -struct ao_gps_orig { - uint8_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint8_t second; - uint8_t flags; - int32_t latitude; /* degrees * 10⁷ */ - int32_t longitude; /* degrees * 10⁷ */ - int16_t altitude; /* m */ - uint16_t ground_speed; /* cm/s */ - uint8_t course; /* degrees / 2 */ - uint8_t hdop; /* * 5 */ - int16_t climb_rate; /* cm/s */ - uint16_t h_error; /* m */ - uint16_t v_error; /* m */ -}; - -struct ao_gps_sat_orig { - uint8_t svid; - uint8_t c_n_1; -}; - -#define AO_MAX_GPS_TRACKING 12 - -struct ao_gps_tracking_orig { - uint8_t channels; - struct ao_gps_sat_orig sats[AO_MAX_GPS_TRACKING]; -}; - -void -ao_gps(void); - -void -ao_gps_print(__xdata struct ao_gps_orig *gps_data); - -void -ao_gps_tracking_print(__xdata struct ao_gps_tracking_orig *gps_tracking_data); - -void -ao_gps_init(void); - -/* - * ao_gps_report.c - */ - -void -ao_gps_report(void); - -void -ao_gps_report_init(void); - -/* - * ao_telemetry_orig.c - */ - -struct ao_telemetry_orig { - uint16_t serial; - uint16_t flight; - uint8_t flight_state; - int16_t accel; - int16_t ground_accel; - union { - struct { - int16_t speed; - int16_t unused; - } k; - int32_t flight_vel; - } u; - int16_t height; - int16_t ground_pres; - int16_t accel_plus_g; - int16_t accel_minus_g; - struct ao_adc adc; - struct ao_gps_orig gps; - char callsign[AO_MAX_CALLSIGN]; - struct ao_gps_tracking_orig gps_tracking; -}; - -struct ao_telemetry_tiny { - uint16_t serial; - uint16_t flight; - uint8_t flight_state; - int16_t height; /* AGL in meters */ - int16_t speed; /* in m/s * 16 */ - int16_t accel; /* in m/s² * 16 */ - int16_t ground_pres; /* sensor units */ - struct ao_adc adc; /* raw ADC readings */ - char callsign[AO_MAX_CALLSIGN]; -}; - -/* - * ao_radio_recv tacks on rssi and status bytes - */ - -struct ao_telemetry_raw_recv { - uint8_t packet[AO_MAX_TELEMETRY + 2]; -}; - -struct ao_telemetry_orig_recv { - struct ao_telemetry_orig telemetry_orig; - int8_t rssi; - uint8_t status; -}; - -struct ao_telemetry_tiny_recv { - struct ao_telemetry_tiny telemetry_tiny; - int8_t rssi; - uint8_t status; -}; - -/* Set delay between telemetry reports (0 to disable) */ - -#define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(1000) -#define AO_TELEMETRY_INTERVAL_FLIGHT AO_MS_TO_TICKS(100) -#define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(1000) - -void -ao_telemetry_set_interval(uint16_t interval); - -void -ao_rdf_set(uint8_t rdf); - -void -ao_telemetry_init(void); - -void -ao_telemetry_orig_init(void); - -void -ao_telemetry_tiny_init(void); - -/* - * ao_radio.c - */ - -extern __xdata uint8_t ao_radio_dma; -extern __xdata uint8_t ao_radio_dma_done; -extern __xdata uint8_t ao_radio_done; -extern __xdata uint8_t ao_radio_mutex; - -void -ao_radio_general_isr(void) __interrupt 16; - -void -ao_radio_get(uint8_t len); - -#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) - -void -ao_radio_set_packet(void); - -void -ao_radio_send(__xdata void *data, uint8_t size) __reentrant; - -uint8_t -ao_radio_recv(__xdata void *data, uint8_t size) __reentrant; - -void -ao_radio_recv_abort(void); - -void -ao_radio_rdf(int ms); - -void -ao_radio_rdf_abort(void); - -void -ao_radio_idle(void); - -void -ao_radio_init(void); - -/* - * ao_monitor.c - */ - -extern const char const * const ao_state_names[]; - -void -ao_monitor(void); - -#define AO_MONITORING_OFF 0 -#define AO_MONITORING_ORIG 1 -#define AO_MONITORING_TINY 2 - -void -ao_set_monitor(uint8_t monitoring); - -void -ao_monitor_init(uint8_t led, uint8_t monitoring) __reentrant; - -/* - * ao_stdio.c - */ - -#define AO_READ_AGAIN ((char) -1) - -struct ao_stdio { - char (*pollchar)(void); - void (*putchar)(char c) __reentrant; - void (*flush)(void); - uint8_t echo; -}; - -extern __xdata struct ao_stdio ao_stdios[]; -extern __pdata int8_t ao_cur_stdio; -extern __pdata int8_t ao_num_stdios; - -void -flush(void); - -extern __xdata uint8_t ao_stdin_ready; - -uint8_t -ao_echo(void); - -int8_t -ao_add_stdio(char (*pollchar)(void), - void (*putchar)(char) __reentrant, - void (*flush)(void)) __reentrant; - -/* - * ao_ignite.c - */ - -enum ao_igniter { - ao_igniter_drogue = 0, - ao_igniter_main = 1 -}; - -void -ao_ignite(enum ao_igniter igniter); - -enum ao_igniter_status { - ao_igniter_unknown, /* unknown status (ambiguous voltage) */ - ao_igniter_ready, /* continuity detected */ - ao_igniter_active, /* igniter firing */ - ao_igniter_open, /* open circuit detected */ -}; - -enum ao_igniter_status -ao_igniter_status(enum ao_igniter igniter); - -void -ao_ignite_set_pins(void); - -void -ao_igniter_init(void); - -/* - * ao_config.c - */ - -#define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 8 - -struct ao_config { - uint8_t major; - uint8_t minor; - uint16_t main_deploy; - int16_t accel_plus_g; /* changed for minor version 2 */ - uint8_t radio_channel; - char callsign[AO_MAX_CALLSIGN + 1]; - uint8_t apogee_delay; /* minor version 1 */ - int16_t accel_minus_g; /* minor version 2 */ - uint32_t radio_cal; /* minor version 3 */ - uint32_t flight_log_max; /* minor version 4 */ - uint8_t ignite_mode; /* minor version 5 */ - uint8_t pad_orientation; /* minor version 6 */ - uint32_t radio_setting; /* minor version 7 */ - uint8_t radio_enable; /* minor version 8 */ -}; - -#define AO_IGNITE_MODE_DUAL 0 -#define AO_IGNITE_MODE_APOGEE 1 -#define AO_IGNITE_MODE_MAIN 2 - -#define AO_PAD_ORIENTATION_ANTENNA_UP 0 -#define AO_PAD_ORIENTATION_ANTENNA_DOWN 1 - -extern __xdata struct ao_config ao_config; - -#define AO_CONFIG_MAX_SIZE 128 - -void -ao_config_get(void); - -void -ao_config_put(void); - -void -ao_config_init(void); - -/* - * ao_rssi.c - */ - -void -ao_rssi_set(int rssi_value); - -void -ao_rssi_init(uint8_t rssi_led); - -/* - * ao_product.c - * - * values which need to be defined for - * each instance of a product - */ - -extern const char ao_version[]; -extern const char ao_manufacturer[]; -extern const char ao_product[]; - -/* - * Fifos - */ - -#define AO_FIFO_SIZE 32 - -struct ao_fifo { - uint8_t insert; - uint8_t remove; - char fifo[AO_FIFO_SIZE]; -}; - -#define ao_fifo_insert(f,c) do { \ - (f).fifo[(f).insert] = (c); \ - (f).insert = ((f).insert + 1) & (AO_FIFO_SIZE-1); \ -} while(0) - -#define ao_fifo_remove(f,c) do {\ - c = (f).fifo[(f).remove]; \ - (f).remove = ((f).remove + 1) & (AO_FIFO_SIZE-1); \ -} while(0) - -#define ao_fifo_full(f) ((((f).insert + 1) & (AO_FIFO_SIZE-1)) == (f).remove) -#define ao_fifo_empty(f) ((f).insert == (f).remove) - -/* - * ao_packet.c - * - * Packet-based command interface - */ - -#define AO_PACKET_MAX 64 -#define AO_PACKET_SYN (uint8_t) 0xff - -struct ao_packet { - uint8_t addr; - uint8_t len; - uint8_t seq; - uint8_t ack; - uint8_t d[AO_PACKET_MAX]; - uint8_t callsign[AO_MAX_CALLSIGN]; -}; - -struct ao_packet_recv { - struct ao_packet packet; - int8_t rssi; - uint8_t status; -}; - -extern __xdata struct ao_packet_recv ao_rx_packet; -extern __xdata struct ao_packet ao_tx_packet; -extern __xdata struct ao_task ao_packet_task; -extern __xdata uint8_t ao_packet_enable; -extern __xdata uint8_t ao_packet_master_sleeping; -extern __pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; - -void -ao_packet_send(void); - -uint8_t -ao_packet_recv(void); - -void -ao_packet_flush(void); - -void -ao_packet_putchar(char c) __reentrant; - -char -ao_packet_pollchar(void) __critical; - -/* ao_packet_master.c */ - -void -ao_packet_master_init(void); - -/* ao_packet_slave.c */ - -void -ao_packet_slave_start(void); - -void -ao_packet_slave_stop(void); - -void -ao_packet_slave_init(uint8_t enable); - -/* ao_btm.c */ - -/* If bt_link is on P2, this interrupt is shared by USB, so the USB - * code calls this function. Otherwise, it's a regular ISR. - */ - -void -ao_btm_isr(void) -#if BT_LINK_ON_P1 - __interrupt 15 -#endif - ; - -void -ao_btm_init(void); - -/* ao_companion.c */ - -#define AO_COMPANION_SETUP 1 -#define AO_COMPANION_FETCH 2 -#define AO_COMPANION_NOTIFY 3 - -struct ao_companion_command { - uint8_t command; - uint8_t flight_state; - uint16_t tick; - uint16_t serial; - uint16_t flight; -}; - -struct ao_companion_setup { - uint16_t board_id; - uint16_t board_id_inverse; - uint8_t update_period; - uint8_t channels; -}; - -extern __pdata uint8_t ao_companion_running; -extern __xdata struct ao_companion_setup ao_companion_setup; -extern __xdata uint8_t ao_companion_mutex; -extern __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; - -void -ao_companion_init(void); - -#endif /* _AO_H_ */ diff --git a/src/ao_adc.c b/src/ao_adc.c deleted file mode 100644 index 786dfd11..00000000 --- a/src/ao_adc.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "ao_pins.h" - -volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; -#if HAS_ACCEL_REF -volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; -#endif -volatile __data uint8_t ao_adc_head; - -void -ao_adc_poll(void) -{ -#if HAS_ACCEL_REF - ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 2; -#else -# ifdef TELENANO_V_0_1 - ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 1; -# else - ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 0; -# endif -#endif -} - -void -ao_adc_get(__xdata struct ao_adc *packet) -{ - uint8_t i = ao_adc_ring_prev(ao_sample_adc); - memcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); -} - -void -ao_adc_isr(void) __interrupt 1 -{ - uint8_t sequence; - uint8_t __xdata *a; - - sequence = (ADCCON2 & ADCCON2_SCH_MASK) >> ADCCON2_SCH_SHIFT; -#if IGNITE_ON_P2 - /* TeleMetrum readings */ -#if HAS_ACCEL_REF - if (sequence == 2) { - a = (uint8_t __xdata *) (&ao_accel_ref[ao_adc_head]); - sequence = 0; - } else -#endif - { - if (sequence == ADCCON3_ECH_TEMP) - sequence = 2; - a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].accel + sequence); - sequence++; - } -#define GOT_ADC - a[0] = ADCL; - a[1] = ADCH; - if (sequence < 6) { -#if HAS_EXTERNAL_TEMP == 0 - /* start next channel conversion */ - /* v0.2 replaces external temp sensor with internal one */ - if (sequence == 2) - ADCCON3 = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP; - else -#endif - ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | sequence; - } -#endif - -#if IGNITE_ON_P0 - /* TeleMini readings */ - a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].pres); -#ifdef TELEMINI_V_1_0 - switch (sequence) { - case 0: - /* pressure */ - a += 0; - sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 1; - break; - case 1: - /* drogue sense */ - a += 6; - sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 2; - break; - case 2: - /* main sense */ - a += 8; - sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 3; - break; - case 3: - /* battery */ - a += 4; - sequence = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP; - break; - case ADCCON3_ECH_TEMP: - a += 2; - sequence = 0; - break; - } -#define GOT_ADC -#endif -#ifdef TELENANO_V_0_1 - switch (sequence) { - case 1: - /* pressure */ - a += 0; - sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 3; - break; - case 3: - /* battery */ - a += 4; - sequence = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP; - break; - case ADCCON3_ECH_TEMP: - a += 2; - sequence = 0; - break; - } -#define GOT_ADC -#endif - a[0] = ADCL; - a[1] = ADCH; - if (sequence) { - /* Start next conversion */ - ADCCON3 = sequence; - } -#endif -#ifndef GOT_ADC -#error No known ADC configuration set -#endif - - else { - /* record this conversion series */ - ao_adc_ring[ao_adc_head].tick = ao_time(); - ao_adc_head = ao_adc_ring_next(ao_adc_head); - ao_wakeup(DATA_TO_XDATA(&ao_adc_head)); - } -} - -static void -ao_adc_dump(void) __reentrant -{ - static __xdata struct ao_adc packet; - ao_adc_get(&packet); - printf("tick: %5u accel: %5d pres: %5d temp: %5d batt: %5d drogue: %5d main: %5d\n", - packet.tick, packet.accel, packet.pres, packet.temp, - packet.v_batt, packet.sense_d, packet.sense_m); -} - -__code struct ao_cmds ao_adc_cmds[] = { - { ao_adc_dump, "a\0Current ADC" }, - { 0, NULL }, -}; - -void -ao_adc_init(void) -{ -#if IGNITE_ON_P2 - /* TeleMetrum configuration */ - ADCCFG = ((1 << 0) | /* acceleration */ - (1 << 1) | /* pressure */ -#if HAS_EXTERNAL_TEMP - (1 << 2) | /* v0.1 temperature */ -#endif - (1 << 3) | /* battery voltage */ - (1 << 4) | /* drogue sense */ - (1 << 5)); /* main sense */ -#endif - -#if IGNITE_ON_P0 - /* TeleMini configuration */ - ADCCFG = ((1 << 0) | /* pressure */ - (1 << 1) | /* drogue sense */ - (1 << 2) | /* main sense */ - (1 << 3)); /* battery voltage */ -#endif - - /* enable interrupts */ - ADCIF = 0; - IEN0 |= IEN0_ADCIE; - ao_cmd_register(&ao_adc_cmds[0]); -} diff --git a/src/ao_adc_fake.c b/src/ao_adc_fake.c deleted file mode 100644 index 6ca88d4e..00000000 --- a/src/ao_adc_fake.c +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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" - -volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; -volatile __data uint8_t ao_adc_head; - -/* Stub for systems which have no ADC */ -void -ao_adc_poll(void) -{ -} diff --git a/src/ao_beep.c b/src/ao_beep.c deleted file mode 100644 index 3642f4c6..00000000 --- a/src/ao_beep.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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_beep(uint8_t beep) -{ - if (beep == 0) { - P2_0 = 0; - P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_GPIO; - T4CTL = 0; - } else { - P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_PERIPHERAL; - T4CC0 = beep; - T4CTL = TxCTL_DIV_32 | TxCTL_MODE_MODULO | TxCTL_START; - } -} - -void -ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant -{ - ao_beep(beep); - ao_delay(ticks); - ao_beep(0); -} - -void -ao_beep_init(void) -{ - /* Our beeper is on P2_0, which is hooked to timer 4 using - * configuration alternative 2 - */ - P2_0 = 0; - P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_GPIO; - PERCFG = (PERCFG & ~PERCFG_T4CFG_ALT_MASK) | PERCFG_T4CFG_ALT_2; - T4CCTL0 = TxCCTLy_CMP_TOGGLE|TxCCTLy_CMP_MODE_ENABLE; -} diff --git a/src/ao_btm.c b/src/ao_btm.c deleted file mode 100644 index 44155ec1..00000000 --- a/src/ao_btm.c +++ /dev/null @@ -1,302 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -int8_t ao_btm_stdio; -__xdata uint8_t ao_btm_connected; - -#define AO_BTM_MAX_REPLY 16 -__xdata char ao_btm_reply[AO_BTM_MAX_REPLY]; - -extern volatile __xdata struct ao_fifo ao_usart1_rx_fifo; - -/* - * Read a line of data from the serial port, truncating - * it after a few characters. - */ - -uint8_t -ao_btm_get_line(void) -{ - uint8_t ao_btm_reply_len = 0; - char c; - - for (;;) { - - while ((c = ao_serial_pollchar()) != AO_READ_AGAIN) { - if (ao_btm_reply_len < sizeof (ao_btm_reply)) - ao_btm_reply[ao_btm_reply_len++] = c; - if (c == '\r' || c == '\n') - goto done; - } - for (c = 0; c < 10; c++) { - ao_delay(AO_MS_TO_TICKS(10)); - if (!ao_fifo_empty(ao_usart1_rx_fifo)) - break; - } - if (c == 10) - goto done; - } -done: - for (c = ao_btm_reply_len; c < sizeof (ao_btm_reply);) - ao_btm_reply[c++] = '\0'; - return ao_btm_reply_len; -} - -/* - * Drain the serial port completely - */ -void -ao_btm_drain() -{ - while (ao_btm_get_line()) - ; -} - -/* - * Set the stdio echo for the bluetooth link - */ -void -ao_btm_echo(uint8_t echo) -{ - ao_stdios[ao_btm_stdio].echo = echo; -} - -/* - * Delay between command charaters; the BT module - * can't keep up with 57600 baud - */ - -void -ao_btm_putchar(char c) -{ - ao_serial_putchar(c); - ao_delay(1); -} - -/* - * Wait for the bluetooth device to return - * status from the previously executed command - */ -uint8_t -ao_btm_wait_reply(void) -{ - for (;;) { - ao_btm_get_line(); - if (!strncmp(ao_btm_reply, "OK", 2)) - return 1; - if (!strncmp(ao_btm_reply, "ERROR", 5)) - return -1; - if (ao_btm_reply[0] == '\0') - return 0; - } -} - -void -ao_btm_string(__code char *cmd) -{ - char c; - - while (c = *cmd++) - ao_btm_putchar(c); -} - -uint8_t -ao_btm_cmd(__code char *cmd) -{ - ao_btm_drain(); - ao_btm_string(cmd); - return ao_btm_wait_reply(); -} - -uint8_t -ao_btm_set_name(void) -{ - char sn[8]; - char *s = sn + 8; - char c; - int n; - ao_btm_string("ATN=TeleBT-"); - *--s = '\0'; - *--s = '\r'; - n = ao_serial_number; - do { - *--s = '0' + n % 10; - } while (n /= 10); - while ((c = *s++)) - ao_btm_putchar(c); - return ao_btm_wait_reply(); -} - -uint8_t -ao_btm_try_speed(uint8_t speed) -{ - ao_serial_set_speed(speed); - ao_btm_drain(); - (void) ao_btm_cmd("\rATE0\rATQ0\r"); - if (ao_btm_cmd("AT\r") == 1) - return 1; - return 0; -} - -/* - * A thread to initialize the bluetooth device and - * hang around to blink the LED when connected - */ -void -ao_btm(void) -{ - /* - * Wait for the bluetooth device to boot - */ - ao_delay(AO_SEC_TO_TICKS(3)); - -#if HAS_BEEP - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); -#endif - - /* - * The first time we connect, the BTM-180 comes up at 19200 baud. - * After that, it will remember and come up at 57600 baud. So, see - * if it is already running at 57600 baud, and if that doesn't work - * then tell it to switch to 57600 from 19200 baud. - */ - while (!ao_btm_try_speed(AO_SERIAL_SPEED_57600)) { - ao_delay(AO_SEC_TO_TICKS(1)); - if (ao_btm_try_speed(AO_SERIAL_SPEED_19200)) - ao_btm_cmd("ATL4\r"); - ao_delay(AO_SEC_TO_TICKS(1)); - } - - /* Disable echo */ - ao_btm_cmd("ATE0\r"); - - /* Enable flow control */ - ao_btm_cmd("ATC1\r"); - - /* Set the reported name to something we can find on the host */ - ao_btm_set_name(); - - /* Turn off status reporting */ - ao_btm_cmd("ATQ1\r"); - - ao_btm_stdio = ao_add_stdio(ao_serial_pollchar, - ao_serial_putchar, - NULL); - ao_btm_echo(0); - - for (;;) { - while (!ao_btm_connected) - ao_sleep(&ao_btm_connected); - while (ao_btm_connected) { - ao_led_for(AO_LED_GREEN, AO_MS_TO_TICKS(20)); - ao_delay(AO_SEC_TO_TICKS(3)); - } - } -} - -__xdata struct ao_task ao_btm_task; - -#if BT_LINK_ON_P2 -#define BT_PICTL_ICON PICTL_P2ICON -#define BT_PIFG P2IFG -#define BT_PDIR P2DIR -#define BT_PINP P2INP -#define BT_IEN2_PIE IEN2_P2IE -#endif -#if BT_LINK_ON_P1 -#define BT_PICTL_ICON PICTL_P1ICON -#define BT_PIFG P1IFG -#define BT_PDIR P1DIR -#define BT_PINP P1INP -#define BT_IEN2_PIE IEN2_P1IE -#endif - -void -ao_btm_check_link() __critical -{ - /* Check the pin and configure the interrupt detector to wait for the - * pin to flip the other way - */ - if (BT_LINK_PIN) { - ao_btm_connected = 0; - PICTL |= BT_PICTL_ICON; - } else { - ao_btm_connected = 1; - PICTL &= ~BT_PICTL_ICON; - } -} - -void -ao_btm_isr(void) -#if BT_LINK_ON_P1 - __interrupt 15 -#endif -{ -#if BT_LINK_ON_P1 - P1IF = 0; -#endif - if (BT_PIFG & (1 << BT_LINK_PIN_INDEX)) { - ao_btm_check_link(); - ao_wakeup(&ao_btm_connected); - } - BT_PIFG = 0; -} - -void -ao_btm_init (void) -{ - ao_serial_init(); - ao_serial_set_speed(AO_SERIAL_SPEED_19200); - -#if BT_LINK_ON_P1 - /* - * Configure ser reset line - */ - - P1_6 = 0; - P1DIR |= (1 << 6); -#endif - - /* - * Configure link status line - */ - - /* Set pin to input */ - BT_PDIR &= ~(1 << BT_LINK_PIN_INDEX); - - /* Set pin to tri-state */ - BT_PINP |= (1 << BT_LINK_PIN_INDEX); - - /* Enable interrupts */ - IEN2 |= BT_IEN2_PIE; - - /* Check current pin state */ - ao_btm_check_link(); - -#if BT_LINK_ON_P2 - /* Eable the pin interrupt */ - PICTL |= PICTL_P2IEN; -#endif -#if BT_LINK_ON_P1 - /* Enable pin interrupt */ - P1IEN |= (1 << BT_LINK_PIN_INDEX); -#endif - - ao_add_task(&ao_btm_task, ao_btm, "bt"); -} diff --git a/src/ao_cmd.c b/src/ao_cmd.c deleted file mode 100644 index 1442ebea..00000000 --- a/src/ao_cmd.c +++ /dev/null @@ -1,320 +0,0 @@ -/* - * 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" - -__pdata uint16_t ao_cmd_lex_i; -__pdata uint32_t ao_cmd_lex_u32; -__pdata char ao_cmd_lex_c; -__pdata enum ao_cmd_status ao_cmd_status; - -#define CMD_LEN 32 - -static __xdata char cmd_line[CMD_LEN]; -static __pdata uint8_t cmd_len; -static __pdata uint8_t cmd_i; - -static void -put_string(__code char *s) -{ - char c; - while (c = *s++) - putchar(c); -} - -static void -readline(void) -{ - __pdata char c; - if (ao_echo()) - put_string("> "); - cmd_len = 0; - for (;;) { - flush(); - c = getchar(); - /* backspace/delete */ - if (c == '\010' || c == '\177') { - if (cmd_len != 0) { - if (ao_echo()) - put_string("\010 \010"); - --cmd_len; - } - continue; - } - - /* ^U */ - if (c == '\025') { - while (cmd_len != 0) { - if (ao_echo()) - put_string("\010 \010"); - --cmd_len; - } - continue; - } - - /* map CR to NL */ - if (c == '\r') - c = '\n'; - - if (c == '\n') { - if (ao_echo()) - putchar('\n'); - break; - } - - if (cmd_len >= CMD_LEN - 2) { - if (ao_echo()) - putchar('\007'); - continue; - } - cmd_line[cmd_len++] = c; - if (ao_echo()) - putchar(c); - } - cmd_line[cmd_len++] = '\n'; - cmd_line[cmd_len++] = '\0'; - cmd_i = 0; -} - -void -ao_cmd_lex(void) -{ - ao_cmd_lex_c = '\n'; - if (cmd_i < cmd_len) - ao_cmd_lex_c = cmd_line[cmd_i++]; -} - -static void -putnibble(uint8_t v) -{ - if (v < 10) - putchar(v + '0'); - else - putchar(v + ('a' - 10)); -} - -void -ao_cmd_put16(uint16_t v) -{ - ao_cmd_put8(v >> 8); - ao_cmd_put8(v); -} - -void -ao_cmd_put8(uint8_t v) -{ - putnibble((v >> 4) & 0xf); - putnibble(v & 0xf); -} - -void -ao_cmd_white(void) -{ - while (ao_cmd_lex_c == ' ' || ao_cmd_lex_c == '\t') - ao_cmd_lex(); -} - -void -ao_cmd_hex(void) -{ - __pdata uint8_t r = ao_cmd_lex_error; - uint8_t n; - - ao_cmd_lex_i = 0; - ao_cmd_white(); - for(;;) { - if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') - n = (ao_cmd_lex_c - '0'); - else if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f') - n = (ao_cmd_lex_c - 'a' + 10); - else if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F') - n = (ao_cmd_lex_c - 'A' + 10); - else - break; - ao_cmd_lex_i = (ao_cmd_lex_i << 4) | n; - r = ao_cmd_success; - ao_cmd_lex(); - } - if (r != ao_cmd_success) - ao_cmd_status = r; -} - -void -ao_cmd_decimal(void) -{ - __pdata uint8_t r = ao_cmd_lex_error; - - ao_cmd_lex_u32 = 0; - ao_cmd_white(); - for(;;) { - if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') - ao_cmd_lex_u32 = (ao_cmd_lex_u32 * 10) + (ao_cmd_lex_c - '0'); - else - break; - r = ao_cmd_success; - ao_cmd_lex(); - } - if (r != ao_cmd_success) - ao_cmd_status = r; - ao_cmd_lex_i = (uint16_t) ao_cmd_lex_u32; -} - -uint8_t -ao_match_word(__code char *word) -{ - while (*word) { - if (ao_cmd_lex_c != *word) { - ao_cmd_status = ao_cmd_syntax_error; - return 0; - } - word++; - ao_cmd_lex(); - } - return 1; -} - -static void -eol(void) -{ - while (ao_cmd_lex_c != '\n') - ao_cmd_lex(); -} - -static void -echo(void) -{ - ao_cmd_hex(); - if (ao_cmd_status == ao_cmd_success) - ao_stdios[ao_cur_stdio].echo = ao_cmd_lex_i != 0; -} - -static void -ao_reboot(void) -{ - ao_cmd_white(); - if (!ao_match_word("eboot")) - return; - WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; - ao_delay(AO_SEC_TO_TICKS(2)); - ao_panic(AO_PANIC_REBOOT); -} - -static void -version(void) -{ - printf("manufacturer %s\n", ao_manufacturer); - printf("product %s\n", ao_product); - printf("serial-number %u\n", ao_serial_number); -#if HAS_EEPROM - printf("log-format %u\n", ao_log_format); -#endif - printf("software-version %s\n", ao_version); -} - -#define NUM_CMDS 11 - -static __code struct ao_cmds *__xdata (ao_cmds[NUM_CMDS]); -static __pdata uint8_t ao_ncmds; - -static void -help(void) -{ - register uint8_t cmds; - register uint8_t cmd; - register __code struct ao_cmds * cs; - - for (cmds = 0; cmds < ao_ncmds; cmds++) { - cs = ao_cmds[cmds]; - for (cmd = 0; cs[cmd].func; cmd++) - printf("%-45s %s\n", - cs[cmd].help, - cs[cmd].help+1+strlen(cs[cmd].help)); - } -} - -static void -report(void) -{ - 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) -{ - char c; - uint8_t cmd, cmds; - __code struct ao_cmds * __xdata cs; - void (*__xdata func)(void); - - for (;;) { - readline(); - ao_cmd_lex(); - ao_cmd_white(); - c = ao_cmd_lex_c; - ao_cmd_lex(); - if (c == '\r' || c == '\n') - continue; - func = (void (*)(void)) NULL; - for (cmds = 0; cmds < ao_ncmds; cmds++) { - cs = ao_cmds[cmds]; - for (cmd = 0; cs[cmd].func; cmd++) - if (cs[cmd].help[0] == c) { - func = cs[cmd].func; - break; - } - if (func) - break; - } - if (func) - (*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, "?\0Help" }, - { ao_task_info, "T\0Show tasks" }, - { echo, "E <0 off, 1 on>\0Set echo mode" }, - { ao_reboot, "r eboot\0Reboot" }, - { version, "v\0Version" }, - { 0, 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/src/ao_companion.c b/src/ao_companion.c deleted file mode 100644 index 4c8f4269..00000000 --- a/src/ao_companion.c +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -#define ao_spi_slow() (U0GCR = (UxGCR_CPOL_NEGATIVE | \ - UxGCR_CPHA_FIRST_EDGE | \ - UxGCR_ORDER_MSB | \ - (13 << UxGCR_BAUD_E_SHIFT))) - -#define ao_spi_fast() (U0GCR = (UxGCR_CPOL_NEGATIVE | \ - UxGCR_CPHA_FIRST_EDGE | \ - UxGCR_ORDER_MSB | \ - (17 << UxGCR_BAUD_E_SHIFT))) - -#define COMPANION_SELECT() do { ao_spi_get_bit(COMPANION_CS); ao_spi_slow(); } while (0) -#define COMPANION_DESELECT() do { ao_spi_fast(); ao_spi_put_bit(COMPANION_CS); } while (0) - -static __xdata struct ao_companion_command ao_companion_command; -__xdata struct ao_companion_setup ao_companion_setup; - -__xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; -__pdata uint8_t ao_companion_running; -__xdata uint8_t ao_companion_mutex; - -static void -ao_companion_send_command(uint8_t command) -{ - ao_companion_command.command = command; - ao_companion_command.flight_state = ao_flight_state; - ao_companion_command.tick = ao_time(); - ao_companion_command.serial = ao_serial_number; - ao_companion_command.flight = ao_flight_number; - ao_spi_send(&ao_companion_command, sizeof (ao_companion_command)); -} - -static uint8_t -ao_companion_get_setup(void) -{ - COMPANION_SELECT(); - ao_companion_send_command(AO_COMPANION_SETUP); - ao_spi_recv(&ao_companion_setup, sizeof (ao_companion_setup)); - COMPANION_DESELECT(); - return (ao_companion_setup.board_id == - ~ao_companion_setup.board_id_inverse); -} - -static void -ao_companion_get_data(void) -{ - COMPANION_SELECT(); - ao_companion_send_command(AO_COMPANION_FETCH); - ao_mutex_get(&ao_companion_mutex); - ao_spi_recv(&ao_companion_data, ao_companion_setup.channels * 2); - ao_mutex_put(&ao_companion_mutex); - COMPANION_DESELECT(); -} - -static void -ao_companion_notify(void) -{ - COMPANION_SELECT(); - ao_companion_send_command(AO_COMPANION_NOTIFY); - COMPANION_DESELECT(); -} - -void -ao_companion(void) -{ - uint8_t i; - while (!ao_flight_number) - ao_sleep(&ao_flight_number); - for (i = 0; i < 10; i++) { - ao_delay(AO_SEC_TO_TICKS(1)); - if ((ao_companion_running = ao_companion_get_setup())) - break; - } - while (ao_companion_running) { - ao_alarm(ao_companion_setup.update_period); - if (ao_sleep(DATA_TO_XDATA(&ao_flight_state))) - ao_companion_get_data(); - else - ao_companion_notify(); - } - ao_exit(); -} - -void -ao_companion_status(void) __reentrant -{ - uint8_t i; - printf("Companion running: %d\n", ao_companion_running); - printf("device: %d\n", ao_companion_setup.board_id); - printf("update period: %d\n", ao_companion_setup.update_period); - printf("channels: %d\n", ao_companion_setup.channels); - printf("data:"); - for(i = 0; i < ao_companion_setup.channels; i++) - printf(" %5u", ao_companion_data[i]); - printf("\n"); -} - -__code struct ao_cmds ao_companion_cmds[] = { - { ao_companion_status, "L\0Companion link status" }, - { 0, NULL }, -}; - -static __xdata struct ao_task ao_companion_task; - -void -ao_companion_init(void) -{ - COMPANION_CS_PORT |= COMPANION_CS_MASK; /* raise all CS pins */ - COMPANION_CS_DIR |= COMPANION_CS_MASK; /* set CS pins as outputs */ - COMPANION_CS_SEL &= ~COMPANION_CS_MASK; /* set CS pins as GPIO */ - - ao_cmd_register(&ao_companion_cmds[0]); - ao_add_task(&ao_companion_task, ao_companion, "companion"); -} diff --git a/src/ao_config.c b/src/ao_config.c deleted file mode 100644 index 0c10e608..00000000 --- a/src/ao_config.c +++ /dev/null @@ -1,542 +0,0 @@ -/* - * 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" - -__xdata struct ao_config ao_config; -__pdata uint8_t ao_config_loaded; -__pdata uint8_t ao_config_dirty; -__xdata uint8_t ao_config_mutex; - -#define AO_CONFIG_DEFAULT_MAIN_DEPLOY 250 -#define AO_CONFIG_DEFAULT_RADIO_CHANNEL 0 -#define AO_CONFIG_DEFAULT_CALLSIGN "N0CALL" -#define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000 -#define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 -#define AO_CONFIG_DEFAULT_IGNITE_MODE AO_IGNITE_MODE_DUAL -#define AO_CONFIG_DEFAULT_PAD_ORIENTATION AO_PAD_ORIENTATION_ANTENNA_UP -#if HAS_EEPROM -#ifndef USE_INTERNAL_FLASH -#error Please define USE_INTERNAL_FLASH -#endif -#endif -#if USE_INTERNAL_FLASH -#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_config -#else -#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 192 * (uint32_t) 1024) -#endif - -#if HAS_EEPROM -static void -_ao_config_put(void) -{ - ao_storage_setup(); - ao_storage_erase(ao_storage_config); - ao_storage_write(ao_storage_config, &ao_config, sizeof (ao_config)); - ao_log_write_erase(0); - ao_storage_flush(); -} - -void -ao_config_put(void) -{ - ao_mutex_get(&ao_config_mutex); - _ao_config_put(); - ao_mutex_put(&ao_config_mutex); -} -#endif - -static void -_ao_config_get(void) -{ - if (ao_config_loaded) - return; -#if HAS_EEPROM - ao_storage_setup(); - ao_storage_read(ao_storage_config, &ao_config, sizeof (ao_config)); -#endif - if (ao_config.major != AO_CONFIG_MAJOR) { - ao_config.major = AO_CONFIG_MAJOR; - ao_config.minor = 0; - ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; - ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; - memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); - memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, - sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); - } - if (ao_config.minor < AO_CONFIG_MINOR) { - /* Fixups for minor version 1 */ - if (ao_config.minor < 1) - ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; - /* Fixups for minor version 2 */ - if (ao_config.minor < 2) { - ao_config.accel_plus_g = 0; - ao_config.accel_minus_g = 0; - } - /* Fixups for minor version 3 */ - if (ao_config.minor < 3) - ao_config.radio_cal = ao_radio_cal; - /* Fixups for minor version 4 */ - if (ao_config.minor < 4) - ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; - /* Fixupes for minor version 5 */ - if (ao_config.minor < 5) - ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; - if (ao_config.minor < 6) - ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; - if (ao_config.minor < 7) - ao_config.radio_setting = ao_config.radio_cal; - if (ao_config.minor < 8) - ao_config.radio_enable = TRUE; - ao_config.minor = AO_CONFIG_MINOR; - ao_config_dirty = 1; - } - ao_config_loaded = 1; -} - -static void -_ao_config_edit_start(void) -{ - ao_mutex_get(&ao_config_mutex); - _ao_config_get(); -} - -static void -_ao_config_edit_finish(void) -{ - ao_config_dirty = 1; - ao_mutex_put(&ao_config_mutex); -} - -void -ao_config_get(void) -{ - _ao_config_edit_start(); - ao_mutex_put(&ao_config_mutex); -} - -void -ao_config_callsign_show(void) -{ - printf ("Callsign: \"%s\"\n", ao_config.callsign); -} - -void -ao_config_callsign_set(void) __reentrant -{ - uint8_t c; - static __xdata char callsign[AO_MAX_CALLSIGN + 1]; - - memset(callsign, '\0', sizeof callsign); - ao_cmd_white(); - c = 0; - while (ao_cmd_lex_c != '\n') { - if (c < AO_MAX_CALLSIGN) - callsign[c++] = ao_cmd_lex_c; - else - ao_cmd_status = ao_cmd_lex_error; - ao_cmd_lex(); - } - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - memcpy(&ao_config.callsign, &callsign, - AO_MAX_CALLSIGN + 1); - _ao_config_edit_finish(); -} - -void -ao_config_radio_channel_show(void) __reentrant -{ - printf("Radio channel: %d\n", - ao_config.radio_channel); -} - -void -ao_config_radio_channel_set(void) __reentrant -{ - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - ao_config.radio_channel = ao_cmd_lex_i; - _ao_config_edit_finish(); - ao_radio_recv_abort(); -} - -#if HAS_ADC - -void -ao_config_main_deploy_show(void) __reentrant -{ - printf("Main deploy: %d meters\n", - ao_config.main_deploy); -} - -void -ao_config_main_deploy_set(void) __reentrant -{ - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - ao_config.main_deploy = ao_cmd_lex_i; - _ao_config_edit_finish(); -} - -#if HAS_ACCEL -void -ao_config_accel_calibrate_show(void) __reentrant -{ - printf("Accel cal +1g: %d -1g: %d\n", - ao_config.accel_plus_g, ao_config.accel_minus_g); -} - -#define ACCEL_CALIBRATE_SAMPLES 1024 -#define ACCEL_CALIBRATE_SHIFT 10 - -static int16_t -ao_config_accel_calibrate_auto(char *orientation) __reentrant -{ - uint16_t i; - int32_t accel_total; - uint8_t cal_adc_ring; - - printf("Orient antenna %s and press a key...", orientation); - flush(); - (void) getchar(); - puts("\r\n"); flush(); - puts("Calibrating..."); flush(); - i = ACCEL_CALIBRATE_SAMPLES; - accel_total = 0; - cal_adc_ring = ao_sample_adc; - while (i) { - ao_sleep(DATA_TO_XDATA(&ao_sample_adc)); - while (i && cal_adc_ring != ao_sample_adc) { - accel_total += (int32_t) ao_adc_ring[cal_adc_ring].accel; - cal_adc_ring = ao_adc_ring_next(cal_adc_ring); - i--; - } - } - return accel_total >> ACCEL_CALIBRATE_SHIFT; -} - -void -ao_config_accel_calibrate_set(void) __reentrant -{ - int16_t up, down; - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - if (ao_cmd_lex_i == 0) { - up = ao_config_accel_calibrate_auto("up"); - down = ao_config_accel_calibrate_auto("down"); - } else { - up = ao_cmd_lex_i; - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - down = ao_cmd_lex_i; - } - if (up >= down) { - printf("Invalid accel: up (%d) down (%d)\n", - up, down); - return; - } - _ao_config_edit_start(); - ao_config.accel_plus_g = up; - ao_config.accel_minus_g = down; - _ao_config_edit_finish(); -} -#endif /* HAS_ACCEL */ - -void -ao_config_apogee_delay_show(void) __reentrant -{ - printf("Apogee delay: %d seconds\n", - ao_config.apogee_delay); -} - -void -ao_config_apogee_delay_set(void) __reentrant -{ - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - ao_config.apogee_delay = ao_cmd_lex_i; - _ao_config_edit_finish(); -} - -#endif /* HAS_ADC */ - -void -ao_config_radio_cal_show(void) __reentrant -{ - printf("Radio cal: %ld\n", ao_config.radio_cal); -} - -void -ao_config_radio_cal_set(void) __reentrant -{ - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - ao_config.radio_setting = ao_config.radio_cal = ao_cmd_lex_u32; - _ao_config_edit_finish(); -} - -#if HAS_EEPROM -void -ao_config_log_show(void) __reentrant -{ - printf("Max flight log: %d kB\n", (int16_t) (ao_config.flight_log_max >> 10)); -} - -void -ao_config_log_set(void) __reentrant -{ - uint16_t block = (uint16_t) (ao_storage_block >> 10); - uint16_t config = (uint16_t) (ao_storage_config >> 10); - - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - if (ao_log_present()) - printf("Storage must be empty before changing log size\n"); - else if (block > 1024 && (ao_cmd_lex_i & (block - 1))) - printf("Flight log size must be multiple of %d kB\n", block); - else if (ao_cmd_lex_i > config) - printf("Flight log max %d kB\n", config); - else { - _ao_config_edit_start(); - ao_config.flight_log_max = (uint32_t) ao_cmd_lex_i << 10; - _ao_config_edit_finish(); - } -} -#endif /* HAS_EEPROM */ - -#if HAS_IGNITE -void -ao_config_ignite_mode_show(void) __reentrant -{ - printf("Ignite mode: %d\n", ao_config.ignite_mode); -} - -void -ao_config_ignite_mode_set(void) __reentrant -{ - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - ao_config.ignite_mode = ao_cmd_lex_i; - _ao_config_edit_finish(); -} -#endif - -#if HAS_ACCEL -void -ao_config_pad_orientation_show(void) __reentrant -{ - printf("Pad orientation: %d\n", ao_config.pad_orientation); -} - -void -ao_config_pad_orientation_set(void) __reentrant -{ - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - ao_cmd_lex_i &= 1; - if (ao_config.pad_orientation != ao_cmd_lex_i) { - uint16_t t; - t = ao_config.accel_plus_g; - ao_config.accel_plus_g = 0x7fff - ao_config.accel_minus_g; - ao_config.accel_minus_g = 0x7fff - t; - } - ao_config.pad_orientation = ao_cmd_lex_i; - _ao_config_edit_finish(); -} -#endif - -void -ao_config_radio_setting_show(void) __reentrant -{ - printf("Radio setting: %ld\n", ao_config.radio_setting); -} - -void -ao_config_radio_setting_set(void) __reentrant -{ - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - ao_config.radio_setting = ao_cmd_lex_u32; - ao_config.radio_channel = 0; - _ao_config_edit_finish(); - ao_radio_recv_abort(); -} - -void -ao_config_radio_enable_show(void) __reentrant -{ - printf("Radio enable: %d\n", ao_config.radio_enable); -} - -void -ao_config_radio_enable_set(void) __reentrant -{ - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - ao_config.radio_enable = ao_cmd_lex_i; - _ao_config_edit_finish(); -} - -struct ao_config_var { - __code char *str; - void (*set)(void) __reentrant; - void (*show)(void) __reentrant; -}; - -static void -ao_config_help(void) __reentrant; - -static void -ao_config_show(void) __reentrant; - -static void -ao_config_write(void) __reentrant; - -__code struct ao_config_var ao_config_vars[] = { -#if HAS_ADC - { "m \0Main deploy (in meters)", - ao_config_main_deploy_set, ao_config_main_deploy_show, }, - { "d \0Apogee delay (in seconds)", - ao_config_apogee_delay_set, ao_config_apogee_delay_show }, -#endif /* HAS_ADC */ - { "r \0Radio channel (freq = 434.550 + chan * .1)", - ao_config_radio_channel_set, ao_config_radio_channel_show }, - { "c \0Callsign (8 char max)", - ao_config_callsign_set, ao_config_callsign_show }, - { "R \0Radio freq control (freq = 434.550 * setting/cal)", - ao_config_radio_setting_set, ao_config_radio_setting_show }, - { "e <0 disable, 1 enable>\0Enable telemetry and RDF", - ao_config_radio_enable_set, ao_config_radio_enable_show }, -#if HAS_ACCEL - { "a <+g> <-g>\0Accel calib (0 for auto)", - ao_config_accel_calibrate_set,ao_config_accel_calibrate_show }, -#endif /* HAS_ACCEL */ - { "f \0Radio calib (cal = rf/(xtal/2^16))", - ao_config_radio_cal_set, ao_config_radio_cal_show }, -#if HAS_EEPROM - { "l \0Flight log size in kB", - ao_config_log_set, ao_config_log_show }, -#endif -#if HAS_IGNITE - { "i <0 dual, 1 apogee, 2 main>\0Set igniter mode", - ao_config_ignite_mode_set, ao_config_ignite_mode_show }, -#endif -#if HAS_ACCEL - { "o <0 antenna up, 1 antenna down>\0Set pad orientation", - ao_config_pad_orientation_set,ao_config_pad_orientation_show }, -#endif - { "s\0Show", - ao_config_show, 0 }, -#if HAS_EEPROM - { "w\0Write to eeprom", - ao_config_write, 0 }, -#endif - { "?\0Help", - ao_config_help, 0 }, - { 0, 0, 0 } -}; - -void -ao_config_set(void) -{ - char c; - uint8_t cmd; - void (*__xdata func)(void) __reentrant; - - ao_cmd_white(); - c = ao_cmd_lex_c; - ao_cmd_lex(); - func = 0; - for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) - if (ao_config_vars[cmd].str[0] == c) { - (*ao_config_vars[cmd].set)(); - return; - } - ao_cmd_status = ao_cmd_syntax_error; -} - -static void -ao_config_help(void) __reentrant -{ - uint8_t cmd; - for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) - printf("%-20s %s\n", - ao_config_vars[cmd].str, - ao_config_vars[cmd].str+1+strlen(ao_config_vars[cmd].str)); -} - -static void -ao_config_show(void) __reentrant -{ - uint8_t cmd; - printf("Config version: %d.%d\n", - ao_config.major, ao_config.minor); - for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) - if (ao_config_vars[cmd].show) - (*ao_config_vars[cmd].show)(); -} - -#if HAS_EEPROM -static void -ao_config_write(void) __reentrant -{ - uint8_t saved = 0; - ao_mutex_get(&ao_config_mutex); - if (ao_config_dirty) { - _ao_config_put(); - ao_config_dirty = 0; - saved = 1; - } - ao_mutex_put(&ao_config_mutex); - if (saved) - puts("Saved"); - else - puts("Nothing to save"); -} -#endif - -__code struct ao_cmds ao_config_cmds[] = { - { ao_config_set, "c \0Set config variable (? for help, s to show)" }, - { 0, NULL }, -}; - -void -ao_config_init(void) -{ - ao_cmd_register(&ao_config_cmds[0]); -} diff --git a/src/ao_convert.c b/src/ao_convert.c deleted file mode 100644 index 0969f107..00000000 --- a/src/ao_convert.c +++ /dev/null @@ -1,85 +0,0 @@ -/* - * 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. - */ - -#if !defined(AO_CONVERT_TEST) && !defined(AO_FLIGHT_TEST) -#include "ao.h" -#endif - -static const int16_t altitude_table[] = { -#include "altitude.h" -}; - -#define ALT_FRAC_SCALE (1 << ALT_FRAC_BITS) -#define ALT_FRAC_MASK (ALT_FRAC_SCALE - 1) - -int16_t -ao_pres_to_altitude(int16_t pres) __reentrant -{ - uint8_t o; - int16_t part; - - if (pres < 0) - pres = 0; - o = pres >> ALT_FRAC_BITS; - part = pres & ALT_FRAC_MASK; - - return ((int32_t) altitude_table[o] * (ALT_FRAC_SCALE - part) + - (int32_t) altitude_table[o+1] * part + (ALT_FRAC_SCALE >> 1)) >> ALT_FRAC_BITS; -} - -int16_t -ao_altitude_to_pres(int16_t alt) __reentrant -{ - int16_t span, sub_span; - uint8_t l, h, m; - int32_t pres; - - l = 0; - h = NALT - 1; - while ((h - l) != 1) { - m = (l + h) >> 1; - if (altitude_table[m] < alt) - h = m; - else - l = m; - } - span = altitude_table[l] - altitude_table[h]; - sub_span = altitude_table[l] - alt; - pres = ((((int32_t) l * (span - sub_span) + (int32_t) h * sub_span) << ALT_FRAC_BITS) + (span >> 1)) / span; - if (pres > 32767) - pres = 32767; - if (pres < 0) - pres = 0; - return (int16_t) pres; -} - -int16_t -ao_temp_to_dC(int16_t temp) __reentrant -{ - int16_t ret; - - /* Output voltage at 0°C = 0.755V - * Coefficient = 0.00247V/°C - * Reference voltage = 1.25V - * - * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247 - * = (value - 19791.268) / 32768 * 1.25 / 0.00247 - * ≃ (value - 19791) * 1012 / 65536 - */ - ret = ((temp - 19791) * 1012L) >> 16; - return ret; -} diff --git a/src/ao_convert_test.c b/src/ao_convert_test.c deleted file mode 100644 index e2c28b73..00000000 --- a/src/ao_convert_test.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include -#define AO_CONVERT_TEST -#include "ao_host.h" -#include "ao_convert.c" - -#define STEP 1 - -static inline i_abs(int i) { return i < 0 ? -i : i; } - -main () -{ - int i; - int16_t p_to_a, p_to_a_to_p; - int16_t a_to_p, a_to_p_to_a; - int max_p_error = 0, max_p_error_p = -1; - int max_a_error = 0, max_a_error_a = -1; - int p_error; - int a_error; - int ret = 0; - - for (i = 0; i < 32767 + STEP; i += STEP) { - if (i > 32767) - i = 32767; - p_to_a = ao_pres_to_altitude(i); - p_to_a_to_p = ao_altitude_to_pres(p_to_a); - p_error = i_abs(p_to_a_to_p - i); - if (p_error > max_p_error) { - max_p_error = p_error; - max_p_error_p = i; - } -// printf ("pres %d alt %d pres %d\n", -// i, p_to_a, p_to_a_to_p); - } - for (i = -1578; i < 15835 + STEP; i += STEP) { - if (i > 15835) - i = 15835; - a_to_p = ao_altitude_to_pres(i); - a_to_p_to_a = ao_pres_to_altitude(a_to_p); - a_error = i_abs(a_to_p_to_a - i); - if (a_error > max_a_error) { - max_a_error = a_error; - max_a_error_a = i; - } -// printf ("alt %d pres %d alt %d\n", -// i, a_to_p, a_to_p_to_a); - } - if (max_p_error > 2) { - printf ("max p error %d at %d\n", max_p_error, - max_p_error_p); - ret++; - } - if (max_a_error > 1) { - printf ("max a error %d at %d\n", max_a_error, - max_a_error_a); - ret++; - } - return ret; -} diff --git a/src/ao_dbg.c b/src/ao_dbg.c deleted file mode 100644 index d4c9567f..00000000 --- a/src/ao_dbg.c +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "ao_pins.h" - -static void -ao_dbg_send_bits(uint8_t msk, uint8_t val) __reentrant -{ - DBG_PORT = (DBG_PORT & ~msk) | (val & msk); - _asm - nop - nop - _endasm; -} - -void -ao_dbg_send_byte(uint8_t byte) -{ - __pdata uint8_t b, d; - - DBG_PORT |= DBG_DATA; - DBG_PORT_DIR |= DBG_DATA; - for (b = 0; b < 8; b++) { - d = 0; - if (byte & 0x80) - d = DBG_DATA; - byte <<= 1; - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA, DBG_CLOCK|d); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA, 0 |d); - } - DBG_PORT_DIR &= ~DBG_DATA; -} - -uint8_t -ao_dbg_recv_byte(void) -{ - __pdata uint8_t byte, b; - - byte = 0; - for (b = 0; b < 8; b++) { - byte = byte << 1; - ao_dbg_send_bits(DBG_CLOCK, DBG_CLOCK); - if (DBG_DATA_PIN) - byte |= 1; - ao_dbg_send_bits(DBG_CLOCK, 0); - } - return byte; -} - -/* 8051 instructions - */ -#define NOP 0x00 -#define MOV_direct_data 0x75 -#define LJMP 0x02 -#define MOV_Rn_data(n) (0x78 | (n)) -#define DJNZ_Rn_rel(n) (0xd8 | (n)) -#define MOV_A_direct 0xe5 -#define MOV_direct1_direct2 0x85 -#define MOV_direct_A 0xf5 -#define MOV_DPTR_data16 0x90 -#define MOV_A_data 0x74 -#define MOVX_atDPTR_A 0xf0 -#define MOVX_A_atDPTR 0xe0 -#define INC_DPTR 0xa3 -#define TRAP 0xa5 -#define SJMP 0x80 -#define JB 0x20 - -#define DEBUG_INSTR(l) (0x54 | (l)) - -#define SFR_PSW 0xD0 -#define SFR_DPL0 0x82 -#define SFR_DPH0 0x83 -#define SFR_DPL1 0x84 -#define SFR_DPH1 0x85 - -__pdata uint8_t save_acc; -__pdata uint8_t save_psw; -__pdata uint8_t save_dpl0; -__pdata uint8_t save_dph0; -__pdata uint8_t save_dpl1; -__pdata uint8_t save_dph1; - -static uint8_t -ao_dbg_inst1(uint8_t a) __reentrant -{ - ao_dbg_send_byte(DEBUG_INSTR(1)); - ao_dbg_send_byte(a); - return ao_dbg_recv_byte(); -} - -static uint8_t -ao_dbg_inst2(uint8_t a, uint8_t b) __reentrant -{ - ao_dbg_send_byte(DEBUG_INSTR(2)); - ao_dbg_send_byte(a); - ao_dbg_send_byte(b); - return ao_dbg_recv_byte(); -} - -static uint8_t -ao_dbg_inst3(uint8_t a, uint8_t b, uint8_t c) __reentrant -{ - ao_dbg_send_byte(DEBUG_INSTR(3)); - ao_dbg_send_byte(a); - ao_dbg_send_byte(b); - ao_dbg_send_byte(c); - return ao_dbg_recv_byte(); -} - -void -ao_dbg_start_transfer(uint16_t addr) -{ - save_acc = ao_dbg_inst1(NOP); - save_psw = ao_dbg_inst2(MOV_A_direct, SFR_PSW); - save_dpl0 = ao_dbg_inst2(MOV_A_direct, SFR_DPL0); - save_dph0 = ao_dbg_inst2(MOV_A_direct, SFR_DPH0); - save_dpl1 = ao_dbg_inst2(MOV_A_direct, SFR_DPL1); - save_dph1 = ao_dbg_inst2(MOV_A_direct, SFR_DPH1); - ao_dbg_inst3(MOV_DPTR_data16, addr >> 8, addr); -} - -void -ao_dbg_end_transfer(void) -{ - ao_dbg_inst3(MOV_direct_data, SFR_DPL0, save_dpl0); - ao_dbg_inst3(MOV_direct_data, SFR_DPH0, save_dph0); - ao_dbg_inst3(MOV_direct_data, SFR_DPL1, save_dpl1); - ao_dbg_inst3(MOV_direct_data, SFR_DPH1, save_dph1); - ao_dbg_inst3(MOV_direct_data, SFR_PSW, save_psw); - ao_dbg_inst2(MOV_A_data, save_acc); -} - -void -ao_dbg_write_byte(uint8_t byte) -{ - ao_dbg_inst2(MOV_A_data, byte); - ao_dbg_inst1(MOVX_atDPTR_A); - ao_dbg_inst1(INC_DPTR); -} - -uint8_t -ao_dbg_read_byte(void) -{ - ao_dbg_inst1(MOVX_A_atDPTR); - return ao_dbg_inst1(INC_DPTR); -} - -static void -ao_dbg_set_pins(void) -{ - /* Make the DBG pins GPIOs. On TeleMetrum, this will - * disable the SPI link, so don't expect SPI to work after - * using the debugger. - */ - DBG_PORT_SEL &= ~(DBG_CLOCK|DBG_DATA|DBG_RESET_N); - - /* make DBG_DATA tri-state */ - DBG_PORT_INP |= DBG_DATA; - - /* Raise RESET_N and CLOCK */ - DBG_PORT |= DBG_RESET_N | DBG_CLOCK; - - /* RESET_N and CLOCK are outputs now */ - DBG_PORT_DIR |= DBG_RESET_N | DBG_CLOCK; - DBG_PORT_DIR &= ~DBG_DATA; -} - -static void -ao_dbg_long_delay(void) -{ - uint8_t n; - - for (n = 0; n < 20; n++) - _asm nop _endasm; -} - -#define AO_RESET_LOW_DELAY AO_MS_TO_TICKS(100) -#define AO_RESET_HIGH_DELAY AO_MS_TO_TICKS(100) - -void -ao_dbg_debug_mode(void) -{ - ao_dbg_set_pins(); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); - ao_delay(AO_RESET_LOW_DELAY); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA|DBG_RESET_N); - ao_delay(AO_RESET_HIGH_DELAY); -} - -void -ao_dbg_reset(void) -{ - ao_dbg_set_pins(); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_delay(AO_RESET_LOW_DELAY); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); - ao_dbg_long_delay(); - ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); - ao_delay(AO_RESET_HIGH_DELAY); -} - -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) -{ - __pdata uint16_t count; - __pdata uint16_t i; - __pdata 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) -{ - __pdata char 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) -{ - __pdata uint16_t count; - __pdata uint16_t addr; - __pdata uint8_t b; - __pdata 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) -{ - __pdata uint16_t count; - __pdata uint16_t addr; - __pdata 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] = { - { debug_enable, "D\0Enable debug" }, - { debug_get, "G \0Get data" }, - { debug_input, "I \0Input at " }, - { debug_output, "O \0Output at " }, - { debug_put, "P ...\0Put data" }, - { debug_reset, "R\0Reset" }, - { 0, NULL }, -}; - -void -ao_dbg_init(void) -{ - ao_cmd_register(&ao_dbg_cmds[0]); -} diff --git a/src/ao_dma.c b/src/ao_dma.c deleted file mode 100644 index 6052964a..00000000 --- a/src/ao_dma.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 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" - -#define NUM_DMA 5 - -/* - * The config address for DMA0 is programmed - * separately from that of DMA1-4, but for simplicity, - * we make them all contiguous. - */ - -static __xdata struct cc_dma_channel ao_dma_config[NUM_DMA]; -static __xdata uint8_t * __xdata ao_dma_done[NUM_DMA]; -static __data uint8_t ao_next_dma; - -uint8_t -ao_dma_alloc(__xdata uint8_t *done) -{ - uint8_t id; - - if (ao_next_dma == NUM_DMA) - ao_panic(AO_PANIC_DMA); - id = ao_next_dma++; - ao_dma_done[id] = done; - - /* When the first dma object is allocated, set up the DMA - * controller - */ - if (id == 0) { - DMAIRQ = 0; - DMAIF = 0; - IEN1 |= IEN1_DMAIE; - } - - return id; -} - -void -ao_dma_set_transfer(uint8_t id, - void __xdata *srcaddr, - void __xdata *dstaddr, - uint16_t count, - uint8_t cfg0, - uint8_t cfg1) -{ - if (DMAARM & (1 << id)) - ao_panic(AO_PANIC_DMA); - ao_dma_config[id].src_high = ((uint16_t) srcaddr) >> 8; - ao_dma_config[id].src_low = ((uint16_t) srcaddr); - ao_dma_config[id].dst_high = ((uint16_t) dstaddr) >> 8; - ao_dma_config[id].dst_low = ((uint16_t) dstaddr); - ao_dma_config[id].len_high = count >> 8; - ao_dma_config[id].len_low = count; - ao_dma_config[id].cfg0 = cfg0; - ao_dma_config[id].cfg1 = cfg1 | DMA_CFG1_IRQMASK; - if (id == 0) { - DMA0CFGH = ((uint16_t) (&ao_dma_config[0])) >> 8; - DMA0CFGL = ((uint16_t) (&ao_dma_config[0])); - } else { - DMA1CFGH = ((uint16_t) (&ao_dma_config[1])) >> 8; - DMA1CFGL = ((uint16_t) (&ao_dma_config[1])); - } -} - -#define nop() _asm nop _endasm; - -void -ao_dma_start(uint8_t id) -{ - uint8_t mask = (1 << id); - DMAIRQ &= ~mask; - 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(); -} - -void -ao_dma_trigger(uint8_t id) -{ - DMAREQ |= (1 << id); -} - -void -ao_dma_abort(uint8_t id) -{ - uint8_t mask = (1 << id); - DMAARM = 0x80 | mask; - DMAIRQ &= ~mask; -} - -void -ao_dma_isr(void) __interrupt 8 -{ - uint8_t id, mask; - - /* Find the first DMA channel which is done */ - mask = 1; - for (id = 0; id < ao_next_dma; id++) { - if (DMAIRQ & mask) { - /* Clear CPU interrupt flag */ - DMAIF = 0; - /* Clear the completed ID */ - DMAIRQ = ~mask; - *(ao_dma_done[id]) = 1; - ao_wakeup(ao_dma_done[id]); - break; - } - mask <<= 1; - } -} diff --git a/src/ao_ee.c b/src/ao_ee.c deleted file mode 100644 index a2fe8dc1..00000000 --- a/src/ao_ee.c +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "25lc1024.h" - -#define EE_BLOCK_SIZE ((uint16_t) (256)) -#define EE_BLOCK_SHIFT 8 -#define EE_DEVICE_SIZE ((uint32_t) 128 * (uint32_t) 1024) - -/* Total bytes of available storage */ -__pdata uint32_t ao_storage_total; - -/* Block size - device is erased in these units. At least 256 bytes */ -__pdata uint32_t ao_storage_block; - -/* Byte offset of config block. Will be ao_storage_block bytes long */ -__pdata uint32_t ao_storage_config; - -/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ -__pdata uint16_t ao_storage_unit; - -/* - * Using SPI on USART 0, with P1_2 as the chip select - */ - -#define EE_CS P1_2 -#define EE_CS_INDEX 2 - -static __xdata uint8_t ao_ee_mutex; - -#define ao_ee_delay() do { \ - _asm nop _endasm; \ - _asm nop _endasm; \ - _asm nop _endasm; \ -} while(0) - -#define ao_ee_cs_low() ao_spi_get_bit(EE_CS) - -#define ao_ee_cs_high() ao_spi_put_bit(EE_CS) - -struct ao_ee_instruction { - uint8_t instruction; - uint8_t address[3]; -} __xdata ao_ee_instruction; - -static void -ao_ee_write_enable(void) -{ - ao_ee_cs_low(); - ao_ee_instruction.instruction = EE_WREN; - ao_spi_send(&ao_ee_instruction, 1); - ao_ee_cs_high(); -} - -static uint8_t -ao_ee_rdsr(void) -{ - ao_ee_cs_low(); - ao_ee_instruction.instruction = EE_RDSR; - ao_spi_send(&ao_ee_instruction, 1); - ao_spi_recv(&ao_ee_instruction, 1); - ao_ee_cs_high(); - return ao_ee_instruction.instruction; -} - -static void -ao_ee_wrsr(uint8_t status) -{ - ao_ee_cs_low(); - ao_ee_instruction.instruction = EE_WRSR; - ao_ee_instruction.address[0] = status; - ao_spi_send(&ao_ee_instruction, 2); - ao_ee_cs_high(); -} - -#define EE_BLOCK_NONE 0xffff - -static __xdata uint8_t ao_ee_data[EE_BLOCK_SIZE]; -static __pdata uint16_t ao_ee_block = EE_BLOCK_NONE; -static __pdata uint8_t ao_ee_block_dirty; - -/* Write the current block to the EEPROM */ -static void -ao_ee_write_block(void) -{ - uint8_t status; - - status = ao_ee_rdsr(); - if (status & (EE_STATUS_BP0|EE_STATUS_BP1|EE_STATUS_WPEN)) { - status &= ~(EE_STATUS_BP0|EE_STATUS_BP1|EE_STATUS_WPEN); - ao_ee_wrsr(status); - } - ao_ee_write_enable(); - ao_ee_cs_low(); - ao_ee_instruction.instruction = EE_WRITE; - ao_ee_instruction.address[0] = ao_ee_block >> 8; - ao_ee_instruction.address[1] = ao_ee_block; - ao_ee_instruction.address[2] = 0; - ao_spi_send(&ao_ee_instruction, 4); - ao_spi_send(ao_ee_data, EE_BLOCK_SIZE); - ao_ee_cs_high(); - for (;;) { - uint8_t status = ao_ee_rdsr(); - if ((status & EE_STATUS_WIP) == 0) - break; - } -} - -/* Read the current block from the EEPROM */ -static void -ao_ee_read_block(void) -{ - ao_ee_cs_low(); - ao_ee_instruction.instruction = EE_READ; - ao_ee_instruction.address[0] = ao_ee_block >> 8; - ao_ee_instruction.address[1] = ao_ee_block; - ao_ee_instruction.address[2] = 0; - ao_spi_send(&ao_ee_instruction, 4); - ao_spi_recv(ao_ee_data, EE_BLOCK_SIZE); - ao_ee_cs_high(); -} - -static void -ao_ee_flush_internal(void) -{ - if (ao_ee_block_dirty) { - ao_ee_write_block(); - ao_ee_block_dirty = 0; - } -} - -static void -ao_ee_fill(uint16_t block) -{ - if (block != ao_ee_block) { - ao_ee_flush_internal(); - ao_ee_block = block; - ao_ee_read_block(); - } -} - -uint8_t -ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant -{ - uint16_t block = (uint16_t) (pos >> EE_BLOCK_SHIFT); - - /* Transfer the data */ - ao_mutex_get(&ao_ee_mutex); { - if (len != EE_BLOCK_SIZE) - ao_ee_fill(block); - else { - ao_ee_flush_internal(); - ao_ee_block = block; - } - memcpy(ao_ee_data + (uint16_t) (pos & 0xff), buf, len); - ao_ee_block_dirty = 1; - } ao_mutex_put(&ao_ee_mutex); - return 1; -} - -uint8_t -ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant -{ - uint16_t block = (uint16_t) (pos >> EE_BLOCK_SHIFT); - - /* Transfer the data */ - ao_mutex_get(&ao_ee_mutex); { - ao_ee_fill(block); - memcpy(buf, ao_ee_data + (uint16_t) (pos & 0xff), len); - } ao_mutex_put(&ao_ee_mutex); - return 1; -} - -void -ao_storage_flush(void) __reentrant -{ - ao_mutex_get(&ao_ee_mutex); { - ao_ee_flush_internal(); - } ao_mutex_put(&ao_ee_mutex); -} - -uint8_t -ao_storage_erase(uint32_t pos) __reentrant -{ - ao_mutex_get(&ao_ee_mutex); { - ao_ee_flush_internal(); - ao_ee_block = (uint16_t) (pos >> EE_BLOCK_SHIFT); - memset(ao_ee_data, 0xff, EE_BLOCK_SIZE); - ao_ee_block_dirty = 1; - } ao_mutex_put(&ao_ee_mutex); - return 1; -} - -static void -ee_store(void) __reentrant -{ -} - -void -ao_storage_setup(void) -{ - if (ao_storage_total == 0) { - ao_storage_total = EE_DEVICE_SIZE; - ao_storage_block = EE_BLOCK_SIZE; - ao_storage_config = EE_DEVICE_SIZE - EE_BLOCK_SIZE; - ao_storage_unit = EE_BLOCK_SIZE; - } -} - -void -ao_storage_device_info(void) __reentrant -{ -} - -/* - * To initialize the chip, set up the CS line and - * the SPI interface - */ -void -ao_storage_device_init(void) -{ - /* set up CS */ - EE_CS = 1; - P1DIR |= (1 << EE_CS_INDEX); - P1SEL &= ~(1 << EE_CS_INDEX); -} diff --git a/src/ao_ee_fake.c b/src/ao_ee_fake.c deleted file mode 100644 index b0c1d61e..00000000 --- a/src/ao_ee_fake.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * 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" - -/* - * For hardware without eeprom, the config code still - * wants to call these functions - */ -uint8_t -ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant -{ - (void) buf; - (void) len; - return 1; -} - -uint8_t -ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant -{ - memset(buf, '\0', len); - return 1; -} diff --git a/src/ao_flash.c b/src/ao_flash.c deleted file mode 100644 index bb40f6f7..00000000 --- a/src/ao_flash.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "at45db161d.h" - -/* Total bytes of available storage */ -__pdata uint32_t ao_storage_total; - -/* Block size - device is erased in these units. At least 256 bytes */ -__pdata uint32_t ao_storage_block; - -/* Byte offset of config block. Will be ao_storage_block bytes long */ -__pdata uint32_t ao_storage_config; - -/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ -__pdata uint16_t ao_storage_unit; - -#define FLASH_CS P1_1 -#define FLASH_CS_INDEX 1 - -#define FLASH_BLOCK_SIZE_MAX 512 - -__xdata uint8_t ao_flash_mutex; - -#define ao_flash_delay() do { \ - _asm nop _endasm; \ - _asm nop _endasm; \ - _asm nop _endasm; \ -} while(0) - -#define ao_flash_cs_low() ao_spi_get_bit(FLASH_CS) - -#define ao_flash_cs_high() ao_spi_put_bit(FLASH_CS) - -struct ao_flash_instruction { - uint8_t instruction; - uint8_t address[3]; -} __xdata ao_flash_instruction; - -static void -ao_flash_set_pagesize_512(void) -{ - ao_flash_cs_low(); - ao_flash_instruction.instruction = FLASH_SET_CONFIG; - ao_flash_instruction.address[0] = FLASH_SET_512_BYTE_0; - ao_flash_instruction.address[1] = FLASH_SET_512_BYTE_1; - ao_flash_instruction.address[2] = FLASH_SET_512_BYTE_2; - ao_spi_send(&ao_flash_instruction, 4); - ao_flash_cs_high(); -} - - -static uint8_t -ao_flash_read_status(void) -{ - ao_flash_cs_low(); - ao_flash_instruction.instruction = FLASH_READ_STATUS; - ao_spi_send(&ao_flash_instruction, 1); - ao_spi_recv(&ao_flash_instruction, 1); - ao_flash_cs_high(); - return ao_flash_instruction.instruction; -} - -#define FLASH_BLOCK_NONE 0xffff - -static __xdata uint8_t ao_flash_data[FLASH_BLOCK_SIZE_MAX]; -static __pdata uint16_t ao_flash_block = FLASH_BLOCK_NONE; -static __pdata uint8_t ao_flash_block_dirty; -static __pdata uint8_t ao_flash_write_pending; -static __pdata uint8_t ao_flash_setup_done; -static __pdata uint8_t ao_flash_block_shift; -static __pdata uint16_t ao_flash_block_size; -static __pdata uint16_t ao_flash_block_mask; - -void -ao_storage_setup(void) __reentrant -{ - uint8_t status; - - if (ao_flash_setup_done) - return; - - ao_mutex_get(&ao_flash_mutex); - if (ao_flash_setup_done) { - ao_mutex_put(&ao_flash_mutex); - return; - } - - /* On first use, check to see if the flash chip has - * been programmed to use 512 byte pages. If not, do so. - * And then, because the flash part must be power cycled - * for that change to take effect, panic. - */ - status = ao_flash_read_status(); - - if (!(status & FLASH_STATUS_PAGESIZE_512)) { - ao_flash_set_pagesize_512(); - ao_panic(AO_PANIC_FLASH); - } - - switch (status & 0x3c) { - - /* AT45DB321D */ - case 0x34: - ao_flash_block_shift = 9; - ao_storage_total = ((uint32_t) 4 * (uint32_t) 1024 * (uint32_t) 1024); - break; - - /* AT45DB161D */ - case 0x2c: - ao_flash_block_shift = 9; - ao_storage_total = ((uint32_t) 2 * (uint32_t) 1024 * (uint32_t) 1024); - break; - - /* AT45DB081D */ - case 0x24: - ao_flash_block_shift = 8; - ao_storage_total = ((uint32_t) 1024 * (uint32_t) 1024); - break; - - /* AT45DB041D */ - case 0x1c: - ao_flash_block_shift = 8; - ao_storage_total = ((uint32_t) 512 * (uint32_t) 1024); - break; - - /* AT45DB021D */ - case 0x14: - ao_flash_block_shift = 8; - ao_storage_total = ((uint32_t) 256 * (uint32_t) 1024); - break; - - /* AT45DB011D */ - case 0x0c: - ao_flash_block_shift = 8; - ao_storage_total = ((uint32_t) 128 * (uint32_t) 1024); - break; - - default: - ao_panic(AO_PANIC_FLASH); - } - ao_flash_block_size = 1 << ao_flash_block_shift; - ao_flash_block_mask = ao_flash_block_size - 1; - - ao_storage_block = ao_flash_block_size; - ao_storage_config = ao_storage_total - ao_storage_block; - ao_storage_unit = ao_flash_block_size; - - ao_flash_setup_done = 1; - ao_mutex_put(&ao_flash_mutex); -} - -static void -ao_flash_wait_write(void) -{ - if (ao_flash_write_pending) { - for (;;) { - uint8_t status = ao_flash_read_status(); - if ((status & FLASH_STATUS_RDY)) - break; - } - ao_flash_write_pending = 0; - } -} - -/* Write the current block to the FLASHPROM */ -static void -ao_flash_write_block(void) -{ - ao_flash_wait_write(); - ao_flash_cs_low(); - ao_flash_instruction.instruction = FLASH_WRITE; - - /* 13/14 block bits + 9/8 byte bits (always 0) */ - ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift); - ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); - ao_flash_instruction.address[2] = 0; - ao_spi_send(&ao_flash_instruction, 4); - ao_spi_send(ao_flash_data, ao_storage_block); - ao_flash_cs_high(); - ao_flash_write_pending = 1; -} - -/* Read the current block from the FLASHPROM */ -static void -ao_flash_read_block(void) -{ - ao_flash_wait_write(); - ao_flash_cs_low(); - ao_flash_instruction.instruction = FLASH_READ; - - /* 13/14 block bits + 9/8 byte bits (always 0) */ - ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift); - ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); - ao_flash_instruction.address[2] = 0; - ao_spi_send(&ao_flash_instruction, 4); - ao_spi_recv(ao_flash_data, ao_flash_block_size); - ao_flash_cs_high(); -} - -static void -ao_flash_flush_internal(void) -{ - if (ao_flash_block_dirty) { - ao_flash_write_block(); - ao_flash_block_dirty = 0; - } -} - -static void -ao_flash_fill(uint16_t block) -{ - if (block != ao_flash_block) { - ao_flash_flush_internal(); - ao_flash_block = block; - ao_flash_read_block(); - } -} - -uint8_t -ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant -{ - uint16_t block = (uint16_t) (pos >> ao_flash_block_shift); - - /* Transfer the data */ - ao_mutex_get(&ao_flash_mutex); { - if (len != ao_flash_block_size) - ao_flash_fill(block); - else { - ao_flash_flush_internal(); - ao_flash_block = block; - } - memcpy(ao_flash_data + (uint16_t) (pos & ao_flash_block_mask), - buf, - len); - ao_flash_block_dirty = 1; - } ao_mutex_put(&ao_flash_mutex); - return 1; -} - -uint8_t -ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant -{ - uint16_t block = (uint16_t) (pos >> ao_flash_block_shift); - - /* Transfer the data */ - ao_mutex_get(&ao_flash_mutex); { - ao_flash_fill(block); - memcpy(buf, - ao_flash_data + (uint16_t) (pos & ao_flash_block_mask), - len); - } ao_mutex_put(&ao_flash_mutex); - return 1; -} - -void -ao_storage_flush(void) __reentrant -{ - ao_mutex_get(&ao_flash_mutex); { - ao_flash_flush_internal(); - } ao_mutex_put(&ao_flash_mutex); -} - -uint8_t -ao_storage_erase(uint32_t pos) __reentrant -{ - ao_mutex_get(&ao_flash_mutex); { - ao_flash_flush_internal(); - ao_flash_block = (uint16_t) (pos >> ao_flash_block_shift); - memset(ao_flash_data, 0xff, ao_flash_block_size); - ao_flash_block_dirty = 1; - } ao_mutex_put(&ao_flash_mutex); - return 1; -} - -void -ao_storage_device_info(void) __reentrant -{ - uint8_t status; - - ao_storage_setup(); - ao_mutex_get(&ao_flash_mutex); { - status = ao_flash_read_status(); - printf ("Flash status: 0x%02x\n", status); - printf ("Flash block shift: %d\n", ao_flash_block_shift); - printf ("Flash block size: %d\n", ao_flash_block_size); - printf ("Flash block mask: %d\n", ao_flash_block_mask); - printf ("Flash device size: %ld\n", ao_storage_total); - } ao_mutex_put(&ao_flash_mutex); -} - -/* - * To initialize the chip, set up the CS line and - * the SPI interface - */ -void -ao_storage_device_init(void) -{ - /* set up CS */ - FLASH_CS = 1; - P1DIR |= (1 << FLASH_CS_INDEX); - P1SEL &= ~(1 << FLASH_CS_INDEX); -} diff --git a/src/ao_flight.c b/src/ao_flight.c deleted file mode 100644 index 85c1825b..00000000 --- a/src/ao_flight.c +++ /dev/null @@ -1,315 +0,0 @@ -/* - * 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. - */ - -#ifndef AO_FLIGHT_TEST -#include "ao.h" -#endif - -#ifndef HAS_ACCEL -#error Please define HAS_ACCEL -#endif - -#ifndef HAS_GPS -#error Please define HAS_GPS -#endif - -#ifndef HAS_USB -#error Please define HAS_USB -#endif - -/* Main flight thread. */ - -__pdata enum ao_flight_state ao_flight_state; /* current flight state */ -__pdata uint16_t ao_launch_tick; /* time of launch detect */ - -/* - * track min/max data over a long interval to detect - * resting - */ -__pdata uint16_t ao_interval_end; -__pdata int16_t ao_interval_min_height; -__pdata int16_t ao_interval_max_height; -__pdata uint8_t ao_flight_force_idle; - -/* We also have a clock, which can be used to sanity check things in - * case of other failures - */ - -#define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) - -/* Landing is detected by getting constant readings from both pressure and accelerometer - * for a fairly long time (AO_INTERVAL_TICKS) - */ -#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(10) - -#define abs(a) ((a) < 0 ? -(a) : (a)) - -void -ao_flight(void) -{ - ao_sample_init(); - ao_flight_state = ao_flight_startup; - for (;;) { - - /* - * Process ADC samples, just looping - * until the sensors are calibrated. - */ - if (!ao_sample()) - continue; - - switch (ao_flight_state) { - case ao_flight_startup: - - /* Check to see what mode we should go to. - * - Invalid mode if accel cal appears to be out - * - pad mode if we're upright, - * - idle mode otherwise - */ -#if HAS_ACCEL - if (ao_config.accel_plus_g == 0 || - ao_config.accel_minus_g == 0 || - ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || - ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) - { - /* Detected an accel value outside -1.5g to 1.5g - * (or uncalibrated values), so we go into invalid mode - */ - ao_flight_state = ao_flight_invalid; - - } else -#endif - if (!ao_flight_force_idle -#if HAS_ACCEL - && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP -#endif - ) - { - /* Set pad mode - we can fly! */ - ao_flight_state = ao_flight_pad; -#if HAS_USB - /* Disable the USB controller in flight mode - * to save power - */ - ao_usb_disable(); -#endif - - /* Disable packet mode in pad state */ - ao_packet_slave_stop(); - - /* Turn on telemetry system */ - ao_rdf_set(1); - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); - - /* signal successful initialization by turning off the LED */ - ao_led_off(AO_LED_RED); - } else { - /* Set idle mode */ - ao_flight_state = ao_flight_idle; - - /* signal successful initialization by turning off the LED */ - ao_led_off(AO_LED_RED); - } - /* wakeup threads due to state change */ - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - - break; - case ao_flight_pad: - - /* pad to boost: - * - * barometer: > 20m vertical motion - * OR - * accelerometer: > 2g AND velocity > 5m/s - * - * The accelerometer should always detect motion before - * the barometer, but we use both to make sure this - * transition is detected. If the device - * doesn't have an accelerometer, then ignore the - * speed and acceleration as they are quite noisy - * on the pad. - */ - if (ao_height > AO_M_TO_HEIGHT(20) -#if HAS_ACCEL - || (ao_accel > AO_MSS_TO_ACCEL(20) && - ao_speed > AO_MS_TO_SPEED(5)) -#endif - ) - { - ao_flight_state = ao_flight_boost; - ao_launch_tick = ao_sample_tick; - - /* start logging data */ - ao_log_start(); - - /* Increase telemetry rate */ - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); - - /* disable RDF beacon */ - ao_rdf_set(0); - -#if HAS_GPS - /* Record current GPS position by waking up GPS log tasks */ - ao_wakeup(&ao_gps_data); - ao_wakeup(&ao_gps_tracking_data); -#endif - - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; - case ao_flight_boost: - - /* boost to fast: - * - * accelerometer: start to fall at > 1/4 G - * OR - * time: boost for more than 15 seconds - * - * Detects motor burn out by the switch from acceleration to - * deceleration, or by waiting until the maximum burn duration - * (15 seconds) has past. - */ - if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || - (int16_t) (ao_sample_tick - ao_launch_tick) > BOOST_TICKS_MAX) - { -#if HAS_ACCEL - ao_flight_state = ao_flight_fast; -#else - ao_flight_state = ao_flight_coast; -#endif - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; -#if HAS_ACCEL - case ao_flight_fast: - /* - * This is essentially the same as coast, - * but the barometer is being ignored as - * it may be unreliable. - */ - if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) - { - ao_flight_state = ao_flight_coast; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; -#endif - case ao_flight_coast: - - /* apogee detect: coast to drogue deploy: - * - * speed: < 0 - * - * Also make sure the model altitude is tracking - * the measured altitude reasonably closely; otherwise - * we're probably transsonic. - */ - if (ao_speed < 0 -#if !HAS_ACCEL - && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) -#endif - ) - { - /* ignite the drogue charge */ - ao_ignite(ao_igniter_drogue); - - /* slow down the telemetry system */ - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); - - /* Turn the RDF beacon back on */ - ao_rdf_set(1); - - /* and enter drogue state */ - ao_flight_state = ao_flight_drogue; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - - break; - case ao_flight_drogue: - - /* drogue to main deploy: - * - * barometer: reach main deploy altitude - * - * Would like to use the accelerometer for this test, but - * the orientation of the flight computer is unknown after - * drogue deploy, so we ignore it. Could also detect - * high descent rate using the pressure sensor to - * recognize drogue deploy failure and eject the main - * at that point. Perhaps also use the drogue sense lines - * to notice continutity? - */ - if (ao_height <= ao_config.main_deploy) - { - ao_ignite(ao_igniter_main); - - /* - * Start recording min/max height - * to figure out when the rocket has landed - */ - - /* initialize interval values */ - ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; - - ao_interval_min_height = ao_interval_max_height = ao_avg_height; - - ao_flight_state = ao_flight_main; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; - - /* fall through... */ - case ao_flight_main: - - /* main to land: - * - * barometer: altitude stable - */ - - if (ao_avg_height < ao_interval_min_height) - ao_interval_min_height = ao_avg_height; - if (ao_avg_height > ao_interval_max_height) - ao_interval_max_height = ao_avg_height; - - if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { - if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4)) - { - ao_flight_state = ao_flight_landed; - - /* turn off the ADC capture */ - ao_timer_set_adc_interval(0); - - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - ao_interval_min_height = ao_interval_max_height = ao_avg_height; - ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; - } - break; - case ao_flight_landed: - break; - } - } -} - -static __xdata struct ao_task flight_task; - -void -ao_flight_init(void) -{ - ao_flight_state = ao_flight_startup; - ao_add_task(&flight_task, ao_flight, "flight"); -} diff --git a/src/ao_flight_nano.c b/src/ao_flight_nano.c deleted file mode 100644 index 2e332b12..00000000 --- a/src/ao_flight_nano.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -/* Main flight thread. */ - -__pdata enum ao_flight_state ao_flight_state; /* current flight state */ -__pdata uint16_t ao_launch_tick; /* time of launch detect */ - -/* - * track min/max data over a long interval to detect - * resting - */ -__pdata uint16_t ao_interval_end; -__pdata int16_t ao_interval_min_height; -__pdata int16_t ao_interval_max_height; - -__pdata uint8_t ao_flight_force_idle; - -/* Landing is detected by getting constant readings from both pressure and accelerometer - * for a fairly long time (AO_INTERVAL_TICKS) - */ -#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(5) - -static void -ao_flight_nano(void) -{ - ao_sample_init(); - ao_flight_state = ao_flight_startup; - - for (;;) { - /* - * Process ADC samples, just looping - * until the sensors are calibrated. - */ - if (!ao_sample()) - continue; - - switch (ao_flight_state) { - case ao_flight_startup: - if (ao_flight_force_idle) { - /* Set idle mode */ - ao_flight_state = ao_flight_idle; - } else { - ao_flight_state = ao_flight_pad; - /* Disable packet mode in pad state */ - ao_packet_slave_stop(); - - /* Turn on telemetry system */ - ao_rdf_set(1); - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); - } - /* signal successful initialization by turning off the LED */ - ao_led_off(AO_LED_RED); - - /* wakeup threads due to state change */ - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - break; - case ao_flight_pad: - if (ao_height> AO_M_TO_HEIGHT(20)) { - ao_flight_state = ao_flight_drogue; - ao_launch_tick = ao_sample_tick; - - /* start logging data */ - ao_log_start(); - - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; - case ao_flight_drogue: - /* drogue/main to land: - * - * barometer: altitude stable - */ - - if (ao_height < ao_interval_min_height) - ao_interval_min_height = ao_height; - if (ao_height > ao_interval_max_height) - ao_interval_max_height = ao_height; - - if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { - if (ao_interval_max_height - ao_interval_min_height < AO_M_TO_HEIGHT(5)) - { - ao_flight_state = ao_flight_landed; - - /* turn off the ADC capture */ - ao_timer_set_adc_interval(0); - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - ao_interval_min_height = ao_interval_max_height = ao_height; - ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; - } - break; - } - } -} - -static __xdata struct ao_task flight_task; - -void -ao_flight_nano_init(void) -{ - ao_flight_state = ao_flight_startup; - ao_add_task(&flight_task, ao_flight_nano, "flight"); -} diff --git a/src/ao_flight_test.c b/src/ao_flight_test.c deleted file mode 100644 index 56733c89..00000000 --- a/src/ao_flight_test.c +++ /dev/null @@ -1,716 +0,0 @@ -/* - * 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 _GNU_SOURCE - -#include -#include -#include -#include -#include -#include - -#define AO_HERTZ 100 - -#define AO_ADC_RING 64 -#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) -#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) - -#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) -#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) -#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) - -/* - * One set of samples read from the A/D converter - */ -struct ao_adc { - uint16_t tick; /* tick when the sample was read */ - int16_t accel; /* accelerometer */ - int16_t pres; /* pressure sensor */ - int16_t pres_real; /* unclipped */ - int16_t temp; /* temperature sensor */ - int16_t v_batt; /* battery voltage */ - int16_t sense_d; /* drogue continuity sense */ - int16_t sense_m; /* main continuity sense */ -}; - -#define __pdata -#define __data -#define __xdata -#define __code -#define __reentrant - -#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) -#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) -#define from_fix(x) ((x) >> 16) - -/* - * Above this height, the baro sensor doesn't work - */ -#define AO_MAX_BARO_HEIGHT 12000 -#define AO_BARO_SATURATE 13000 -#define AO_MIN_BARO_VALUE ao_altitude_to_pres(AO_BARO_SATURATE) - -/* - * Above this speed, baro measurements are unreliable - */ -#define AO_MAX_BARO_SPEED 200 - -#define ACCEL_NOSE_UP (ao_accel_2g >> 2) - -enum ao_flight_state { - ao_flight_startup = 0, - ao_flight_idle = 1, - ao_flight_pad = 2, - ao_flight_boost = 3, - ao_flight_fast = 4, - ao_flight_coast = 5, - ao_flight_drogue = 6, - ao_flight_main = 7, - ao_flight_landed = 8, - ao_flight_invalid = 9 -}; - -extern enum ao_flight_state ao_flight_state; - -#define FALSE 0 -#define TRUE 1 - -struct ao_adc ao_adc_ring[AO_ADC_RING]; -uint8_t ao_adc_head; -int ao_summary = 0; - -#define ao_led_on(l) -#define ao_led_off(l) -#define ao_timer_set_adc_interval(i) -#define ao_wakeup(wchan) ao_dump_state() -#define ao_cmd_register(c) -#define ao_usb_disable() -#define ao_telemetry_set_interval(x) -#define ao_rdf_set(rdf) -#define ao_packet_slave_start() -#define ao_packet_slave_stop() - -enum ao_igniter { - ao_igniter_drogue = 0, - ao_igniter_main = 1 -}; - -struct ao_adc ao_adc_static; - -int drogue_height; -double drogue_time; -int main_height; -double main_time; - -int tick_offset; - -static int32_t ao_k_height; - -void -ao_ignite(enum ao_igniter igniter) -{ - double time = (double) (ao_adc_static.tick + tick_offset) / 100; - - if (igniter == ao_igniter_drogue) { - drogue_time = time; - drogue_height = ao_k_height >> 16; - } else { - main_time = time; - main_height = ao_k_height >> 16; - } -} - -struct ao_task { - int dummy; -}; - -#define ao_add_task(t,f,n) - -#define ao_log_start() -#define ao_log_stop() - -#define AO_MS_TO_TICKS(ms) ((ms) / 10) -#define AO_SEC_TO_TICKS(s) ((s) * 100) - -#define AO_FLIGHT_TEST - -int ao_flight_debug; - -FILE *emulator_in; -char *emulator_app; -char *emulator_name; -double emulator_error_max = 4; -double emulator_height_error_max = 20; /* noise in the baro sensor */ - -void -ao_dump_state(void); - -void -ao_sleep(void *wchan); - -const char const * const ao_state_names[] = { - "startup", "idle", "pad", "boost", "fast", - "coast", "drogue", "main", "landed", "invalid" -}; - -struct ao_cmds { - void (*func)(void); - const char *help; -}; - -#include "ao_convert.c" - -struct ao_config { - uint16_t main_deploy; - int16_t accel_plus_g; - int16_t accel_minus_g; - uint8_t pad_orientation; -}; - -#define AO_PAD_ORIENTATION_ANTENNA_UP 0 -#define AO_PAD_ORIENTATION_ANTENNA_DOWN 1 - -#define ao_config_get() - -struct ao_config ao_config; - -#define DATA_TO_XDATA(x) (x) - -#define HAS_FLIGHT 1 -#define HAS_ADC 1 -#define HAS_USB 1 -#define HAS_GPS 1 -#ifndef HAS_ACCEL -#define HAS_ACCEL 1 -#define HAS_ACCEL_REF 0 -#endif - -#define GRAVITY 9.80665 -extern int16_t ao_ground_accel, ao_flight_accel; -extern int16_t ao_accel_2g; - -extern uint16_t ao_sample_tick; - -extern int16_t ao_sample_height; -extern int16_t ao_sample_accel; -extern int32_t ao_accel_scale; -extern int16_t ao_ground_height; -extern int16_t ao_sample_alt; - -int ao_sample_prev_tick; -uint16_t prev_tick; - -#include "ao_kalman.c" -#include "ao_sample.c" -#include "ao_flight.c" - -#define to_double(f) ((f) / 65536.0) - -static int ao_records_read = 0; -static int ao_eof_read = 0; -static int ao_flight_ground_accel; -static int ao_flight_started = 0; -static int ao_test_max_height; -static double ao_test_max_height_time; -static int ao_test_main_height; -static double ao_test_main_height_time; -static double ao_test_landed_time; -static double ao_test_landed_height; -static double ao_test_landed_time; -static int landed_set; -static double landed_time; -static double landed_height; - -void -ao_test_exit(void) -{ - double drogue_error; - double main_error; - double landed_error; - double landed_time_error; - - if (!ao_test_main_height_time) { - ao_test_main_height_time = ao_test_max_height_time; - ao_test_main_height = ao_test_max_height; - } - drogue_error = fabs(ao_test_max_height_time - drogue_time); - main_error = fabs(ao_test_main_height_time - main_time); - landed_error = fabs(ao_test_landed_height - landed_height); - landed_time_error = ao_test_landed_time - landed_time; - if (drogue_error > emulator_error_max || main_error > emulator_error_max || - landed_time_error > emulator_error_max || landed_error > emulator_height_error_max) { - printf ("%s %s\n", - emulator_app, emulator_name); - printf ("\tApogee error %g\n", drogue_error); - printf ("\tMain error %g\n", main_error); - printf ("\tLanded height error %g\n", landed_error); - printf ("\tLanded time error %g\n", landed_time_error); - printf ("\tActual: apogee: %d at %7.2f main: %d at %7.2f landed %7.2f at %7.2f\n", - ao_test_max_height, ao_test_max_height_time, - ao_test_main_height, ao_test_main_height_time, - ao_test_landed_height, ao_test_landed_time); - printf ("\tComputed: apogee: %d at %7.2f main: %d at %7.2f landed %7.2f at %7.2f\n", - drogue_height, drogue_time, main_height, main_time, - landed_height, landed_time); - exit (1); - } - exit(0); -} - -void -ao_insert(void) -{ - double time; - - ao_adc_ring[ao_adc_head] = ao_adc_static; - ao_adc_head = ao_adc_ring_next(ao_adc_head); - if (ao_flight_state != ao_flight_startup) { - double height = ao_pres_to_altitude(ao_adc_static.pres_real) - ao_ground_height; - double accel = ((ao_flight_ground_accel - ao_adc_static.accel) * GRAVITY * 2.0) / - (ao_config.accel_minus_g - ao_config.accel_plus_g); - - if (!tick_offset) - tick_offset = -ao_adc_static.tick; - if ((prev_tick - ao_adc_static.tick) > 0x400) - tick_offset += 65536; - prev_tick = ao_adc_static.tick; - time = (double) (ao_adc_static.tick + tick_offset) / 100; - - if (ao_test_max_height < height) { - ao_test_max_height = height; - ao_test_max_height_time = time; - ao_test_landed_height = height; - ao_test_landed_time = time; - } - if (height > ao_config.main_deploy) { - ao_test_main_height_time = time; - ao_test_main_height = height; - } - - if (ao_test_landed_height > height) { - ao_test_landed_height = height; - ao_test_landed_time = time; - } - - if (ao_flight_state == ao_flight_landed && !landed_set) { - landed_set = 1; - landed_time = time; - landed_height = height; - } - - if (!ao_summary) { - printf("%7.2f height %8.2f accel %8.3f state %-8.8s k_height %8.2f k_speed %8.3f k_accel %8.3f avg_height %5d drogue %4d main %4d error %5d\n", - time, - height, - accel, - ao_state_names[ao_flight_state], - ao_k_height / 65536.0, - ao_k_speed / 65536.0 / 16.0, - ao_k_accel / 65536.0 / 16.0, - ao_avg_height, - drogue_height, - main_height, - ao_error_h_sq_avg); - -// if (ao_flight_state == ao_flight_landed) -// ao_test_exit(); - } - } -} - -#define AO_MAX_CALLSIGN 8 -#define AO_MAX_VERSION 8 -#define AO_MAX_TELEMETRY 128 - -struct ao_telemetry_generic { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t payload[27]; /* 5 */ - /* 32 */ -}; - -#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 -#define AO_TELEMETRY_SENSOR_TELEMINI 0x02 -#define AO_TELEMETRY_SENSOR_TELENANO 0x03 - -struct ao_telemetry_sensor { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t state; /* 5 flight state */ - int16_t accel; /* 6 accelerometer (TM only) */ - int16_t pres; /* 8 pressure sensor */ - int16_t temp; /* 10 temperature sensor */ - int16_t v_batt; /* 12 battery voltage */ - int16_t sense_d; /* 14 drogue continuity sense (TM/Tm) */ - int16_t sense_m; /* 16 main continuity sense (TM/Tm) */ - - int16_t acceleration; /* 18 m/s² * 16 */ - int16_t speed; /* 20 m/s * 16 */ - int16_t height; /* 22 m */ - - int16_t ground_pres; /* 24 average pres on pad */ - int16_t ground_accel; /* 26 average accel on pad */ - int16_t accel_plus_g; /* 28 accel calibration at +1g */ - int16_t accel_minus_g; /* 30 accel calibration at -1g */ - /* 32 */ -}; - -#define AO_TELEMETRY_CONFIGURATION 0x04 - -struct ao_telemetry_configuration { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t device; /* 5 device type */ - uint16_t flight; /* 6 flight number */ - uint8_t config_major; /* 8 Config major version */ - uint8_t config_minor; /* 9 Config minor version */ - uint16_t apogee_delay; /* 10 Apogee deploy delay in seconds */ - uint16_t main_deploy; /* 12 Main deploy alt in meters */ - uint16_t flight_log_max; /* 14 Maximum flight log size in kB */ - char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ - char version[AO_MAX_VERSION]; /* 24 Software version */ - /* 32 */ -}; - -#define AO_TELEMETRY_LOCATION 0x05 - -#define AO_GPS_MODE_NOT_VALID 'N' -#define AO_GPS_MODE_AUTONOMOUS 'A' -#define AO_GPS_MODE_DIFFERENTIAL 'D' -#define AO_GPS_MODE_ESTIMATED 'E' -#define AO_GPS_MODE_MANUAL 'M' -#define AO_GPS_MODE_SIMULATED 'S' - -struct ao_telemetry_location { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t flags; /* 5 Number of sats and other flags */ - int16_t altitude; /* 6 GPS reported altitude (m) */ - int32_t latitude; /* 8 latitude (degrees * 10⁷) */ - int32_t longitude; /* 12 longitude (degrees * 10⁷) */ - uint8_t year; /* 16 (- 2000) */ - uint8_t month; /* 17 (1-12) */ - uint8_t day; /* 18 (1-31) */ - uint8_t hour; /* 19 (0-23) */ - uint8_t minute; /* 20 (0-59) */ - uint8_t second; /* 21 (0-59) */ - uint8_t pdop; /* 22 (m * 5) */ - uint8_t hdop; /* 23 (m * 5) */ - uint8_t vdop; /* 24 (m * 5) */ - uint8_t mode; /* 25 */ - uint16_t ground_speed; /* 26 cm/s */ - int16_t climb_rate; /* 28 cm/s */ - uint8_t course; /* 30 degrees / 2 */ - uint8_t unused[1]; /* 31 */ - /* 32 */ -}; - -#define AO_TELEMETRY_SATELLITE 0x06 - -struct ao_telemetry_satellite_info { - uint8_t svid; - uint8_t c_n_1; -}; - -struct ao_telemetry_satellite { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t channels; /* 5 number of reported sats */ - - struct ao_telemetry_satellite_info sats[12]; /* 6 */ - uint8_t unused[2]; /* 30 */ - /* 32 */ -}; - -union ao_telemetry_all { - struct ao_telemetry_generic generic; - struct ao_telemetry_sensor sensor; - struct ao_telemetry_configuration configuration; - struct ao_telemetry_location location; - struct ao_telemetry_satellite satellite; -}; - -uint16_t -uint16(uint8_t *bytes, int off) -{ - off++; - return (uint16_t) bytes[off] | (((uint16_t) bytes[off+1]) << 8); -} - -int16_t -int16(uint8_t *bytes, int off) -{ - return (int16_t) uint16(bytes, off); -} - -void -ao_sleep(void *wchan) -{ - if (wchan == &ao_adc_head) { - char type; - uint16_t tick; - uint16_t a, b; - int ret; - uint8_t bytes[1024]; - union ao_telemetry_all telem; - char line[1024]; - char *saveptr; - char *l; - char *words[64]; - int nword; - - for (;;) { - if (ao_records_read > 2 && ao_flight_state == ao_flight_startup) - { - ao_adc_static.accel = ao_flight_ground_accel; - ao_insert(); - return; - } - - if (!fgets(line, sizeof (line), emulator_in)) { - if (++ao_eof_read >= 1000) { - if (!ao_summary) - printf ("no more data, exiting simulation\n"); - ao_test_exit(); - } - ao_adc_static.tick += 10; - ao_insert(); - return; - } - l = line; - for (nword = 0; nword < 64; nword++) { - words[nword] = strtok_r(l, " \t\n", &saveptr); - l = NULL; - if (words[nword] == NULL) - break; - } - if (nword == 4) { - type = words[0][0]; - tick = strtoul(words[1], NULL, 16); - a = strtoul(words[2], NULL, 16); - b = strtoul(words[3], NULL, 16); - if (type == 'P') - type = 'A'; - } else if (nword >= 6 && strcmp(words[0], "Accel") == 0) { - ao_config.accel_plus_g = atoi(words[3]); - ao_config.accel_minus_g = atoi(words[5]); - } else if (nword >= 4 && strcmp(words[0], "Main") == 0) { - ao_config.main_deploy = atoi(words[2]); - } else if (nword >= 36 && strcmp(words[0], "CALL") == 0) { - tick = atoi(words[10]); - if (!ao_flight_started) { - type = 'F'; - a = atoi(words[26]); - ao_flight_started = 1; - } else { - type = 'A'; - a = atoi(words[12]); - b = atoi(words[14]); - } - } else if (nword == 3 && strcmp(words[0], "BARO") == 0) { - tick = strtol(words[1], NULL, 16); - a = 16384 - 328; - b = strtol(words[2], NULL, 10); - type = 'A'; - if (!ao_flight_started) { - ao_flight_ground_accel = 16384 - 328; - ao_config.accel_plus_g = 16384 - 328; - ao_config.accel_minus_g = 16384 + 328; - ao_flight_started = 1; - } - } else if (nword == 2 && strcmp(words[0], "TELEM") == 0) { - char *hex = words[1]; - char elt[3]; - int i, len; - uint8_t sum; - - len = strlen(hex); - if (len > sizeof (bytes) * 2) { - len = sizeof (bytes)*2; - hex[len] = '\0'; - } - for (i = 0; i < len; i += 2) { - elt[0] = hex[i]; - elt[1] = hex[i+1]; - elt[2] = '\0'; - bytes[i/2] = (uint8_t) strtol(elt, NULL, 16); - } - len = i/2; - if (bytes[0] != len - 2) { - printf ("bad length %d != %d\n", bytes[0], len - 2); - continue; - } - sum = 0x5a; - for (i = 1; i < len-1; i++) - sum += bytes[i]; - if (sum != bytes[len-1]) { - printf ("bad checksum\n"); - continue; - } - if ((bytes[len-2] & 0x80) == 0) { - continue; - } - if (len == 36) { - memcpy(&telem, bytes + 1, 32); - tick = telem.generic.tick; - switch (telem.generic.type) { - case AO_TELEMETRY_SENSOR_TELEMETRUM: - case AO_TELEMETRY_SENSOR_TELEMINI: - case AO_TELEMETRY_SENSOR_TELENANO: - if (!ao_flight_started) { - ao_flight_ground_accel = telem.sensor.ground_accel; - ao_config.accel_plus_g = telem.sensor.accel_plus_g; - ao_config.accel_minus_g = telem.sensor.accel_minus_g; - ao_flight_started = 1; - } - type = 'A'; - a = telem.sensor.accel; - b = telem.sensor.pres; - break; - } - } else if (len == 99) { - ao_flight_started = 1; - tick = uint16(bytes, 21); - ao_flight_ground_accel = int16(bytes, 7); - ao_config.accel_plus_g = int16(bytes, 17); - ao_config.accel_minus_g = int16(bytes, 19); - type = 'A'; - a = int16(bytes, 23); - b = int16(bytes, 25); - } else if (len == 98) { - ao_flight_started = 1; - tick = uint16(bytes, 20); - ao_flight_ground_accel = int16(bytes, 6); - ao_config.accel_plus_g = int16(bytes, 16); - ao_config.accel_minus_g = int16(bytes, 18); - type = 'A'; - a = int16(bytes, 22); - b = int16(bytes, 24); - } else { - printf("unknown len %d\n", len); - continue; - } - } - if (type != 'F' && !ao_flight_started) - continue; - - switch (type) { - case 'F': - ao_flight_ground_accel = a; - if (ao_config.accel_plus_g == 0) { - ao_config.accel_plus_g = a; - ao_config.accel_minus_g = a + 530; - } - if (ao_config.main_deploy == 0) - ao_config.main_deploy = 250; - ao_flight_started = 1; - break; - case 'S': - break; - case 'A': - ao_adc_static.tick = tick; - ao_adc_static.accel = a; - ao_adc_static.pres_real = b; - if (b < AO_MIN_BARO_VALUE) - b = AO_MIN_BARO_VALUE; - ao_adc_static.pres = b; - ao_records_read++; - ao_insert(); - return; - case 'T': - ao_adc_static.tick = tick; - ao_adc_static.temp = a; - ao_adc_static.v_batt = b; - break; - case 'D': - case 'G': - case 'N': - case 'W': - case 'H': - break; - } - } - - } -} -#define COUNTS_PER_G 264.8 - -void -ao_dump_state(void) -{ -} - -static const struct option options[] = { - { .name = "summary", .has_arg = 0, .val = 's' }, - { .name = "debug", .has_arg = 0, .val = 'd' }, - { 0, 0, 0, 0}, -}; - -void run_flight_fixed(char *name, FILE *f, int summary) -{ - emulator_name = name; - emulator_in = f; - ao_summary = summary; - ao_flight_init(); - ao_flight(); -} - -int -main (int argc, char **argv) -{ - int summary = 0; - int c; - int i; - -#if HAS_ACCEL - emulator_app="full"; -#else - emulator_app="baro"; -#endif - while ((c = getopt_long(argc, argv, "sd", options, NULL)) != -1) { - switch (c) { - case 's': - summary = 1; - break; - case 'd': - ao_flight_debug = 1; - break; - } - } - - if (optind == argc) - run_flight_fixed("", stdin, summary); - else - for (i = optind; i < argc; i++) { - FILE *f = fopen(argv[i], "r"); - if (!f) { - perror(argv[i]); - continue; - } - run_flight_fixed(argv[i], f, summary); - fclose(f); - } -} diff --git a/src/ao_gps_print.c b/src/ao_gps_print.c deleted file mode 100644 index fcdedd30..00000000 --- a/src/ao_gps_print.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * 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. - */ - -#ifndef AO_GPS_TEST -#include "ao.h" -#endif -#include "ao_telem.h" - -void -ao_gps_print(__xdata struct ao_gps_orig *gps_data) __reentrant -{ - char state; - - if (gps_data->flags & AO_GPS_VALID) - state = AO_TELEM_GPS_STATE_LOCKED; - else if (gps_data->flags & AO_GPS_RUNNING) - state = AO_TELEM_GPS_STATE_UNLOCKED; - else - state = AO_TELEM_GPS_STATE_ERROR; - printf(AO_TELEM_GPS_STATE " %c " - AO_TELEM_GPS_NUM_SAT " %d ", - state, - (gps_data->flags & AO_GPS_NUM_SAT_MASK) >> AO_GPS_NUM_SAT_SHIFT); - if (!(gps_data->flags & AO_GPS_VALID)) - return; - printf(AO_TELEM_GPS_LATITUDE " %ld " - AO_TELEM_GPS_LONGITUDE " %ld " - AO_TELEM_GPS_ALTITUDE " %d ", - gps_data->latitude, - gps_data->longitude, - gps_data->altitude); - - if (gps_data->flags & AO_GPS_DATE_VALID) - printf(AO_TELEM_GPS_YEAR " %d " - AO_TELEM_GPS_MONTH " %d " - AO_TELEM_GPS_DAY " %d ", - gps_data->year, - gps_data->month, - gps_data->day); - - printf(AO_TELEM_GPS_HOUR " %d " - AO_TELEM_GPS_MINUTE " %d " - AO_TELEM_GPS_SECOND " %d ", - gps_data->hour, - gps_data->minute, - gps_data->second); - - printf(AO_TELEM_GPS_HDOP " %d ", - gps_data->hdop * 2); - - if (gps_data->flags & AO_GPS_COURSE_VALID) { - printf(AO_TELEM_GPS_HERROR " %d " - AO_TELEM_GPS_VERROR " %d " - AO_TELEM_GPS_VERTICAL_SPEED " %d " - AO_TELEM_GPS_HORIZONTAL_SPEED " %d " - AO_TELEM_GPS_COURSE " %d ", - gps_data->h_error, - gps_data->v_error, - gps_data->climb_rate, - gps_data->ground_speed, - (int) gps_data->course * 2); - } -} - -void -ao_gps_tracking_print(__xdata struct ao_gps_tracking_orig *gps_tracking_data) __reentrant -{ - uint8_t c, n, v; - __xdata struct ao_gps_sat_orig *sat; - - n = gps_tracking_data->channels; - if (n == 0) - return; - - sat = gps_tracking_data->sats; - v = 0; - for (c = 0; c < n; c++) { - if (sat->svid) - v++; - sat++; - } - - printf (AO_TELEM_SAT_NUM " %d ", - v); - - sat = gps_tracking_data->sats; - v = 0; - for (c = 0; c < n; c++) { - if (sat->svid) { - printf (AO_TELEM_SAT_SVID "%d %d " - AO_TELEM_SAT_C_N_0 "%d %d ", - v, sat->svid, - v, sat->c_n_1); - v++; - } - sat++; - } -} diff --git a/src/ao_gps_report.c b/src/ao_gps_report.c deleted file mode 100644 index e57f8744..00000000 --- a/src/ao_gps_report.c +++ /dev/null @@ -1,99 +0,0 @@ -/* - * 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_report(void) -{ - static __xdata struct ao_log_record gps_log; - static __xdata struct ao_telemetry_location gps_data; - uint8_t date_reported = 0; - - for (;;) { - ao_sleep(&ao_gps_data); - ao_mutex_get(&ao_gps_mutex); - memcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); - ao_mutex_put(&ao_gps_mutex); - - if (!(gps_data.flags & AO_GPS_VALID)) - continue; - - gps_log.tick = ao_gps_tick; - gps_log.type = AO_LOG_GPS_TIME; - gps_log.u.gps_time.hour = gps_data.hour; - gps_log.u.gps_time.minute = gps_data.minute; - gps_log.u.gps_time.second = gps_data.second; - gps_log.u.gps_time.flags = gps_data.flags; - ao_log_data(&gps_log); - gps_log.type = AO_LOG_GPS_LAT; - gps_log.u.gps_latitude = gps_data.latitude; - ao_log_data(&gps_log); - gps_log.type = AO_LOG_GPS_LON; - gps_log.u.gps_longitude = gps_data.longitude; - ao_log_data(&gps_log); - gps_log.type = AO_LOG_GPS_ALT; - gps_log.u.gps_altitude.altitude = gps_data.altitude; - gps_log.u.gps_altitude.unused = 0xffff; - ao_log_data(&gps_log); - if (!date_reported && (gps_data.flags & AO_GPS_DATE_VALID)) { - gps_log.type = AO_LOG_GPS_DATE; - gps_log.u.gps_date.year = gps_data.year; - gps_log.u.gps_date.month = gps_data.month; - gps_log.u.gps_date.day = gps_data.day; - gps_log.u.gps_date.extra = 0; - date_reported = ao_log_data(&gps_log); - } - } -} - -void -ao_gps_tracking_report(void) -{ - static __xdata struct ao_log_record gps_log; - static __xdata struct ao_telemetry_satellite gps_tracking_data; - uint8_t c, n; - - for (;;) { - ao_sleep(&ao_gps_tracking_data); - ao_mutex_get(&ao_gps_mutex); - gps_log.tick = ao_gps_tick; - memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); - ao_mutex_put(&ao_gps_mutex); - - if (!(n = gps_tracking_data.channels)) - continue; - - gps_log.type = AO_LOG_GPS_SAT; - for (c = 0; c < n; c++) - if ((gps_log.u.gps_sat.svid = gps_tracking_data.sats[c].svid)) - { - gps_log.u.gps_sat.c_n = gps_tracking_data.sats[c].c_n_1; - ao_log_data(&gps_log); - } - } -} - -__xdata struct ao_task ao_gps_report_task; -__xdata struct ao_task ao_gps_tracking_report_task; - -void -ao_gps_report_init(void) -{ - ao_add_task(&ao_gps_report_task, ao_gps_report, "gps_report"); - ao_add_task(&ao_gps_tracking_report_task, ao_gps_tracking_report, "gps_tracking_report"); -} diff --git a/src/ao_gps_sirf.c b/src/ao_gps_sirf.c deleted file mode 100644 index f2abbf84..00000000 --- a/src/ao_gps_sirf.c +++ /dev/null @@ -1,442 +0,0 @@ -/* - * 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. - */ - -#ifndef AO_GPS_TEST -#include "ao.h" -#endif - -__xdata uint8_t ao_gps_mutex; -__pdata uint16_t ao_gps_tick; -__xdata struct ao_telemetry_location ao_gps_data; -__xdata struct ao_telemetry_satellite ao_gps_tracking_data; - -static const char ao_gps_set_nmea[] = "\r\n$PSRF100,0,57600,8,1,0*37\r\n"; - -const char ao_gps_config[] = { - - 0xa0, 0xa2, 0x00, 0x0e, /* length: 14 bytes */ - 136, /* mode control */ - 0, 0, /* reserved */ - 0, /* degraded mode (allow 1-SV navigation) */ - 0, 0, /* reserved */ - 0, 0, /* user specified altitude */ - 2, /* alt hold mode (disabled, require 3d fixes) */ - 0, /* alt hold source (use last computed altitude) */ - 0, /* reserved */ - 10, /* Degraded time out (10 sec) */ - 10, /* Dead Reckoning time out (10 sec) */ - 0, /* Track smoothing (disabled) */ - 0x00, 0x8e, 0xb0, 0xb3, - - 0xa0, 0xa2, 0x00, 0x08, /* length: 8 bytes */ - 166, /* Set message rate */ - 2, /* enable/disable all messages */ - 0, /* message id (ignored) */ - 0, /* update rate (0 = disable) */ - 0, 0, 0, 0, /* reserved */ - 0x00, 0xa8, 0xb0, 0xb3, - - 0xa0, 0xa2, 0x00, 0x02, /* length: 2 bytes */ - 143, /* static navigation */ - 0, /* disable */ - 0x00, 0x8f, 0xb0, 0xb3, -}; - -#define NAV_TYPE_GPS_FIX_TYPE_MASK (7 << 0) -#define NAV_TYPE_NO_FIX (0 << 0) -#define NAV_TYPE_SV_KF (1 << 0) -#define NAV_TYPE_2_SV_KF (2 << 0) -#define NAV_TYPE_3_SV_KF (3 << 0) -#define NAV_TYPE_4_SV_KF (4 << 0) -#define NAV_TYPE_2D_LEAST_SQUARES (5 << 0) -#define NAV_TYPE_3D_LEAST_SQUARES (6 << 0) -#define NAV_TYPE_DR (7 << 0) -#define NAV_TYPE_TRICKLE_POWER (1 << 3) -#define NAV_TYPE_ALTITUDE_HOLD_MASK (3 << 4) -#define NAV_TYPE_ALTITUDE_HOLD_NONE (0 << 4) -#define NAV_TYPE_ALTITUDE_HOLD_KF (1 << 4) -#define NAV_TYPE_ALTITUDE_HOLD_USER (2 << 4) -#define NAV_TYPE_ALTITUDE_HOLD_ALWAYS (3 << 4) -#define NAV_TYPE_DOP_LIMIT_EXCEEDED (1 << 6) -#define NAV_TYPE_DGPS_APPLIED (1 << 7) -#define NAV_TYPE_SENSOR_DR (1 << 8) -#define NAV_TYPE_OVERDETERMINED (1 << 9) -#define NAV_TYPE_DR_TIMEOUT_EXCEEDED (1 << 10) -#define NAV_TYPE_FIX_MI_EDIT (1 << 11) -#define NAV_TYPE_INVALID_VELOCITY (1 << 12) -#define NAV_TYPE_ALTITUDE_HOLD_DISABLED (1 << 13) -#define NAV_TYPE_DR_ERROR_STATUS_MASK (3 << 14) -#define NAV_TYPE_DR_ERROR_STATUS_GPS_ONLY (0 << 14) -#define NAV_TYPE_DR_ERROR_STATUS_DR_FROM_GPS (1 << 14) -#define NAV_TYPE_DR_ERROR_STATUS_DR_SENSOR_ERROR (2 << 14) -#define NAV_TYPE_DR_ERROR_STATUS_DR_IN_TEST (3 << 14) - -struct sirf_geodetic_nav_data { - uint16_t nav_type; - uint16_t utc_year; - uint8_t utc_month; - uint8_t utc_day; - uint8_t utc_hour; - uint8_t utc_minute; - uint16_t utc_second; - int32_t lat; - int32_t lon; - int32_t alt_msl; - uint16_t ground_speed; - uint16_t course; - int16_t climb_rate; - uint32_t h_error; - uint32_t v_error; - uint8_t num_sv; - uint8_t hdop; -}; - -static __xdata struct sirf_geodetic_nav_data ao_sirf_data; - -struct sirf_measured_sat_data { - uint8_t svid; - uint8_t c_n_1; -}; - -struct sirf_measured_tracker_data { - int16_t gps_week; - uint32_t gps_tow; - uint8_t channels; - struct sirf_measured_sat_data sats[12]; -}; - -static __xdata struct sirf_measured_tracker_data ao_sirf_tracker_data; - -static __pdata uint16_t ao_sirf_cksum; -static __pdata uint16_t ao_sirf_len; - -#define ao_sirf_byte() ((uint8_t) ao_serial_getchar()) - -static uint8_t data_byte(void) -{ - uint8_t c = ao_sirf_byte(); - --ao_sirf_len; - ao_sirf_cksum += c; - return c; -} - -static char __xdata *sirf_target; - -static void sirf_u16(uint8_t offset) -{ - uint16_t __xdata *ptr = (uint16_t __xdata *) (sirf_target + offset); - uint16_t val; - - val = data_byte() << 8; - val |= data_byte (); - *ptr = val; -} - -static void sirf_u8(uint8_t offset) -{ - uint8_t __xdata *ptr = (uint8_t __xdata *) (sirf_target + offset); - uint8_t val; - - val = data_byte (); - *ptr = val; -} - -static void sirf_u32(uint8_t offset) __reentrant -{ - uint32_t __xdata *ptr = (uint32_t __xdata *) (sirf_target + offset); - uint32_t val; - - val = ((uint32_t) data_byte ()) << 24; - val |= ((uint32_t) data_byte ()) << 16; - val |= ((uint32_t) data_byte ()) << 8; - val |= ((uint32_t) data_byte ()); - *ptr = val; -} - -static void sirf_discard(uint8_t len) -{ - while (len--) - data_byte(); -} - -#define SIRF_END 0 -#define SIRF_DISCARD 1 -#define SIRF_U8 2 -#define SIRF_U16 3 -#define SIRF_U32 4 -#define SIRF_U8X10 5 - -struct sirf_packet_parse { - uint8_t type; - uint8_t offset; -}; - -static void -ao_sirf_parse(void __xdata *target, const struct sirf_packet_parse *parse) __reentrant -{ - uint8_t i, offset, j; - - sirf_target = target; - for (i = 0; ; i++) { - offset = parse[i].offset; - switch (parse[i].type) { - case SIRF_END: - return; - case SIRF_DISCARD: - sirf_discard(offset); - break; - case SIRF_U8: - sirf_u8(offset); - break; - case SIRF_U16: - sirf_u16(offset); - break; - case SIRF_U32: - sirf_u32(offset); - break; - case SIRF_U8X10: - for (j = 10; j--;) - sirf_u8(offset++); - break; - } - } -} - -static const struct sirf_packet_parse geodetic_nav_data_packet[] = { - { SIRF_DISCARD, 2 }, /* 1 nav valid */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, nav_type) }, /* 3 */ - { SIRF_DISCARD, 6 }, /* 5 week number, time of week */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, utc_year) }, /* 11 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_month) }, /* 13 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_day) }, /* 14 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_hour) }, /* 15 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_minute) }, /* 16 */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, utc_second) }, /* 17 */ - { SIRF_DISCARD, 4 }, /* satellite id list */ /* 19 */ - { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, lat) }, /* 23 */ - { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, lon) }, /* 27 */ - { SIRF_DISCARD, 4 }, /* altitude from ellipsoid */ /* 31 */ - { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, alt_msl) }, /* 35 */ - { SIRF_DISCARD, 1 }, /* map datum */ /* 39 */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, ground_speed) }, /* 40 */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, course) }, /* 42 */ - { SIRF_DISCARD, 2 }, /* magnetic variation */ /* 44 */ - { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, climb_rate) }, /* 46 */ - { SIRF_DISCARD, 2 }, /* turn rate */ /* 48 */ - { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, h_error) }, /* 50 */ - { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, v_error) }, /* 54 */ - { SIRF_DISCARD, 30 }, /* time error, h_vel error, clock_bias, - clock bias error, clock drift, - clock drift error, distance, - distance error, heading error */ /* 58 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, num_sv) }, /* 88 */ - { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, hdop) }, /* 89 */ - { SIRF_DISCARD, 1 }, /* additional mode info */ /* 90 */ - { SIRF_END, 0 }, /* 91 */ -}; - -static void -ao_sirf_parse_41(void) __reentrant -{ - ao_sirf_parse(&ao_sirf_data, geodetic_nav_data_packet); -} - -static const struct sirf_packet_parse measured_tracker_data_packet[] = { - { SIRF_U16, offsetof (struct sirf_measured_tracker_data, gps_week) }, /* 1 week */ - { SIRF_U32, offsetof (struct sirf_measured_tracker_data, gps_tow) }, /* 3 time of week */ - { SIRF_U8, offsetof (struct sirf_measured_tracker_data, channels) }, /* 7 channels */ - { SIRF_END, 0 }, -}; - -static const struct sirf_packet_parse measured_sat_data_packet[] = { - { SIRF_U8, offsetof (struct sirf_measured_sat_data, svid) }, /* 0 SV id */ - { SIRF_DISCARD, 4 }, /* 1 azimuth, 2 elevation, 3 state */ - { SIRF_U8, offsetof (struct sirf_measured_sat_data, c_n_1) }, /* C/N0 1 */ - { SIRF_DISCARD, 9 }, /* C/N0 2-10 */ - { SIRF_END, 0 }, -}; - -static void -ao_sirf_parse_4(void) __reentrant -{ - uint8_t i; - ao_sirf_parse(&ao_sirf_tracker_data, measured_tracker_data_packet); - for (i = 0; i < 12; i++) - ao_sirf_parse(&ao_sirf_tracker_data.sats[i], measured_sat_data_packet); -} - -static void -ao_gps_setup(void) __reentrant -{ - uint8_t i, k; - ao_serial_set_speed(AO_SERIAL_SPEED_4800); - for (i = 0; i < 64; i++) - ao_serial_putchar(0x00); - for (k = 0; k < 3; k++) - for (i = 0; i < sizeof (ao_gps_set_nmea); i++) - ao_serial_putchar(ao_gps_set_nmea[i]); - ao_serial_set_speed(AO_SERIAL_SPEED_57600); - for (i = 0; i < 64; i++) - ao_serial_putchar(0x00); -} - -static const char ao_gps_set_message_rate[] = { - 0xa0, 0xa2, 0x00, 0x08, - 166, - 0, -}; - -void -ao_sirf_set_message_rate(uint8_t msg, uint8_t rate) __reentrant -{ - uint16_t cksum = 0x00a6; - uint8_t i; - - for (i = 0; i < sizeof (ao_gps_set_message_rate); i++) - ao_serial_putchar(ao_gps_set_message_rate[i]); - ao_serial_putchar(msg); - ao_serial_putchar(rate); - cksum = 0xa6 + msg + rate; - for (i = 0; i < 4; i++) - ao_serial_putchar(0); - ao_serial_putchar((cksum >> 8) & 0x7f); - ao_serial_putchar(cksum & 0xff); - ao_serial_putchar(0xb0); - ao_serial_putchar(0xb3); -} - -static const uint8_t sirf_disable[] = { - 2, - 9, - 10, - 27, - 50, - 52, -}; - -void -ao_gps(void) __reentrant -{ - uint8_t i, k; - uint16_t cksum; - - ao_gps_setup(); - for (k = 0; k < 5; k++) - { - for (i = 0; i < sizeof (ao_gps_config); i++) - ao_serial_putchar(ao_gps_config[i]); - for (i = 0; i < sizeof (sirf_disable); i++) - ao_sirf_set_message_rate(sirf_disable[i], 0); - ao_sirf_set_message_rate(41, 1); - ao_sirf_set_message_rate(4, 1); - } - for (;;) { - /* Locate the begining of the next record */ - while (ao_sirf_byte() != (uint8_t) 0xa0) - ; - if (ao_sirf_byte() != (uint8_t) 0xa2) - continue; - - /* Length */ - ao_sirf_len = ao_sirf_byte() << 8; - ao_sirf_len |= ao_sirf_byte(); - if (ao_sirf_len > 1023) - continue; - - ao_sirf_cksum = 0; - - /* message ID */ - i = data_byte (); /* 0 */ - - switch (i) { - case 41: - if (ao_sirf_len < 90) - break; - ao_sirf_parse_41(); - break; - case 4: - if (ao_sirf_len < 187) - break; - ao_sirf_parse_4(); - break; - } - if (ao_sirf_len != 0) - continue; - - /* verify checksum and end sequence */ - ao_sirf_cksum &= 0x7fff; - cksum = ao_sirf_byte() << 8; - cksum |= ao_sirf_byte(); - if (ao_sirf_cksum != cksum) - continue; - if (ao_sirf_byte() != (uint8_t) 0xb0) - continue; - if (ao_sirf_byte() != (uint8_t) 0xb3) - continue; - - switch (i) { - case 41: - ao_mutex_get(&ao_gps_mutex); - ao_gps_tick = ao_time(); - ao_gps_data.hour = ao_sirf_data.utc_hour; - ao_gps_data.minute = ao_sirf_data.utc_minute; - ao_gps_data.second = ao_sirf_data.utc_second / 1000; - ao_gps_data.flags = ((ao_sirf_data.num_sv << AO_GPS_NUM_SAT_SHIFT) & AO_GPS_NUM_SAT_MASK) | AO_GPS_RUNNING; - if ((ao_sirf_data.nav_type & NAV_TYPE_GPS_FIX_TYPE_MASK) >= NAV_TYPE_4_SV_KF) - ao_gps_data.flags |= AO_GPS_VALID; - ao_gps_data.latitude = ao_sirf_data.lat; - ao_gps_data.longitude = ao_sirf_data.lon; - ao_gps_data.altitude = ao_sirf_data.alt_msl / 100; - ao_gps_data.ground_speed = ao_sirf_data.ground_speed; - ao_gps_data.course = ao_sirf_data.course / 200; - ao_gps_data.hdop = ao_sirf_data.hdop; - ao_gps_data.climb_rate = ao_sirf_data.climb_rate; - ao_gps_data.flags |= AO_GPS_COURSE_VALID; -#if 0 - if (ao_sirf_data.h_error > 6553500) - ao_gps_data.h_error = 65535; - else - ao_gps_data.h_error = ao_sirf_data.h_error / 100; - if (ao_sirf_data.v_error > 6553500) - ao_gps_data.v_error = 65535; - else - ao_gps_data.v_error = ao_sirf_data.v_error / 100; -#endif - ao_mutex_put(&ao_gps_mutex); - ao_wakeup(&ao_gps_data); - break; - case 4: - ao_mutex_get(&ao_gps_mutex); - ao_gps_tracking_data.channels = ao_sirf_tracker_data.channels; - for (i = 0; i < 12; i++) { - ao_gps_tracking_data.sats[i].svid = ao_sirf_tracker_data.sats[i].svid; - ao_gps_tracking_data.sats[i].c_n_1 = ao_sirf_tracker_data.sats[i].c_n_1; - } - ao_mutex_put(&ao_gps_mutex); - ao_wakeup(&ao_gps_tracking_data); - break; - } - } -} - -__xdata struct ao_task ao_gps_task; - -void -ao_gps_init(void) -{ - ao_add_task(&ao_gps_task, ao_gps, "gps"); -} diff --git a/src/ao_gps_skytraq.c b/src/ao_gps_skytraq.c deleted file mode 100644 index 7ac26946..00000000 --- a/src/ao_gps_skytraq.c +++ /dev/null @@ -1,490 +0,0 @@ -/* - * 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. - */ - -#ifndef AO_GPS_TEST -#include "ao.h" -#endif - -#define AO_GPS_LEADER 2 - -static __code char ao_gps_header[] = "GP"; - -__xdata uint8_t ao_gps_mutex; -static __data char ao_gps_char; -static __pdata uint8_t ao_gps_cksum; -static __pdata uint8_t ao_gps_error; - -__pdata uint16_t ao_gps_tick; -__xdata struct ao_telemetry_location ao_gps_data; -__xdata struct ao_telemetry_satellite ao_gps_tracking_data; - -static __pdata uint16_t ao_gps_next_tick; -static __xdata struct ao_telemetry_location ao_gps_next; -static __pdata uint8_t ao_gps_date_flags; -static __xdata struct ao_telemetry_satellite ao_gps_tracking_next; - -#define STQ_S 0xa0, 0xa1 -#define STQ_E 0x0d, 0x0a -#define SKYTRAQ_MSG_2(id,a,b) \ - STQ_S, 0, 3, id, a,b, (id^a^b), STQ_E -#define SKYTRAQ_MSG_3(id,a,b,c) \ - STQ_S, 0, 4, id, a,b,c, (id^a^b^c), STQ_E -#define SKYTRAQ_MSG_8(id,a,b,c,d,e,f,g,h) \ - STQ_S, 0, 9, id, a,b,c,d,e,f,g,h, (id^a^b^c^d^e^f^g^h), STQ_E -#define SKYTRAQ_MSG_14(id,a,b,c,d,e,f,g,h,i,j,k,l,m,n) \ - STQ_S, 0,15, id, a,b,c,d,e,f,g,h,i,j,k,l,m,n, \ - (id^a^b^c^d^e^f^g^h^i^j^k^l^m^n), STQ_E - -static __code uint8_t ao_gps_config[] = { - SKYTRAQ_MSG_8(0x08, 1, 1, 1, 1, 1, 1, 1, 0), /* configure nmea */ - /* gga interval */ - /* gsa interval */ - /* gsv interval */ - /* gll interval */ - /* rmc interval */ - /* vtg interval */ - /* zda interval */ - /* attributes (0 = update to sram, 1 = update flash too) */ - - SKYTRAQ_MSG_2(0x3c, 0x00, 0x00), /* configure navigation mode */ - /* 0 = car, 1 = pedestrian */ - /* 0 = update to sram, 1 = update sram + flash */ -}; - -static void -ao_gps_lexchar(void) -{ - if (ao_gps_error) - ao_gps_char = '\n'; - else - ao_gps_char = ao_serial_getchar(); - ao_gps_cksum ^= ao_gps_char; -} - -void -ao_gps_skip_field(void) -{ - while (ao_gps_char != ',' && ao_gps_char != '*' && ao_gps_char != '\n') - ao_gps_lexchar(); -} - -void -ao_gps_skip_sep(void) -{ - if (ao_gps_char == ',' || ao_gps_char == '.' || ao_gps_char == '*') - ao_gps_lexchar(); -} - -__pdata static uint8_t ao_gps_num_width; - -static int16_t -ao_gps_decimal(uint8_t max_width) -{ - int16_t v; - __pdata uint8_t neg = 0; - - ao_gps_skip_sep(); - if (ao_gps_char == '-') { - neg = 1; - ao_gps_lexchar(); - } - v = 0; - ao_gps_num_width = 0; - while (ao_gps_num_width < max_width) { - if (ao_gps_char < '0' || '9' < ao_gps_char) - break; - v = v * (int16_t) 10 + ao_gps_char - '0'; - ao_gps_num_width++; - ao_gps_lexchar(); - } - if (neg) - v = -v; - return v; -} - -static uint8_t -ao_gps_hex(uint8_t max_width) -{ - uint8_t v, d; - - ao_gps_skip_sep(); - v = 0; - ao_gps_num_width = 0; - while (ao_gps_num_width < max_width) { - if ('0' <= ao_gps_char && ao_gps_char <= '9') - d = ao_gps_char - '0'; - else if ('A' <= ao_gps_char && ao_gps_char <= 'F') - d = ao_gps_char - 'A' + 10; - else if ('a' <= ao_gps_char && ao_gps_char <= 'f') - d = ao_gps_char - 'a' + 10; - else - break; - v = (v << 4) | d; - ao_gps_num_width++; - ao_gps_lexchar(); - } - return v; -} - -static int32_t -ao_gps_parse_pos(uint8_t deg_width) __reentrant -{ - int32_t d; - int32_t m; - int32_t f; - - d = ao_gps_decimal(deg_width); - m = ao_gps_decimal(2); - if (ao_gps_char == '.') { - f = ao_gps_decimal(4); - while (ao_gps_num_width < 4) { - f *= 10; - ao_gps_num_width++; - } - } else { - f = 0; - if (ao_gps_char != ',') - ao_gps_error = 1; - } - d = d * 10000000l; - m = m * 10000l + f; - d = d + m * 50 / 3; - return d; -} - -static uint8_t -ao_gps_parse_flag(char no_c, char yes_c) __reentrant -{ - uint8_t ret = 0; - ao_gps_skip_sep(); - if (ao_gps_char == yes_c) - ret = 1; - else if (ao_gps_char == no_c) - ret = 0; - else - ao_gps_error = 1; - ao_gps_lexchar(); - return ret; -} - -static void -ao_nmea_gga() -{ - uint8_t i; - - /* Now read the data into the gps data record - * - * $GPGGA,025149.000,4528.1723,N,12244.2480,W,1,05,2.0,103.5,M,-19.5,M,,0000*66 - * - * Essential fix data - * - * 025149.000 time (02:51:49.000 GMT) - * 4528.1723,N Latitude 45°28.1723' N - * 12244.2480,W Longitude 122°44.2480' W - * 1 Fix quality: - * 0 = invalid - * 1 = GPS fix (SPS) - * 2 = DGPS fix - * 3 = PPS fix - * 4 = Real Time Kinematic - * 5 = Float RTK - * 6 = estimated (dead reckoning) - * 7 = Manual input mode - * 8 = Simulation mode - * 05 Number of satellites (5) - * 2.0 Horizontal dilution - * 103.5,M Altitude, 103.5M above msl - * -19.5,M Height of geoid above WGS84 ellipsoid - * ? time in seconds since last DGPS update - * 0000 DGPS station ID - * *66 checksum - */ - - ao_gps_next_tick = ao_time(); - ao_gps_next.flags = AO_GPS_RUNNING | ao_gps_date_flags; - ao_gps_next.hour = ao_gps_decimal(2); - ao_gps_next.minute = ao_gps_decimal(2); - ao_gps_next.second = ao_gps_decimal(2); - ao_gps_skip_field(); /* skip seconds fraction */ - - ao_gps_next.latitude = ao_gps_parse_pos(2); - if (ao_gps_parse_flag('N', 'S')) - ao_gps_next.latitude = -ao_gps_next.latitude; - ao_gps_next.longitude = ao_gps_parse_pos(3); - if (ao_gps_parse_flag('E', 'W')) - ao_gps_next.longitude = -ao_gps_next.longitude; - - i = ao_gps_decimal(0xff); - if (i == 1) - ao_gps_next.flags |= AO_GPS_VALID; - - i = ao_gps_decimal(0xff) << AO_GPS_NUM_SAT_SHIFT; - if (i > AO_GPS_NUM_SAT_MASK) - i = AO_GPS_NUM_SAT_MASK; - ao_gps_next.flags |= i; - - ao_gps_lexchar(); - i = ao_gps_decimal(0xff); - if (i <= 50) { - i = (uint8_t) 5 * i; - if (ao_gps_char == '.') - i = (i + ((uint8_t) ao_gps_decimal(1) >> 1)); - } else - i = 255; - ao_gps_next.hdop = i; - ao_gps_skip_field(); - - ao_gps_next.altitude = ao_gps_decimal(0xff); - ao_gps_skip_field(); /* skip any fractional portion */ - - /* Skip remaining fields */ - while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { - ao_gps_lexchar(); - ao_gps_skip_field(); - } - if (ao_gps_char == '*') { - uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex(2)) - ao_gps_error = 1; - } else - ao_gps_error = 1; - if (!ao_gps_error) { - ao_mutex_get(&ao_gps_mutex); - ao_gps_tick = ao_gps_next_tick; - memcpy(&ao_gps_data, &ao_gps_next, sizeof (ao_gps_data)); - ao_mutex_put(&ao_gps_mutex); - ao_wakeup(&ao_gps_data); - } -} - -static void -ao_nmea_gsv(void) -{ - char c; - uint8_t i; - uint8_t done; - /* Now read the data into the GPS tracking data record - * - * $GPGSV,3,1,12,05,54,069,45,12,44,061,44,21,07,184,46,22,78,289,47*72 - * - * Satellites in view data - * - * 3 Total number of GSV messages - * 1 Sequence number of current GSV message - * 12 Total sats in view (0-12) - * 05 SVID - * 54 Elevation - * 069 Azimuth - * 45 C/N0 in dB - * ... other SVIDs - * 72 checksum - */ - c = ao_gps_decimal(1); /* total messages */ - i = ao_gps_decimal(1); /* message sequence */ - if (i == 1) { - ao_gps_tracking_next.channels = 0; - } - done = (uint8_t) c == i; - ao_gps_lexchar(); - ao_gps_skip_field(); /* sats in view */ - while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { - i = ao_gps_tracking_next.channels; - c = ao_gps_decimal(2); /* SVID */ - if (i < AO_MAX_GPS_TRACKING) - ao_gps_tracking_next.sats[i].svid = c; - ao_gps_lexchar(); - ao_gps_skip_field(); /* elevation */ - ao_gps_lexchar(); - ao_gps_skip_field(); /* azimuth */ - c = ao_gps_decimal(2); /* C/N0 */ - if (i < AO_MAX_GPS_TRACKING) { - if ((ao_gps_tracking_next.sats[i].c_n_1 = c) != 0) - ao_gps_tracking_next.channels = i + 1; - } - } - if (ao_gps_char == '*') { - uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex(2)) - ao_gps_error = 1; - } - else - ao_gps_error = 1; - if (ao_gps_error) - ao_gps_tracking_next.channels = 0; - else if (done) { - ao_mutex_get(&ao_gps_mutex); - memcpy(&ao_gps_tracking_data, &ao_gps_tracking_next, - sizeof(ao_gps_tracking_data)); - ao_mutex_put(&ao_gps_mutex); - ao_wakeup(&ao_gps_tracking_data); - } -} - -static void -ao_nmea_rmc(void) -{ - char a, c; - uint8_t i; - /* Parse the RMC record to read out the current date */ - - /* $GPRMC,111636.932,A,2447.0949,N,12100.5223,E,000.0,000.0,030407,,,A*61 - * - * Recommended Minimum Specific GNSS Data - * - * 111636.932 UTC time 11:16:36.932 - * A Data Valid (V = receiver warning) - * 2447.0949 Latitude - * N North/south indicator - * 12100.5223 Longitude - * E East/west indicator - * 000.0 Speed over ground - * 000.0 Course over ground - * 030407 UTC date (ddmmyy format) - * A Mode indicator: - * N = data not valid - * A = autonomous mode - * D = differential mode - * E = estimated (dead reckoning) mode - * M = manual input mode - * S = simulator mode - * 61 checksum - */ - ao_gps_skip_field(); - for (i = 0; i < 8; i++) { - ao_gps_lexchar(); - ao_gps_skip_field(); - } - a = ao_gps_decimal(2); - c = ao_gps_decimal(2); - i = ao_gps_decimal(2); - /* Skip remaining fields */ - while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { - ao_gps_lexchar(); - ao_gps_skip_field(); - } - if (ao_gps_char == '*') { - uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex(2)) - ao_gps_error = 1; - } else - ao_gps_error = 1; - if (!ao_gps_error) { - ao_gps_next.year = i; - ao_gps_next.month = c; - ao_gps_next.day = a; - ao_gps_date_flags = AO_GPS_DATE_VALID; - } -} - -#define ao_skytraq_sendstruct(s) ao_skytraq_sendbytes((s), sizeof(s)) - -static void -ao_skytraq_sendbytes(__code uint8_t *b, uint8_t l) -{ - while (l--) { - uint8_t c = *b++; - if (c == 0xa0) - ao_delay(AO_MS_TO_TICKS(500)); - ao_serial_putchar(c); - } -} - -static void -ao_gps_nmea_parse(void) -{ - uint8_t a, b, c; - - ao_gps_cksum = 0; - ao_gps_error = 0; - - for (a = 0; a < AO_GPS_LEADER; a++) { - ao_gps_lexchar(); - if (ao_gps_char != ao_gps_header[a]) - return; - } - - ao_gps_lexchar(); - a = ao_gps_char; - ao_gps_lexchar(); - b = ao_gps_char; - ao_gps_lexchar(); - c = ao_gps_char; - ao_gps_lexchar(); - - if (ao_gps_char != ',') - return; - - if (a == (uint8_t) 'G' && b == (uint8_t) 'G' && c == (uint8_t) 'A') { - ao_nmea_gga(); - } else if (a == (uint8_t) 'G' && b == (uint8_t) 'S' && c == (uint8_t) 'V') { - ao_nmea_gsv(); - } else if (a == (uint8_t) 'R' && b == (uint8_t) 'M' && c == (uint8_t) 'C') { - ao_nmea_rmc(); - } -} - -void -ao_gps(void) __reentrant -{ - ao_serial_set_speed(AO_SERIAL_SPEED_9600); - - /* give skytraq time to boot in case of cold start */ - ao_delay(AO_MS_TO_TICKS(2000)); - - ao_skytraq_sendstruct(ao_gps_config); - - for (;;) { - /* Locate the begining of the next record */ - if (ao_serial_getchar() == '$') { - ao_gps_nmea_parse(); - } - - } -} - -__xdata struct ao_task ao_gps_task; - -static void -gps_dump(void) __reentrant -{ - uint8_t i; - ao_mutex_get(&ao_gps_mutex); - printf ("Date: %02d/%02d/%02d\n", ao_gps_data.year, ao_gps_data.month, ao_gps_data.day); - printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second); - printf ("Lat/Lon: %ld %ld\n", ao_gps_data.latitude, ao_gps_data.longitude); - printf ("Alt: %d\n", ao_gps_data.altitude); - printf ("Flags: 0x%x\n", ao_gps_data.flags); - printf ("Sats: %d", ao_gps_tracking_data.channels); - for (i = 0; i < ao_gps_tracking_data.channels; i++) - printf (" %d %d", - ao_gps_tracking_data.sats[i].svid, - ao_gps_tracking_data.sats[i].c_n_1); - printf ("\ndone\n"); - ao_mutex_put(&ao_gps_mutex); -} - -__code struct ao_cmds ao_gps_cmds[] = { - { gps_dump, "g\0Display GPS" }, - { 0, NULL }, -}; - -void -ao_gps_init(void) -{ - ao_add_task(&ao_gps_task, ao_gps, "gps"); - ao_cmd_register(&ao_gps_cmds[0]); -} diff --git a/src/ao_gps_test.c b/src/ao_gps_test.c deleted file mode 100644 index 93d7a9ab..00000000 --- a/src/ao_gps_test.c +++ /dev/null @@ -1,508 +0,0 @@ -/* - * 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_GPS_TEST -#include "ao_host.h" -#include -#include -#include -#include -#include -#define AO_GPS_NUM_SAT_MASK (0xf << 0) -#define AO_GPS_NUM_SAT_SHIFT (0) - -#define AO_GPS_VALID (1 << 4) -#define AO_GPS_RUNNING (1 << 5) -#define AO_GPS_DATE_VALID (1 << 6) -#define AO_GPS_COURSE_VALID (1 << 7) - -struct ao_gps_orig { - uint8_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint8_t second; - uint8_t flags; - int32_t latitude; /* degrees * 10⁷ */ - int32_t longitude; /* degrees * 10⁷ */ - int16_t altitude; /* m */ - uint16_t ground_speed; /* cm/s */ - uint8_t course; /* degrees / 2 */ - uint8_t hdop; /* * 5 */ - int16_t climb_rate; /* cm/s */ - uint16_t h_error; /* m */ - uint16_t v_error; /* m */ -}; - -#define SIRF_SAT_STATE_ACQUIRED (1 << 0) -#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) -#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) -#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) -#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) -#define SIRF_SAT_CODE_LOCKED (1 << 5) -#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) -#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) - -struct ao_gps_sat_orig { - uint8_t svid; - uint8_t c_n_1; -}; - -#define AO_MAX_GPS_TRACKING 12 - -struct ao_gps_tracking_orig { - uint8_t channels; - struct ao_gps_sat_orig sats[AO_MAX_GPS_TRACKING]; -}; - -#define ao_telemetry_location ao_gps_orig -#define ao_telemetry_satellite ao_gps_tracking_orig -#define ao_telemetry_satellite_info ao_gps_sat_orig - -void -ao_mutex_get(uint8_t *mutex) -{ -} - -void -ao_mutex_put(uint8_t *mutex) -{ -} - -static int -ao_gps_fd; - -static void -ao_dbg_char(char c) -{ - char line[128]; - line[0] = '\0'; - if (c < ' ') { - if (c == '\n') - sprintf (line, "\n"); - else - sprintf (line, "\\%02x", ((int) c) & 0xff); - } else { - sprintf (line, "%c", c); - } - write(1, line, strlen(line)); -} - -#define QUEUE_LEN 4096 - -static char input_queue[QUEUE_LEN]; -int input_head, input_tail; - -#include - -int -get_millis(void) -{ - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec * 1000 + tv.tv_usec / 1000; -} - -static void -check_sirf_message(char *from, uint8_t *msg, int len) -{ - uint16_t encoded_len, encoded_cksum; - uint16_t cksum; - uint8_t id; - int i; - - if (msg[0] != 0xa0 || msg[1] != 0xa2) { - printf ("bad header\n"); - return; - } - if (len < 7) { - printf("short\n"); - return; - } - if (msg[len-1] != 0xb3 || msg[len-2] != 0xb0) { - printf ("bad trailer\n"); - return; - } - encoded_len = (msg[2] << 8) | msg[3]; - id = msg[4]; -/* printf ("%9d: %3d\n", get_millis(), id); */ - if (encoded_len != len - 8) { - if (id != 52) - printf ("length mismatch (got %d, wanted %d)\n", - len - 8, encoded_len); - return; - } - encoded_cksum = (msg[len - 4] << 8) | msg[len-3]; - cksum = 0; - for (i = 4; i < len - 4; i++) - cksum = (cksum + msg[i]) & 0x7fff; - if (encoded_cksum != cksum) { - printf ("cksum mismatch (got %04x wanted %04x)\n", - cksum, encoded_cksum); - return; - } - id = msg[4]; - switch (id) { - case 41:{ - int off = 4; - - uint8_t id; - uint16_t nav_valid; - uint16_t nav_type; - uint16_t week; - uint32_t tow; - uint16_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint16_t second; - uint32_t sat_list; - int32_t lat; - int32_t lon; - int32_t alt_ell; - int32_t alt_msl; - int8_t datum; - uint16_t sog; - uint16_t cog; - int16_t mag_var; - int16_t climb_rate; - int16_t heading_rate; - uint32_t h_error; - uint32_t v_error; - uint32_t t_error; - uint16_t h_v_error; - -#define get_u8(u) u = (msg[off]); off+= 1 -#define get_u16(u) u = (msg[off] << 8) | (msg[off + 1]); off+= 2 -#define get_u32(u) u = (msg[off] << 24) | (msg[off + 1] << 16) | (msg[off+2] << 8) | (msg[off+3]); off+= 4 - - get_u8(id); - get_u16(nav_valid); - get_u16(nav_type); - get_u16(week); - get_u32(tow); - get_u16(year); - get_u8(month); - get_u8(day); - get_u8(hour); - get_u8(minute); - get_u16(second); - get_u32(sat_list); - get_u32(lat); - get_u32(lon); - get_u32(alt_ell); - get_u32(alt_msl); - get_u8(datum); - get_u16(sog); - get_u16(cog); - get_u16(mag_var); - get_u16(climb_rate); - get_u16(heading_rate); - get_u32(h_error); - get_u32(v_error); - get_u32(t_error); - get_u16(h_v_error); - - - printf ("Geodetic Navigation Data (41):\n"); - printf ("\tNav valid %04x\n", nav_valid); - printf ("\tNav type %04x\n", nav_type); - printf ("\tWeek %5d", week); - printf (" TOW %9d", tow); - printf (" %4d-%2d-%2d %02d:%02d:%07.4f\n", - year, month, day, - hour, minute, second / 1000.0); - printf ("\tsats: %08x\n", sat_list); - printf ("\tlat: %g", lat / 1.0e7); - printf (" lon: %g", lon / 1.0e7); - printf (" alt_ell: %g", alt_ell / 100.0); - printf (" alt_msll: %g", alt_msl / 100.0); - printf (" datum: %d\n", datum); - printf ("\tground speed: %g", sog / 100.0); - printf (" course: %g", cog / 100.0); - printf (" climb: %g", climb_rate / 100.0); - printf (" heading rate: %g\n", heading_rate / 100.0); - printf ("\th error: %g", h_error / 100.0); - printf (" v error: %g", v_error / 100.0); - printf (" t error: %g", t_error / 100.0); - printf (" h vel error: %g\n", h_v_error / 100.0); - break; - } - case 4: { - int off = 4; - uint8_t id; - int16_t gps_week; - uint32_t gps_tow; - uint8_t channels; - int j, k; - - get_u8(id); - get_u16(gps_week); - get_u32(gps_tow); - get_u8(channels); - - printf ("Measured Tracker Data (4):\n"); - printf ("GPS week: %d\n", gps_week); - printf ("GPS time of week: %d\n", gps_tow); - printf ("channels: %d\n", channels); - for (j = 0; j < 12; j++) { - uint8_t svid, azimuth, elevation; - uint16_t state; - uint8_t c_n[10]; - get_u8(svid); - get_u8(azimuth); - get_u8(elevation); - get_u16(state); - for (k = 0; k < 10; k++) { - get_u8(c_n[k]); - } - printf ("Sat %3d:", svid); - printf (" aziumuth: %6.1f", azimuth * 1.5); - printf (" elevation: %6.1f", elevation * 0.5); - printf (" state: 0x%02x", state); - printf (" c_n:"); - for (k = 0; k < 10; k++) - printf(" %3d", c_n[k]); - if (state & SIRF_SAT_STATE_ACQUIRED) - printf(" acq,"); - if (state & SIRF_SAT_STATE_CARRIER_PHASE_VALID) - printf(" car,"); - if (state & SIRF_SAT_BIT_SYNC_COMPLETE) - printf(" bit,"); - if (state & SIRF_SAT_SUBFRAME_SYNC_COMPLETE) - printf(" sub,"); - if (state & SIRF_SAT_CARRIER_PULLIN_COMPLETE) - printf(" pullin,"); - if (state & SIRF_SAT_CODE_LOCKED) - printf(" code,"); - if (state & SIRF_SAT_ACQUISITION_FAILED) - printf(" fail,"); - if (state & SIRF_SAT_EPHEMERIS_AVAILABLE) - printf(" ephem,"); - printf ("\n"); - } - break; - } - default: - return; - printf ("%s %4d:", from, encoded_len); - for (i = 4; i < len - 4; i++) { - if (((i - 4) & 0xf) == 0) - printf("\n "); - printf (" %3d", msg[i]); - } - printf ("\n"); - } -} - -static uint8_t sirf_message[4096]; -static int sirf_message_len; -static uint8_t sirf_in_message[4096]; -static int sirf_in_len; - -char -ao_serial_getchar(void) -{ - char c; - uint8_t uc; - - while (input_head == input_tail) { - for (;;) { - input_tail = read(ao_gps_fd, input_queue, QUEUE_LEN); - if (input_tail < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - perror ("getchar"); - exit (1); - } - input_head = 0; - break; - } - } - c = input_queue[input_head]; - input_head = (input_head + 1) % QUEUE_LEN; - uc = c; - if (sirf_in_len || uc == 0xa0) { - if (sirf_in_len < 4096) - sirf_in_message[sirf_in_len++] = uc; - if (uc == 0xb3) { - check_sirf_message("recv", sirf_in_message, sirf_in_len); - sirf_in_len = 0; - } - } - return c; -} - - -void -ao_serial_putchar(char c) -{ - int i; - uint8_t uc = (uint8_t) c; - - if (sirf_message_len || uc == 0xa0) { - if (sirf_message_len < 4096) - sirf_message[sirf_message_len++] = uc; - if (uc == 0xb3) { - check_sirf_message("send", sirf_message, sirf_message_len); - sirf_message_len = 0; - } - } - for (;;) { - i = write(ao_gps_fd, &c, 1); - if (i == 1) { - if ((uint8_t) c == 0xb3 || c == '\r') { - static const struct timespec delay = { - .tv_sec = 0, - .tv_nsec = 100 * 1000 * 1000 - }; - tcdrain(ao_gps_fd); -// nanosleep(&delay, NULL); - } - break; - } - if (i < 0 && (errno == EINTR || errno == EAGAIN)) - continue; - perror("putchar"); - exit(1); - } -} - -#define AO_SERIAL_SPEED_4800 0 -#define AO_SERIAL_SPEED_57600 1 - -static void -ao_serial_set_speed(uint8_t speed) -{ - int fd = ao_gps_fd; - struct termios termios; - - tcdrain(fd); - tcgetattr(fd, &termios); - switch (speed) { - case AO_SERIAL_SPEED_4800: - cfsetspeed(&termios, B4800); - break; - case AO_SERIAL_SPEED_57600: - cfsetspeed(&termios, B57600); - break; - } - tcsetattr(fd, TCSAFLUSH, &termios); - tcflush(fd, TCIFLUSH); -} - -#define ao_time() 0 - -#include "ao_gps_print.c" -#include "ao_gps_sirf.c" - -void -ao_dump_state(void *wchan) -{ - double lat, lon; - int i; - if (wchan == &ao_gps_data) - ao_gps_print(&ao_gps_data); - else - ao_gps_tracking_print(&ao_gps_tracking_data); - putchar('\n'); - return; - printf ("%02d:%02d:%02d", - ao_gps_data.hour, ao_gps_data.minute, - ao_gps_data.second); - printf (" nsat %d %svalid", - ao_gps_data.flags & AO_GPS_NUM_SAT_MASK, - ao_gps_data.flags & AO_GPS_VALID ? "" : "not "); - printf (" lat %g lon %g alt %d", - ao_gps_data.latitude / 1.0e7, - ao_gps_data.longitude / 1.0e7, - ao_gps_data.altitude); - printf (" speed %g climb %g course %d", - ao_gps_data.ground_speed / 100.0, - ao_gps_data.climb_rate / 100.0, - ao_gps_data.course * 2); - printf (" hdop %g h_error %d v_error %d", - ao_gps_data.hdop / 5.0, - ao_gps_data.h_error, ao_gps_data.v_error); - printf("\n"); - printf ("\t"); - for (i = 0; i < 12; i++) - printf (" %2d(%02d)", - ao_gps_tracking_data.sats[i].svid, - ao_gps_tracking_data.sats[i].c_n_1); - printf ("\n"); -} - -int -ao_gps_open(const char *tty) -{ - struct termios termios; - int fd; - - fd = open (tty, O_RDWR); - if (fd < 0) - return -1; - - tcgetattr(fd, &termios); - cfmakeraw(&termios); - cfsetspeed(&termios, B4800); - tcsetattr(fd, TCSAFLUSH, &termios); - - tcdrain(fd); - tcflush(fd, TCIFLUSH); - return fd; -} - -#include - -static const struct option options[] = { - { .name = "tty", .has_arg = 1, .val = 'T' }, - { 0, 0, 0, 0}, -}; - -static void usage(char *program) -{ - fprintf(stderr, "usage: %s [--tty ]\n", program); - exit(1); -} - -int -main (int argc, char **argv) -{ - char *tty = "/dev/ttyUSB0"; - int c; - - while ((c = getopt_long(argc, argv, "T:", options, NULL)) != -1) { - switch (c) { - case 'T': - tty = optarg; - break; - default: - usage(argv[0]); - break; - } - } - ao_gps_fd = ao_gps_open(tty); - if (ao_gps_fd < 0) { - perror (tty); - exit (1); - } - ao_gps_setup(); - ao_gps(); -} diff --git a/src/ao_gps_test_skytraq.c b/src/ao_gps_test_skytraq.c deleted file mode 100644 index a78fae0f..00000000 --- a/src/ao_gps_test_skytraq.c +++ /dev/null @@ -1,490 +0,0 @@ -/* - * 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_GPS_TEST -#include "ao_host.h" -#include -#include -#include -#include -#include -#define AO_GPS_NUM_SAT_MASK (0xf << 0) -#define AO_GPS_NUM_SAT_SHIFT (0) - -#define AO_GPS_VALID (1 << 4) -#define AO_GPS_RUNNING (1 << 5) -#define AO_GPS_DATE_VALID (1 << 6) -#define AO_GPS_COURSE_VALID (1 << 7) - -struct ao_gps_orig { - uint8_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint8_t second; - uint8_t flags; - int32_t latitude; /* degrees * 10⁷ */ - int32_t longitude; /* degrees * 10⁷ */ - int16_t altitude; /* m */ - uint16_t ground_speed; /* cm/s */ - uint8_t course; /* degrees / 2 */ - uint8_t hdop; /* * 5 */ - int16_t climb_rate; /* cm/s */ - uint16_t h_error; /* m */ - uint16_t v_error; /* m */ -}; - -#define SIRF_SAT_STATE_ACQUIRED (1 << 0) -#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) -#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) -#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) -#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) -#define SIRF_SAT_CODE_LOCKED (1 << 5) -#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) -#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) - -struct ao_gps_sat_orig { - uint8_t svid; - uint8_t c_n_1; -}; - -#define AO_MAX_GPS_TRACKING 12 - -struct ao_gps_tracking_orig { - uint8_t channels; - struct ao_gps_sat_orig sats[AO_MAX_GPS_TRACKING]; -}; - -#define ao_telemetry_location ao_gps_orig -#define ao_telemetry_satellite ao_gps_tracking_orig -#define ao_telemetry_satellite_info ao_gps_sat_orig - -void -ao_mutex_get(uint8_t *mutex) -{ -} - -void -ao_mutex_put(uint8_t *mutex) -{ -} - -static int -ao_gps_fd; - -static void -ao_dbg_char(char c) -{ - char line[128]; - line[0] = '\0'; - if (c < ' ') { - if (c == '\n') - sprintf (line, "\n"); - else - sprintf (line, "\\%02x", ((int) c) & 0xff); - } else { - sprintf (line, "%c", c); - } - write(1, line, strlen(line)); -} - -#define QUEUE_LEN 4096 - -static char input_queue[QUEUE_LEN]; -int input_head, input_tail; - -#include - -int -get_millis(void) -{ - struct timeval tv; - gettimeofday(&tv, NULL); - return tv.tv_sec * 1000 + tv.tv_usec / 1000; -} - -static void -check_skytraq_message(char *from, uint8_t *msg, int len) -{ - uint16_t encoded_len, encoded_cksum; - uint16_t cksum; - uint8_t id; - int i; - -// fwrite(msg, 1, len, stdout); - return; - if (msg[0] != 0xa0 || msg[1] != 0xa2) { - printf ("bad header\n"); - return; - } - if (len < 7) { - printf("short\n"); - return; - } - if (msg[len-1] != 0xb3 || msg[len-2] != 0xb0) { - printf ("bad trailer\n"); - return; - } - encoded_len = (msg[2] << 8) | msg[3]; - id = msg[4]; -/* printf ("%9d: %3d\n", get_millis(), id); */ - if (encoded_len != len - 8) { - if (id != 52) - printf ("length mismatch (got %d, wanted %d)\n", - len - 8, encoded_len); - return; - } - encoded_cksum = (msg[len - 4] << 8) | msg[len-3]; - cksum = 0; - for (i = 4; i < len - 4; i++) - cksum = (cksum + msg[i]) & 0x7fff; - if (encoded_cksum != cksum) { - printf ("cksum mismatch (got %04x wanted %04x)\n", - cksum, encoded_cksum); - return; - } - id = msg[4]; - switch (id) { - case 41:{ - int off = 4; - - uint8_t id; - uint16_t nav_valid; - uint16_t nav_type; - uint16_t week; - uint32_t tow; - uint16_t year; - uint8_t month; - uint8_t day; - uint8_t hour; - uint8_t minute; - uint16_t second; - uint32_t sat_list; - int32_t lat; - int32_t lon; - int32_t alt_ell; - int32_t alt_msl; - int8_t datum; - uint16_t sog; - uint16_t cog; - int16_t mag_var; - int16_t climb_rate; - int16_t heading_rate; - uint32_t h_error; - uint32_t v_error; - uint32_t t_error; - uint16_t h_v_error; - -#define get_u8(u) u = (msg[off]); off+= 1 -#define get_u16(u) u = (msg[off] << 8) | (msg[off + 1]); off+= 2 -#define get_u32(u) u = (msg[off] << 24) | (msg[off + 1] << 16) | (msg[off+2] << 8) | (msg[off+3]); off+= 4 - - get_u8(id); - get_u16(nav_valid); - get_u16(nav_type); - get_u16(week); - get_u32(tow); - get_u16(year); - get_u8(month); - get_u8(day); - get_u8(hour); - get_u8(minute); - get_u16(second); - get_u32(sat_list); - get_u32(lat); - get_u32(lon); - get_u32(alt_ell); - get_u32(alt_msl); - get_u8(datum); - get_u16(sog); - get_u16(cog); - get_u16(mag_var); - get_u16(climb_rate); - get_u16(heading_rate); - get_u32(h_error); - get_u32(v_error); - get_u32(t_error); - get_u16(h_v_error); - - - printf ("Geodetic Navigation Data (41):\n"); - printf ("\tNav valid %04x\n", nav_valid); - printf ("\tNav type %04x\n", nav_type); - printf ("\tWeek %5d", week); - printf (" TOW %9d", tow); - printf (" %4d-%2d-%2d %02d:%02d:%07.4f\n", - year, month, day, - hour, minute, second / 1000.0); - printf ("\tsats: %08x\n", sat_list); - printf ("\tlat: %g", lat / 1.0e7); - printf (" lon: %g", lon / 1.0e7); - printf (" alt_ell: %g", alt_ell / 100.0); - printf (" alt_msll: %g", alt_msl / 100.0); - printf (" datum: %d\n", datum); - printf ("\tground speed: %g", sog / 100.0); - printf (" course: %g", cog / 100.0); - printf (" climb: %g", climb_rate / 100.0); - printf (" heading rate: %g\n", heading_rate / 100.0); - printf ("\th error: %g", h_error / 100.0); - printf (" v error: %g", v_error / 100.0); - printf (" t error: %g", t_error / 100.0); - printf (" h vel error: %g\n", h_v_error / 100.0); - break; - } - case 4: { - int off = 4; - uint8_t id; - int16_t gps_week; - uint32_t gps_tow; - uint8_t channels; - int j, k; - - get_u8(id); - get_u16(gps_week); - get_u32(gps_tow); - get_u8(channels); - - printf ("Measured Tracker Data (4):\n"); - printf ("GPS week: %d\n", gps_week); - printf ("GPS time of week: %d\n", gps_tow); - printf ("channels: %d\n", channels); - for (j = 0; j < 12; j++) { - uint8_t svid, azimuth, elevation; - uint16_t state; - uint8_t c_n[10]; - get_u8(svid); - get_u8(azimuth); - get_u8(elevation); - get_u16(state); - for (k = 0; k < 10; k++) { - get_u8(c_n[k]); - } - printf ("Sat %3d:", svid); - printf (" aziumuth: %6.1f", azimuth * 1.5); - printf (" elevation: %6.1f", elevation * 0.5); - printf (" state: 0x%02x", state); - printf (" c_n:"); - for (k = 0; k < 10; k++) - printf(" %3d", c_n[k]); - if (state & SIRF_SAT_STATE_ACQUIRED) - printf(" acq,"); - if (state & SIRF_SAT_STATE_CARRIER_PHASE_VALID) - printf(" car,"); - if (state & SIRF_SAT_BIT_SYNC_COMPLETE) - printf(" bit,"); - if (state & SIRF_SAT_SUBFRAME_SYNC_COMPLETE) - printf(" sub,"); - if (state & SIRF_SAT_CARRIER_PULLIN_COMPLETE) - printf(" pullin,"); - if (state & SIRF_SAT_CODE_LOCKED) - printf(" code,"); - if (state & SIRF_SAT_ACQUISITION_FAILED) - printf(" fail,"); - if (state & SIRF_SAT_EPHEMERIS_AVAILABLE) - printf(" ephem,"); - printf ("\n"); - } - break; - } - default: - return; - printf ("%s %4d:", from, encoded_len); - for (i = 4; i < len - 4; i++) { - if (((i - 4) & 0xf) == 0) - printf("\n "); - printf (" %3d", msg[i]); - } - printf ("\n"); - } -} - -static uint8_t skytraq_message[4096]; -static int skytraq_message_len; -static uint8_t skytraq_in_message[4096]; -static int skytraq_in_len; - -char -ao_serial_getchar(void) -{ - char c; - uint8_t uc; - - while (input_head == input_tail) { - for (;;) { - input_tail = read(ao_gps_fd, input_queue, QUEUE_LEN); - if (input_tail < 0) { - if (errno == EINTR || errno == EAGAIN) - continue; - perror ("getchar"); - exit (1); - } - input_head = 0; - break; - } - } - c = input_queue[input_head]; - input_head = (input_head + 1) % QUEUE_LEN; - uc = c; -// printf ("c: %02x %c\n", uc, uc); - if (skytraq_in_len || uc == '$') { - if (skytraq_in_len < 4096) - skytraq_in_message[skytraq_in_len++] = uc; - if (uc == 0x0a) { - check_skytraq_message("recv", skytraq_in_message, skytraq_in_len); - skytraq_in_len = 0; - } - } - return c; -} - - -void -ao_serial_putchar(char c) -{ - int i; - uint8_t uc = (uint8_t) c; - - if (skytraq_message_len || uc == 0xa0) { - if (skytraq_message_len < 4096) - skytraq_message[skytraq_message_len++] = uc; - if (uc == 0x0a) { - check_skytraq_message("send", skytraq_message, skytraq_message_len); - skytraq_message_len = 0; - } - } - for (;;) { - i = write(ao_gps_fd, &c, 1); - if (i == 1) { - if ((uint8_t) c == 0xb3 || c == '\r') { - static const struct timespec delay = { - .tv_sec = 0, - .tv_nsec = 100 * 1000 * 1000 - }; - tcdrain(ao_gps_fd); -// nanosleep(&delay, NULL); - } - break; - } - if (i < 0 && (errno == EINTR || errno == EAGAIN)) - continue; - perror("putchar"); - exit(1); - } -} - -#define AO_SERIAL_SPEED_4800 0 -#define AO_SERIAL_SPEED_9600 1 -#define AO_SERIAL_SPEED_57600 2 - -static void -ao_serial_set_speed(uint8_t speed) -{ - int fd = ao_gps_fd; - struct termios termios; - - tcdrain(fd); - tcgetattr(fd, &termios); - switch (speed) { - case AO_SERIAL_SPEED_4800: - cfsetspeed(&termios, B4800); - break; - case AO_SERIAL_SPEED_9600: - cfsetspeed(&termios, B38400); - break; - case AO_SERIAL_SPEED_57600: - cfsetspeed(&termios, B57600); - break; - } - tcsetattr(fd, TCSAFLUSH, &termios); - tcflush(fd, TCIFLUSH); -} - -#define ao_time() 0 - -#include "ao_gps_print.c" -#include "ao_gps_skytraq.c" - -void -ao_dump_state(void *wchan) -{ - double lat, lon; - int i; - if (wchan == &ao_gps_data) - ao_gps_print(&ao_gps_data); - else - ao_gps_tracking_print(&ao_gps_tracking_data); - putchar('\n'); - return; -} - -int -ao_gps_open(const char *tty) -{ - struct termios termios; - int fd; - - fd = open (tty, O_RDWR); - if (fd < 0) - return -1; - - tcgetattr(fd, &termios); - cfmakeraw(&termios); - cfsetspeed(&termios, B4800); - tcsetattr(fd, TCSAFLUSH, &termios); - - tcdrain(fd); - tcflush(fd, TCIFLUSH); - return fd; -} - -#include - -static const struct option options[] = { - { .name = "tty", .has_arg = 1, .val = 'T' }, - { 0, 0, 0, 0}, -}; - -static void usage(char *program) -{ - fprintf(stderr, "usage: %s [--tty ]\n", program); - exit(1); -} - -int -main (int argc, char **argv) -{ - char *tty = "/dev/ttyUSB0"; - int c; - - while ((c = getopt_long(argc, argv, "T:", options, NULL)) != -1) { - switch (c) { - case 'T': - tty = optarg; - break; - default: - usage(argv[0]); - break; - } - } - ao_gps_fd = ao_gps_open(tty); - if (ao_gps_fd < 0) { - perror (tty); - exit (1); - } - ao_gps(); -} diff --git a/src/ao_host.h b/src/ao_host.h deleted file mode 100644 index 65c25fe5..00000000 --- a/src/ao_host.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - * 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 _GNU_SOURCE - -#include -#include -#include -#include -#include - -#define AO_ADC_RING 64 -#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) -#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) - -/* - * One set of samples read from the A/D converter - */ -struct ao_adc { - uint16_t tick; /* tick when the sample was read */ - int16_t accel; /* accelerometer */ - int16_t pres; /* pressure sensor */ - int16_t temp; /* temperature sensor */ - int16_t v_batt; /* battery voltage */ - int16_t sense_d; /* drogue continuity sense */ - int16_t sense_m; /* main continuity sense */ -}; - -#define __pdata -#define __data -#define __xdata -#define __code -#define __reentrant - -enum ao_flight_state { - ao_flight_startup = 0, - ao_flight_idle = 1, - ao_flight_pad = 2, - ao_flight_boost = 3, - ao_flight_fast = 4, - ao_flight_coast = 5, - ao_flight_drogue = 6, - ao_flight_main = 7, - ao_flight_landed = 8, - ao_flight_invalid = 9 -}; - -struct ao_adc ao_adc_ring[AO_ADC_RING]; -uint8_t ao_adc_head; - -#define ao_led_on(l) -#define ao_led_off(l) -#define ao_timer_set_adc_interval(i) -#define ao_wakeup(wchan) ao_dump_state(wchan) -#define ao_cmd_register(c) -#define ao_usb_disable() -#define ao_telemetry_set_interval(x) -#define ao_delay(x) - -enum ao_igniter { - ao_igniter_drogue = 0, - ao_igniter_main = 1 -}; - -void -ao_ignite(enum ao_igniter igniter) -{ - printf ("ignite %s\n", igniter == ao_igniter_drogue ? "drogue" : "main"); -} - -struct ao_task { - int dummy; -}; - -#define ao_add_task(t,f,n) - -#define ao_log_start() -#define ao_log_stop() - -#define AO_MS_TO_TICKS(ms) ((ms) / 10) -#define AO_SEC_TO_TICKS(s) ((s) * 100) - -#define AO_FLIGHT_TEST - -struct ao_adc ao_adc_static; - -FILE *emulator_in; - -void -ao_dump_state(void *wchan); - -void -ao_sleep(void *wchan); - -const char const * const ao_state_names[] = { - "startup", "idle", "pad", "boost", "fast", - "coast", "drogue", "main", "landed", "invalid" -}; - -struct ao_cmds { - void (*func)(void); - const char *help; -}; - - -struct ao_config { - uint16_t main_deploy; - int16_t accel_zero_g; -}; - -#define ao_config_get() - -struct ao_config ao_config = { 250, 16000 }; diff --git a/src/ao_ignite.c b/src/ao_ignite.c deleted file mode 100644 index 5238beb4..00000000 --- a/src/ao_ignite.c +++ /dev/null @@ -1,218 +0,0 @@ -/* - * 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" - -#if IGNITE_ON_P2 -#define AO_IGNITER_DROGUE P2_3 -#define AO_IGNITER_MAIN P2_4 -#define AO_IGNITER_DIR P2DIR -#define AO_IGNITER_DROGUE_BIT (1 << 3) -#define AO_IGNITER_MAIN_BIT (1 << 4) -#endif - -#if IGNITE_ON_P0 -#define AO_IGNITER_DROGUE P0_5 -#define AO_IGNITER_MAIN P0_4 -#define AO_IGNITER_DIR P0DIR -#define AO_IGNITER_DROGUE_BIT (1 << 5) -#define AO_IGNITER_MAIN_BIT (1 << 4) -#endif - -/* test these values with real igniters */ -#define AO_IGNITER_OPEN 1000 -#define AO_IGNITER_CLOSED 7000 -#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) -#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) - -struct ao_ignition { - uint8_t request; - uint8_t fired; - uint8_t firing; -}; - -__xdata struct ao_ignition ao_ignition[2]; - -void -ao_ignite(enum ao_igniter igniter) __critical -{ - ao_ignition[igniter].request = 1; - ao_wakeup(&ao_ignition); -} - -enum ao_igniter_status -ao_igniter_status(enum ao_igniter igniter) -{ - __xdata struct ao_adc adc; - __pdata int16_t value; - __pdata uint8_t request, firing, fired; - - __critical { - ao_adc_get(&adc); - request = ao_ignition[igniter].request; - fired = ao_ignition[igniter].fired; - firing = ao_ignition[igniter].firing; - } - if (firing || (request && !fired)) - return ao_igniter_active; - - value = (AO_IGNITER_CLOSED>>1); - switch (igniter) { - case ao_igniter_drogue: - value = adc.sense_d; - break; - case ao_igniter_main: - value = adc.sense_m; - break; - } - if (value < AO_IGNITER_OPEN) - return ao_igniter_open; - else if (value > AO_IGNITER_CLOSED) - return ao_igniter_ready; - else - return ao_igniter_unknown; -} - -void -ao_igniter_fire(enum ao_igniter igniter) __critical -{ - ao_ignition[igniter].firing = 1; - switch(ao_config.ignite_mode) { - case AO_IGNITE_MODE_DUAL: - switch (igniter) { - case ao_igniter_drogue: - AO_IGNITER_DROGUE = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_DROGUE = 0; - break; - case ao_igniter_main: - AO_IGNITER_MAIN = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_MAIN = 0; - break; - } - break; - case AO_IGNITE_MODE_APOGEE: - switch (igniter) { - case ao_igniter_drogue: - AO_IGNITER_DROGUE = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_DROGUE = 0; - ao_delay(AO_IGNITER_CHARGE_TIME); - AO_IGNITER_MAIN = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_MAIN = 0; - break; - } - break; - case AO_IGNITE_MODE_MAIN: - switch (igniter) { - case ao_igniter_main: - AO_IGNITER_DROGUE = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_DROGUE = 0; - ao_delay(AO_IGNITER_CHARGE_TIME); - AO_IGNITER_MAIN = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_MAIN = 0; - break; - } - break; - } - ao_ignition[igniter].firing = 0; -} - -void -ao_igniter(void) -{ - __xdata enum ao_ignter igniter; - - ao_config_get(); - for (;;) { - ao_sleep(&ao_ignition); - for (igniter = ao_igniter_drogue; igniter <= ao_igniter_main; igniter++) { - if (ao_ignition[igniter].request && !ao_ignition[igniter].fired) { - if (igniter == ao_igniter_drogue && ao_config.apogee_delay) - ao_delay(AO_SEC_TO_TICKS(ao_config.apogee_delay)); - - ao_igniter_fire(igniter); - ao_delay(AO_IGNITER_CHARGE_TIME); - ao_ignition[igniter].fired = 1; - } - } - } -} - -void -ao_ignite_manual(void) -{ - ao_cmd_white(); - if (!ao_match_word("DoIt")) - return; - ao_cmd_white(); - if (ao_cmd_lex_c == 'm') { - if(ao_match_word("main")) - ao_igniter_fire(ao_igniter_main); - } else { - if(ao_match_word("drogue")) - ao_igniter_fire(ao_igniter_drogue); - } -} - -static __code char * __code igniter_status_names[] = { - "unknown", "ready", "active", "open" -}; - -void -ao_ignite_print_status(enum ao_igniter igniter, __code char *name) __reentrant -{ - enum ao_igniter_status status = ao_igniter_status(igniter); - printf("Igniter: %6s Status: %s\n", - name, - igniter_status_names[status]); -} - -void -ao_ignite_test(void) -{ - ao_ignite_print_status(ao_igniter_drogue, "drogue"); - ao_ignite_print_status(ao_igniter_main, "main"); -} - -__code struct ao_cmds ao_ignite_cmds[] = { - { ao_ignite_manual, "i {main|drogue}\0Fire igniter. is doit with D&I" }, - { ao_ignite_test, "t\0Test igniter" }, - { 0, NULL }, -}; - -__xdata struct ao_task ao_igniter_task; - -void -ao_ignite_set_pins(void) -{ - AO_IGNITER_DROGUE = 0; - AO_IGNITER_MAIN = 0; - AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; -} - -void -ao_igniter_init(void) -{ - ao_ignite_set_pins(); - ao_cmd_register(&ao_ignite_cmds[0]); - ao_add_task(&ao_igniter_task, ao_igniter, "igniter"); -} diff --git a/src/ao_intflash.c b/src/ao_intflash.c deleted file mode 100644 index d76d954e..00000000 --- a/src/ao_intflash.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright © 2011 Anthony Towns - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "cc1111.h" - -#define ENDOFCODE (CODESIZE) -#define AO_INTFLASH_BLOCK 1024 -#define AO_INTFLASH_BLOCKS ((0x8000 - ENDOFCODE)/AO_INTFLASH_BLOCK) -#define AO_INTFLASH_SIZE (AO_INTFLASH_BLOCK * AO_INTFLASH_BLOCKS) -#define AO_INTFLASH_LOCATION (0x8000 - AO_INTFLASH_SIZE) - -/* - * 21000 * 24e6 - * FWT = ------------ - * 16e9 - * - * = 31.5 - * - * Round up and use 32 - */ - -#define FLASH_TIMING 0x20 - -#if AO_INTFLASH_BLOCKS < 2 -#error "Too few pages" -#endif - -#if AO_INFTLASH_LOCATION % 1024 != 0 -#error "Pages aren't aligned properly" -#endif - -__xdata __at(AO_INTFLASH_LOCATION) uint8_t ao_intflash[AO_INTFLASH_SIZE]; - -/* Total bytes of available storage */ -__pdata uint32_t ao_storage_total = sizeof(ao_intflash); - -/* Block size - device is erased in these units. */ -__pdata uint32_t ao_storage_block = AO_INTFLASH_BLOCK; - -/* Byte offset of config block. Will be ao_storage_block bytes long */ -__pdata uint32_t ao_storage_config = sizeof(ao_intflash) - AO_INTFLASH_BLOCK; - -/* Storage unit size - device reads and writes must be within blocks of this size. */ -__pdata uint16_t ao_storage_unit = AO_INTFLASH_BLOCK; - -__xdata static uint8_t ao_intflash_dma_done; -static uint8_t ao_intflash_dma; - -/* - * The internal flash chip is arranged in 1kB sectors; the - * chip cannot erase in units smaller than that. - * - * Writing happens in units of 2 bytes and - * can only change bits from 1 to 0. So, you can rewrite - * the same contents, or append to an existing page easily enough - */ - -/* - * Erase the specified sector - */ -uint8_t -ao_storage_erase(uint32_t pos) __reentrant -{ - uint16_t addr; - - if (pos >= ao_storage_total || pos + ao_storage_block > ao_storage_total) - return 0; - - addr = ((uint16_t)(ao_intflash + pos) >> 1); - - FADDRH = addr >> 8; - FADDRL = addr; - - __critical { - _asm - .even - orl _FCTL, #FCTL_ERASE; ; FCTL |= FCTL_ERASE - nop ; Required, see datasheet. - _endasm; - } - - return 1; -} - -/* - * Write to flash - */ - -static void -ao_intflash_write_aligned(uint16_t pos, __xdata void *d, uint16_t len) __reentrant -{ - pos = ((uint16_t) ao_intflash + pos) >> 1; - - ao_dma_set_transfer(ao_intflash_dma, - d, - &FWDATAXADDR, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_FLASH, - DMA_CFG1_SRCINC_1 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_HIGH); - - FADDRH = pos >> 8; - FADDRL = pos; - - ao_dma_start(ao_intflash_dma); - - __critical { - _asm - .even - orl _FCTL, #FCTL_WRITE; ; FCTL |= FCTL_WRITE - nop - _endasm; - } -} - -static void -ao_intflash_write_byte(uint16_t pos, uint8_t byte) __reentrant -{ - static __xdata uint8_t b[2]; - - if (pos & 1) { - b[0] = 0xff; - b[1] = byte; - } else { - b[0] = byte; - b[1] = 0xff; - } - ao_intflash_write_aligned(pos, b, 2); -} - -uint8_t -ao_storage_device_write(uint32_t pos32, __xdata void *v, uint16_t len) __reentrant -{ - uint16_t pos = pos32; - __xdata uint8_t *d = v; - uint8_t oddlen; - - if (pos >= ao_storage_total || pos + len > ao_storage_total) - return 0; - if (len == 0) - return 1; - - if (pos & 1) { - ao_intflash_write_byte(pos++, *d++); - len--; - } - oddlen = len & 1; - len -= oddlen; - if (len) - ao_intflash_write_aligned(pos, d, len); - if (oddlen) - ao_intflash_write_byte(pos + len, d[len]); - - return 1; -} - -/* - * Read from flash - */ -uint8_t -ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant -{ - if (pos >= ao_storage_total || pos + len > ao_storage_total) - return 0; - memcpy(d, ao_intflash+pos, len); - return 1; -} - -void -ao_storage_flush(void) __reentrant -{ -} - -void -ao_storage_setup(void) -{ -} - -void -ao_storage_device_info(void) __reentrant -{ - printf ("Using internal flash, starting at 0x%04x\n", AO_INTFLASH_LOCATION); -} - -void -ao_storage_device_init(void) -{ - ao_intflash_dma = ao_dma_alloc(&ao_intflash_dma_done); - - FWT = FLASH_TIMING; -} diff --git a/src/ao_kalman.c b/src/ao_kalman.c deleted file mode 100644 index ee01949e..00000000 --- a/src/ao_kalman.c +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef AO_FLIGHT_TEST -#include "ao.h" -#endif - -#include "ao_kalman.h" - -static __pdata int32_t ao_k_height; -static __pdata int32_t ao_k_speed; -static __pdata int32_t ao_k_accel; - -#define AO_K_STEP_100 to_fix16(0.01) -#define AO_K_STEP_2_2_100 to_fix16(0.00005) - -#define AO_K_STEP_10 to_fix16(0.1) -#define AO_K_STEP_2_2_10 to_fix16(0.005) - -#define AO_K_STEP_1 to_fix16(1) -#define AO_K_STEP_2_2_1 to_fix16(0.5) - -__pdata int16_t ao_height; -__pdata int16_t ao_speed; -__pdata int16_t ao_accel; -__pdata int16_t ao_max_height; -static __pdata int32_t ao_avg_height_scaled; -__pdata int16_t ao_avg_height; - -__pdata int16_t ao_error_h; -__pdata int16_t ao_error_h_sq_avg; - -#if HAS_ACCEL -__pdata int16_t ao_error_a; -#endif - -static void -ao_kalman_predict(void) -{ -#ifdef AO_FLIGHT_TEST - if (ao_sample_tick - ao_sample_prev_tick > 50) { - ao_k_height += ((int32_t) ao_speed * AO_K_STEP_1 + - (int32_t) ao_accel * AO_K_STEP_2_2_1) >> 4; - ao_k_speed += (int32_t) ao_accel * AO_K_STEP_1; - - return; - } - if (ao_sample_tick - ao_sample_prev_tick > 5) { - ao_k_height += ((int32_t) ao_speed * AO_K_STEP_10 + - (int32_t) ao_accel * AO_K_STEP_2_2_10) >> 4; - ao_k_speed += (int32_t) ao_accel * AO_K_STEP_10; - - return; - } - if (ao_flight_debug) { - printf ("predict speed %g + (%g * %g) = %g\n", - ao_k_speed / (65536.0 * 16.0), ao_accel / 16.0, AO_K_STEP_100 / 65536.0, - (ao_k_speed + (int32_t) ao_accel * AO_K_STEP_100) / (65536.0 * 16.0)); - } -#endif - ao_k_height += ((int32_t) ao_speed * AO_K_STEP_100 + - (int32_t) ao_accel * AO_K_STEP_2_2_100) >> 4; - ao_k_speed += (int32_t) ao_accel * AO_K_STEP_100; -} - -static void -ao_kalman_err_height(void) -{ - int16_t e; - int16_t height_distrust; -#if HAS_ACCEL - int16_t speed_distrust; -#endif - - ao_error_h = ao_sample_height - (int16_t) (ao_k_height >> 16); - - e = ao_error_h; - if (e < 0) - e = -e; - if (e > 127) - e = 127; -#if HAS_ACCEL - ao_error_h_sq_avg -= ao_error_h_sq_avg >> 2; - ao_error_h_sq_avg += (e * e) >> 2; -#else - ao_error_h_sq_avg -= ao_error_h_sq_avg >> 4; - ao_error_h_sq_avg += (e * e) >> 4; -#endif - - if (ao_flight_state >= ao_flight_drogue) - return; - height_distrust = ao_sample_alt - AO_MAX_BARO_HEIGHT; -#if HAS_ACCEL - /* speed is stored * 16, but we need to ramp between 200 and 328, so - * we want to multiply by 2. The result is a shift by 3. - */ - speed_distrust = (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) >> (4 - 1); - if (speed_distrust <= 0) - speed_distrust = 0; - else if (speed_distrust > height_distrust) - height_distrust = speed_distrust; -#endif - if (height_distrust > 0) { -#ifdef AO_FLIGHT_TEST - int old_ao_error_h = ao_error_h; -#endif - if (height_distrust > 0x100) - height_distrust = 0x100; - ao_error_h = (int16_t) (((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8); -#ifdef AO_FLIGHT_TEST - if (ao_flight_debug) { - printf("over height %g over speed %g distrust: %g height: error %d -> %d\n", - (double) (ao_sample_alt - AO_MAX_BARO_HEIGHT), - (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) / 16.0, - height_distrust / 256.0, - old_ao_error_h, ao_error_h); - } -#endif - } -} - -static void -ao_kalman_correct_baro(void) -{ - ao_kalman_err_height(); -#ifdef AO_FLIGHT_TEST - if (ao_sample_tick - ao_sample_prev_tick > 50) { - ao_k_height += (int32_t) AO_BARO_K0_1 * ao_error_h; - ao_k_speed += (int32_t) AO_BARO_K1_1 * ao_error_h; - ao_k_accel += (int32_t) AO_BARO_K2_1 * ao_error_h; - return; - } - if (ao_sample_tick - ao_sample_prev_tick > 5) { - ao_k_height += (int32_t) AO_BARO_K0_10 * ao_error_h; - ao_k_speed += (int32_t) AO_BARO_K1_10 * ao_error_h; - ao_k_accel += (int32_t) AO_BARO_K2_10 * ao_error_h; - return; - } -#endif - ao_k_height += (int32_t) AO_BARO_K0_100 * ao_error_h; - ao_k_speed += (int32_t) AO_BARO_K1_100 * ao_error_h; - ao_k_accel += (int32_t) AO_BARO_K2_100 * ao_error_h; -} - -#if HAS_ACCEL - -static void -ao_kalman_err_accel(void) -{ - int32_t accel; - - accel = (ao_ground_accel - ao_sample_accel) * ao_accel_scale; - - /* Can't use ao_accel here as it is the pre-prediction value still */ - ao_error_a = (accel - ao_k_accel) >> 16; -} - -static void -ao_kalman_correct_both(void) -{ - ao_kalman_err_height(); - ao_kalman_err_accel(); - -#ifdef AO_FLIGHT_TEST - if (ao_sample_tick - ao_sample_prev_tick > 50) { - if (ao_flight_debug) { - printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", - ao_k_speed / (65536.0 * 16.0), - (double) ao_error_h, AO_BOTH_K10_1 / 65536.0, - (double) ao_error_a, AO_BOTH_K11_1 / 65536.0, - (ao_k_speed + - (int32_t) AO_BOTH_K10_1 * ao_error_h + - (int32_t) AO_BOTH_K11_1 * ao_error_a) / (65536.0 * 16.0)); - } - ao_k_height += - (int32_t) AO_BOTH_K00_1 * ao_error_h + - (int32_t) AO_BOTH_K01_1 * ao_error_a; - ao_k_speed += - (int32_t) AO_BOTH_K10_1 * ao_error_h + - (int32_t) AO_BOTH_K11_1 * ao_error_a; - ao_k_accel += - (int32_t) AO_BOTH_K20_1 * ao_error_h + - (int32_t) AO_BOTH_K21_1 * ao_error_a; - return; - } - if (ao_sample_tick - ao_sample_prev_tick > 5) { - if (ao_flight_debug) { - printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", - ao_k_speed / (65536.0 * 16.0), - (double) ao_error_h, AO_BOTH_K10_10 / 65536.0, - (double) ao_error_a, AO_BOTH_K11_10 / 65536.0, - (ao_k_speed + - (int32_t) AO_BOTH_K10_10 * ao_error_h + - (int32_t) AO_BOTH_K11_10 * ao_error_a) / (65536.0 * 16.0)); - } - ao_k_height += - (int32_t) AO_BOTH_K00_10 * ao_error_h + - (int32_t) AO_BOTH_K01_10 * ao_error_a; - ao_k_speed += - (int32_t) AO_BOTH_K10_10 * ao_error_h + - (int32_t) AO_BOTH_K11_10 * ao_error_a; - ao_k_accel += - (int32_t) AO_BOTH_K20_10 * ao_error_h + - (int32_t) AO_BOTH_K21_10 * ao_error_a; - return; - } - if (ao_flight_debug) { - printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", - ao_k_speed / (65536.0 * 16.0), - (double) ao_error_h, AO_BOTH_K10_100 / 65536.0, - (double) ao_error_a, AO_BOTH_K11_100 / 65536.0, - (ao_k_speed + - (int32_t) AO_BOTH_K10_100 * ao_error_h + - (int32_t) AO_BOTH_K11_100 * ao_error_a) / (65536.0 * 16.0)); - } -#endif - ao_k_height += - (int32_t) AO_BOTH_K00_100 * ao_error_h + - (int32_t) AO_BOTH_K01_100 * ao_error_a; - ao_k_speed += - (int32_t) AO_BOTH_K10_100 * ao_error_h + - (int32_t) AO_BOTH_K11_100 * ao_error_a; - ao_k_accel += - (int32_t) AO_BOTH_K20_100 * ao_error_h + - (int32_t) AO_BOTH_K21_100 * ao_error_a; -} - -#ifdef FORCE_ACCEL -static void -ao_kalman_correct_accel(void) -{ - ao_kalman_err_accel(); - - if (ao_sample_tick - ao_sample_prev_tick > 5) { - ao_k_height +=(int32_t) AO_ACCEL_K0_10 * ao_error_a; - ao_k_speed += (int32_t) AO_ACCEL_K1_10 * ao_error_a; - ao_k_accel += (int32_t) AO_ACCEL_K2_10 * ao_error_a; - return; - } - ao_k_height += (int32_t) AO_ACCEL_K0_100 * ao_error_a; - ao_k_speed += (int32_t) AO_ACCEL_K1_100 * ao_error_a; - ao_k_accel += (int32_t) AO_ACCEL_K2_100 * ao_error_a; -} -#endif -#endif /* HAS_ACCEL */ - -void -ao_kalman(void) -{ - ao_kalman_predict(); -#if HAS_ACCEL - if (ao_flight_state <= ao_flight_coast) { -#ifdef FORCE_ACCEL - ao_kalman_correct_accel(); -#else - ao_kalman_correct_both(); -#endif - } else -#endif - ao_kalman_correct_baro(); - ao_height = from_fix(ao_k_height); - ao_speed = from_fix(ao_k_speed); - ao_accel = from_fix(ao_k_accel); - if (ao_height > ao_max_height) - ao_max_height = ao_height; - ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_sample_height; -#ifdef AO_FLIGHT_TEST - if (ao_sample_tick - ao_sample_prev_tick > 50) - ao_avg_height = (ao_avg_height_scaled + 1) >> 1; - else if (ao_sample_tick - ao_sample_prev_tick > 5) - ao_avg_height = (ao_avg_height_scaled + 7) >> 4; - else -#endif - ao_avg_height = (ao_avg_height_scaled + 63) >> 7; -#ifdef AO_FLIGHT_TEST - ao_sample_prev_tick = ao_sample_tick; -#endif -} diff --git a/src/ao_led.c b/src/ao_led.c deleted file mode 100644 index 5beed58d..00000000 --- a/src/ao_led.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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" - -__pdata uint8_t ao_led_enable; - -void -ao_led_on(uint8_t colors) -{ - P1 |= (colors & ao_led_enable); -} - -void -ao_led_off(uint8_t colors) -{ - P1 &= ~(colors & ao_led_enable); -} - -void -ao_led_set(uint8_t colors) -{ - P1 = (P1 & ~(ao_led_enable)) | (colors & ao_led_enable); -} - -void -ao_led_toggle(uint8_t colors) -{ - P1 ^= (colors & ao_led_enable); -} - -void -ao_led_for(uint8_t colors, uint16_t ticks) __reentrant -{ - ao_led_on(colors); - ao_delay(ticks); - ao_led_off(colors); -} - -void -ao_led_init(uint8_t enable) -{ - ao_led_enable = enable; - P1SEL &= ~enable; - P1 &= ~enable; - P1DIR |= enable; -} diff --git a/src/ao_log.c b/src/ao_log.c deleted file mode 100644 index 6d3ad535..00000000 --- a/src/ao_log.c +++ /dev/null @@ -1,284 +0,0 @@ -/* - * 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" - -__pdata uint32_t ao_log_current_pos; -__pdata uint32_t ao_log_end_pos; -__pdata uint32_t ao_log_start_pos; -__xdata uint8_t ao_log_running; -__pdata enum flight_state ao_log_state; -__xdata uint16_t ao_flight_number; - -__code uint8_t ao_log_format = AO_LOG_FORMAT_FULL; - -void -ao_log_flush(void) -{ - ao_storage_flush(); -} - -/* - * When erasing a flight log, make sure the config block - * has an up-to-date version of the current flight number - */ - -struct ao_log_erase { - uint8_t unused; - uint16_t flight; -}; - -static __xdata struct ao_log_erase erase; - -#define LOG_MAX_ERASE 16 - -static uint32_t -ao_log_erase_pos(uint8_t i) -{ - return i * sizeof (struct ao_log_erase) + AO_STORAGE_ERASE_LOG; -} - -void -ao_log_write_erase(uint8_t pos) -{ - erase.unused = 0x00; - erase.flight = ao_flight_number; - ao_storage_write(ao_log_erase_pos(pos), &erase, sizeof (erase)); - ao_storage_flush(); -} - -static void -ao_log_read_erase(uint8_t pos) -{ - ao_storage_read(ao_log_erase_pos(pos), &erase, sizeof (erase)); -} - - -static void -ao_log_erase_mark(void) -{ - uint8_t i; - - for (i = 0; i < LOG_MAX_ERASE; i++) { - ao_log_read_erase(i); - if (erase.unused == 0 && erase.flight == ao_flight_number) - return; - if (erase.unused == 0xff) { - ao_log_write_erase(i); - return; - } - } - ao_config_put(); -} - -static uint8_t -ao_log_slots() -{ - return (uint8_t) (ao_storage_config / ao_config.flight_log_max); -} - -uint32_t -ao_log_pos(uint8_t slot) -{ - return ((slot) * ao_config.flight_log_max); -} - -static uint16_t -ao_log_max_flight(void) -{ - uint8_t log_slot; - uint8_t log_slots; - uint16_t log_flight; - uint16_t max_flight = 0; - - /* Scan the log space looking for the biggest flight number */ - log_slots = ao_log_slots(); - for (log_slot = 0; log_slot < log_slots; log_slot++) { - log_flight = ao_log_flight(log_slot); - if (!log_flight) - continue; - if (max_flight == 0 || (int16_t) (log_flight - max_flight) > 0) - max_flight = log_flight; - } - return max_flight; -} - -void -ao_log_scan(void) __reentrant -{ - uint8_t log_slot; - uint8_t log_slots; - uint8_t log_want; - - ao_config_get(); - - ao_flight_number = ao_log_max_flight(); - if (ao_flight_number) - if (++ao_flight_number == 0) - ao_flight_number = 1; - - /* Now look through the log of flight numbers from erase operations and - * see if the last one is bigger than what we found above - */ - for (log_slot = LOG_MAX_ERASE; log_slot-- > 0;) { - ao_log_read_erase(log_slot); - if (erase.unused == 0) { - if (ao_flight_number == 0 || - (int16_t) (erase.flight - ao_flight_number) > 0) - ao_flight_number = erase.flight; - break; - } - } - if (ao_flight_number == 0) - ao_flight_number = 1; - - /* With a flight number in hand, find a place to write a new log, - * use the target flight number to index the available log slots so - * that we write logs to each spot about the same number of times. - */ - - /* Find a log slot for the next flight, if available */ - ao_log_current_pos = ao_log_end_pos = 0; - log_slots = ao_log_slots(); - log_want = (ao_flight_number - 1) % log_slots; - log_slot = log_want; - do { - if (ao_log_flight(log_slot) == 0) { - ao_log_current_pos = ao_log_pos(log_slot); - ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; - break; - } - if (++log_slot >= log_slots) - log_slot = 0; - } while (log_slot != log_want); - - ao_wakeup(&ao_flight_number); -} - -void -ao_log_start(void) -{ - /* start logging */ - ao_log_running = 1; - ao_wakeup(&ao_log_running); -} - -void -ao_log_stop(void) -{ - ao_log_running = 0; - ao_log_flush(); -} - -uint8_t -ao_log_present(void) -{ - return ao_log_max_flight() != 0; -} - -uint8_t -ao_log_full(void) -{ - return ao_log_current_pos == ao_log_end_pos; -} - -static __xdata struct ao_task ao_log_task; - -void -ao_log_list(void) __reentrant -{ - uint8_t slot; - uint8_t slots; - uint16_t flight; - - slots = ao_log_slots(); - for (slot = 0; slot < slots; slot++) - { - flight = ao_log_flight(slot); - if (flight) - printf ("flight %d start %x end %x\n", - flight, - (uint16_t) (ao_log_pos(slot) >> 8), - (uint16_t) (ao_log_pos(slot+1) >> 8)); - } - printf ("done\n"); -} - -void -ao_log_delete(void) __reentrant -{ - uint8_t slot; - uint8_t slots; - - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - - slots = ao_log_slots(); - /* Look for the flight log matching the requested flight */ - if (ao_cmd_lex_i) { - for (slot = 0; slot < slots; slot++) { - if (ao_log_flight(slot) == ao_cmd_lex_i) { - ao_log_erase_mark(); - ao_log_current_pos = ao_log_pos(slot); - ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; - while (ao_log_current_pos < ao_log_end_pos) { - uint8_t i; - static __xdata uint8_t b; - - /* - * Check to see if we've reached the end of - * the used memory to avoid re-erasing the same - * memory over and over again - */ - for (i = 0; i < 16; i++) { - if (ao_storage_read(ao_log_current_pos + i, &b, 1)) - if (b != 0xff) - break; - } - if (i == 16) - break; - ao_storage_erase(ao_log_current_pos); - ao_log_current_pos += ao_storage_block; - } - puts("Erased"); - return; - } - } - } - printf("No such flight: %d\n", ao_cmd_lex_i); -} - -__code struct ao_cmds ao_log_cmds[] = { - { ao_log_list, "l\0List flight logs" }, - { ao_log_delete, "d \0Delete flight" }, - { 0, NULL }, -}; - -void -ao_log_init(void) -{ - ao_log_running = 0; - - /* For now, just log the flight starting at the begining of eeprom */ - ao_log_state = ao_flight_invalid; - - ao_cmd_register(&ao_log_cmds[0]); - - /* Create a task to log events to eeprom */ - ao_add_task(&ao_log_task, ao_log, "log"); -} diff --git a/src/ao_log_big.c b/src/ao_log_big.c deleted file mode 100644 index 74d94c4b..00000000 --- a/src/ao_log_big.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -static __xdata uint8_t ao_log_mutex; -static __xdata struct ao_log_record log; - -static uint8_t -ao_log_csum(__xdata uint8_t *b) __reentrant -{ - uint8_t sum = 0x5a; - uint8_t i; - - for (i = 0; i < sizeof (struct ao_log_record); i++) - sum += *b++; - return -sum; -} - -uint8_t -ao_log_data(__xdata struct ao_log_record *log) __reentrant -{ - uint8_t wrote = 0; - /* set checksum */ - log->csum = 0; - log->csum = ao_log_csum((__xdata uint8_t *) log); - ao_mutex_get(&ao_log_mutex); { - if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) - ao_log_stop(); - if (ao_log_running) { - wrote = 1; - ao_storage_write(ao_log_current_pos, - log, - sizeof (struct ao_log_record)); - ao_log_current_pos += sizeof (struct ao_log_record); - } - } ao_mutex_put(&ao_log_mutex); - return wrote; -} - -static uint8_t -ao_log_dump_check_data(void) -{ - if (ao_log_csum((uint8_t *) &log) != 0) - return 0; - return 1; -} - -static __data uint8_t ao_log_adc_pos; - -/* a hack to make sure that ao_log_records fill the eeprom block in even units */ -typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; - -#define AO_SENSOR_INTERVAL_ASCENT 1 -#define AO_SENSOR_INTERVAL_DESCENT 10 -#define AO_OTHER_INTERVAL 32 - -void -ao_log(void) -{ - __pdata uint16_t next_sensor, next_other; - - ao_storage_setup(); - - ao_log_scan(); - - while (!ao_log_running) - ao_sleep(&ao_log_running); - - log.type = AO_LOG_FLIGHT; - log.tick = ao_sample_tick; -#if HAS_ACCEL - log.u.flight.ground_accel = ao_ground_accel; -#endif - log.u.flight.flight = ao_flight_number; - ao_log_data(&log); - - /* Write the whole contents of the ring to the log - * when starting up. - */ - ao_log_adc_pos = ao_adc_ring_next(ao_sample_adc); - next_other = next_sensor = ao_adc_ring[ao_log_adc_pos].tick; - ao_log_state = ao_flight_startup; - for (;;) { - /* Write samples to EEPROM */ - while (ao_log_adc_pos != ao_sample_adc) { - log.tick = ao_adc_ring[ao_log_adc_pos].tick; - if ((int16_t) (log.tick - next_sensor) >= 0) { - log.type = AO_LOG_SENSOR; - log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel; - log.u.sensor.pres = ao_adc_ring[ao_log_adc_pos].pres; - ao_log_data(&log); - if (ao_log_state <= ao_flight_coast) - next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; - else - next_sensor = log.tick + AO_SENSOR_INTERVAL_DESCENT; - } - if ((int16_t) (log.tick - next_other) >= 0) { - log.type = AO_LOG_TEMP_VOLT; - log.u.temp_volt.temp = ao_adc_ring[ao_log_adc_pos].temp; - log.u.temp_volt.v_batt = ao_adc_ring[ao_log_adc_pos].v_batt; - ao_log_data(&log); - log.type = AO_LOG_DEPLOY; - log.u.deploy.drogue = ao_adc_ring[ao_log_adc_pos].sense_d; - log.u.deploy.main = ao_adc_ring[ao_log_adc_pos].sense_m; - ao_log_data(&log); - next_other = log.tick + AO_OTHER_INTERVAL; - } - ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); - } - /* Write state change to EEPROM */ - if (ao_flight_state != ao_log_state) { - ao_log_state = ao_flight_state; - log.type = AO_LOG_STATE; - log.tick = ao_sample_tick; - log.u.state.state = ao_log_state; - log.u.state.reason = 0; - ao_log_data(&log); - - if (ao_log_state == ao_flight_landed) - ao_log_stop(); - } - - /* Wait for a while */ - ao_delay(AO_MS_TO_TICKS(100)); - - /* Stop logging when told to */ - while (!ao_log_running) - ao_sleep(&ao_log_running); - } -} - -uint16_t -ao_log_flight(uint8_t slot) -{ - if (!ao_storage_read(ao_log_pos(slot), - &log, - sizeof (struct ao_log_record))) - return 0; - - if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) - return log.u.flight.flight; - return 0; -} diff --git a/src/ao_log_telem.c b/src/ao_log_telem.c deleted file mode 100644 index 1b472efe..00000000 --- a/src/ao_log_telem.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -void -ao_log_write_erase(uint8_t pos) -{ - (void) pos; -} - -uint8_t -ao_log_present(void) -{ - return 0; -} diff --git a/src/ao_log_tiny.c b/src/ao_log_tiny.c deleted file mode 100644 index d5a3b99f..00000000 --- a/src/ao_log_tiny.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -static __data uint16_t ao_log_tiny_interval; - -#define AO_LOG_TINY_INTERVAL_DEFAULT AO_MS_TO_TICKS(1000) -#if USE_FAST_ASCENT_LOG -#define AO_LOG_TINY_INTERVAL_ASCENT AO_MS_TO_TICKS(100) -#define AO_PAD_RING 8 -#else -#define AO_LOG_TINY_INTERVAL_ASCENT AO_LOG_TINY_INTERVAL_DEFAULT -#define AO_PAD_RING 2 -#endif - -__code uint8_t ao_log_format = AO_LOG_FORMAT_TINY; - -void -ao_log_tiny_set_interval(uint16_t ticks) -{ - ao_log_tiny_interval = ticks; -} - - -static void ao_log_tiny_data(uint16_t d) -{ - if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) - ao_log_stop(); - if (ao_log_running) { - ao_storage_write(ao_log_current_pos, DATA_TO_XDATA(&d), 2); - ao_log_current_pos += 2; - } -} - -static __xdata uint16_t ao_log_pad_ring[AO_PAD_RING]; -static __pdata uint8_t ao_log_pad_ring_pos; - -#define ao_pad_ring_next(n) (((n) + 1) & (AO_PAD_RING - 1)) - -static void ao_log_tiny_queue(uint16_t d) -{ - ao_log_pad_ring[ao_log_pad_ring_pos] = d; - ao_log_pad_ring_pos = ao_pad_ring_next(ao_log_pad_ring_pos); -} - -static void ao_log_tiny_start(void) -{ - uint8_t p; - uint16_t d; - - ao_log_tiny_data(ao_flight_number); - ao_log_tiny_data(ao_ground_pres); - p = ao_log_pad_ring_pos; - do { - d = ao_log_pad_ring[p]; - /* - * ignore unwritten slots - */ - if (d) - ao_log_tiny_data(d); - p = ao_pad_ring_next(p); - } while (p != ao_log_pad_ring_pos); -} - -void -ao_log(void) -{ - uint16_t last_time; - uint16_t now; - enum ao_flight_state ao_log_tiny_state; - int32_t sum; - int16_t count; - uint8_t ao_log_adc; - uint8_t ao_log_started = 0; - - ao_storage_setup(); - - ao_log_scan(); - - ao_log_tiny_state = ao_flight_invalid; - ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; - sum = 0; - count = 0; - ao_log_adc = ao_sample_adc; - last_time = ao_time(); - for (;;) { - - /* - * Add in pending sample data - */ - ao_sleep(DATA_TO_XDATA(&ao_sample_adc)); - while (ao_log_adc != ao_sample_adc) { - sum += ao_adc_ring[ao_log_adc].pres; - count++; - ao_log_adc = ao_adc_ring_next(ao_log_adc); - } - if (ao_log_running) { - if (!ao_log_started) { - ao_log_tiny_start(); - ao_log_started = 1; - } - if (ao_flight_state != ao_log_tiny_state) { - ao_log_tiny_data(ao_flight_state | 0x8000); - ao_log_tiny_state = ao_flight_state; - ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT; -#if AO_LOG_TINY_INTERVAL_ASCENT != AO_LOG_TINY_INTERVAL_DEFAULT - if (ao_log_tiny_state <= ao_flight_coast) - ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; -#endif - if (ao_log_tiny_state == ao_flight_landed) - ao_log_stop(); - } - } - - /* Stop logging when told to */ - if (!ao_log_running && ao_log_started) - ao_exit(); - - /* - * Write out the sample when finished - */ - now = ao_time(); - if ((int16_t) (now - (last_time + ao_log_tiny_interval)) >= 0 && count) { - count = sum / count; - if (ao_log_started) - ao_log_tiny_data(count); - else - ao_log_tiny_queue(count); - sum = 0; - count = 0; - last_time = now; - } - } -} - -uint16_t -ao_log_flight(uint8_t slot) -{ - static __xdata uint16_t flight; - - (void) slot; - ao_storage_read(0, &flight, 2); - if (flight == 0xffff) - flight = 0; - return flight; -} diff --git a/src/ao_m25.c b/src/ao_m25.c deleted file mode 100644 index d7208273..00000000 --- a/src/ao_m25.c +++ /dev/null @@ -1,380 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -/* Total bytes of available storage */ -__pdata uint32_t ao_storage_total; - -/* Block size - device is erased in these units. At least 256 bytes */ -__pdata uint32_t ao_storage_block; - -/* Byte offset of config block. Will be ao_storage_block bytes long */ -__pdata uint32_t ao_storage_config; - -/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ -__pdata uint16_t ao_storage_unit; - -/* - * Each flash chip is arranged in 64kB sectors; the - * chip cannot erase in units smaller than that. - * - * Writing happens in units of 256 byte pages and - * can only change bits from 1 to 0. So, you can rewrite - * the same contents, or append to an existing page easily enough - */ - -#define M25_WREN 0x06 /* Write Enable */ -#define M25_WRDI 0x04 /* Write Disable */ -#define M25_RDID 0x9f /* Read Identification */ -#define M25_RDSR 0x05 /* Read Status Register */ -#define M25_WRSR 0x01 /* Write Status Register */ -#define M25_READ 0x03 /* Read Data Bytes */ -#define M25_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */ -#define M25_PP 0x02 /* Page Program */ -#define M25_SE 0xd8 /* Sector Erase */ -#define M25_BE 0xc7 /* Bulk Erase */ -#define M25_DP 0xb9 /* Deep Power-down */ - -/* RDID response */ -#define M25_MANUF_OFFSET 0 -#define M25_MEMORY_TYPE_OFFSET 1 -#define M25_CAPACITY_OFFSET 2 -#define M25_UID_OFFSET 3 -#define M25_CFI_OFFSET 4 -#define M25_RDID_LEN 4 /* that's all we need */ - -#define M25_CAPACITY_128KB 0x11 -#define M25_CAPACITY_256KB 0x12 -#define M25_CAPACITY_512KB 0x13 -#define M25_CAPACITY_1MB 0x14 -#define M25_CAPACITY_2MB 0x15 - -/* - * Status register bits - */ - -#define M25_STATUS_SRWD (1 << 7) /* Status register write disable */ -#define M25_STATUS_BP_MASK (7 << 2) /* Block protect bits */ -#define M25_STATUS_BP_SHIFT (2) -#define M25_STATUS_WEL (1 << 1) /* Write enable latch */ -#define M25_STATUS_WIP (1 << 0) /* Write in progress */ - -/* - * On teleterra, the m25 chip select pins are - * wired on P0_0 through P0_3. - */ - -#if M25_MAX_CHIPS > 1 -static uint8_t ao_m25_size[M25_MAX_CHIPS]; /* number of sectors in each chip */ -static uint8_t ao_m25_pin[M25_MAX_CHIPS]; /* chip select pin for each chip */ -static uint8_t ao_m25_numchips; /* number of chips detected */ -#endif -static uint8_t ao_m25_total; /* total sectors available */ -static uint8_t ao_m25_wip; /* write in progress */ - -static __xdata uint8_t ao_m25_mutex; - -/* - * This little array is abused to send and receive data. A particular - * caution -- the read and write addresses are written into the last - * three bytes of the array by ao_m25_set_page_address and then the - * first byte is used by ao_m25_wait_wip and ao_m25_write_enable, neither - * of which touch those last three bytes. - */ - -static __xdata uint8_t ao_m25_instruction[4]; - -#define M25_SELECT(cs) ao_spi_get_mask(SPI_CS_PORT,cs) -#define M25_DESELECT(cs) ao_spi_put_mask(SPI_CS_PORT,cs) - -#define M25_BLOCK_SHIFT 16 -#define M25_BLOCK 65536L -#define M25_POS_TO_SECTOR(pos) ((uint8_t) ((pos) >> M25_BLOCK_SHIFT)) -#define M25_SECTOR_TO_POS(sector) (((uint32_t) (sector)) << M25_BLOCK_SHIFT) - -/* - * Block until the specified chip is done writing - */ -static void -ao_m25_wait_wip(uint8_t cs) -{ - if (ao_m25_wip & cs) { - M25_SELECT(cs); - ao_m25_instruction[0] = M25_RDSR; - ao_spi_send(ao_m25_instruction, 1); - do { - ao_spi_recv(ao_m25_instruction, 1); - } while (ao_m25_instruction[0] & M25_STATUS_WIP); - M25_DESELECT(cs); - ao_m25_wip &= ~cs; - } -} - -/* - * Set the write enable latch so that page program and sector - * erase commands will work. Also mark the chip as busy writing - * so that future operations will block until the WIP bit goes off - */ -static void -ao_m25_write_enable(uint8_t cs) -{ - M25_SELECT(cs); - ao_m25_instruction[0] = M25_WREN; - ao_spi_send(&ao_m25_instruction, 1); - M25_DESELECT(cs); - ao_m25_wip |= cs; -} - - -/* - * Returns the number of 64kB sectors - */ -static uint8_t -ao_m25_read_capacity(uint8_t cs) -{ - uint8_t capacity; - M25_SELECT(cs); - ao_m25_instruction[0] = M25_RDID; - ao_spi_send(ao_m25_instruction, 1); - ao_spi_recv(ao_m25_instruction, M25_RDID_LEN); - M25_DESELECT(cs); - - /* Check to see if the chip is present */ - if (ao_m25_instruction[0] == 0xff) - return 0; - capacity = ao_m25_instruction[M25_CAPACITY_OFFSET]; - - /* Sanity check capacity number */ - if (capacity < 0x11 || 0x1f < capacity) - return 0; - return 1 << (capacity - 0x10); -} - -static uint8_t -ao_m25_set_address(uint32_t pos) -{ - uint8_t chip; -#if M25_MAX_CHIPS > 1 - uint8_t size; - - for (chip = 0; chip < ao_m25_numchips; chip++) { - size = ao_m25_size[chip]; - if (M25_POS_TO_SECTOR(pos) < size) - break; - pos -= M25_SECTOR_TO_POS(size); - } - if (chip == ao_m25_numchips) - return 0xff; - - chip = ao_m25_pin[chip]; -#else - chip = M25_CS_MASK; -#endif - ao_m25_wait_wip(chip); - - ao_m25_instruction[1] = pos >> 16; - ao_m25_instruction[2] = pos >> 8; - ao_m25_instruction[3] = pos; - return chip; -} - -/* - * Scan the possible chip select lines - * to see which flash chips are connected - */ -static uint8_t -ao_m25_scan(void) -{ -#if M25_MAX_CHIPS > 1 - uint8_t pin, size; -#endif - - if (ao_m25_total) - return 1; - -#if M25_MAX_CHIPS > 1 - ao_m25_numchips = 0; - for (pin = 1; pin != 0; pin <<= 1) { - if (M25_CS_MASK & pin) { - size = ao_m25_read_capacity(pin); - if (size != 0) { - ao_m25_size[ao_m25_numchips] = size; - ao_m25_pin[ao_m25_numchips] = pin; - ao_m25_total += size; - ao_m25_numchips++; - } - } - } -#else - ao_m25_total = ao_m25_read_capacity(M25_CS_MASK); -#endif - if (!ao_m25_total) - return 0; - ao_storage_total = M25_SECTOR_TO_POS(ao_m25_total); - ao_storage_block = M25_BLOCK; - ao_storage_config = ao_storage_total - M25_BLOCK; - ao_storage_unit = 256; - return 1; -} - -/* - * Erase the specified sector - */ -uint8_t -ao_storage_erase(uint32_t pos) __reentrant -{ - uint8_t cs; - - if (pos >= ao_storage_total || pos + ao_storage_block > ao_storage_total) - return 0; - - ao_mutex_get(&ao_m25_mutex); - ao_m25_scan(); - - cs = ao_m25_set_address(pos); - - ao_m25_wait_wip(cs); - ao_m25_write_enable(cs); - - ao_m25_instruction[0] = M25_SE; - M25_SELECT(cs); - ao_spi_send(ao_m25_instruction, 4); - M25_DESELECT(cs); - ao_m25_wip |= cs; - - ao_mutex_put(&ao_m25_mutex); - return 1; -} - -/* - * Write to flash - */ -uint8_t -ao_storage_device_write(uint32_t pos, __xdata void *d, uint16_t len) __reentrant -{ - uint8_t cs; - - if (pos >= ao_storage_total || pos + len > ao_storage_total) - return 0; - - ao_mutex_get(&ao_m25_mutex); - ao_m25_scan(); - - cs = ao_m25_set_address(pos); - ao_m25_write_enable(cs); - - ao_m25_instruction[0] = M25_PP; - M25_SELECT(cs); - ao_spi_send(ao_m25_instruction, 4); - ao_spi_send(d, len); - M25_DESELECT(cs); - - ao_mutex_put(&ao_m25_mutex); - return 1; -} - -/* - * Read from flash - */ -uint8_t -ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant -{ - uint8_t cs; - - if (pos >= ao_storage_total || pos + len > ao_storage_total) - return 0; - ao_mutex_get(&ao_m25_mutex); - ao_m25_scan(); - - cs = ao_m25_set_address(pos); - - /* No need to use the FAST_READ as we're running at only 8MHz */ - ao_m25_instruction[0] = M25_READ; - M25_SELECT(cs); - ao_spi_send(ao_m25_instruction, 4); - ao_spi_recv(d, len); - M25_DESELECT(cs); - - ao_mutex_put(&ao_m25_mutex); - return 1; -} - -void -ao_storage_flush(void) __reentrant -{ -} - -void -ao_storage_setup(void) -{ - ao_mutex_get(&ao_m25_mutex); - ao_m25_scan(); - ao_mutex_put(&ao_m25_mutex); -} - -void -ao_storage_device_info(void) __reentrant -{ - uint8_t cs; -#if M25_MAX_CHIPS > 1 - uint8_t chip; -#endif - - ao_mutex_get(&ao_m25_mutex); - ao_m25_scan(); - ao_mutex_put(&ao_m25_mutex); - -#if M25_MAX_CHIPS > 1 - printf ("Detected chips %d size %d\n", ao_m25_numchips, ao_m25_total); - for (chip = 0; chip < ao_m25_numchips; chip++) - printf ("Flash chip %d select %02x size %d\n", - chip, ao_m25_pin[chip], ao_m25_size[chip]); -#else - printf ("Detected chips 1 size %d\n", ao_m25_total); -#endif - - printf ("Available chips:\n"); - for (cs = 1; cs != 0; cs <<= 1) { - if ((M25_CS_MASK & cs) == 0) - continue; - - ao_mutex_get(&ao_m25_mutex); - M25_SELECT(cs); - ao_m25_instruction[0] = M25_RDID; - ao_spi_send(ao_m25_instruction, 1); - ao_spi_recv(ao_m25_instruction, M25_RDID_LEN); - M25_DESELECT(cs); - - printf ("Select %02x manf %02x type %02x cap %02x uid %02x\n", - cs, - ao_m25_instruction[M25_MANUF_OFFSET], - ao_m25_instruction[M25_MEMORY_TYPE_OFFSET], - ao_m25_instruction[M25_CAPACITY_OFFSET], - ao_m25_instruction[M25_UID_OFFSET]); - ao_mutex_put(&ao_m25_mutex); - } -} - -void -ao_storage_device_init(void) -{ - /* Set up chip select wires */ - SPI_CS_PORT |= M25_CS_MASK; /* raise all CS pins */ - SPI_CS_DIR |= M25_CS_MASK; /* set CS pins as outputs */ - SPI_CS_SEL &= ~M25_CS_MASK; /* set CS pins as GPIO */ -} diff --git a/src/ao_main.c b/src/ao_main.c deleted file mode 100644 index 25acccfc..00000000 --- a/src/ao_main.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * 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) -{ - ao_clock_init(); - - /* 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/src/ao_monitor.c b/src/ao_monitor.c deleted file mode 100644 index 69eb58e8..00000000 --- a/src/ao_monitor.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "ao_telem.h" - -#if !HAS_MONITOR -#error Must define HAS_MONITOR to 1 -#endif - -__xdata uint8_t ao_monitoring; -__pdata uint8_t ao_monitor_led; - -#define AO_MONITOR_RING 8 - -__xdata union ao_monitor { - struct ao_telemetry_raw_recv raw; - struct ao_telemetry_orig_recv orig; - struct ao_telemetry_tiny_recv tiny; -} ao_monitor_ring[AO_MONITOR_RING]; - -#define ao_monitor_ring_next(n) (((n) + 1) & (AO_MONITOR_RING - 1)) - -__data uint8_t ao_monitor_head; - -void -ao_monitor_get(void) -{ - uint8_t size; - - for (;;) { - switch (ao_monitoring) { - case 0: - ao_sleep(&ao_monitoring); - continue; - case AO_MONITORING_ORIG: - size = sizeof (struct ao_telemetry_orig_recv); - break; - case AO_MONITORING_TINY: - size = sizeof (struct ao_telemetry_tiny_recv); - break; - default: - if (ao_monitoring > AO_MAX_TELEMETRY) - ao_monitoring = AO_MAX_TELEMETRY; - size = ao_monitoring; - break; - } - if (!ao_radio_recv(&ao_monitor_ring[ao_monitor_head], size + 2)) - continue; - ao_monitor_head = ao_monitor_ring_next(ao_monitor_head); - ao_wakeup(DATA_TO_XDATA(&ao_monitor_head)); - ao_led_toggle(ao_monitor_led); - } -} - -void -ao_monitor_put(void) -{ - __xdata char callsign[AO_MAX_CALLSIGN+1]; - - uint8_t ao_monitor_tail; - uint8_t state; - uint8_t sum, byte; - int16_t rssi; - __xdata union ao_monitor *m; - -#define recv_raw ((m->raw)) -#define recv_orig ((m->orig)) -#define recv_tiny ((m->tiny)) - - ao_monitor_tail = ao_monitor_head; - for (;;) { - while (ao_monitor_tail == ao_monitor_head) - ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); - m = &ao_monitor_ring[ao_monitor_tail]; - ao_monitor_tail = ao_monitor_ring_next(ao_monitor_tail); - switch (ao_monitoring) { - case AO_MONITORING_ORIG: - state = recv_orig.telemetry_orig.flight_state; - - /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ - rssi = (int16_t) (recv_orig.rssi >> 1) - 74; - memcpy(callsign, recv_orig.telemetry_orig.callsign, AO_MAX_CALLSIGN); - if (state > ao_flight_invalid) - state = ao_flight_invalid; - if (recv_orig.status & PKT_APPEND_STATUS_1_CRC_OK) { - - /* General header fields */ - printf(AO_TELEM_VERSION " %d " - AO_TELEM_CALL " %s " - AO_TELEM_SERIAL " %d " - AO_TELEM_FLIGHT " %d " - AO_TELEM_RSSI " %d " - AO_TELEM_STATE " %s " - AO_TELEM_TICK " %d ", - AO_TELEMETRY_VERSION, - callsign, - recv_orig.telemetry_orig.serial, - recv_orig.telemetry_orig.flight, - rssi, - ao_state_names[state], - recv_orig.telemetry_orig.adc.tick); - - /* Raw sensor values */ - printf(AO_TELEM_RAW_ACCEL " %d " - AO_TELEM_RAW_BARO " %d " - AO_TELEM_RAW_THERMO " %d " - AO_TELEM_RAW_BATT " %d " - AO_TELEM_RAW_DROGUE " %d " - AO_TELEM_RAW_MAIN " %d ", - recv_orig.telemetry_orig.adc.accel, - recv_orig.telemetry_orig.adc.pres, - recv_orig.telemetry_orig.adc.temp, - recv_orig.telemetry_orig.adc.v_batt, - recv_orig.telemetry_orig.adc.sense_d, - recv_orig.telemetry_orig.adc.sense_m); - - /* Sensor calibration values */ - printf(AO_TELEM_CAL_ACCEL_GROUND " %d " - AO_TELEM_CAL_BARO_GROUND " %d " - AO_TELEM_CAL_ACCEL_PLUS " %d " - AO_TELEM_CAL_ACCEL_MINUS " %d ", - recv_orig.telemetry_orig.ground_accel, - recv_orig.telemetry_orig.ground_pres, - recv_orig.telemetry_orig.accel_plus_g, - recv_orig.telemetry_orig.accel_minus_g); - - if (recv_orig.telemetry_orig.u.k.unused == 0x8000) { - /* Kalman state values */ - printf(AO_TELEM_KALMAN_HEIGHT " %d " - AO_TELEM_KALMAN_SPEED " %d " - AO_TELEM_KALMAN_ACCEL " %d ", - recv_orig.telemetry_orig.height, - recv_orig.telemetry_orig.u.k.speed, - recv_orig.telemetry_orig.accel); - } else { - /* Ad-hoc flight values */ - printf(AO_TELEM_ADHOC_ACCEL " %d " - AO_TELEM_ADHOC_SPEED " %ld " - AO_TELEM_ADHOC_BARO " %d ", - recv_orig.telemetry_orig.accel, - recv_orig.telemetry_orig.u.flight_vel, - recv_orig.telemetry_orig.height); - } - ao_gps_print(&recv_orig.telemetry_orig.gps); - ao_gps_tracking_print(&recv_orig.telemetry_orig.gps_tracking); - putchar('\n'); - ao_rssi_set(rssi); - } else { - printf("CRC INVALID RSSI %3d\n", rssi); - } - break; - case AO_MONITORING_TINY: - state = recv_tiny.telemetry_tiny.flight_state; - - /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ - rssi = (int16_t) (recv_tiny.rssi >> 1) - 74; - memcpy(callsign, recv_tiny.telemetry_tiny.callsign, AO_MAX_CALLSIGN); - if (state > ao_flight_invalid) - state = ao_flight_invalid; - if (recv_tiny.status & PKT_APPEND_STATUS_1_CRC_OK) { - /* General header fields */ - printf(AO_TELEM_VERSION " %d " - AO_TELEM_CALL " %s " - AO_TELEM_SERIAL " %d " - AO_TELEM_FLIGHT " %d " - AO_TELEM_RSSI " %d " - AO_TELEM_STATE " %s " - AO_TELEM_TICK " %d ", - AO_TELEMETRY_VERSION, - callsign, - recv_tiny.telemetry_tiny.serial, - recv_tiny.telemetry_tiny.flight, - rssi, - ao_state_names[state], - recv_tiny.telemetry_tiny.adc.tick); - - /* Raw sensor values */ - printf(AO_TELEM_RAW_BARO " %d " - AO_TELEM_RAW_THERMO " %d " - AO_TELEM_RAW_BATT " %d " - AO_TELEM_RAW_DROGUE " %d " - AO_TELEM_RAW_MAIN " %d ", - recv_tiny.telemetry_tiny.adc.pres, - recv_tiny.telemetry_tiny.adc.temp, - recv_tiny.telemetry_tiny.adc.v_batt, - recv_tiny.telemetry_tiny.adc.sense_d, - recv_tiny.telemetry_tiny.adc.sense_m); - - /* Sensor calibration values */ - printf(AO_TELEM_CAL_BARO_GROUND " %d ", - recv_tiny.telemetry_tiny.ground_pres); - -#if 1 - /* Kalman state values */ - printf(AO_TELEM_KALMAN_HEIGHT " %d " - AO_TELEM_KALMAN_SPEED " %d " - AO_TELEM_KALMAN_ACCEL " %d\n", - recv_tiny.telemetry_tiny.height, - recv_tiny.telemetry_tiny.speed, - recv_tiny.telemetry_tiny.accel); -#else - /* Ad-hoc flight values */ - printf(AO_TELEM_ADHOC_ACCEL " %d " - AO_TELEM_ADHOC_SPEED " %ld " - AO_TELEM_ADHOC_BARO " %d\n", - recv_tiny.telemetry_tiny.flight_accel, - recv_tiny.telemetry_tiny.flight_vel, - recv_tiny.telemetry_tiny.flight_pres); -#endif - ao_rssi_set(rssi); - } else { - printf("CRC INVALID RSSI %3d\n", rssi); - } - break; - default: - printf ("TELEM %02x", ao_monitoring + 2); - sum = 0x5a; - for (state = 0; state < ao_monitoring + 2; state++) { - byte = recv_raw.packet[state]; - sum += byte; - printf("%02x", byte); - } - printf("%02x\n", sum); - break; - } - ao_usb_flush(); - } -} - -__xdata struct ao_task ao_monitor_get_task; -__xdata struct ao_task ao_monitor_put_task; - -void -ao_set_monitor(uint8_t monitoring) -{ - if (ao_monitoring) - ao_radio_recv_abort(); - ao_monitoring = monitoring; - ao_wakeup(&ao_monitoring); -} - -static void -set_monitor(void) -{ - ao_cmd_hex(); - ao_set_monitor(ao_cmd_lex_i); -} - -__code struct ao_cmds ao_monitor_cmds[] = { - { set_monitor, "m <0 off, 1 full, 2 tiny>\0Enable/disable radio monitoring" }, - { 0, NULL }, -}; - -void -ao_monitor_init(uint8_t monitor_led, uint8_t monitoring) __reentrant -{ - ao_monitor_led = monitor_led; - ao_monitoring = monitoring; - ao_cmd_register(&ao_monitor_cmds[0]); - ao_add_task(&ao_monitor_get_task, ao_monitor_get, "monitor_get"); - ao_add_task(&ao_monitor_put_task, ao_monitor_put, "monitor_put"); -} diff --git a/src/ao_mutex.c b/src/ao_mutex.c deleted file mode 100644 index c82a7d57..00000000 --- a/src/ao_mutex.c +++ /dev/null @@ -1,41 +0,0 @@ -/* - * 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_mutex_get(__xdata uint8_t *mutex) __reentrant -{ - if (*mutex == ao_cur_task->task_id) - ao_panic(AO_PANIC_MUTEX); - __critical { - while (*mutex) - ao_sleep(mutex); - *mutex = ao_cur_task->task_id; - } -} - -void -ao_mutex_put(__xdata uint8_t *mutex) __reentrant -{ - if (*mutex != ao_cur_task->task_id) - ao_panic(AO_PANIC_MUTEX); - __critical { - *mutex = 0; - ao_wakeup(mutex); - } -} diff --git a/src/ao_packet.c b/src/ao_packet.c deleted file mode 100644 index f627e02b..00000000 --- a/src/ao_packet.c +++ /dev/null @@ -1,148 +0,0 @@ -/* - * 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" - -__xdata struct ao_packet_recv ao_rx_packet; -__xdata struct ao_packet ao_tx_packet; -__pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; - -static __xdata char tx_data[AO_PACKET_MAX]; -static __xdata char rx_data[AO_PACKET_MAX]; -static __pdata uint8_t rx_seq; - -__xdata struct ao_task ao_packet_task; -__xdata uint8_t ao_packet_enable; -__xdata uint8_t ao_packet_master_sleeping; - -void -ao_packet_send(void) -{ - ao_led_on(AO_LED_RED); - /* If any tx data is pending then copy it into the tx packet */ - if (ao_packet_tx_used && ao_tx_packet.len == 0) { - memcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); - ao_tx_packet.len = ao_packet_tx_used; - ao_tx_packet.seq++; - ao_packet_tx_used = 0; - ao_wakeup(&tx_data); - } - ao_radio_send(&ao_tx_packet, sizeof (ao_tx_packet)); - ao_led_off(AO_LED_RED); -} - -uint8_t -ao_packet_recv(void) -{ - uint8_t dma_done; - -#ifdef AO_LED_GREEN - ao_led_on(AO_LED_GREEN); -#endif - dma_done = ao_radio_recv(&ao_rx_packet, sizeof (struct ao_packet_recv)); -#ifdef AO_LED_GREEN - ao_led_off(AO_LED_GREEN); -#endif - - /* Check to see if we got a valid packet */ - if (!dma_done) - return 0; - if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) - return 0; - - /* SYN packets carry no data */ - if (ao_rx_packet.packet.len == AO_PACKET_SYN) { - rx_seq = ao_rx_packet.packet.seq; - ao_tx_packet.seq = ao_rx_packet.packet.ack; - ao_tx_packet.ack = rx_seq; - } else if (ao_rx_packet.packet.len) { - - /* Check for incoming data at the next sequence and - * for an empty data buffer - */ - if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) && - ao_packet_rx_used == ao_packet_rx_len) { - - /* Copy data to the receive data buffer and set up the - * offsets - */ - memcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); - ao_packet_rx_used = 0; - ao_packet_rx_len = ao_rx_packet.packet.len; - - /* Mark the sequence that we've received to - * let the sender know when we return a packet - */ - rx_seq = ao_rx_packet.packet.seq; - ao_tx_packet.ack = rx_seq; - - /* Poke anyone looking for received data */ - ao_wakeup(&ao_stdin_ready); - } - } - - /* If the other side has seen the latest data we queued, - * wake up any task waiting to send data and let them go again - */ - if (ao_rx_packet.packet.ack == ao_tx_packet.seq) { - ao_tx_packet.len = 0; - ao_wakeup(&ao_tx_packet); - } - return 1; -} - -#ifndef PACKET_HAS_MASTER -#define PACKET_HAS_MASTER 1 -#endif - -#if PACKET_HAS_MASTER -void -ao_packet_flush(void) -{ - /* If there is data to send, and this is the master, - * then poke the master to send all queued data - */ - if (ao_packet_tx_used && ao_packet_master_sleeping) - ao_wakeup(&ao_packet_master_sleeping); -} -#endif /* PACKET_HAS_MASTER */ - -void -ao_packet_putchar(char c) __reentrant -{ - while (ao_packet_tx_used == AO_PACKET_MAX && ao_packet_enable) { -#if PACKET_HAS_MASTER - ao_packet_flush(); -#endif - ao_sleep(&tx_data); - } - - if (ao_packet_enable) - tx_data[ao_packet_tx_used++] = c; -} - -char -ao_packet_pollchar(void) __critical -{ - if (!ao_packet_enable) - return AO_READ_AGAIN; - - if (ao_packet_rx_used == ao_packet_rx_len) - return AO_READ_AGAIN; - - return rx_data[ao_packet_rx_used++]; -} diff --git a/src/ao_packet_master.c b/src/ao_packet_master.c deleted file mode 100644 index b0fdf5a8..00000000 --- a/src/ao_packet_master.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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" - -static char -ao_packet_getchar(void) __critical -{ - char c; - while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) { - if (!ao_packet_enable) - break; - if (ao_packet_master_sleeping) - ao_wakeup(&ao_packet_master_sleeping); - flush(); - ao_sleep(&ao_stdin_ready); - } - return c; -} - -static void -ao_packet_echo(void) __reentrant -{ - char c; - while (ao_packet_enable) { - c = ao_packet_getchar(); - if (c != AO_READ_AGAIN) - putchar(c); - } - ao_exit(); -} - -static __xdata struct ao_task ao_packet_echo_task; -static __xdata uint16_t ao_packet_master_delay; -static __xdata uint16_t ao_packet_master_time; - -#define AO_PACKET_MASTER_DELAY_SHORT AO_MS_TO_TICKS(100) -#define AO_PACKET_MASTER_DELAY_LONG AO_MS_TO_TICKS(1000) -#define AO_PACKET_MASTER_DELAY_TIMEOUT AO_MS_TO_TICKS(2000) - -static void -ao_packet_master_busy(void) -{ - ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; - ao_packet_master_time = ao_time(); -} - -static void -ao_packet_master_check_busy(void) -{ - int16_t idle; - if (ao_packet_master_delay != AO_PACKET_MASTER_DELAY_SHORT) - return; - idle = (int16_t) (ao_time() - ao_packet_master_time); - - if (idle > AO_PACKET_MASTER_DELAY_TIMEOUT) - ao_packet_master_delay = AO_PACKET_MASTER_DELAY_LONG; -} - -void -ao_packet_master(void) -{ - ao_config_get(); - ao_tx_packet.addr = ao_serial_number; - ao_tx_packet.len = AO_PACKET_SYN; - ao_packet_master_time = ao_time(); - ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; - while (ao_packet_enable) { - memcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN); - ao_packet_send(); - if (ao_tx_packet.len) - ao_packet_master_busy(); - ao_packet_master_check_busy(); - ao_alarm(ao_packet_master_delay); - if (ao_packet_recv()) { - /* if we can transmit data, do so */ - if (ao_packet_tx_used && ao_tx_packet.len == 0) - continue; - if (ao_rx_packet.packet.len) - ao_packet_master_busy(); - ao_packet_master_sleeping = 1; - ao_alarm(ao_packet_master_delay); - ao_sleep(&ao_packet_master_sleeping); - ao_packet_master_sleeping = 0; - } - } - ao_exit(); -} - -static void -ao_packet_forward(void) __reentrant -{ - char c; - ao_packet_enable = 1; - ao_cmd_white(); - - flush(); -#if HAS_MONITOR - ao_set_monitor(0); -#endif - ao_add_task(&ao_packet_task, ao_packet_master, "master"); - ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); - while ((c = getchar()) != '~') { - if (c == '\r') c = '\n'; - ao_packet_putchar(c); - } - - /* Wait for a second if there is any pending data */ - for (c = 0; (ao_packet_tx_used || ao_tx_packet.len) && c < 10; c++) - ao_delay(AO_MS_TO_TICKS(100)); - ao_packet_enable = 0; - while (ao_packet_echo_task.wchan || ao_packet_task.wchan) { - ao_radio_recv_abort(); - ao_wakeup(&ao_stdin_ready); - ao_delay(AO_MS_TO_TICKS(10)); - } -} - - - -__code struct ao_cmds ao_packet_master_cmds[] = { - { ao_packet_forward, "p\0Remote packet link." }, - { 0, NULL }, -}; - -void -ao_packet_master_init(void) -{ - ao_cmd_register(&ao_packet_master_cmds[0]); -} diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c deleted file mode 100644 index 9f14052a..00000000 --- a/src/ao_packet_slave.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * 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_packet_slave(void) -{ - ao_tx_packet.addr = ao_serial_number; - ao_tx_packet.len = AO_PACKET_SYN; - while (ao_packet_enable) { - if (ao_packet_recv()) { - memcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN); -#if HAS_FLIGHT - ao_flight_force_idle = TRUE; -#endif - ao_packet_send(); - } - } - ao_exit(); -} - -void -ao_packet_slave_start(void) -{ - ao_packet_enable = 1; - ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); -} - -void -ao_packet_slave_stop(void) -{ - if (ao_packet_enable) { - ao_packet_enable = 0; - while (ao_packet_task.wchan) { - ao_radio_recv_abort(); - ao_delay(AO_MS_TO_TICKS(10)); - } - } -} - -void -ao_packet_slave_init(uint8_t enable) -{ - ao_add_stdio(ao_packet_pollchar, - ao_packet_putchar, - NULL); - if (enable) - ao_packet_slave_start(); -} diff --git a/src/ao_panic.c b/src/ao_panic.c deleted file mode 100644 index fdada201..00000000 --- a/src/ao_panic.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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" - -#ifndef HAS_BEEP -#error Please define HAS_BEEP -#endif - -#if !HAS_BEEP -#define ao_beep(x) -#endif - -static void -ao_panic_delay(uint8_t n) -{ - uint8_t i = 0, j = 0; - - while (n--) - while (--j) - while (--i) - _asm nop _endasm; -} - -void -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); - ao_panic_delay(1); - ao_led_off(AO_LED_RED); - ao_beep(AO_BEEP_LOW); - ao_panic_delay(1); - } - 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); - ao_panic_delay(10); - ao_led_off(AO_LED_RED); - ao_beep(AO_BEEP_OFF); - ao_panic_delay(10); - } - } -} diff --git a/src/ao_pins.h b/src/ao_pins.h deleted file mode 100644 index e1f5459f..00000000 --- a/src/ao_pins.h +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_PINS_H_ -#define _AO_PINS_H_ - -#if defined(TELEMETRUM_V_1_0) - #define HAS_FLIGHT 1 - #define HAS_USB 1 - #define HAS_BEEP 1 - #define HAS_GPS 1 - #define HAS_SERIAL_1 1 - #define HAS_ADC 1 - #define USE_SERIAL_STDIN 0 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 0 - #define HAS_DBG 1 - #define DBG_ON_P1 1 - #define DBG_ON_P0 0 - #define IGNITE_ON_P2 1 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - - #define HAS_COMPANION 1 - #define COMPANION_CS_ON_P1 1 - #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ - #define COMPANION_CS P1_2 - - #define AO_LED_RED 1 - #define LEDS_AVAILABLE (AO_LED_RED) - #define HAS_EXTERNAL_TEMP 0 - #define HAS_ACCEL_REF 0 - #define HAS_ACCEL 1 - #define HAS_IGNITE 1 - #define HAS_MONITOR 0 -#endif - -#if defined(TELEMETRUM_V_1_1) - #define HAS_FLIGHT 1 - #define HAS_USB 1 - #define HAS_BEEP 1 - #define HAS_GPS 1 - #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 1 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 0 - #define HAS_DBG 1 - #define DBG_ON_P1 1 - #define DBG_ON_P0 0 - #define IGNITE_ON_P2 1 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - - #define HAS_COMPANION 1 - #define COMPANION_CS_ON_P1 1 - #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ - #define COMPANION_CS P1_2 - - #define AO_LED_RED 1 - #define LEDS_AVAILABLE (AO_LED_RED) - #define HAS_EXTERNAL_TEMP 0 - #define HAS_ACCEL_REF 1 - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ - #define M25_MAX_CHIPS 1 - #define HAS_ACCEL 1 - #define HAS_IGNITE 1 - #define HAS_MONITOR 0 -#endif - -#if defined(TELEDONGLE_V_0_2) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 0 - #define HAS_DBG 1 - #define HAS_EEPROM 0 - #define DBG_ON_P1 1 - #define DBG_ON_P0 0 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 1 - #define AO_LED_GREEN 2 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define HAS_IGNITE 0 - #define HAS_MONITOR 1 -#endif - -#if defined(TELEMINI_V_1_0) - #define HAS_FLIGHT 1 - #define HAS_USB 0 - #define HAS_BEEP 0 - #define HAS_GPS 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 1 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 1 - #define HAS_DBG 0 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 1 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - #define USE_FAST_ASCENT_LOG 1 - - #define AO_LED_GREEN 1 - #define AO_LED_RED 2 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define HAS_EXTERNAL_TEMP 0 - #define HAS_ACCEL 0 - #define HAS_IGNITE 1 - #define HAS_MONITOR 0 -#endif - -#if defined(TELENANO_V_0_1) - #define HAS_FLIGHT 1 - #define HAS_USB 0 - #define HAS_BEEP 0 - #define HAS_GPS 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 1 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 1 - #define HAS_DBG 0 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 1 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - - #define AO_LED_GREEN 1 - #define AO_LED_RED 2 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define HAS_EXTERNAL_TEMP 0 - #define HAS_ACCEL 0 - #define HAS_IGNITE 0 - #define HAS_MONITOR 0 -#endif - -#if defined(TELEMETRUM_V_0_1) - #define HAS_FLIGHT 1 - #define HAS_USB 1 - #define HAS_BEEP 1 - #define HAS_GPS 1 - #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 1 - #define HAS_DBG 0 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 0 - #define DBG_ON_P1 0 - #define DBG_ON_P0 1 - #define IGNITE_ON_P2 1 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - #define AO_LED_RED 2 - #define AO_LED_GREEN 1 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define HAS_EXTERNAL_TEMP 1 - #define HAS_ACCEL_REF 0 - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define HAS_ACCEL 1 - #define HAS_IGNITE 1 - #define HAS_MONITOR 0 -#endif - -#if defined(TELEDONGLE_V_0_1) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 0 - #define HAS_DBG 0 - #define HAS_EEPROM 0 - #define DBG_ON_P1 0 - #define DBG_ON_P0 1 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 2 - #define AO_LED_GREEN 1 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define SPI_CS_ON_P1 0 - #define SPI_CS_ON_P0 1 - #define HAS_IGNITE 0 - #define HAS_MONITOR 1 -#endif - -#if defined(TIDONGLE) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 0 - #define HAS_DBG 1 - #define HAS_EEPROM 0 - #define DBG_ON_P1 0 - #define DBG_ON_P0 1 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 2 - #define LEDS_AVAILABLE (AO_LED_RED) - #define SPI_CS_ON_P1 0 - #define SPI_CS_ON_P0 1 - #define HAS_IGNITE 0 - #define HAS_MONITOR 1 -#endif - -#if defined(TELEBT_V_0_0) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 0 - #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 1 - #define HAS_ADC 0 - #define HAS_DBG 1 - #define HAS_EEPROM 0 - #define HAS_BTM 1 - #define DBG_ON_P1 0 - #define DBG_ON_P0 1 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 2 - #define AO_LED_GREEN 1 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define HAS_IGNITE 0 - #define BT_LINK_ON_P2 1 - #define BT_LINK_ON_P1 0 - #define BT_LINK_PIN_INDEX 7 - #define BT_LINK_PIN P2_1 - #define HAS_MONITOR 1 -#endif - -#if defined(TELEBT_V_0_1) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 1 - #define HAS_SERIAL_1 1 - #define HAS_SERIAL_1_ALT_1 1 - #define HAS_SERIAL_1_ALT_2 0 - #define HAS_SERIAL_1_HW_FLOW 1 - #define USE_SERIAL_STDIN 1 - #define HAS_ADC 0 - #define HAS_DBG 1 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 0 - #define HAS_BTM 1 - #define DBG_ON_P1 1 - #define DBG_ON_P0 0 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 1 - #define AO_LED_GREEN 2 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define M25_CS_MASK 0x04 /* CS0 is P1_2 */ - #define M25_MAX_CHIPS 1 - #define HAS_ACCEL 0 - #define HAS_IGNITE 0 - #define BT_LINK_ON_P2 0 - #define BT_LINK_ON_P1 1 - #define BT_LINK_PIN_INDEX 7 - #define BT_LINK_PIN P1_7 - #define HAS_MONITOR 1 -#endif - -#if DBG_ON_P1 - - #define DBG_CLOCK (1 << 4) /* mi0 */ - #define DBG_DATA (1 << 5) /* mo0 */ - #define DBG_RESET_N (1 << 3) /* c0 */ - - #define DBG_CLOCK_PIN (P1_4) - #define DBG_DATA_PIN (P1_5) - #define DBG_RESET_N_PIN (P1_3) - - #define DBG_PORT_NUM 1 - #define DBG_PORT P1 - #define DBG_PORT_SEL P1SEL - #define DBG_PORT_INP P1INP - #define DBG_PORT_DIR P1DIR - -#endif /* DBG_ON_P1 */ - -#if DBG_ON_P0 - - #define DBG_CLOCK (1 << 3) - #define DBG_DATA (1 << 4) - #define DBG_RESET_N (1 << 5) - - #define DBG_CLOCK_PIN (P0_3) - #define DBG_DATA_PIN (P0_4) - #define DBG_RESET_N_PIN (P0_5) - - #define DBG_PORT_NUM 0 - #define DBG_PORT P0 - #define DBG_PORT_SEL P0SEL - #define DBG_PORT_INP P0INP - #define DBG_PORT_DIR P0DIR - -#endif /* DBG_ON_P0 */ - -#if COMPANION_CS_ON_P1 - #define COMPANION_CS_PORT P1 - #define COMPANION_CS_SEL P1SEL - #define COMPANION_CS_DIR P1DIR -#endif - -#if SPI_CS_ON_P1 - #define SPI_CS_PORT P1 - #define SPI_CS_SEL P1SEL - #define SPI_CS_DIR P1DIR -#endif - -#if SPI_CS_ON_P0 - #define SPI_CS_PORT P0 - #define SPI_CS_SEL P0SEL - #define SPI_CS_DIR P0DIR -#endif - -#ifndef IGNITE_ON_P2 -#error Please define IGNITE_ON_P2 -#endif - -#ifndef IGNITE_ON_P0 -#error Please define IGNITE_ON_P0 -#endif - -#ifndef HAS_SERIAL_1 -#error Please define HAS_SERIAL_1 -#endif - -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - -#ifndef HAS_ADC -#error Please define HAS_ADC -#endif - -#ifndef HAS_EEPROM -#error Please define HAS_EEPROM -#endif - -#if HAS_EEPROM -#ifndef USE_INTERNAL_FLASH -#error Please define USE_INTERNAL_FLASH -#endif -#endif - -#ifndef HAS_DBG -#error Please define HAS_DBG -#endif - -#ifndef HAS_IGNITE -#error Please define HAS_IGNITE -#endif - -#ifndef PACKET_HAS_MASTER -#error Please define PACKET_HAS_MASTER -#endif - -#ifndef PACKET_HAS_SLAVE -#error Please define PACKET_HAS_SLAVE -#endif - -#ifndef HAS_MONITOR -#error Please define HAS_MONITOR -#endif -#endif /* _AO_PINS_H_ */ diff --git a/src/ao_product.c b/src/ao_product.c deleted file mode 100644 index fb59580b..00000000 --- a/src/ao_product.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "ao_product.h" - -/* Defines which mark this particular AltOS product */ - -const char ao_version[AO_MAX_VERSION] = AO_iVersion_STRING; -const char ao_manufacturer[] = AO_iManufacturer_STRING; -const char ao_product[] = AO_iProduct_STRING; - -#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) - -#if HAS_USB -#include "ao_usb.h" -/* USB descriptors in one giant block of bytes */ -__code __at(0x00aa) uint8_t ao_usb_descriptors [] = -{ - /* Device descriptor */ - 0x12, - AO_USB_DESC_DEVICE, - LE_WORD(0x0110), /* bcdUSB */ - 0x02, /* bDeviceClass */ - 0x00, /* bDeviceSubClass */ - 0x00, /* bDeviceProtocol */ - AO_USB_CONTROL_SIZE, /* bMaxPacketSize */ - LE_WORD(0xFFFE), /* idVendor */ - LE_WORD(AO_idProduct_NUMBER), /* idProduct */ - LE_WORD(0x0100), /* bcdDevice */ - 0x01, /* iManufacturer */ - 0x02, /* iProduct */ - 0x03, /* iSerialNumber */ - 0x01, /* bNumConfigurations */ - - /* Configuration descriptor */ - 0x09, - AO_USB_DESC_CONFIGURATION, - LE_WORD(67), /* wTotalLength */ - 0x02, /* bNumInterfaces */ - 0x01, /* bConfigurationValue */ - 0x00, /* iConfiguration */ - 0xC0, /* bmAttributes */ - 0x32, /* bMaxPower */ - - /* Control class interface */ - 0x09, - AO_USB_DESC_INTERFACE, - 0x00, /* bInterfaceNumber */ - 0x00, /* bAlternateSetting */ - 0x01, /* bNumEndPoints */ - 0x02, /* bInterfaceClass */ - 0x02, /* bInterfaceSubClass */ - 0x01, /* bInterfaceProtocol, linux requires value of 1 for the cdc_acm module */ - 0x00, /* iInterface */ - - /* Header functional descriptor */ - 0x05, - CS_INTERFACE, - 0x00, /* bDescriptor SubType Header */ - LE_WORD(0x0110), /* CDC version 1.1 */ - - /* Call management functional descriptor */ - 0x05, - CS_INTERFACE, - 0x01, /* bDescriptor SubType Call Management */ - 0x01, /* bmCapabilities = device handles call management */ - 0x01, /* bDataInterface call management interface number */ - - /* ACM functional descriptor */ - 0x04, - CS_INTERFACE, - 0x02, /* bDescriptor SubType Abstract Control Management */ - 0x02, /* bmCapabilities = D1 (Set_line_Coding, Set_Control_Line_State, Get_Line_Coding and Serial_State) */ - - /* Union functional descriptor */ - 0x05, - CS_INTERFACE, - 0x06, /* bDescriptor SubType Union Functional descriptor */ - 0x00, /* bMasterInterface */ - 0x01, /* bSlaveInterface0 */ - - /* Notification EP */ - 0x07, - AO_USB_DESC_ENDPOINT, - AO_USB_INT_EP|0x80, /* bEndpointAddress */ - 0x03, /* bmAttributes = intr */ - LE_WORD(8), /* wMaxPacketSize */ - 0x0A, /* bInterval */ - - /* Data class interface descriptor */ - 0x09, - AO_USB_DESC_INTERFACE, - 0x01, /* bInterfaceNumber */ - 0x00, /* bAlternateSetting */ - 0x02, /* bNumEndPoints */ - 0x0A, /* bInterfaceClass = data */ - 0x00, /* bInterfaceSubClass */ - 0x00, /* bInterfaceProtocol */ - 0x00, /* iInterface */ - - /* Data EP OUT */ - 0x07, - AO_USB_DESC_ENDPOINT, - AO_USB_OUT_EP, /* bEndpointAddress */ - 0x02, /* bmAttributes = bulk */ - LE_WORD(AO_USB_OUT_SIZE),/* wMaxPacketSize */ - 0x00, /* bInterval */ - - /* Data EP in */ - 0x07, - AO_USB_DESC_ENDPOINT, - AO_USB_IN_EP|0x80, /* bEndpointAddress */ - 0x02, /* bmAttributes = bulk */ - LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */ - 0x00, /* bInterval */ - - /* String descriptors */ - 0x04, - AO_USB_DESC_STRING, - LE_WORD(0x0409), - - /* iManufacturer */ - AO_iManufacturer_LEN, - AO_USB_DESC_STRING, - AO_iManufacturer_UCS2, - - /* iProduct */ - AO_iProduct_LEN, - AO_USB_DESC_STRING, - AO_iProduct_UCS2, - - /* iSerial */ - AO_iSerial_LEN, - AO_USB_DESC_STRING, - AO_iSerial_UCS2, - - /* Terminating zero */ - 0 -}; -#endif diff --git a/src/ao_radio.c b/src/ao_radio.c deleted file mode 100644 index 00816b33..00000000 --- a/src/ao_radio.c +++ /dev/null @@ -1,475 +0,0 @@ -/* - * 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 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 - -/* - * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone), - * so the DRATE_E and DRATE_M values are: - * - * M is 94 and E is 6 - * - * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes - */ - -#define RDF_DRATE_E 6 -#define RDF_DRATE_M 94 -#define RDF_PACKET_LEN 50 - -/* - * RDF deviation should match the normal NFM value of 5kHz - * - * M is 6 and E is 1 - * - */ - -#define RDF_DEVIATION_M 6 -#define RDF_DEVIATION_E 1 - -/* 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_10_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_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_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, -}; - -static __code uint8_t rdf_setup[] = { - RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | - (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | - (RDF_DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)), - RF_MDMCFG3_OFF, (RDF_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_DIS | - RF_MDMCFG1_NUM_PREAMBLE_2 | - (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), - - RF_DEVIATN_OFF, ((RDF_DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | - (RDF_DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), - - /* packet length is set in-line */ - RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| - PKTCTRL1_ADR_CHK_NONE), - RF_PKTCTRL0_OFF, (RF_PKTCTRL0_PKT_FORMAT_NORMAL| - RF_PKTCTRL0_LENGTH_CONFIG_FIXED), -}; - -static __code uint8_t fixed_pkt_setup[] = { - 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_DEVIATN_OFF, ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | - (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), - - /* max packet length -- now set inline */ - 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), -}; - -__xdata uint8_t ao_radio_dma; -__xdata uint8_t ao_radio_dma_done; -__xdata uint8_t ao_radio_done; -__xdata uint8_t ao_radio_abort; -__xdata uint8_t ao_radio_mutex; - -void -ao_radio_general_isr(void) __interrupt 16 -{ - S1CON &= ~0x03; - if (RFIF & RFIF_IM_TIMEOUT) { - ao_radio_recv_abort(); - RFIF &= ~ RFIF_IM_TIMEOUT; - } else if (RFIF & RFIF_IM_DONE) { - ao_radio_done = 1; - ao_wakeup(&ao_radio_done); - RFIF &= ~RFIF_IM_DONE; - } -} - -void -ao_radio_set_packet(void) -{ - uint8_t i; - for (i = 0; i < sizeof (fixed_pkt_setup); i += 2) - RF[fixed_pkt_setup[i]] = fixed_pkt_setup[i+1]; -} - -void -ao_radio_idle(void) -{ - if (RF_MARCSTATE != RF_MARCSTATE_IDLE) - { - do { - RFST = RFST_SIDLE; - ao_yield(); - } while (RF_MARCSTATE != RF_MARCSTATE_IDLE); - } -} - -void -ao_radio_get(uint8_t len) -{ - ao_config_get(); - ao_mutex_get(&ao_radio_mutex); - ao_radio_idle(); - RF_CHANNR = ao_config.radio_channel; - RF_FREQ2 = (uint8_t) (ao_config.radio_setting >> 16); - RF_FREQ1 = (uint8_t) (ao_config.radio_setting >> 8); - RF_FREQ0 = (uint8_t) (ao_config.radio_setting); - RF_PKTLEN = len; -} - - -void -ao_radio_send(__xdata void *packet, uint8_t size) __reentrant -{ - ao_radio_get(size); - ao_radio_done = 0; - ao_dma_set_transfer(ao_radio_dma, - packet, - &RFDXADDR, - size, - 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; - __critical while (!ao_radio_done) - ao_sleep(&ao_radio_done); - ao_radio_put(); -} - -uint8_t -ao_radio_recv(__xdata void *packet, uint8_t size) __reentrant -{ - ao_radio_abort = 0; - ao_radio_get(size - 2); - ao_dma_set_transfer(ao_radio_dma, - &RFDXADDR, - packet, - size, - 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; - - /* Wait for DMA to be done, for the radio receive process to - * get aborted or for a receive timeout to fire - */ - __critical while (!ao_radio_dma_done && !ao_radio_abort) - if (ao_sleep(&ao_radio_dma_done)) - break; - - /* If recv was aborted, clean up by stopping the DMA engine - * and idling the radio - */ - if (!ao_radio_dma_done) { - ao_dma_abort(ao_radio_dma); - ao_radio_idle(); - } - ao_radio_put(); - return ao_radio_dma_done; -} - -/* - * Wake up a task waiting to receive a radio packet - * and tell them to abort the transfer - */ - -void -ao_radio_recv_abort(void) -{ - ao_radio_abort = 1; - ao_wakeup(&ao_radio_dma_done); -} - -__xdata ao_radio_rdf_value = 0x55; - -void -ao_radio_rdf(int ms) -{ - uint8_t i; - uint8_t pkt_len; - - /* - * Compute the packet length as follows: - * - * 2000 bps (for a 1kHz tone) - * so, for 'ms' milliseconds, we need - * 2 * ms bits, or ms / 4 bytes - */ - if (ms > (255 * 4)) - ms = 255 * 4; - pkt_len = ms >> 2; - - ao_radio_abort = 0; - ao_radio_get(pkt_len); - ao_radio_done = 0; - for (i = 0; i < sizeof (rdf_setup); i += 2) - RF[rdf_setup[i]] = rdf_setup[i+1]; - - ao_dma_set_transfer(ao_radio_dma, - &ao_radio_rdf_value, - &RFDXADDR, - pkt_len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_RADIO, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_HIGH); - ao_dma_start(ao_radio_dma); - RFST = RFST_STX; - __critical while (!ao_radio_done && !ao_radio_abort) - ao_sleep(&ao_radio_done); - if (!ao_radio_done) { - ao_dma_abort(ao_radio_dma); - ao_radio_idle(); - } - ao_radio_set_packet(); - ao_radio_put(); -} - -void -ao_radio_rdf_abort(void) -{ - ao_radio_abort = 1; - ao_wakeup(&ao_radio_done); -} - - -/* Output carrier */ -void -ao_radio_test(void) -{ - uint8_t mode = 2; - static __xdata radio_on; - ao_cmd_white(); - if (ao_cmd_lex_c != '\n') { - ao_cmd_decimal(); - mode = (uint8_t) ao_cmd_lex_u32; - } - mode++; - if ((mode & 2) && !radio_on) { -#if HAS_MONITOR - ao_set_monitor(0); -#endif -#if PACKET_HAS_SLAVE - ao_packet_slave_stop(); -#endif - ao_radio_get(0xff); - RFST = RFST_STX; - radio_on = 1; - } - if (mode == 3) { - printf ("Hit a character to stop..."); flush(); - getchar(); - putchar('\n'); - } - if ((mode & 1) && radio_on) { - ao_radio_idle(); - ao_radio_put(); - radio_on = 0; - } -} - -__code struct ao_cmds ao_radio_cmds[] = { - { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" }, - { 0, NULL }, -}; - -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_set_packet(); - ao_radio_dma_done = 1; - ao_radio_dma = ao_dma_alloc(&ao_radio_dma_done); - RFIF = 0; - RFIM = RFIM_IM_TIMEOUT|RFIM_IM_DONE; - IEN2 |= IEN2_RFIE; - ao_cmd_register(&ao_radio_cmds[0]); -} diff --git a/src/ao_reboot.c b/src/ao_reboot.c deleted file mode 100644 index 8c47b893..00000000 --- a/src/ao_reboot.c +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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" - -/* Use the watchdog timer to force a complete reboot - */ -void -ao_reboot(void) -{ - WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_32768; - ao_delay(AO_SEC_TO_TICKS(2)); - ao_panic(AO_PANIC_REBOOT); -} diff --git a/src/ao_report.c b/src/ao_report.c deleted file mode 100644 index 3cf558e1..00000000 --- a/src/ao_report.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * 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" - -#define BIT(i,x) ((x) ? (1 << (i)) : 0) -#define MORSE1(a) (1 | BIT(3,a)) -#define MORSE2(a,b) (2 | BIT(3,a) | BIT(4,b)) -#define MORSE3(a,b,c) (3 | BIT(3,a) | BIT(4,b) | BIT(5,c)) -#define MORSE4(a,b,c,d) (4 | BIT(3,a) | BIT(4,b) | BIT(5,c) | BIT(6,d)) -#define MORSE5(a,b,c,d,e) (5 | BIT(3,a) | BIT(4,b) | BIT(5,c) | BIT(6,d) | BIT(7,e)) - -static const uint8_t flight_reports[] = { - MORSE3(0,0,0), /* startup, 'S' */ - MORSE2(0,0), /* idle 'I' */ - MORSE4(0,1,1,0), /* pad 'P' */ - MORSE4(1,0,0,0), /* boost 'B' */ - MORSE4(0,0,1,0), /* fast 'F' */ - MORSE4(1,0,1,0), /* coast 'C' */ - MORSE3(1,0,0), /* drogue 'D' */ - MORSE2(1,1), /* main 'M' */ - MORSE4(0,1,0,0), /* landed 'L' */ - MORSE4(1,0,0,1), /* invalid 'X' */ -}; - -#if HAS_BEEP -#define low(time) ao_beep_for(AO_BEEP_LOW, time) -#define mid(time) ao_beep_for(AO_BEEP_MID, time) -#define high(time) ao_beep_for(AO_BEEP_HIGH, time) -#else -#define low(time) ao_led_for(AO_LED_GREEN, time) -#define mid(time) ao_led_for(AO_LED_RED, time) -#define high(time) ao_led_for(AO_LED_GREEN|AO_LED_RED, time) -#endif -#define pause(time) ao_delay(time) - -static __pdata enum ao_flight_state ao_report_state; - -static void -ao_report_beep(void) __reentrant -{ - uint8_t r = flight_reports[ao_flight_state]; - uint8_t l = r & 7; - - if (!r) - return; - while (l--) { - if (r & 8) - mid(AO_MS_TO_TICKS(600)); - else - mid(AO_MS_TO_TICKS(200)); - pause(AO_MS_TO_TICKS(200)); - r >>= 1; - } - pause(AO_MS_TO_TICKS(400)); -} - -static void -ao_report_digit(uint8_t digit) __reentrant -{ - if (!digit) { - mid(AO_MS_TO_TICKS(500)); - pause(AO_MS_TO_TICKS(200)); - } else { - while (digit--) { - mid(AO_MS_TO_TICKS(200)); - pause(AO_MS_TO_TICKS(200)); - } - } - pause(AO_MS_TO_TICKS(300)); -} - -static void -ao_report_altitude(void) -{ - __pdata int16_t agl = ao_max_height; - __xdata uint8_t digits[10]; - __pdata uint8_t ndigits, i; - - if (agl < 0) - agl = 0; - ndigits = 0; - do { - digits[ndigits++] = agl % 10; - agl /= 10; - } while (agl); - - for (;;) { - ao_report_beep(); - i = ndigits; - do - ao_report_digit(digits[--i]); - while (i != 0); - pause(AO_SEC_TO_TICKS(5)); - } -} - -#if HAS_IGNITE -static uint8_t -ao_report_igniter_ready(enum ao_igniter igniter) -{ - return ao_igniter_status(igniter) == ao_igniter_ready ? 1 : 0; -} - -static void -ao_report_continuity(void) __reentrant -{ - uint8_t c = (ao_report_igniter_ready(ao_igniter_drogue) | - (ao_report_igniter_ready(ao_igniter_main) << 1)); - if (c) { - while (c--) { - high(AO_MS_TO_TICKS(25)); - pause(AO_MS_TO_TICKS(100)); - } - } else { - c = 10; - while (c--) { - high(AO_MS_TO_TICKS(20)); - low(AO_MS_TO_TICKS(20)); - } - } - if (ao_log_full()) { - pause(AO_MS_TO_TICKS(100)); - c = 2; - while (c--) { - low(AO_MS_TO_TICKS(100)); - mid(AO_MS_TO_TICKS(100)); - high(AO_MS_TO_TICKS(100)); - mid(AO_MS_TO_TICKS(100)); - } - } - c = 50; - while (c-- && ao_flight_state == ao_flight_pad) - pause(AO_MS_TO_TICKS(100)); -} -#endif - -void -ao_report(void) -{ - ao_report_state = ao_flight_state; - for(;;) { - if (ao_flight_state == ao_flight_landed) - ao_report_altitude(); - ao_report_beep(); -#if HAS_IGNITE - if (ao_flight_state == ao_flight_idle) - ao_report_continuity(); - while (ao_flight_state == ao_flight_pad) - ao_report_continuity(); -#endif - __critical { - while (ao_report_state == ao_flight_state) - ao_sleep(DATA_TO_XDATA(&ao_flight_state)); - ao_report_state = ao_flight_state; - } - } -} - -static __xdata struct ao_task ao_report_task; - -void -ao_report_init(void) -{ - ao_add_task(&ao_report_task, ao_report, "report"); -} diff --git a/src/ao_romconfig.c b/src/ao_romconfig.c deleted file mode 100644 index f3fe61b1..00000000 --- a/src/ao_romconfig.c +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -__code __at (0x00a0) uint16_t ao_romconfig_version = AO_ROMCONFIG_VERSION; -__code __at (0x00a2) uint16_t ao_romconfig_check = ~AO_ROMCONFIG_VERSION; -__code __at (0x00a4) uint16_t ao_serial_number = 0; -/* - * For 434.550MHz, the frequency value is: - * - * 434.550e6 / (24e6 / 2**16) = 1186611.2 - * - * This value is stored in a const variable so that - * ao-load can change it during programming for - * devices that have no eeprom for config data. - */ -__code __at (0x00a6) uint32_t ao_radio_cal = 1186611; diff --git a/src/ao_rssi.c b/src/ao_rssi.c deleted file mode 100644 index e3964d2d..00000000 --- a/src/ao_rssi.c +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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" - -static __xdata volatile uint16_t ao_rssi_time; -static __pdata volatile uint16_t ao_rssi_delay; -static __pdata uint8_t ao_rssi_led; - -void -ao_rssi(void) -{ - for (;;) { - while ((int16_t) (ao_time() - ao_rssi_time) > AO_SEC_TO_TICKS(3)) - ao_sleep(&ao_rssi_time); - ao_led_for(ao_rssi_led, AO_MS_TO_TICKS(100)); - ao_delay(ao_rssi_delay); - } -} - -void -ao_rssi_set(int rssi_value) -{ - if (rssi_value > 0) - rssi_value = 0; - ao_rssi_delay = AO_MS_TO_TICKS((-rssi_value) * 5); - ao_rssi_time = ao_time(); - ao_wakeup(&ao_rssi_time); -} - -__xdata struct ao_task ao_rssi_task; - -void -ao_rssi_init(uint8_t rssi_led) -{ - ao_rssi_led = rssi_led; - ao_rssi_delay = 0; - ao_add_task(&ao_rssi_task, ao_rssi, "rssi"); -} diff --git a/src/ao_sample.c b/src/ao_sample.c deleted file mode 100644 index b2b8e9f6..00000000 --- a/src/ao_sample.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef AO_FLIGHT_TEST -#include "ao.h" -#endif - -/* - * Current sensor values - */ - -__pdata uint16_t ao_sample_tick; /* time of last data */ -__pdata int16_t ao_sample_pres; -__pdata int16_t ao_sample_alt; -__pdata int16_t ao_sample_height; -#if HAS_ACCEL -__pdata int16_t ao_sample_accel; -#endif - -__data uint8_t ao_sample_adc; - -/* - * Sensor calibration values - */ - -__pdata int16_t ao_ground_pres; /* startup pressure */ -__pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ - -#if HAS_ACCEL -__pdata int16_t ao_ground_accel; /* startup acceleration */ -__pdata int16_t ao_accel_2g; /* factory accel calibration */ -__pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ -#endif - -static __pdata uint8_t ao_preflight; /* in preflight mode */ - -static __pdata uint16_t nsamples; -__pdata int32_t ao_sample_pres_sum; -#if HAS_ACCEL -__pdata int32_t ao_sample_accel_sum; -#endif - -static void -ao_sample_preflight(void) -{ - /* startup state: - * - * Collect 512 samples of acceleration and pressure - * data and average them to find the resting values - */ - if (nsamples < 512) { -#if HAS_ACCEL - ao_sample_accel_sum += ao_sample_accel; -#endif - ao_sample_pres_sum += ao_sample_pres; - ++nsamples; - } else { - ao_config_get(); -#if HAS_ACCEL - ao_ground_accel = ao_sample_accel_sum >> 9; - ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; - ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; -#endif - ao_ground_pres = ao_sample_pres_sum >> 9; - ao_ground_height = ao_pres_to_altitude(ao_ground_pres); - ao_preflight = FALSE; - } -} - -uint8_t -ao_sample(void) -{ - ao_wakeup(DATA_TO_XDATA(&ao_sample_adc)); - ao_sleep(DATA_TO_XDATA(&ao_adc_head)); - while (ao_sample_adc != ao_adc_head) { - __xdata struct ao_adc *ao_adc; - - /* Capture a sample */ - ao_adc = &ao_adc_ring[ao_sample_adc]; - ao_sample_tick = ao_adc->tick; - ao_sample_pres = ao_adc->pres; - ao_sample_alt = ao_pres_to_altitude(ao_sample_pres); - ao_sample_height = ao_sample_alt - ao_ground_height; -#if HAS_ACCEL - ao_sample_accel = ao_adc->accel; -#if HAS_ACCEL_REF - /* - * Ok, the math here is a bit tricky. - * - * ao_sample_accel: ADC output for acceleration - * ao_accel_ref: ADC output for the 5V reference. - * ao_cook_accel: Corrected acceleration value - * Vcc: 3.3V supply to the CC1111 - * Vac: 5V supply to the accelerometer - * accel: input voltage to accelerometer ADC pin - * ref: input voltage to 5V reference ADC pin - * - * - * Measured acceleration is ratiometric to Vcc: - * - * ao_sample_accel accel - * ------------ = ----- - * 32767 Vcc - * - * Measured 5v reference is also ratiometric to Vcc: - * - * ao_accel_ref ref - * ------------ = ----- - * 32767 Vcc - * - * - * ao_accel_ref = 32767 * (ref / Vcc) - * - * Acceleration is measured ratiometric to the 5V supply, - * so what we want is: - * - * ao_cook_accel accel - * ------------- = ----- - * 32767 ref - * - * - * accel Vcc - * = ----- * --- - * Vcc ref - * - * ao_sample_accel 32767 - * = ------------ * ------------ - * 32767 ao_accel_ref - * - * Multiply through by 32767: - * - * ao_sample_accel * 32767 - * ao_cook_accel = -------------------- - * ao_accel_ref - * - * Now, the tricky part. Getting this to compile efficiently - * and keeping all of the values in-range. - * - * First off, we need to use a shift of 16 instead of * 32767 as SDCC - * does the obvious optimizations for byte-granularity shifts: - * - * ao_cook_accel = (ao_sample_accel << 16) / ao_accel_ref - * - * Next, lets check our input ranges: - * - * 0 <= ao_sample_accel <= 0x7fff (singled ended ADC conversion) - * 0x7000 <= ao_accel_ref <= 0x7fff (the 5V ref value is close to 0x7fff) - * - * Plugging in our input ranges, we get an output range of 0 - 0x12490, - * which is 17 bits. That won't work. If we take the accel ref and shift - * by a bit, we'll change its range: - * - * 0xe000 <= ao_accel_ref<<1 <= 0xfffe - * - * ao_cook_accel = (ao_sample_accel << 16) / (ao_accel_ref << 1) - * - * Now the output range is 0 - 0x9248, which nicely fits in 16 bits. It - * is, however, one bit too large for our signed computations. So, we - * take the result and shift that by a bit: - * - * ao_cook_accel = ((ao_sample_accel << 16) / (ao_accel_ref << 1)) >> 1 - * - * This finally creates an output range of 0 - 0x4924. As the ADC only - * provides 11 bits of data, we haven't actually lost any precision, - * just dropped a bit of noise off the low end. - */ - ao_sample_accel = (uint16_t) ((((uint32_t) ao_sample_accel << 16) / (ao_accel_ref[ao_sample_adc] << 1))) >> 1; - if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) - ao_sample_accel = 0x7fff - ao_sample_accel; - ao_adc->accel = ao_sample_accel; -#endif -#endif - - if (ao_preflight) - ao_sample_preflight(); - else - ao_kalman(); - ao_sample_adc = ao_adc_ring_next(ao_sample_adc); - } - return !ao_preflight; -} - -void -ao_sample_init(void) -{ - nsamples = 0; - ao_sample_pres_sum = 0; - ao_sample_pres = 0; -#if HAS_ACCEL - ao_sample_accel_sum = 0; - ao_sample_accel = 0; -#endif - ao_sample_adc = ao_adc_head; - ao_preflight = TRUE; -} diff --git a/src/ao_serial.c b/src/ao_serial.c deleted file mode 100644 index 82370c64..00000000 --- a/src/ao_serial.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * 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" - -volatile __xdata struct ao_fifo ao_usart1_rx_fifo; -volatile __xdata struct ao_fifo ao_usart1_tx_fifo; - -void -ao_serial_rx1_isr(void) __interrupt 3 -{ - if (!ao_fifo_full(ao_usart1_rx_fifo)) - ao_fifo_insert(ao_usart1_rx_fifo, U1DBUF); - ao_wakeup(&ao_usart1_rx_fifo); -#if USE_SERIAL_STDIN - ao_wakeup(&ao_stdin_ready); -#endif -} - -static __xdata uint8_t ao_serial_tx1_started; - -static void -ao_serial_tx1_start(void) -{ - if (!ao_fifo_empty(ao_usart1_tx_fifo) && - !ao_serial_tx1_started) - { - ao_serial_tx1_started = 1; - ao_fifo_remove(ao_usart1_tx_fifo, U1DBUF); - } -} - -void -ao_serial_tx1_isr(void) __interrupt 14 -{ - UTX1IF = 0; - ao_serial_tx1_started = 0; - ao_serial_tx1_start(); - ao_wakeup(&ao_usart1_tx_fifo); -} - -char -ao_serial_getchar(void) __critical -{ - char c; - while (ao_fifo_empty(ao_usart1_rx_fifo)) - ao_sleep(&ao_usart1_rx_fifo); - ao_fifo_remove(ao_usart1_rx_fifo, c); - return c; -} - -#if USE_SERIAL_STDIN -char -ao_serial_pollchar(void) __critical -{ - char c; - if (ao_fifo_empty(ao_usart1_rx_fifo)) - return AO_READ_AGAIN; - ao_fifo_remove(ao_usart1_rx_fifo,c); - return c; -} -#endif - -void -ao_serial_putchar(char c) __critical -{ - while (ao_fifo_full(ao_usart1_tx_fifo)) - ao_sleep(&ao_usart1_tx_fifo); - ao_fifo_insert(ao_usart1_tx_fifo, c); - ao_serial_tx1_start(); -} - -void -ao_serial_drain(void) __critical -{ - while (!ao_fifo_empty(ao_usart1_tx_fifo)) - ao_sleep(&ao_usart1_tx_fifo); -} - -static __code struct { - uint8_t baud; - uint8_t gcr; -} ao_serial_speeds[] = { - /* [AO_SERIAL_SPEED_4800] = */ { - /* .baud = */ 163, - /* .gcr = */ (7 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB - }, - /* [AO_SERIAL_SPEED_9600] = */ { - /* .baud = */ 163, - /* .gcr = */ (8 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB - }, - /* [AO_SERIAL_SPEED_19200] = */ { - /* .baud = */ 163, - /* .gcr = */ (9 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB - }, - /* [AO_SERIAL_SPEED_57600] = */ { - /* .baud = */ 59, - /* .gcr = */ (11 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB - }, -}; - -void -ao_serial_set_speed(uint8_t speed) -{ - ao_serial_drain(); - if (speed > AO_SERIAL_SPEED_57600) - return; - U1UCR |= UxUCR_FLUSH; - U1BAUD = ao_serial_speeds[speed].baud; - U1GCR = ao_serial_speeds[speed].gcr; -} - -void -ao_serial_init(void) -{ -#if HAS_SERIAL_1_ALT_1 - /* Set up the USART pin assignment */ - PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_1; - - P2DIR = (P2DIR & ~P2DIR_PRIP0_MASK) | P2DIR_PRIP0_USART1_USART0; - - /* Make the USART pins be controlled by the USART */ - P0SEL |= (1 << 5) | (1 << 4); -#if HAS_SERIAL_1_HW_FLOW - P0SEL |= (1 << 3) | (1 << 2); -#endif -#else - /* Set up the USART pin assignment */ - PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_2; - - P2SEL = (P2SEL & ~(P2SEL_PRI3P1_MASK | P2SEL_PRI2P1_MASK)) | - (P2SEL_PRI3P1_USART1 | P2SEL_PRI2P1_USART1); - - /* Make the USART pins be controlled by the USART */ - P1SEL |= (1 << 6) | (1 << 7); - P1SEL |= (1 << 5) | (1 << 4); -#endif - - /* UART mode with receiver enabled */ - U1CSR = (UxCSR_MODE_UART | UxCSR_RE); - - /* Pick a 4800 baud rate */ - ao_serial_set_speed(AO_SERIAL_SPEED_4800); - - /* Reasonable serial parameters */ - U1UCR = (UxUCR_FLUSH | -#if HAS_SERIAL_1_HW_FLOW - UxUCR_FLOW_ENABLE | -#else - UxUCR_FLOW_DISABLE | -#endif - UxUCR_D9_EVEN_PARITY | - UxUCR_BIT9_8_BITS | - UxUCR_PARITY_DISABLE | - UxUCR_SPB_1_STOP_BIT | - UxUCR_STOP_HIGH | - UxUCR_START_LOW); - - IEN0 |= IEN0_URX1IE; - IEN2 |= IEN2_UTX1IE; -} diff --git a/src/ao_spi.c b/src/ao_spi.c deleted file mode 100644 index fbe613c7..00000000 --- a/src/ao_spi.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -/* Shared mutex to protect SPI bus, must cover the entire - * operation, from CS low to CS high. This means that any SPI - * user must protect the SPI bus with this mutex - */ -__xdata uint8_t ao_spi_mutex; -__xdata uint8_t ao_spi_dma_in_done; -__xdata uint8_t ao_spi_dma_out_done; - -uint8_t ao_spi_dma_out_id; -uint8_t ao_spi_dma_in_id; - -static __xdata uint8_t ao_spi_const = 0xff; - -/* Send bytes over SPI. - * - * This sets up two DMA engines, one writing the data and another reading - * bytes coming back. We use the bytes coming back to tell when the transfer - * is complete, as the transmit register is double buffered and hence signals - * completion one byte before the transfer is actually complete - */ -void -ao_spi_send(void __xdata *block, uint16_t len) __reentrant -{ - ao_dma_set_transfer(ao_spi_dma_in_id, - &U0DBUFXADDR, - &ao_spi_const, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_URX0, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_set_transfer(ao_spi_dma_out_id, - block, - &U0DBUFXADDR, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_UTX0, - DMA_CFG1_SRCINC_1 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_start(ao_spi_dma_in_id); - ao_dma_start(ao_spi_dma_out_id); - ao_dma_trigger(ao_spi_dma_out_id); - __critical while (!ao_spi_dma_in_done) - ao_sleep(&ao_spi_dma_in_done); -} - -/* Receive bytes over SPI. - * - * This sets up tow DMA engines, one reading the data and another - * writing constant values to the SPI transmitter as that is what - * clocks the data coming in. - */ -void -ao_spi_recv(void __xdata *block, uint16_t len) __reentrant -{ - ao_dma_set_transfer(ao_spi_dma_in_id, - &U0DBUFXADDR, - block, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_URX0, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_1 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_set_transfer(ao_spi_dma_out_id, - &ao_spi_const, - &U0DBUFXADDR, - len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_UTX0, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_NORMAL); - - ao_dma_start(ao_spi_dma_in_id); - ao_dma_start(ao_spi_dma_out_id); - ao_dma_trigger(ao_spi_dma_out_id); - __critical while (!ao_spi_dma_in_done) - ao_sleep(&ao_spi_dma_in_done); -} - -/* - * Initialize USART0 for SPI using config alt 2 - * - * MO P1_5 - * MI P1_4 - * CLK P1_3 - * - * Chip select is the responsibility of the caller - */ - -void -ao_spi_init(void) -{ - /* Set up the USART pin assignment */ - PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2; - - /* Ensure that USART0 takes precidence over USART1 for pins that - * they share - */ - P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | P2SEL_PRI3P1_USART0; - - /* Make the SPI pins be controlled by the USART peripheral */ - P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3)); - - /* Set up OUT DMA */ - ao_spi_dma_out_id = ao_dma_alloc(&ao_spi_dma_out_done); - - /* Set up IN DMA */ - ao_spi_dma_in_id = ao_dma_alloc(&ao_spi_dma_in_done); - - /* Set up the USART. - * - * SPI master mode - */ - U0CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_MASTER); - - /* Set the baud rate and signal parameters - * - * The cc1111 is limited to a 24/8 MHz SPI clock. - * Every peripheral I've ever seen goes faster than that, - * so set the clock to 3MHz (BAUD_E 17, BAUD_M 0) - */ - U0BAUD = 0; - U0GCR = (UxGCR_CPOL_NEGATIVE | - UxGCR_CPHA_FIRST_EDGE | - UxGCR_ORDER_MSB | - (17 << UxGCR_BAUD_E_SHIFT)); -} diff --git a/src/ao_state.c b/src/ao_state.c deleted file mode 100644 index ed197aa5..00000000 --- a/src/ao_state.c +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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" - -const char const * const ao_state_names[] = { - "startup", "idle", "pad", "boost", "fast", - "coast", "drogue", "main", "landed", "invalid" -}; diff --git a/src/ao_stdio.c b/src/ao_stdio.c deleted file mode 100644 index c0138a30..00000000 --- a/src/ao_stdio.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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 - */ - -#define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) - -__xdata struct ao_stdio ao_stdios[AO_NUM_STDIOS]; -__pdata int8_t ao_cur_stdio; -__pdata int8_t ao_num_stdios; - -void -putchar(char c) -{ - if (c == '\n') - (*ao_stdios[ao_cur_stdio].putchar)('\r'); - (*ao_stdios[ao_cur_stdio].putchar)(c); -} - -void -flush(void) -{ - if (ao_stdios[ao_cur_stdio].flush) - ao_stdios[ao_cur_stdio].flush(); -} - -__xdata uint8_t ao_stdin_ready; - -char -getchar(void) __reentrant __critical -{ - char c; - int8_t stdio = ao_cur_stdio; - - for (;;) { - c = ao_stdios[stdio].pollchar(); - if (c != AO_READ_AGAIN) - break; - if (++stdio == ao_num_stdios) - stdio = 0; - if (stdio == ao_cur_stdio) - ao_sleep(&ao_stdin_ready); - } - ao_cur_stdio = stdio; - return c; -} - -uint8_t -ao_echo(void) -{ - return ao_stdios[ao_cur_stdio].echo; -} - -int8_t -ao_add_stdio(char (*pollchar)(void), - void (*putchar)(char), - void (*flush)(void)) __reentrant -{ - if (ao_num_stdios == AO_NUM_STDIOS) - ao_panic(AO_PANIC_STDIO); - ao_stdios[ao_num_stdios].pollchar = pollchar; - ao_stdios[ao_num_stdios].putchar = putchar; - ao_stdios[ao_num_stdios].flush = flush; - ao_stdios[ao_num_stdios].echo = 1; - return ao_num_stdios++; -} diff --git a/src/ao_storage.c b/src/ao_storage.c deleted file mode 100644 index 6ffca0e5..00000000 --- a/src/ao_storage.c +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -uint8_t -ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant -{ - uint16_t this_len; - uint16_t this_off; - - ao_storage_setup(); - if (pos >= ao_storage_total || pos + len > ao_storage_total) - return 0; - while (len) { - - /* Compute portion of transfer within - * a single block - */ - this_off = (uint16_t) pos & (ao_storage_unit - 1); - this_len = ao_storage_unit - this_off; - if (this_len > len) - this_len = len; - - if (!ao_storage_device_read(pos, buf, this_len)) - return 0; - - /* See how much is left */ - buf += this_len; - len -= this_len; - pos += this_len; - } - return 1; -} - -uint8_t -ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant -{ - uint16_t this_len; - uint16_t this_off; - - ao_storage_setup(); - if (pos >= ao_storage_total || pos + len > ao_storage_total) - return 0; - while (len) { - - /* Compute portion of transfer within - * a single block - */ - this_off = (uint16_t) pos & (ao_storage_unit - 1); - this_len = ao_storage_unit - this_off; - if (this_len > len) - this_len = len; - - if (!ao_storage_device_write(pos, buf, this_len)) - return 0; - - /* See how much is left */ - buf += this_len; - len -= this_len; - pos += this_len; - } - return 1; -} - -static __xdata uint8_t storage_data[8]; - -static void -ao_storage_dump(void) __reentrant -{ - uint8_t i, j; - - ao_cmd_hex(); - if (ao_cmd_status != ao_cmd_success) - return; - for (i = 0; ; i += 8) { - if (ao_storage_read(((uint32_t) (ao_cmd_lex_i) << 8) + i, - storage_data, - 8)) { - ao_cmd_put16((uint16_t) i); - for (j = 0; j < 8; j++) { - putchar(' '); - ao_cmd_put8(storage_data[j]); - } - putchar ('\n'); - } - if (i == 248) - break; - } -} - -#if 0 - -/* not enough space for this today - */ -static void -ao_storage_store(void) __reentrant -{ - uint16_t block; - uint8_t i; - uint16_t len; - static __xdata uint8_t b; - 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_storage_write(addr, &b, 1); - addr++; - } -} -#endif - -void -ao_storage_zap(void) __reentrant -{ - ao_cmd_hex(); - if (ao_cmd_status != ao_cmd_success) - return; - ao_storage_erase((uint32_t) ao_cmd_lex_i << 8); -} - -void -ao_storage_zapall(void) __reentrant -{ - uint32_t pos; - - ao_cmd_white(); - if (!ao_match_word("DoIt")) - return; - for (pos = 0; pos < ao_storage_config; pos += ao_storage_block) - ao_storage_erase(pos); -} - -void -ao_storage_info(void) __reentrant -{ - printf("Storage size: %ld\n", ao_storage_total); - printf("Storage erase unit: %ld\n", ao_storage_block); - ao_storage_device_info(); -} - -__code struct ao_cmds ao_storage_cmds[] = { - { ao_storage_info, "f\0Show storage" }, - { ao_storage_dump, "e \0Dump flash" }, -#ifdef HAS_STORAGE_DBG - { ao_storage_store, "w ...\0Write data to flash" }, -#endif - { ao_storage_zap, "z \0Erase " }, - { ao_storage_zapall,"Z \0Erase all. is doit with D&I" }, - { 0, NULL }, -}; - -void -ao_storage_init(void) -{ - ao_storage_device_init(); - ao_cmd_register(&ao_storage_cmds[0]); -} diff --git a/src/ao_task.c b/src/ao_task.c deleted file mode 100644 index f5850fa4..00000000 --- a/src/ao_task.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * 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" - -#define AO_NO_TASK_INDEX 0xff - -__xdata struct ao_task * __xdata ao_tasks[AO_NUM_TASKS]; -__data uint8_t ao_num_tasks; -__data uint8_t ao_cur_task_index; -__xdata struct ao_task *__data ao_cur_task; - -void -ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant -{ - uint8_t __xdata *stack; - uint8_t task_id; - uint8_t t; - if (ao_num_tasks == AO_NUM_TASKS) - ao_panic(AO_PANIC_NO_TASK); - for (task_id = 1; task_id != 0; task_id++) { - for (t = 0; t < ao_num_tasks; t++) - if (ao_tasks[t]->task_id == task_id) - break; - if (t == ao_num_tasks) - break; - } - ao_tasks[ao_num_tasks++] = task; - task->task_id = task_id; - task->name = name; - /* - * Construct a stack frame so that it will 'return' - * to the start of the task - */ - stack = task->stack; - - *stack++ = ((uint16_t) start); /* 0 */ - *stack++ = ((uint16_t) start) >> 8; /* 1 */ - - /* and the stuff saved by ao_switch */ - *stack++ = 0; /* 2 acc */ - *stack++ = 0x80; /* 3 IE */ - - /* 4 DPL - * 5 DPH - * 6 B - * 7 R2 - * 8 R3 - * 9 R4 - * 10 R5 - * 11 R6 - * 12 R7 - * 13 R0 - * 14 R1 - * 15 PSW - * 16 BP - */ - for (t = 0; t < 13; t++) - *stack++ = 0; - - task->stack_count = 17; - task->wchan = NULL; -} - -/* Task switching function. This must not use any stack variables */ -void -ao_yield(void) __naked -{ - - /* Save current context */ - _asm - /* Push ACC first, as when restoring the context it must be restored - * last (it is used to set the IE register). */ - push ACC - /* Store the IE register then enable interrupts. */ - push _IEN0 - setb _EA - push DPL - push DPH - push b - push ar2 - push ar3 - push ar4 - push ar5 - push ar6 - push ar7 - push ar0 - push ar1 - push PSW - _endasm; - PSW = 0; - _asm - push _bp - _endasm; - - if (ao_cur_task_index == AO_NO_TASK_INDEX) - ao_cur_task_index = ao_num_tasks-1; - else - { - uint8_t stack_len; - __data uint8_t *stack_ptr; - __xdata uint8_t *save_ptr; - /* Save the current stack */ - stack_len = SP - (AO_STACK_START - 1); - ao_cur_task->stack_count = stack_len; - stack_ptr = (uint8_t __data *) AO_STACK_START; - save_ptr = (uint8_t __xdata *) ao_cur_task->stack; - do - *save_ptr++ = *stack_ptr++; - while (--stack_len); - } - - /* Empty the stack; might as well let interrupts have the whole thing */ - SP = AO_STACK_START - 1; - - /* Find a task to run. If there isn't any runnable task, - * this loop will run forever, which is just fine - */ - { - __pdata uint8_t ao_next_task_index = ao_cur_task_index; - for (;;) { - ++ao_next_task_index; - if (ao_next_task_index == ao_num_tasks) - ao_next_task_index = 0; - - ao_cur_task = ao_tasks[ao_next_task_index]; - if (ao_cur_task->wchan == NULL) { - ao_cur_task_index = ao_next_task_index; - break; - } - - /* Check if the alarm is set for a time which has passed */ - if (ao_cur_task->alarm && - (int16_t) (ao_time() - ao_cur_task->alarm) >= 0) { - ao_cur_task_index = ao_next_task_index; - break; - } - - /* Enter lower power mode when there isn't anything to do */ - if (ao_next_task_index == ao_cur_task_index) - PCON = PCON_IDLE; - } - } - - { - uint8_t stack_len; - __data uint8_t *stack_ptr; - __xdata uint8_t *save_ptr; - - /* Restore the old stack */ - stack_len = ao_cur_task->stack_count; - SP = AO_STACK_START - 1 + stack_len; - - stack_ptr = (uint8_t __data *) AO_STACK_START; - save_ptr = (uint8_t __xdata *) ao_cur_task->stack; - do - *stack_ptr++ = *save_ptr++; - while (--stack_len); - } - - _asm - pop _bp - pop PSW - pop ar1 - pop ar0 - pop ar7 - pop ar6 - pop ar5 - pop ar4 - pop ar3 - pop ar2 - pop b - pop DPH - pop DPL - /* The next byte of the stack is the IE register. Only the global - enable bit forms part of the task context. Pop off the IE then set - the global enable bit to match that of the stored IE register. */ - pop ACC - JB ACC.7,0098$ - CLR _EA - LJMP 0099$ - 0098$: - SETB _EA - 0099$: - /* Finally pop off the ACC, which was the first register saved. */ - pop ACC - ret - _endasm; -} - -uint8_t -ao_sleep(__xdata void *wchan) -{ - __critical { - ao_cur_task->wchan = wchan; - } - ao_yield(); - ao_cur_task->alarm = 0; - if (ao_cur_task->wchan) { - ao_cur_task->wchan = NULL; - return 1; - } - return 0; -} - -void -ao_wakeup(__xdata void *wchan) -{ - uint8_t i; - - for (i = 0; i < ao_num_tasks; i++) - if (ao_tasks[i]->wchan == wchan) - ao_tasks[i]->wchan = NULL; -} - -void -ao_alarm(uint16_t delay) -{ - /* Make sure we sleep *at least* delay ticks, which means adding - * one to account for the fact that we may be close to the next tick - */ - if (!(ao_cur_task->alarm = ao_time() + delay + 1)) - ao_cur_task->alarm = 1; -} - -void -ao_exit(void) __critical -{ - uint8_t i; - ao_num_tasks--; - for (i = ao_cur_task_index; i < ao_num_tasks; i++) - ao_tasks[i] = ao_tasks[i+1]; - ao_cur_task_index = AO_NO_TASK_INDEX; - ao_yield(); - /* we'll never get back here */ -} - -void -ao_task_info(void) -{ - uint8_t i; - uint8_t pc_loc; - __xdata struct ao_task *task; - - for (i = 0; i < ao_num_tasks; i++) { - task = ao_tasks[i]; - pc_loc = task->stack_count - 17; - printf("%12s: wchan %04x pc %04x\n", - task->name, - (int16_t) task->wchan, - (task->stack[pc_loc]) | (task->stack[pc_loc+1] << 8)); - } -} - -void -ao_start_scheduler(void) -{ - ao_cur_task_index = AO_NO_TASK_INDEX; - ao_cur_task = NULL; - ao_yield(); -} diff --git a/src/ao_telebt.c b/src/ao_telebt.c deleted file mode 100644 index 85565172..00000000 --- a/src/ao_telebt.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -__code uint8_t ao_log_format = AO_LOG_FORMAT_NONE; /* until we actually log stuff */ - -void -main(void) -{ - ao_clock_init(); - - /* Turn on the LED until the system is stable */ - ao_led_init(LEDS_AVAILABLE); - ao_led_on(AO_LED_RED); - ao_timer_init(); -#if HAS_BEEP - ao_beep_init(); -#endif - ao_cmd_init(); -#if HAS_EEPROM - ao_spi_init(); - ao_storage_init(); -#endif - ao_usb_init(); - ao_monitor_init(AO_LED_GREEN, TRUE); - ao_rssi_init(AO_LED_RED); - ao_radio_init(); - ao_packet_master_init(); - ao_btm_init(); -#if HAS_DBG - ao_dbg_init(); -#endif - ao_config_init(); - ao_start_scheduler(); -} diff --git a/src/ao_teledongle.c b/src/ao_teledongle.c deleted file mode 100644 index 008b200a..00000000 --- a/src/ao_teledongle.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 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) -{ - ao_clock_init(); - - /* Turn on the LED until the system is stable */ - ao_led_init(LEDS_AVAILABLE); - ao_led_on(AO_LED_RED); - ao_timer_init(); - ao_cmd_init(); - ao_usb_init(); - ao_monitor_init(AO_LED_GREEN, TRUE); - ao_rssi_init(AO_LED_RED); - ao_radio_init(); - ao_packet_master_init(); -#if HAS_DBG - ao_dbg_init(); -#endif - ao_config_init(); - ao_start_scheduler(); -} diff --git a/src/ao_telem.h b/src/ao_telem.h deleted file mode 100644 index 1a8da291..00000000 --- a/src/ao_telem.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_TELEM_H_ -#define _AO_TELEM_H_ - -#define AO_TELEMETRY_VERSION 4 - -/* - * Telemetry version 4 and higher format: - * - * General header fields - * - * Name Value - * - * VERSION Telemetry version number (4 or more). Must be first. - * c Callsign (string, no spaces allowed) - * n Flight unit serial number (integer) - * f Flight number (integer) - * r Packet RSSI value (integer) - * s Flight computer state (string, no spaces allowed) - * t Flight computer clock (integer in centiseconds) - */ - -#define AO_TELEM_VERSION "VERSION" -#define AO_TELEM_CALL "c" -#define AO_TELEM_SERIAL "n" -#define AO_TELEM_FLIGHT "f" -#define AO_TELEM_RSSI "r" -#define AO_TELEM_STATE "s" -#define AO_TELEM_TICK "t" - -/* - * Raw sensor values - * - * Name Value - * r_a Accelerometer reading (integer) - * r_b Barometer reading (integer) - * r_t Thermometer reading (integer) - * r_v Battery reading (integer) - * r_d Drogue continuity (integer) - * r_m Main continuity (integer) - */ - -#define AO_TELEM_RAW_ACCEL "r_a" -#define AO_TELEM_RAW_BARO "r_b" -#define AO_TELEM_RAW_THERMO "r_t" -#define AO_TELEM_RAW_BATT "r_v" -#define AO_TELEM_RAW_DROGUE "r_d" -#define AO_TELEM_RAW_MAIN "r_m" - -/* - * Sensor calibration values - * - * Name Value - * c_a Ground accelerometer reading (integer) - * c_b Ground barometer reading (integer) - * c_p Accelerometer reading for +1g - * c_m Accelerometer reading for -1g - */ - -#define AO_TELEM_CAL_ACCEL_GROUND "c_a" -#define AO_TELEM_CAL_BARO_GROUND "c_b" -#define AO_TELEM_CAL_ACCEL_PLUS "c_p" -#define AO_TELEM_CAL_ACCEL_MINUS "c_m" - -/* - * Kalman state values - * - * Name Value - * k_h Height above pad (integer, meters) - * k_s Vertical speeed (integer, m/s * 16) - * k_a Vertical acceleration (integer, m/s² * 16) - */ - -#define AO_TELEM_KALMAN_HEIGHT "k_h" -#define AO_TELEM_KALMAN_SPEED "k_s" -#define AO_TELEM_KALMAN_ACCEL "k_a" - -/* - * Ad-hoc flight values - * - * Name Value - * a_a Acceleration (integer, sensor units) - * a_s Speed (integer, integrated acceleration value) - * a_b Barometer reading (integer, sensor units) - */ - -#define AO_TELEM_ADHOC_ACCEL "a_a" -#define AO_TELEM_ADHOC_SPEED "a_s" -#define AO_TELEM_ADHOC_BARO "a_b" - -/* - * GPS values - * - * Name Value - * g GPS state (string): - * l locked - * u unlocked - * e error (missing or broken) - * g_n Number of sats used in solution - * g_ns Latitude (degrees * 10e7) - * g_ew Longitude (degrees * 10e7) - * g_a Altitude (integer meters) - * g_Y GPS year (integer) - * g_M GPS month (integer - 1-12) - * g_D GPS day (integer - 1-31) - * g_h GPS hour (integer - 0-23) - * g_m GPS minute (integer - 0-59) - * g_s GPS second (integer - 0-59) - * g_v GPS vertical speed (integer, cm/sec) - * g_g GPS horizontal speed (integer, cm/sec) - * g_c GPS course (integer, 0-359) - * g_hd GPS hdop (integer * 10) - * g_vd GPS vdop (integer * 10) - * g_he GPS h error (integer) - * g_ve GPS v error (integer) - */ - -#define AO_TELEM_GPS_STATE "g" -#define AO_TELEM_GPS_STATE_LOCKED 'l' -#define AO_TELEM_GPS_STATE_UNLOCKED 'u' -#define AO_TELEM_GPS_STATE_ERROR 'e' -#define AO_TELEM_GPS_NUM_SAT "g_n" -#define AO_TELEM_GPS_LATITUDE "g_ns" -#define AO_TELEM_GPS_LONGITUDE "g_ew" -#define AO_TELEM_GPS_ALTITUDE "g_a" -#define AO_TELEM_GPS_YEAR "g_Y" -#define AO_TELEM_GPS_MONTH "g_M" -#define AO_TELEM_GPS_DAY "g_D" -#define AO_TELEM_GPS_HOUR "g_h" -#define AO_TELEM_GPS_MINUTE "g_m" -#define AO_TELEM_GPS_SECOND "g_s" -#define AO_TELEM_GPS_VERTICAL_SPEED "g_v" -#define AO_TELEM_GPS_HORIZONTAL_SPEED "g_g" -#define AO_TELEM_GPS_COURSE "g_c" -#define AO_TELEM_GPS_HDOP "g_hd" -#define AO_TELEM_GPS_VDOP "g_vd" -#define AO_TELEM_GPS_HERROR "g_he" -#define AO_TELEM_GPS_VERROR "g_ve" - -/* - * GPS satellite values - * - * Name Value - * s_n Number of satellites reported (integer) - * s_v0 Space vehicle ID (integer) for report 0 - * s_c0 C/N0 number (integer) for report 0 - * s_v1 Space vehicle ID (integer) for report 1 - * s_c1 C/N0 number (integer) for report 1 - * ... - */ - -#define AO_TELEM_SAT_NUM "s_n" -#define AO_TELEM_SAT_SVID "s_v" -#define AO_TELEM_SAT_C_N_0 "s_c" - -#endif /* _AO_TELEM_H_ */ diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c deleted file mode 100644 index f560740a..00000000 --- a/src/ao_telemetrum.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "ao_pins.h" - -void -main(void) -{ - /* - * Reduce the transient on the ignite pins at startup by - * pulling the pins low as soon as possible at power up - */ - ao_ignite_set_pins(); - - ao_clock_init(); - - /* Turn on the red LED until the system is stable */ - ao_led_init(LEDS_AVAILABLE); - ao_led_on(AO_LED_RED); - - /* A hack -- look at the SPI clock pin, if it's sitting at - * ground, then we force the computer to idle mode instead of - * flight mode - */ - if (P1_3 == 0) { - ao_flight_force_idle = 1; - while (P1_3 == 0) - ; - } - ao_timer_init(); - ao_adc_init(); - ao_beep_init(); - ao_cmd_init(); - ao_spi_init(); - ao_storage_init(); - ao_flight_init(); - ao_log_init(); - ao_report_init(); - ao_usb_init(); - ao_serial_init(); - ao_gps_init(); - ao_gps_report_init(); - ao_telemetry_init(); - ao_radio_init(); - ao_packet_slave_init(TRUE); - ao_igniter_init(); -#if HAS_DBG - ao_dbg_init(); -#endif -#if HAS_COMPANION - ao_companion_init(); -#endif - ao_config_init(); - ao_start_scheduler(); -} diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c deleted file mode 100644 index c7338a58..00000000 --- a/src/ao_telemetry.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "ao_product.h" - -static __pdata uint16_t ao_telemetry_interval; -static __pdata int8_t ao_telemetry_config_max; -static __pdata int8_t ao_telemetry_config_cur; -#if HAS_GPS -static __pdata int8_t ao_telemetry_loc_cur; -static __pdata int8_t ao_telemetry_sat_cur; -#endif -#if HAS_COMPANION -static __pdata int8_t ao_telemetry_companion_max; -static __pdata int8_t ao_telemetry_companion_cur; -#endif -static __pdata uint8_t ao_rdf = 0; -static __pdata uint16_t ao_rdf_time; - -#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) -#define AO_RDF_LENGTH_MS 500 - -#if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) -#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMETRUM -#endif - -#if defined(TELEMINI_V_1_0) -#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMINI -#endif - -#if defined(TELENANO_V_0_1) -#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELENANO -#endif - -static __xdata union ao_telemetry_all telemetry; - -/* Send sensor packet */ -static void -ao_send_sensor(void) -{ - uint8_t sample; - sample = ao_sample_adc; - - telemetry.generic.tick = ao_adc_ring[sample].tick; - telemetry.generic.type = AO_TELEMETRY_SENSOR; - - telemetry.sensor.state = ao_flight_state; -#if HAS_ACCEL - telemetry.sensor.accel = ao_adc_ring[sample].accel; -#else - telemetry.sensor.accel = 0; -#endif - telemetry.sensor.pres = ao_adc_ring[sample].pres; - telemetry.sensor.temp = ao_adc_ring[sample].temp; - telemetry.sensor.v_batt = ao_adc_ring[sample].v_batt; -#if HAS_IGNITE - telemetry.sensor.sense_d = ao_adc_ring[sample].sense_d; - telemetry.sensor.sense_m = ao_adc_ring[sample].sense_m; -#else - telemetry.sensor.sense_d = 0; - telemetry.sensor.sense_m = 0; -#endif - - telemetry.sensor.acceleration = ao_accel; - telemetry.sensor.speed = ao_speed; - telemetry.sensor.height = ao_height; - - telemetry.sensor.ground_pres = ao_ground_pres; -#if HAS_ACCEL - telemetry.sensor.ground_accel = ao_ground_accel; - telemetry.sensor.accel_plus_g = ao_config.accel_plus_g; - telemetry.sensor.accel_minus_g = ao_config.accel_minus_g; -#else - telemetry.sensor.ground_accel = 0; - telemetry.sensor.accel_plus_g = 0; - telemetry.sensor.accel_minus_g = 0; -#endif - - ao_radio_send(&telemetry, sizeof (telemetry)); -} - -static void -ao_send_configuration(void) -{ - if (--ao_telemetry_config_cur <= 0) - { - telemetry.generic.type = AO_TELEMETRY_CONFIGURATION; - telemetry.configuration.device = AO_idProduct_NUMBER; - telemetry.configuration.flight = ao_log_full() ? 0 : ao_flight_number; - telemetry.configuration.config_major = AO_CONFIG_MAJOR; - telemetry.configuration.config_minor = AO_CONFIG_MINOR; - telemetry.configuration.apogee_delay = ao_config.apogee_delay; - telemetry.configuration.main_deploy = ao_config.main_deploy; - telemetry.configuration.flight_log_max = ao_config.flight_log_max >> 10; - memcpy (telemetry.configuration.callsign, - ao_config.callsign, - AO_MAX_CALLSIGN); - memcpy (telemetry.configuration.version, - ao_version, - AO_MAX_VERSION); - ao_radio_send(&telemetry, sizeof (telemetry)); - ao_telemetry_config_cur = ao_telemetry_config_max; - } -} - -#if HAS_GPS -static void -ao_send_location(void) -{ - if (--ao_telemetry_loc_cur <= 0) - { - telemetry.generic.type = AO_TELEMETRY_LOCATION; - ao_mutex_get(&ao_gps_mutex); - memcpy(&telemetry.location.flags, - &ao_gps_data.flags, - 26); - ao_mutex_put(&ao_gps_mutex); - ao_radio_send(&telemetry, sizeof (telemetry)); - ao_telemetry_loc_cur = ao_telemetry_config_max; - } -} - -static void -ao_send_satellite(void) -{ - if (--ao_telemetry_sat_cur <= 0) - { - telemetry.generic.type = AO_TELEMETRY_SATELLITE; - ao_mutex_get(&ao_gps_mutex); - telemetry.satellite.channels = ao_gps_tracking_data.channels; - memcpy(&telemetry.satellite.sats, - &ao_gps_tracking_data.sats, - AO_MAX_GPS_TRACKING * sizeof (struct ao_telemetry_satellite_info)); - ao_mutex_put(&ao_gps_mutex); - ao_radio_send(&telemetry, sizeof (telemetry)); - ao_telemetry_sat_cur = ao_telemetry_config_max; - } -} -#endif - -#if HAS_COMPANION -static void -ao_send_companion(void) -{ - if (--ao_telemetry_companion_cur <= 0) { - telemetry.generic.type = AO_TELEMETRY_COMPANION; - telemetry.companion.board_id = ao_companion_setup.board_id; - telemetry.companion.update_period = ao_companion_setup.update_period; - telemetry.companion.channels = ao_companion_setup.channels; - ao_mutex_get(&ao_companion_mutex); - memcpy(&telemetry.companion.companion_data, - ao_companion_data, - ao_companion_setup.channels * 2); - ao_mutex_put(&ao_companion_mutex); - ao_radio_send(&telemetry, sizeof (telemetry)); - ao_telemetry_companion_cur = ao_telemetry_companion_max; - } -} -#endif - -void -ao_telemetry(void) -{ - uint16_t time; - int16_t delay; - - ao_config_get(); - if (!ao_config.radio_enable) - ao_exit(); - while (!ao_flight_number) - ao_sleep(&ao_flight_number); - - telemetry.generic.serial = ao_serial_number; - for (;;) { - while (ao_telemetry_interval == 0) - ao_sleep(&telemetry); - time = ao_rdf_time = ao_time(); - while (ao_telemetry_interval) { - - - ao_send_sensor(); -#if HAS_COMPANION - if (ao_companion_running) - ao_send_companion(); -#endif - ao_send_configuration(); -#if HAS_GPS - ao_send_location(); - ao_send_satellite(); -#endif - if (ao_rdf && - (int16_t) (ao_time() - ao_rdf_time) >= 0) - { - ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; - ao_radio_rdf(AO_RDF_LENGTH_MS); - } - time += ao_telemetry_interval; - delay = time - ao_time(); - if (delay > 0) - ao_delay(delay); - else - time = ao_time(); - } - } -} - -void -ao_telemetry_set_interval(uint16_t interval) -{ - ao_telemetry_interval = interval; - -#if HAS_COMPANION - if (!ao_companion_setup.update_period) - ao_companion_setup.update_period = AO_SEC_TO_TICKS(1); - ao_telemetry_companion_max = ao_companion_setup.update_period / interval; - ao_telemetry_companion_cur = 1; -#endif - - ao_telemetry_config_max = AO_SEC_TO_TICKS(1) / interval; -#if HAS_COMPANION - ao_telemetry_config_cur = ao_telemetry_companion_cur; - if (ao_telemetry_config_max > ao_telemetry_config_cur) - ao_telemetry_config_cur++; -#else - ao_telemetry_config_cur = 1; -#endif - -#if HAS_GPS - ao_telemetry_loc_cur = ao_telemetry_config_cur; - if (ao_telemetry_config_max > ao_telemetry_loc_cur) - ao_telemetry_loc_cur++; - ao_telemetry_sat_cur = ao_telemetry_loc_cur; - if (ao_telemetry_config_max > ao_telemetry_sat_cur) - ao_telemetry_sat_cur++; -#endif - ao_wakeup(&telemetry); -} - -void -ao_rdf_set(uint8_t rdf) -{ - ao_rdf = rdf; - if (rdf == 0) - ao_radio_rdf_abort(); - else - ao_rdf_time = ao_time(); -} - -__xdata struct ao_task ao_telemetry_task; - -void -ao_telemetry_init() -{ - ao_add_task(&ao_telemetry_task, ao_telemetry, "telemetry"); -} diff --git a/src/ao_telemini.c b/src/ao_telemini.c deleted file mode 100644 index fa23de01..00000000 --- a/src/ao_telemini.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "ao_pins.h" - -void -main(void) -{ - /* - * Reduce the transient on the ignite pins at startup by - * pulling the pins low as soon as possible at power up - */ - ao_ignite_set_pins(); - - ao_clock_init(); - - /* Turn on the red LED until the system is stable */ - ao_led_init(LEDS_AVAILABLE); - ao_led_on(AO_LED_RED); - - ao_timer_init(); - ao_adc_init(); - ao_cmd_init(); - ao_storage_init(); - ao_flight_init(); - ao_log_init(); - ao_report_init(); - ao_telemetry_init(); - ao_radio_init(); - ao_packet_slave_init(TRUE); - ao_igniter_init(); - ao_config_init(); - ao_start_scheduler(); -} diff --git a/src/ao_telenano.c b/src/ao_telenano.c deleted file mode 100644 index d91983d0..00000000 --- a/src/ao_telenano.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "ao_pins.h" - -void -main(void) -{ - ao_clock_init(); - - - /* Turn on the red LED until the system is stable */ - ao_led_init(LEDS_AVAILABLE); - ao_led_on(AO_LED_RED); - - ao_timer_init(); - ao_adc_init(); - ao_cmd_init(); - ao_storage_init(); - ao_flight_nano_init(); - ao_log_init(); - ao_report_init(); - ao_telemetry_init(); - ao_radio_init(); - ao_packet_slave_init(TRUE); - ao_config_init(); - ao_start_scheduler(); -} diff --git a/src/ao_teleterra.c b/src/ao_teleterra.c deleted file mode 100644 index d696b914..00000000 --- a/src/ao_teleterra.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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_ADC_ISR 1 -#include "ao.h" - -void -main(void) -{ - ao_clock_init(); - - /* Turn on the red LED until the system is stable */ - ao_led_init(AO_LED_RED|AO_LED_GREEN); - ao_led_on(AO_LED_RED); - ao_timer_init(); - ao_beep_init(); - ao_cmd_init(); - ao_usb_init(); - ao_serial_init(); - ao_monitor_init(AO_LED_GREEN, TRUE); - ao_radio_init(); - ao_config_init(); - ao_start_scheduler(); -} diff --git a/src/ao_test.c b/src/ao_test.c deleted file mode 100644 index 14c2eb75..00000000 --- a/src/ao_test.c +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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" - -struct ao_task __xdata blink_0_task; -struct ao_task __xdata blink_1_task; -struct ao_task __xdata wakeup_task; -struct ao_task __xdata beep_task; -struct ao_task __xdata echo_task; - -void delay(int n) __reentrant -{ - uint8_t j = 0; - while (--n) - while (--j) - ao_yield(); -} - -static __xdata uint8_t blink_chan; - -void -blink_0(void) -{ - uint8_t b = 0; - for (;;) { - b = 1 - b; - if (b) - ao_led_on(AO_LED_GREEN); - else - ao_led_off(AO_LED_GREEN); - ao_sleep(&blink_chan); - } -} - -void -blink_1(void) -{ - static __xdata struct ao_adc adc; - - for (;;) { - ao_sleep(&ao_adc_head); - ao_adc_get(&adc); - if (adc.accel < 15900) - ao_led_on(AO_LED_RED); - else - ao_led_off(AO_LED_RED); - } -} - -void -wakeup(void) -{ - for (;;) { - ao_delay(AO_MS_TO_TICKS(100)); - ao_wakeup(&blink_chan); - } -} - -void -beep(void) -{ - static __xdata struct ao_adc adc; - - for (;;) { - ao_delay(AO_SEC_TO_TICKS(1)); - ao_adc_get(&adc); - if (adc.temp > 7400) - ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(50)); - } -} - -void -echo(void) -{ - char c; - for (;;) { - ao_usb_flush(); - c = ao_usb_getchar(); - ao_usb_putchar(c); - if (c == '\r') - ao_usb_putchar('\n'); - } -} - -void -main(void) -{ - ao_clock_init(); - -// ao_add_task(&blink_0_task, blink_0); -// ao_add_task(&blink_1_task, blink_1); -// ao_add_task(&wakeup_task, wakeup); -// ao_add_task(&beep_task, beep); - ao_add_task(&echo_task, echo); - ao_timer_init(); - ao_adc_init(); - ao_beep_init(); - ao_led_init(); - ao_usb_init(); - - ao_start_scheduler(); -} diff --git a/src/ao_tidongle.c b/src/ao_tidongle.c deleted file mode 100644 index 3b7c2733..00000000 --- a/src/ao_tidongle.c +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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) -{ - ao_clock_init(); - - /* Turn on the LED until the system is stable */ - ao_led_init(AO_LED_RED); - ao_led_on(AO_LED_RED); - ao_timer_init(); - ao_cmd_init(); - ao_usb_init(); - ao_monitor_init(AO_LED_RED, TRUE); - ao_rssi_init(AO_LED_RED); - ao_radio_init(); - ao_dbg_init(); - ao_config_init(); - /* Bring up the USB link */ - P1DIR |= 1; - P1 |= 1; - ao_start_scheduler(); -} diff --git a/src/ao_timer.c b/src/ao_timer.c deleted file mode 100644 index c977fbc8..00000000 --- a/src/ao_timer.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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" - -static volatile __data uint16_t ao_tick_count; - -uint16_t ao_time(void) __critical -{ - return ao_tick_count; -} - -static __xdata uint8_t ao_forever; - -void -ao_delay(uint16_t ticks) -{ - ao_alarm(ticks); - ao_sleep(&ao_forever); -} - -#define T1_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ -#define T1_SAMPLE_TIME 30000 /* 3e6/30000 = 100 */ - -#if HAS_ADC -volatile __data uint8_t ao_adc_interval = 1; -volatile __data uint8_t ao_adc_count; -#endif - -void ao_timer_isr(void) __interrupt 9 -{ - ++ao_tick_count; -#if HAS_ADC - if (++ao_adc_count == ao_adc_interval) { - ao_adc_count = 0; - ao_adc_poll(); - } -#endif -} - -#if HAS_ADC -void -ao_timer_set_adc_interval(uint8_t interval) __critical -{ - ao_adc_interval = interval; - ao_adc_count = 0; -} -#endif - -void -ao_timer_init(void) -{ - /* NOTE: This uses a timer only present on cc1111 architecture. */ - - /* disable timer 1 */ - T1CTL = 0; - - /* set the sample rate */ - T1CC0H = T1_SAMPLE_TIME >> 8; - T1CC0L = (uint8_t) T1_SAMPLE_TIME; - - T1CCTL0 = T1CCTL_MODE_COMPARE; - T1CCTL1 = 0; - T1CCTL2 = 0; - - /* clear timer value */ - T1CNTL = 0; - - /* enable overflow interrupt */ - OVFIM = 1; - /* enable timer 1 interrupt */ - T1IE = 1; - - /* enable timer 1 in module mode, dividing by 8 */ - T1CTL = T1CTL_MODE_MODULO | T1CTL_DIV_8; -} - -/* - * AltOS always cranks the clock to the max frequency - */ -void -ao_clock_init(void) -{ - /* Switch system clock to crystal oscilator */ - CLKCON = (CLKCON & ~CLKCON_OSC_MASK) | (CLKCON_OSC_XTAL); - - while (!(SLEEP & SLEEP_XOSC_STB)) - ; - - /* Crank up the timer tick and system clock speed */ - CLKCON = ((CLKCON & ~(CLKCON_TICKSPD_MASK | CLKCON_CLKSPD_MASK)) | - (CLKCON_TICKSPD_1 | CLKCON_CLKSPD_1)); - - while ((CLKCON & (CLKCON_TICKSPD_MASK|CLKCON_CLKSPD_MASK)) != - (CLKCON_TICKSPD_1 | CLKCON_CLKSPD_1)) - ; -} diff --git a/src/ao_usb.c b/src/ao_usb.c deleted file mode 100644 index 08cb7390..00000000 --- a/src/ao_usb.c +++ /dev/null @@ -1,460 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "ao_usb.h" - -struct ao_task __xdata ao_usb_task; - -static __xdata uint16_t ao_usb_in_bytes; -static __pdata uint16_t ao_usb_in_bytes_last; -static __xdata uint16_t ao_usb_out_bytes; -static __pdata uint8_t ao_usb_iif; -static __pdata uint8_t ao_usb_running; - -static void -ao_usb_set_interrupts(void) -{ - /* IN interrupts on the control an IN endpoints */ - USBIIE = (1 << AO_USB_CONTROL_EP) | (1 << AO_USB_IN_EP); - - /* OUT interrupts on the OUT endpoint */ - USBOIE = (1 << AO_USB_OUT_EP); - - /* Only care about reset */ - USBCIE = USBCIE_RSTIE; -} - -/* This interrupt is shared with port 2, - * so when we hook that up, fix this - */ -void -ao_usb_isr(void) __interrupt 6 -{ - USBIF = 0; - ao_usb_iif |= USBIIF; - if (ao_usb_iif & 1) - ao_wakeup(&ao_usb_task); - if (ao_usb_iif & (1 << AO_USB_IN_EP)) - ao_wakeup(&ao_usb_in_bytes); - - if (USBOIF & (1 << AO_USB_OUT_EP)) - ao_wakeup(&ao_stdin_ready); - - if (USBCIF & USBCIF_RSTIF) - ao_usb_set_interrupts(); -#if HAS_BTM -#if BT_LINK_ON_P2 - ao_btm_isr(); -#endif -#endif -} - -struct ao_usb_setup { - uint8_t dir_type_recip; - uint8_t request; - uint16_t value; - uint16_t index; - uint16_t length; -} __xdata ao_usb_setup; - -__pdata uint8_t ao_usb_ep0_state; -uint8_t * __pdata ao_usb_ep0_in_data; -__pdata uint8_t ao_usb_ep0_in_len; -__pdata uint8_t ao_usb_ep0_in_buf[2]; -__pdata uint8_t ao_usb_ep0_out_len; -__xdata uint8_t *__pdata ao_usb_ep0_out_data; -__pdata uint8_t ao_usb_configuration; - -/* Send an IN data packet */ -static void -ao_usb_ep0_flush(void) -{ - __pdata uint8_t this_len; - __pdata uint8_t cs0; - - /* If the IN packet hasn't been picked up, just return */ - USBINDEX = 0; - cs0 = USBCS0; - if (cs0 & USBCS0_INPKT_RDY) - return; - - this_len = ao_usb_ep0_in_len; - if (this_len > AO_USB_CONTROL_SIZE) - this_len = AO_USB_CONTROL_SIZE; - cs0 = USBCS0_INPKT_RDY; - if (this_len != AO_USB_CONTROL_SIZE) { - cs0 = USBCS0_INPKT_RDY | USBCS0_DATA_END; - ao_usb_ep0_state = AO_USB_EP0_IDLE; - } - ao_usb_ep0_in_len -= this_len; - while (this_len--) - USBFIFO[0] = *ao_usb_ep0_in_data++; - USBINDEX = 0; - USBCS0 = cs0; -} - -__xdata static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; - -/* Walk through the list of descriptors and find a match - */ -static void -ao_usb_get_descriptor(uint16_t value) -{ - __code uint8_t *__pdata descriptor; - __pdata uint8_t type = value >> 8; - __pdata uint8_t index = value; - - descriptor = ao_usb_descriptors; - while (descriptor[0] != 0) { - if (descriptor[1] == type && index-- == 0) { - if (type == AO_USB_DESC_CONFIGURATION) - ao_usb_ep0_in_len = descriptor[2]; - else - ao_usb_ep0_in_len = descriptor[0]; - ao_usb_ep0_in_data = descriptor; - break; - } - descriptor += descriptor[0]; - } -} - -/* Read data from the ep0 OUT fifo - */ -static void -ao_usb_ep0_fill(void) -{ - __pdata uint8_t len; - - USBINDEX = 0; - len = USBCNT0; - if (len > ao_usb_ep0_out_len) - len = ao_usb_ep0_out_len; - ao_usb_ep0_out_len -= len; - while (len--) - *ao_usb_ep0_out_data++ = USBFIFO[0]; -} - -void -ao_usb_ep0_queue_byte(uint8_t a) -{ - ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a; -} - -void -ao_usb_set_address(uint8_t address) -{ - ao_usb_running = 1; - USBADDR = address | 0x80; - while (USBADDR & 0x80) - ; -} - -static void -ao_usb_set_configuration(void) -{ - /* Set the IN max packet size, double buffered */ - USBINDEX = AO_USB_IN_EP; - USBMAXI = AO_USB_IN_SIZE >> 3; - USBCSIH |= USBCSIH_IN_DBL_BUF; - - /* Set the OUT max packet size, double buffered */ - USBINDEX = AO_USB_OUT_EP; - USBMAXO = AO_USB_OUT_SIZE >> 3; - USBCSOH = USBCSOH_OUT_DBL_BUF; -} - -static void -ao_usb_ep0_setup(void) -{ - /* Pull the setup packet out of the fifo */ - ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_setup; - ao_usb_ep0_out_len = 8; - ao_usb_ep0_fill(); - if (ao_usb_ep0_out_len != 0) - return; - - /* Figure out how to ACK the setup packet */ - if (ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) { - if (ao_usb_setup.length) - ao_usb_ep0_state = AO_USB_EP0_DATA_IN; - else - ao_usb_ep0_state = AO_USB_EP0_IDLE; - } else { - if (ao_usb_setup.length) - ao_usb_ep0_state = AO_USB_EP0_DATA_OUT; - else - ao_usb_ep0_state = AO_USB_EP0_IDLE; - } - USBINDEX = 0; - if (ao_usb_ep0_state == AO_USB_EP0_IDLE) - USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END; - else - USBCS0 = USBCS0_CLR_OUTPKT_RDY; - - ao_usb_ep0_in_data = ao_usb_ep0_in_buf; - ao_usb_ep0_in_len = 0; - switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_TYPE_MASK) { - case AO_USB_TYPE_STANDARD: - switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_RECIP_MASK) { - case AO_USB_RECIP_DEVICE: - switch(ao_usb_setup.request) { - case AO_USB_REQ_GET_STATUS: - ao_usb_ep0_queue_byte(0); - ao_usb_ep0_queue_byte(0); - break; - case AO_USB_REQ_SET_ADDRESS: - ao_usb_set_address(ao_usb_setup.value); - break; - case AO_USB_REQ_GET_DESCRIPTOR: - ao_usb_get_descriptor(ao_usb_setup.value); - break; - case AO_USB_REQ_GET_CONFIGURATION: - ao_usb_ep0_queue_byte(ao_usb_configuration); - break; - case AO_USB_REQ_SET_CONFIGURATION: - ao_usb_configuration = ao_usb_setup.value; - ao_usb_set_configuration(); - break; - } - 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); - ao_usb_ep0_queue_byte(0); - break; - case AO_USB_REQ_GET_INTERFACE: - ao_usb_ep0_queue_byte(0); - break; - case AO_USB_REQ_SET_INTERFACE: - break; - } - break; - case AO_USB_RECIP_ENDPOINT: - switch(ao_usb_setup.request) { - case AO_USB_REQ_GET_STATUS: - ao_usb_ep0_queue_byte(0); - ao_usb_ep0_queue_byte(0); - break; - } - break; - } - break; - case AO_USB_TYPE_CLASS: - switch (ao_usb_setup.request) { - case SET_LINE_CODING: - ao_usb_ep0_out_len = 7; - ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_line_coding; - break; - case GET_LINE_CODING: - ao_usb_ep0_in_len = 7; - ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding; - break; - case SET_CONTROL_LINE_STATE: - break; - } - break; - } - if (ao_usb_ep0_state != AO_USB_EP0_DATA_OUT) { - if (ao_usb_setup.length < ao_usb_ep0_in_len) - ao_usb_ep0_in_len = ao_usb_setup.length; - ao_usb_ep0_flush(); - } -} - -/* End point 0 receives all of the control messages. */ -static void -ao_usb_ep0(void) -{ - __pdata uint8_t cs0; - - ao_usb_ep0_state = AO_USB_EP0_IDLE; - for (;;) { - __critical for (;;) { - if (ao_usb_iif & 1) { - ao_usb_iif &= ~1; - break; - } - ao_sleep(&ao_usb_task); - } - USBINDEX = 0; - cs0 = USBCS0; - if (cs0 & USBCS0_SETUP_END) { - ao_usb_ep0_state = AO_USB_EP0_IDLE; - USBCS0 = USBCS0_CLR_SETUP_END; - } - if (cs0 & USBCS0_SENT_STALL) { - ao_usb_ep0_state = AO_USB_EP0_IDLE; - USBCS0 &= ~USBCS0_SENT_STALL; - } - if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN && - (cs0 & USBCS0_INPKT_RDY) == 0) - { - ao_usb_ep0_flush(); - } - if (cs0 & USBCS0_OUTPKT_RDY) { - switch (ao_usb_ep0_state) { - case AO_USB_EP0_IDLE: - ao_usb_ep0_setup(); - break; - case AO_USB_EP0_DATA_OUT: - ao_usb_ep0_fill(); - if (ao_usb_ep0_out_len == 0) - ao_usb_ep0_state = AO_USB_EP0_IDLE; - USBINDEX = 0; - if (ao_usb_ep0_state == AO_USB_EP0_IDLE) - USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END; - else - USBCS0 = USBCS0_CLR_OUTPKT_RDY; - break; - } - } - } -} - -/* Wait for a free IN buffer */ -static void -ao_usb_in_wait(void) -{ - for (;;) { - USBINDEX = AO_USB_IN_EP; - if ((USBCSIL & USBCSIL_INPKT_RDY) == 0) - break; - ao_sleep(&ao_usb_in_bytes); - } -} - -/* Send the current IN packet */ -static void -ao_usb_in_send(void) -{ - USBINDEX = AO_USB_IN_EP; - USBCSIL |= USBCSIL_INPKT_RDY; - ao_usb_in_bytes_last = ao_usb_in_bytes; - ao_usb_in_bytes = 0; -} - -void -ao_usb_flush(void) __critical -{ - if (!ao_usb_running) - return; - - /* If there are pending bytes, or if the last packet was full, - * send another IN packet - */ - if (ao_usb_in_bytes || (ao_usb_in_bytes_last == AO_USB_IN_SIZE)) { - ao_usb_in_wait(); - ao_usb_in_send(); - } -} - -void -ao_usb_putchar(char c) __critical __reentrant -{ - if (!ao_usb_running) - return; - - ao_usb_in_wait(); - - /* Queue a byte, sending the packet when full */ - USBFIFO[AO_USB_IN_EP << 1] = c; - if (++ao_usb_in_bytes == AO_USB_IN_SIZE) - ao_usb_in_send(); -} - -char -ao_usb_pollchar(void) __critical -{ - char c; - if (ao_usb_out_bytes == 0) { - USBINDEX = AO_USB_OUT_EP; - if ((USBCSOL & USBCSOL_OUTPKT_RDY) == 0) - return AO_READ_AGAIN; - ao_usb_out_bytes = (USBCNTH << 8) | USBCNTL; - if (ao_usb_out_bytes == 0) { - USBINDEX = AO_USB_OUT_EP; - USBCSOL &= ~USBCSOL_OUTPKT_RDY; - return AO_READ_AGAIN; - } - } - --ao_usb_out_bytes; - c = USBFIFO[AO_USB_OUT_EP << 1]; - if (ao_usb_out_bytes == 0) { - USBINDEX = AO_USB_OUT_EP; - USBCSOL &= ~USBCSOL_OUTPKT_RDY; - } - return c; -} - -char -ao_usb_getchar(void) __critical -{ - char c; - - while ((c = ao_usb_pollchar()) == AO_READ_AGAIN) - ao_sleep(&ao_stdin_ready); - return c; -} - -void -ao_usb_enable(void) -{ - /* Turn on the USB controller */ - SLEEP |= SLEEP_USB_EN; - - ao_usb_set_configuration(); - - ao_usb_set_interrupts(); - - /* enable USB interrupts */ - IEN2 |= IEN2_USBIE; - - /* Clear any pending interrupts */ - USBCIF = 0; - USBOIF = 0; - USBIIF = 0; -} - -void -ao_usb_disable(void) -{ - /* Disable USB interrupts */ - USBIIE = 0; - USBOIE = 0; - USBCIE = 0; - IEN2 &= ~IEN2_USBIE; - - /* Clear any pending interrupts */ - USBCIF = 0; - USBOIF = 0; - USBIIF = 0; - - /* Turn off the USB controller */ - SLEEP &= ~SLEEP_USB_EN; -} - -void -ao_usb_init(void) -{ - ao_usb_enable(); - - ao_add_task(&ao_usb_task, ao_usb_ep0, "usb"); - ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); -} diff --git a/src/ao_usb.h b/src/ao_usb.h deleted file mode 100644 index 6633dafc..00000000 --- a/src/ao_usb.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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. - */ - -#ifndef _AO_USB_H_ -#define _AO_USB_H_ - -#define AO_USB_SETUP_DIR_MASK (0x01 << 7) -#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) -#define AO_USB_SETUP_RECIP_MASK (0x1f) - -#define AO_USB_DIR_OUT 0 -#define AO_USB_DIR_IN (1 << 7) - -#define AO_USB_TYPE_STANDARD 0 -#define AO_USB_TYPE_CLASS (1 << 5) -#define AO_USB_TYPE_VENDOR (2 << 5) -#define AO_USB_TYPE_RESERVED (3 << 5) - -#define AO_USB_RECIP_DEVICE 0 -#define AO_USB_RECIP_INTERFACE 1 -#define AO_USB_RECIP_ENDPOINT 2 -#define AO_USB_RECIP_OTHER 3 - -/* standard requests */ -#define AO_USB_REQ_GET_STATUS 0x00 -#define AO_USB_REQ_CLEAR_FEATURE 0x01 -#define AO_USB_REQ_SET_FEATURE 0x03 -#define AO_USB_REQ_SET_ADDRESS 0x05 -#define AO_USB_REQ_GET_DESCRIPTOR 0x06 -#define AO_USB_REQ_SET_DESCRIPTOR 0x07 -#define AO_USB_REQ_GET_CONFIGURATION 0x08 -#define AO_USB_REQ_SET_CONFIGURATION 0x09 -#define AO_USB_REQ_GET_INTERFACE 0x0A -#define AO_USB_REQ_SET_INTERFACE 0x0B -#define AO_USB_REQ_SYNCH_FRAME 0x0C - -#define AO_USB_DESC_DEVICE 1 -#define AO_USB_DESC_CONFIGURATION 2 -#define AO_USB_DESC_STRING 3 -#define AO_USB_DESC_INTERFACE 4 -#define AO_USB_DESC_ENDPOINT 5 -#define AO_USB_DESC_DEVICE_QUALIFIER 6 -#define AO_USB_DESC_OTHER_SPEED 7 -#define AO_USB_DESC_INTERFACE_POWER 8 - -#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) -#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) - -#define AO_USB_CONTROL_EP 0 -#define AO_USB_INT_EP 1 -#define AO_USB_OUT_EP 4 -#define AO_USB_IN_EP 5 -#define AO_USB_CONTROL_SIZE 32 -/* - * Double buffer IN and OUT EPs, so each - * gets half of the available space - * - * Ah, but USB bulk packets can only come in 8, 16, 32 and 64 - * byte sizes, so we'll use 64 for everything - */ -#define AO_USB_IN_SIZE 64 -#define AO_USB_OUT_SIZE 64 - -#define AO_USB_EP0_IDLE 0 -#define AO_USB_EP0_DATA_IN 1 -#define AO_USB_EP0_DATA_OUT 2 - -#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) - -/* CDC definitions */ -#define CS_INTERFACE 0x24 -#define CS_ENDPOINT 0x25 - -#define SET_LINE_CODING 0x20 -#define GET_LINE_CODING 0x21 -#define SET_CONTROL_LINE_STATE 0x22 - -/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ -struct ao_usb_line_coding { - uint32_t rate; - uint8_t char_format; - uint8_t parity; - uint8_t data_bits; -} ; - -#endif /* _AO_USB_H_ */ diff --git a/src/at45db161d.h b/src/at45db161d.h deleted file mode 100644 index 9ee6f1b6..00000000 --- a/src/at45db161d.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -/* Defines for the Atmel AT45DB161D 16Mbit SPI Bus DataFlash® */ - -#ifndef _AT45DB161D_H_ -#define _AT45DB161D_H_ - -/* - * We reserve the last block on the device for - * configuration space. Writes and reads in this - * area return errors. - */ - - -#define FLASH_READ 0x03 -#define FLASH_WRITE 0x82 -#define FLASH_PAGE_ERASE 0x81 -#define FLASH_READ_STATUS 0xd7 -#define FLASH_SET_CONFIG 0x3d - -#define FLASH_SET_512_BYTE_0 0x2a -#define FLASH_SET_512_BYTE_1 0x80 -#define FLASH_SET_512_BYTE_2 0xa6 - -#define FLASH_STATUS_RDY (1 << 7) -#define FLASH_STATUS_COMP (1 << 6) -#define FLASH_STATUS_PROTECT (1 << 1) -#define FLASH_STATUS_PAGESIZE_512 (1 << 0) - -#endif /* _AT45DB161D_H_ */ diff --git a/src/cc1111.h b/src/cc1111.h deleted file mode 100644 index e52aa79f..00000000 --- a/src/cc1111.h +++ /dev/null @@ -1,1306 +0,0 @@ -/*------------------------------------------------------------------------- - Register Declarations for the ChipCon CC1111 Processor Range - - Copyright © 2008 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. - - Adapted from the Cygnal C8051F12x config file which is: - - Copyright (C) 2003 - Maarten Brock, sourceforge.brock@dse.nl - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA --------------------------------------------------------------------------*/ - -#ifndef _CC1111_H_ -#define _CC1111_H_ -#include -#include - -__sfr __at 0xA8 IEN0; /* Interrupt Enable 0 Register */ - -sbit __at 0xA8 RFTXRXIE; /* RF TX/RX done interrupt enable */ -sbit __at 0xA9 ADCIE; /* ADC interrupt enable */ -sbit __at 0xAA URX0IE; /* USART0 RX interrupt enable */ -sbit __at 0xAB URX1IE; /* USART1 RX interrupt enable (shared with I2S RX) */ -sbit __at 0xAB I2SRXIE; /* I2S RX interrupt enable (shared with USART1 RX) */ -sbit __at 0xAC ENCIE; /* AES encryption/decryption interrupt enable */ -sbit __at 0xAD STIE; /* Sleep Timer interrupt enable */ -sbit __at 0xAF EA; /* Enable All */ - -#define IEN0_EA (1 << 7) -#define IEN0_STIE (1 << 5) -#define IEN0_ENCIE (1 << 4) -#define IEN0_URX1IE (1 << 3) -#define IEN0_I2SRXIE (1 << 3) -#define IEN0_URX0IE (1 << 2) -#define IEN0_ADCIE (1 << 1) -#define IEN0_RFTXRXIE (1 << 0) - -__sfr __at 0xB8 IEN1; /* Interrupt Enable 1 Register */ - -#define IEN1_P0IE (1 << 5) /* Port 0 interrupt enable */ -#define IEN1_T4IE (1 << 4) /* Timer 4 interrupt enable */ -#define IEN1_T3IE (1 << 3) /* Timer 3 interrupt enable */ -#define IEN1_T2IE (1 << 2) /* Timer 2 interrupt enable */ -#define IEN1_T1IE (1 << 1) /* Timer 1 interrupt enable */ -#define IEN1_DMAIE (1 << 0) /* DMA transfer interrupt enable */ - -/* IEN2 */ -__sfr __at 0x9A IEN2; /* Interrupt Enable 2 Register */ - -#define IEN2_WDTIE (1 << 5) /* Watchdog timer interrupt enable */ -#define IEN2_P1IE (1 << 4) /* Port 1 interrupt enable */ -#define IEN2_UTX1IE (1 << 3) /* USART1 TX interrupt enable */ -#define IEN2_I2STXIE (1 << 3) /* I2S TX interrupt enable */ -#define IEN2_UTX0IE (1 << 2) /* USART0 TX interrupt enable */ -#define IEN2_P2IE (1 << 1) /* Port 2 interrupt enable */ -#define IEN2_USBIE (1 << 1) /* USB interrupt enable */ -#define IEN2_RFIE (1 << 0) /* RF general interrupt enable */ - -/* CLKCON 0xC6 */ -__sfr __at 0xC6 CLKCON; /* Clock Control */ - -#define CLKCON_OSC32K_RC (1 << 7) -#define CLKCON_OSC32K_XTAL (0 << 7) -#define CLKCON_OSC32K_MASK (1 << 7) -#define CLKCON_OSC_RC (1 << 6) -#define CLKCON_OSC_XTAL (0 << 6) -#define CLKCON_OSC_MASK (1 << 6) -#define CLKCON_TICKSPD_MASK (7 << 3) -# define CLKCON_TICKSPD_1 (0 << 3) -# define CLKCON_TICKSPD_1_2 (1 << 3) -# define CLKCON_TICKSPD_1_4 (2 << 3) -# define CLKCON_TICKSPD_1_8 (3 << 3) -# define CLKCON_TICKSPD_1_16 (4 << 3) -# define CLKCON_TICKSPD_1_32 (5 << 3) -# define CLKCON_TICKSPD_1_64 (6 << 3) -# define CLKCON_TICKSPD_1_128 (7 << 3) - -#define CLKCON_CLKSPD_MASK (7 << 0) -# define CLKCON_CLKSPD_1 (0 << 0) -# define CLKCON_CLKSPD_1_2 (1 << 0) -# define CLKCON_CLKSPD_1_4 (2 << 0) -# define CLKCON_CLKSPD_1_8 (3 << 0) -# define CLKCON_CLKSPD_1_16 (4 << 0) -# define CLKCON_CLKSPD_1_32 (5 << 0) -# define CLKCON_CLKSPD_1_64 (6 << 0) -# define CLKCON_CLKSPD_1_128 (7 << 0) - -/* SLEEP 0xBE */ -#define SLEEP_USB_EN (1 << 7) -#define SLEEP_XOSC_STB (1 << 6) -#define SLEEP_HFRC_STB (1 << 5) -#define SLEEP_RST_POWER (0 << 3) -#define SLEEP_RST_EXTERNAL (1 << 3) -#define SLEEP_RST_WATCHDOG (2 << 3) -#define SLEEP_RST_MASK (3 << 3) -#define SLEEP_OSC_PD (1 << 2) -#define SLEEP_MODE_PM0 (0 << 0) -#define SLEEP_MODE_PM1 (1 << 0) -#define SLEEP_MODE_PM2 (2 << 0) -#define SLEEP_MODE_PM3 (3 << 0) -#define SLEEP_MODE_MASK (3 << 0) - -/* PCON 0x87 */ -__sfr __at 0x87 PCON; /* Power Mode Control Register */ - -#define PCON_IDLE (1 << 0) - -/* - * TCON - */ -__sfr __at 0x88 TCON; /* CPU Interrupt Flag 1 */ - -sbit __at 0x8F URX1IF; /* USART1 RX interrupt flag. Automatically cleared */ -sbit __at 0x8F I2SRXIF; /* I2S RX interrupt flag. Automatically cleared */ -sbit __at 0x8D ADCIF; /* ADC interrupt flag. Automatically cleared */ -sbit __at 0x8B URX0IF; /* USART0 RX interrupt flag. Automatically cleared */ -sbit __at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically cleared */ - -#define TCON_URX1IF (1 << 7) -#define TCON_I2SRXIF (1 << 7) -#define TCON_ADCIF (1 << 5) -#define TCON_URX0IF (1 << 3) -#define TCON_RFTXRXIF (1 << 1) - -/* - * S0CON - */ -__sfr __at 0x98 S0CON; /* CPU Interrupt Flag 2 */ - -sbit __at 0x98 ENCIF_0; /* AES interrupt 0. */ -sbit __at 0x99 ENCIF_1; /* AES interrupt 1. */ - -#define S0CON_ENCIF_1 (1 << 1) -#define S0CON_ENCIF_0 (1 << 0) - -/* - * S1CON - */ -__sfr __at 0x9B S1CON; /* CPU Interrupt Flag 3 */ - -#define S1CON_RFIF_1 (1 << 1) -#define S1CON_RFIF_0 (1 << 0) - -/* - * IRCON - */ -__sfr __at 0xC0 IRCON; /* CPU Interrupt Flag 4 */ - -sbit __at 0xC0 DMAIF; /* DMA complete interrupt flag */ -sbit __at 0xC1 T1IF; /* Timer 1 interrupt flag. Automatically cleared */ -sbit __at 0xC2 T2IF; /* Timer 2 interrupt flag. Automatically cleared */ -sbit __at 0xC3 T3IF; /* Timer 3 interrupt flag. Automatically cleared */ -sbit __at 0xC4 T4IF; /* Timer 4 interrupt flag. Automatically cleared */ -sbit __at 0xC5 P0IF; /* Port0 interrupt flag */ -sbit __at 0xC7 STIF; /* Sleep Timer interrupt flag */ - -#define IRCON_DMAIF (1 << 0) /* DMA complete interrupt flag */ -#define IRCON_T1IF (1 << 1) /* Timer 1 interrupt flag. Automatically cleared */ -#define IRCON_T2IF (1 << 2) /* Timer 2 interrupt flag. Automatically cleared */ -#define IRCON_T3IF (1 << 3) /* Timer 3 interrupt flag. Automatically cleared */ -#define IRCON_T4IF (1 << 4) /* Timer 4 interrupt flag. Automatically cleared */ -#define IRCON_P0IF (1 << 5) /* Port0 interrupt flag */ -#define IRCON_STIF (1 << 7) /* Sleep Timer interrupt flag */ - -/* - * IRCON2 - */ -__sfr __at 0xE8 IRCON2; /* CPU Interrupt Flag 5 */ - -sbit __at 0xE8 USBIF; /* USB interrupt flag (shared with Port2) */ -sbit __at 0xE8 P2IF; /* Port2 interrupt flag (shared with USB) */ -sbit __at 0xE9 UTX0IF; /* USART0 TX interrupt flag */ -sbit __at 0xEA UTX1IF; /* USART1 TX interrupt flag (shared with I2S TX) */ -sbit __at 0xEA I2STXIF; /* I2S TX interrupt flag (shared with USART1 TX) */ -sbit __at 0xEB P1IF; /* Port1 interrupt flag */ -sbit __at 0xEC WDTIF; /* Watchdog timer interrupt flag */ - -#define IRCON2_USBIF (1 << 0) /* USB interrupt flag (shared with Port2) */ -#define IRCON2_P2IF (1 << 0) /* Port2 interrupt flag (shared with USB) */ -#define IRCON2_UTX0IF (1 << 1) /* USART0 TX interrupt flag */ -#define IRCON2_UTX1IF (1 << 2) /* USART1 TX interrupt flag (shared with I2S TX) */ -#define IRCON2_I2STXIF (1 << 2) /* I2S TX interrupt flag (shared with USART1 TX) */ -#define IRCON2_P1IF (1 << 3) /* Port1 interrupt flag */ -#define IRCON2_WDTIF (1 << 4) /* Watchdog timer interrupt flag */ - -/* - * IP1 - Interrupt Priority 1 - */ - -/* - * Interrupt priority groups: - * - * IPG0 RFTXRX RF DMA - * IPG1 ADC T1 P2INT/USB - * IPG2 URX0 T2 UTX0 - * IPG3 URX1/I2SRX T3 UTX1 / I2STX - * IPG4 ENC T4 P1INT - * IPG5 ST P0INT WDT - * - * Priority = (IP1 << 1) | IP0. Higher priority interrupts served first - */ - -__sfr __at 0xB9 IP1; /* Interrupt Priority 1 */ -__sfr __at 0xA9 IP0; /* Interrupt Priority 0 */ - -#define IP1_IPG5 (1 << 5) -#define IP1_IPG4 (1 << 4) -#define IP1_IPG3 (1 << 3) -#define IP1_IPG2 (1 << 2) -#define IP1_IPG1 (1 << 1) -#define IP1_IPG0 (1 << 0) - -#define IP0_IPG5 (1 << 5) -#define IP0_IPG4 (1 << 4) -#define IP0_IPG3 (1 << 3) -#define IP0_IPG2 (1 << 2) -#define IP0_IPG1 (1 << 1) -#define IP0_IPG0 (1 << 0) - -/* - * Timer 1 - */ -#define T1CTL_MODE_SUSPENDED (0 << 0) -#define T1CTL_MODE_FREE (1 << 0) -#define T1CTL_MODE_MODULO (2 << 0) -#define T1CTL_MODE_UP_DOWN (3 << 0) -#define T1CTL_MODE_MASK (3 << 0) -#define T1CTL_DIV_1 (0 << 2) -#define T1CTL_DIV_8 (1 << 2) -#define T1CTL_DIV_32 (2 << 2) -#define T1CTL_DIV_128 (3 << 2) -#define T1CTL_DIV_MASK (3 << 2) -#define T1CTL_OVFIF (1 << 4) -#define T1CTL_CH0IF (1 << 5) -#define T1CTL_CH1IF (1 << 6) -#define T1CTL_CH2IF (1 << 7) - -#define T1CCTL_NO_CAPTURE (0 << 0) -#define T1CCTL_CAPTURE_RISING (1 << 0) -#define T1CCTL_CAPTURE_FALLING (2 << 0) -#define T1CCTL_CAPTURE_BOTH (3 << 0) -#define T1CCTL_CAPTURE_MASK (3 << 0) - -#define T1CCTL_MODE_CAPTURE (0 << 2) -#define T1CCTL_MODE_COMPARE (1 << 2) - -#define T1CTL_CMP_SET (0 << 3) -#define T1CTL_CMP_CLEAR (1 << 3) -#define T1CTL_CMP_TOGGLE (2 << 3) -#define T1CTL_CMP_SET_CLEAR (3 << 3) -#define T1CTL_CMP_CLEAR_SET (4 << 3) - -#define T1CTL_IM_DISABLED (0 << 6) -#define T1CTL_IM_ENABLED (1 << 6) - -#define T1CTL_CPSEL_NORMAL (0 << 7) -#define T1CTL_CPSEL_RF (1 << 7) - -/* - * Timer 3 and Timer 4 - */ - -/* Timer count */ -__sfr __at 0xCA T3CNT; -__sfr __at 0xEA T4CNT; - -/* Timer control */ - -__sfr __at 0xCB T3CTL; -__sfr __at 0xEB T4CTL; - -#define TxCTL_DIV_1 (0 << 5) -#define TxCTL_DIV_2 (1 << 5) -#define TxCTL_DIV_4 (2 << 5) -#define TxCTL_DIV_8 (3 << 5) -#define TxCTL_DIV_16 (4 << 5) -#define TxCTL_DIV_32 (5 << 5) -#define TxCTL_DIV_64 (6 << 5) -#define TxCTL_DIV_128 (7 << 5) -#define TxCTL_START (1 << 4) -#define TxCTL_OVFIM (1 << 3) -#define TxCTL_CLR (1 << 2) -#define TxCTL_MODE_FREE (0 << 0) -#define TxCTL_MODE_DOWN (1 << 0) -#define TxCTL_MODE_MODULO (2 << 0) -#define TxCTL_MODE_UP_DOWN (3 << 0) - -/* Timer 4 channel 0 compare control */ - -__sfr __at 0xCC T3CCTL0; -__sfr __at 0xCE T3CCTL1; -__sfr __at 0xEC T4CCTL0; -__sfr __at 0xEE T4CCTL1; - -#define TxCCTLy_IM (1 << 6) -#define TxCCTLy_CMP_SET (0 << 3) -#define TxCCTLy_CMP_CLEAR (1 << 3) -#define TxCCTLy_CMP_TOGGLE (2 << 3) -#define TxCCTLy_CMP_SET_UP_CLEAR_DOWN (3 << 3) -#define TxCCTLy_CMP_CLEAR_UP_SET_DOWN (4 << 3) -#define TxCCTLy_CMP_SET_CLEAR_FF (5 << 3) -#define TxCCTLy_CMP_CLEAR_SET_00 (6 << 3) -#define TxCCTLy_CMP_MODE_ENABLE (1 << 2) - -/* Timer compare value */ -__sfr __at 0xCD T3CC0; -__sfr __at 0xCF T3CC1; -__sfr __at 0xED T4CC0; -__sfr __at 0xEF T4CC1; - -/* - * Peripheral control - */ - -__sfr __at 0xf1 PERCFG; -#define PERCFG_T1CFG_ALT_1 (0 << 6) -#define PERCFG_T1CFG_ALT_2 (1 << 6) -#define PERCFG_T1CFG_ALT_MASK (1 << 6) - -#define PERCFG_T3CFG_ALT_1 (0 << 5) -#define PERCFG_T3CFG_ALT_2 (1 << 5) -#define PERCFG_T3CFG_ALT_MASK (1 << 5) - -#define PERCFG_T4CFG_ALT_1 (0 << 4) -#define PERCFG_T4CFG_ALT_2 (1 << 4) -#define PERCFG_T4CFG_ALT_MASK (1 << 4) - -#define PERCFG_U1CFG_ALT_1 (0 << 1) -#define PERCFG_U1CFG_ALT_2 (1 << 1) -#define PERCFG_U1CFG_ALT_MASK (1 << 1) - -#define PERCFG_U0CFG_ALT_1 (0 << 0) -#define PERCFG_U0CFG_ALT_2 (1 << 0) -#define PERCFG_U0CFG_ALT_MASK (1 << 0) - -/* directly addressed USB registers */ -__xdata __at (0xde00) volatile uint8_t USBADDR; -__xdata __at (0xde01) volatile uint8_t USBPOW; -__xdata __at (0xde02) volatile uint8_t USBIIF; - -__xdata __at (0xde04) volatile uint8_t USBOIF; - -__xdata __at (0xde06) volatile uint8_t USBCIF; - -# define USBCIF_SOFIF (1 << 3) -# define USBCIF_RSTIF (1 << 2) -# define USBCIF_RESUMEIF (1 << 1) -# define USBCIF_SUSPENDIF (1 << 0) - -__xdata __at (0xde07) volatile uint8_t USBIIE; - -__xdata __at (0xde09) volatile uint8_t USBOIE; - -__xdata __at (0xde0b) volatile uint8_t USBCIE; - -# define USBCIE_SOFIE (1 << 3) -# define USBCIE_RSTIE (1 << 2) -# define USBCIE_RESUMEIE (1 << 1) -# define USBCIE_SUSPENDIE (1 << 0) - -__xdata __at (0xde0c) volatile uint8_t USBFRML; -__xdata __at (0xde0d) volatile uint8_t USBFRMH; -__xdata __at (0xde0e) volatile uint8_t USBINDEX; - -/* indexed USB registers, must set USBINDEX to 0-5 */ -__xdata __at (0xde10) volatile uint8_t USBMAXI; -__xdata __at (0xde11) volatile uint8_t USBCS0; - -# define USBCS0_CLR_SETUP_END (1 << 7) -# define USBCS0_CLR_OUTPKT_RDY (1 << 6) -# define USBCS0_SEND_STALL (1 << 5) -# define USBCS0_SETUP_END (1 << 4) -# define USBCS0_DATA_END (1 << 3) -# define USBCS0_SENT_STALL (1 << 2) -# define USBCS0_INPKT_RDY (1 << 1) -# define USBCS0_OUTPKT_RDY (1 << 0) - -__xdata __at (0xde11) volatile uint8_t USBCSIL; - -# define USBCSIL_CLR_DATA_TOG (1 << 6) -# define USBCSIL_SENT_STALL (1 << 5) -# define USBCSIL_SEND_STALL (1 << 4) -# define USBCSIL_FLUSH_PACKET (1 << 3) -# define USBCSIL_UNDERRUN (1 << 2) -# define USBCSIL_PKT_PRESENT (1 << 1) -# define USBCSIL_INPKT_RDY (1 << 0) - -__xdata __at (0xde12) volatile uint8_t USBCSIH; - -# define USBCSIH_AUTOSET (1 << 7) -# define USBCSIH_ISO (1 << 6) -# define USBCSIH_FORCE_DATA_TOG (1 << 3) -# define USBCSIH_IN_DBL_BUF (1 << 0) - -__xdata __at (0xde13) volatile uint8_t USBMAXO; -__xdata __at (0xde14) volatile uint8_t USBCSOL; - -# define USBCSOL_CLR_DATA_TOG (1 << 7) -# define USBCSOL_SENT_STALL (1 << 6) -# define USBCSOL_SEND_STALL (1 << 5) -# define USBCSOL_FLUSH_PACKET (1 << 4) -# define USBCSOL_DATA_ERROR (1 << 3) -# define USBCSOL_OVERRUN (1 << 2) -# define USBCSOL_FIFO_FULL (1 << 1) -# define USBCSOL_OUTPKT_RDY (1 << 0) - -__xdata __at (0xde15) volatile uint8_t USBCSOH; - -# define USBCSOH_AUTOCLEAR (1 << 7) -# define USBCSOH_ISO (1 << 6) -# define USBCSOH_OUT_DBL_BUF (1 << 0) - -__xdata __at (0xde16) volatile uint8_t USBCNT0; -__xdata __at (0xde16) volatile uint8_t USBCNTL; -__xdata __at (0xde17) volatile uint8_t USBCNTH; - -__xdata __at (0xde20) volatile uint8_t USBFIFO[12]; - -/* ADC Data register, low and high */ -__sfr at 0xBA ADCL; -__sfr at 0xBB ADCH; -__xdata __at (0xDFBA) volatile uint16_t ADCXDATA; - -/* ADC Control Register 1 */ -__sfr at 0xB4 ADCCON1; - -# define ADCCON1_EOC (1 << 7) /* conversion complete */ -# define ADCCON1_ST (1 << 6) /* start conversion */ - -# define ADCCON1_STSEL_MASK (3 << 4) /* start select */ -# define ADCCON1_STSEL_EXTERNAL (0 << 4) /* P2_0 pin triggers */ -# define ADCCON1_STSEL_FULLSPEED (1 << 4) /* full speed, no waiting */ -# define ADCCON1_STSEL_TIMER1 (2 << 4) /* timer 1 channel 0 */ -# define ADCCON1_STSEL_START (3 << 4) /* set start bit */ - -# define ADCCON1_RCTRL_MASK (3 << 2) /* random number control */ -# define ADCCON1_RCTRL_COMPLETE (0 << 2) /* operation completed */ -# define ADCCON1_RCTRL_CLOCK_LFSR (1 << 2) /* Clock the LFSR once */ - -/* ADC Control Register 2 */ -__sfr at 0xB5 ADCCON2; - -# define ADCCON2_SREF_MASK (3 << 6) /* reference voltage */ -# define ADCCON2_SREF_1_25V (0 << 6) /* internal 1.25V */ -# define ADCCON2_SREF_EXTERNAL (1 << 6) /* external on AIN7 cc1110 */ -# define ADCCON2_SREF_VDD (2 << 6) /* VDD on the AVDD pin */ -# define ADCCON2_SREF_EXTERNAL_DIFF (3 << 6) /* external on AIN6-7 cc1110 */ - -# define ADCCON2_SDIV_MASK (3 << 4) /* decimation rate */ -# define ADCCON2_SDIV_64 (0 << 4) /* 7 bits */ -# define ADCCON2_SDIV_128 (1 << 4) /* 9 bits */ -# define ADCCON2_SDIV_256 (2 << 4) /* 10 bits */ -# define ADCCON2_SDIV_512 (3 << 4) /* 12 bits */ - -# define ADCCON2_SCH_MASK (0xf << 0) /* Sequence channel select */ -# define ADCCON2_SCH_SHIFT 0 -# define ADCCON2_SCH_AIN0 (0 << 0) -# define ADCCON2_SCH_AIN1 (1 << 0) -# define ADCCON2_SCH_AIN2 (2 << 0) -# define ADCCON2_SCH_AIN3 (3 << 0) -# define ADCCON2_SCH_AIN4 (4 << 0) -# define ADCCON2_SCH_AIN5 (5 << 0) -# define ADCCON2_SCH_AIN6 (6 << 0) -# define ADCCON2_SCH_AIN7 (7 << 0) -# define ADCCON2_SCH_AIN0_AIN1 (8 << 0) -# define ADCCON2_SCH_AIN2_AIN3 (9 << 0) -# define ADCCON2_SCH_AIN4_AIN5 (0xa << 0) -# define ADCCON2_SCH_AIN6_AIN7 (0xb << 0) -# define ADCCON2_SCH_GND (0xc << 0) -# define ADCCON2_SCH_VREF (0xd << 0) -# define ADCCON2_SCH_TEMP (0xe << 0) -# define ADCCON2_SCH_VDD_3 (0xf << 0) - - -/* ADC Control Register 3 */ -__sfr at 0xB6 ADCCON3; - -# define ADCCON3_EREF_MASK (3 << 6) /* extra conversion reference */ -# define ADCCON3_EREF_1_25 (0 << 6) /* internal 1.25V */ -# define ADCCON3_EREF_EXTERNAL (1 << 6) /* external AIN7 cc1110 */ -# define ADCCON3_EREF_VDD (2 << 6) /* VDD on the AVDD pin */ -# define ADCCON3_EREF_EXTERNAL_DIFF (3 << 6) /* external AIN6-7 cc1110 */ -# define ADCCON3_EDIV_MASK (3 << 4) /* extral decimation */ -# define ADCCON3_EDIV_64 (0 << 4) /* 7 bits */ -# define ADCCON3_EDIV_128 (1 << 4) /* 9 bits */ -# define ADCCON3_EDIV_256 (2 << 4) /* 10 bits */ -# define ADCCON3_EDIV_512 (3 << 4) /* 12 bits */ -# define ADCCON3_ECH_MASK (0xf << 0) /* Sequence channel select */ -# define ADCCON3_ECH_SHIFT 0 -# define ADCCON3_ECH_AIN0 (0 << 0) -# define ADCCON3_ECH_AIN1 (1 << 0) -# define ADCCON3_ECH_AIN2 (2 << 0) -# define ADCCON3_ECH_AIN3 (3 << 0) -# define ADCCON3_ECH_AIN4 (4 << 0) -# define ADCCON3_ECH_AIN5 (5 << 0) -# define ADCCON3_ECH_AIN6 (6 << 0) -# define ADCCON3_ECH_AIN7 (7 << 0) -# define ADCCON3_ECH_AIN0_AIN1 (8 << 0) -# define ADCCON3_ECH_AIN2_AIN3 (9 << 0) -# define ADCCON3_ECH_AIN4_AIN5 (0xa << 0) -# define ADCCON3_ECH_AIN6_AIN7 (0xb << 0) -# define ADCCON3_ECH_GND (0xc << 0) -# define ADCCON3_ECH_VREF (0xd << 0) -# define ADCCON3_ECH_TEMP (0xe << 0) -# define ADCCON3_ECH_VDD_3 (0xf << 0) - -/* - * ADC configuration register, this selects which - * GPIO pins are to be used as ADC inputs - */ -__sfr at 0xF2 ADCCFG; - -/* - * Watchdog timer - */ - -__sfr at 0xc9 WDCTL; - -#define WDCTL_CLEAR_FIRST (0xa << 4) -#define WDCTL_CLEAR_SECOND (0x5 << 4) -#define WDCTL_EN (1 << 3) -#define WDCTL_MODE_WATCHDOG (0 << 2) -#define WDCTL_MODE_TIMER (1 << 2) -#define WDCTL_MODE_MASK (1 << 2) -#define WDCTL_INT_32768 (0 << 0) -#define WDCTL_INT_8192 (1 << 0) -#define WDCTL_INT_512 (2 << 0) -#define WDCTL_INT_64 (3 << 0) - -/* - * Pin selectors, these set which pins are - * using their peripheral function - */ -__sfr at 0xF3 P0SEL; -__sfr at 0xF4 P1SEL; -__sfr at 0xF5 P2SEL; - -#define P2SEL_PRI3P1_USART0 (0 << 6) -#define P2SEL_PRI3P1_USART1 (1 << 6) -#define P2SEL_PRI3P1_MASK (1 << 6) -#define P2SEL_PRI2P1_USART1 (0 << 5) -#define P2SEL_PRI2P1_TIMER3 (1 << 5) -#define P2SEL_PRI2P1_MASK (1 << 5) -#define P2SEL_PRI1P1_TIMER1 (0 << 4) -#define P2SEL_PRI1P1_TIMER4 (1 << 4) -#define P2SEL_PRI1P1_MASK (1 << 4) -#define P2SEL_PRI0P1_USART0 (0 << 3) -#define P2SEL_PRI0P1_TIMER1 (1 << 3) -#define P2SEL_PRI0P1_MASK (1 << 3) -#define P2SEL_SELP2_4_GPIO (0 << 2) -#define P2SEL_SELP2_4_PERIPHERAL (1 << 2) -#define P2SEL_SELP2_4_MASK (1 << 2) -#define P2SEL_SELP2_3_GPIO (0 << 1) -#define P2SEL_SELP2_3_PERIPHERAL (1 << 1) -#define P2SEL_SELP2_3_MASK (1 << 1) -#define P2SEL_SELP2_0_GPIO (0 << 0) -#define P2SEL_SELP2_0_PERIPHERAL (1 << 0) -#define P2SEL_SELP2_0_MASK (1 << 0) - -/* - * For pins used as GPIOs, these set which are used as outputs - */ -__sfr at 0xFD P0DIR; -__sfr at 0xFE P1DIR; -__sfr at 0xFF P2DIR; - -#define P2DIR_PRIP0_USART0_USART1 (0 << 6) -#define P2DIR_PRIP0_USART1_USART0 (1 << 6) -#define P2DIR_PRIP0_TIMER1_01_USART1 (2 << 6) -#define P2DIR_PRIP0_TIMER1_2_USART0 (3 << 6) -#define P2DIR_PRIP0_MASK (3 << 6) - -__sfr at 0x8F P0INP; - -/* Select between tri-state and pull up/down - * for pins P0_0 - P0_7. - */ -#define P0INP_MDP0_7_PULL (0 << 7) -#define P0INP_MDP0_7_TRISTATE (1 << 7) -#define P0INP_MDP0_6_PULL (0 << 6) -#define P0INP_MDP0_6_TRISTATE (1 << 6) -#define P0INP_MDP0_5_PULL (0 << 5) -#define P0INP_MDP0_5_TRISTATE (1 << 5) -#define P0INP_MDP0_4_PULL (0 << 4) -#define P0INP_MDP0_4_TRISTATE (1 << 4) -#define P0INP_MDP0_3_PULL (0 << 3) -#define P0INP_MDP0_3_TRISTATE (1 << 3) -#define P0INP_MDP0_2_PULL (0 << 2) -#define P0INP_MDP0_2_TRISTATE (1 << 2) -#define P0INP_MDP0_1_PULL (0 << 1) -#define P0INP_MDP0_1_TRISTATE (1 << 1) -#define P0INP_MDP0_0_PULL (0 << 0) -#define P0INP_MDP0_0_TRISTATE (1 << 0) - -__sfr at 0xF6 P1INP; - -/* Select between tri-state and pull up/down - * for pins P1_2 - P1_7. Pins P1_0 and P1_1 are - * always tri-stated - */ -#define P1INP_MDP1_7_PULL (0 << 7) -#define P1INP_MDP1_7_TRISTATE (1 << 7) -#define P1INP_MDP1_6_PULL (0 << 6) -#define P1INP_MDP1_6_TRISTATE (1 << 6) -#define P1INP_MDP1_5_PULL (0 << 5) -#define P1INP_MDP1_5_TRISTATE (1 << 5) -#define P1INP_MDP1_4_PULL (0 << 4) -#define P1INP_MDP1_4_TRISTATE (1 << 4) -#define P1INP_MDP1_3_PULL (0 << 3) -#define P1INP_MDP1_3_TRISTATE (1 << 3) -#define P1INP_MDP1_2_PULL (0 << 2) -#define P1INP_MDP1_2_TRISTATE (1 << 2) - -__sfr at 0xF7 P2INP; -/* P2INP has three extra bits which are used to choose - * between pull-up and pull-down when they are not tri-stated - */ -#define P2INP_PDUP2_PULL_UP (0 << 7) -#define P2INP_PDUP2_PULL_DOWN (1 << 7) -#define P2INP_PDUP1_PULL_UP (0 << 6) -#define P2INP_PDUP1_PULL_DOWN (1 << 6) -#define P2INP_PDUP0_PULL_UP (0 << 5) -#define P2INP_PDUP0_PULL_DOWN (1 << 5) - -/* For the P2 pins, choose between tri-state and pull up/down - * mode - */ -#define P2INP_MDP2_4_PULL (0 << 4) -#define P2INP_MDP2_4_TRISTATE (1 << 4) -#define P2INP_MDP2_3_PULL (0 << 3) -#define P2INP_MDP2_3_TRISTATE (1 << 3) -#define P2INP_MDP2_2_PULL (0 << 2) -#define P2INP_MDP2_2_TRISTATE (1 << 2) -#define P2INP_MDP2_1_PULL (0 << 1) -#define P2INP_MDP2_1_TRISTATE (1 << 1) -#define P2INP_MDP2_0_PULL (0 << 0) -#define P2INP_MDP2_0_TRISTATE (1 << 0) - -/* GPIO interrupt status flags */ -__sfr at 0x89 P0IFG; -__sfr at 0x8A P1IFG; -__sfr at 0x8B P2IFG; - -#define P0IFG_USB_RESUME (1 << 7) - -__sfr at 0x8C PICTL; -#define PICTL_P2IEN (1 << 5) -#define PICTL_P0IENH (1 << 4) -#define PICTL_P0IENL (1 << 3) -#define PICTL_P2ICON (1 << 2) -#define PICTL_P1ICON (1 << 1) -#define PICTL_P0ICON (1 << 0) - -/* GPIO pins */ -__sfr at 0x80 P0; - -sbit at 0x80 P0_0; -sbit at 0x81 P0_1; -sbit at 0x82 P0_2; -sbit at 0x83 P0_3; -sbit at 0x84 P0_4; -sbit at 0x85 P0_5; -sbit at 0x86 P0_6; -sbit at 0x87 P0_7; - -__sfr at 0x90 P1; - -sbit at 0x90 P1_0; -sbit at 0x91 P1_1; -sbit at 0x92 P1_2; -sbit at 0x93 P1_3; -sbit at 0x94 P1_4; -sbit at 0x95 P1_5; -sbit at 0x96 P1_6; -sbit at 0x97 P1_7; - -__sfr at 0xa0 P2; - -sbit at 0xa0 P2_0; -sbit at 0xa1 P2_1; -sbit at 0xa2 P2_2; -sbit at 0xa3 P2_3; -sbit at 0xa4 P2_4; - -/* DMA controller */ -struct cc_dma_channel { - uint8_t src_high; - uint8_t src_low; - uint8_t dst_high; - uint8_t dst_low; - uint8_t len_high; - uint8_t len_low; - uint8_t cfg0; - uint8_t cfg1; -}; - -# define DMA_LEN_HIGH_VLEN_MASK (7 << 5) -# define DMA_LEN_HIGH_VLEN_LEN (0 << 5) -# define DMA_LEN_HIGH_VLEN_PLUS_1 (1 << 5) -# define DMA_LEN_HIGH_VLEN (2 << 5) -# define DMA_LEN_HIGH_VLEN_PLUS_2 (3 << 5) -# define DMA_LEN_HIGH_VLEN_PLUS_3 (4 << 5) -# define DMA_LEN_HIGH_MASK (0x1f) - -# define DMA_CFG0_WORDSIZE_8 (0 << 7) -# define DMA_CFG0_WORDSIZE_16 (1 << 7) -# define DMA_CFG0_TMODE_MASK (3 << 5) -# define DMA_CFG0_TMODE_SINGLE (0 << 5) -# define DMA_CFG0_TMODE_BLOCK (1 << 5) -# define DMA_CFG0_TMODE_REPEATED_SINGLE (2 << 5) -# define DMA_CFG0_TMODE_REPEATED_BLOCK (3 << 5) - -/* - * DMA triggers - */ -# define DMA_CFG0_TRIGGER_NONE 0 -# define DMA_CFG0_TRIGGER_PREV 1 -# define DMA_CFG0_TRIGGER_T1_CH0 2 -# define DMA_CFG0_TRIGGER_T1_CH1 3 -# define DMA_CFG0_TRIGGER_T1_CH2 4 -# define DMA_CFG0_TRIGGER_T2_OVFL 6 -# define DMA_CFG0_TRIGGER_T3_CH0 7 -# define DMA_CFG0_TRIGGER_T3_CH1 8 -# define DMA_CFG0_TRIGGER_T4_CH0 9 -# define DMA_CFG0_TRIGGER_T4_CH1 10 -# define DMA_CFG0_TRIGGER_IOC_0 12 -# define DMA_CFG0_TRIGGER_IOC_1 13 -# define DMA_CFG0_TRIGGER_URX0 14 -# define DMA_CFG0_TRIGGER_UTX0 15 -# define DMA_CFG0_TRIGGER_URX1 16 -# define DMA_CFG0_TRIGGER_UTX1 17 -# define DMA_CFG0_TRIGGER_FLASH 18 -# define DMA_CFG0_TRIGGER_RADIO 19 -# define DMA_CFG0_TRIGGER_ADC_CHALL 20 -# define DMA_CFG0_TRIGGER_ADC_CH0 21 -# define DMA_CFG0_TRIGGER_ADC_CH1 22 -# define DMA_CFG0_TRIGGER_ADC_CH2 23 -# define DMA_CFG0_TRIGGER_ADC_CH3 24 -# define DMA_CFG0_TRIGGER_ADC_CH4 25 -# define DMA_CFG0_TRIGGER_ADC_CH5 26 -# define DMA_CFG0_TRIGGER_ADC_CH6 27 -# define DMA_CFG0_TRIGGER_I2SRX 27 -# define DMA_CFG0_TRIGGER_ADC_CH7 28 -# define DMA_CFG0_TRIGGER_I2STX 28 -# define DMA_CFG0_TRIGGER_ENC_DW 29 -# define DMA_CFG0_TRIGGER_DNC_UP 30 - -# define DMA_CFG1_SRCINC_MASK (3 << 6) -# define DMA_CFG1_SRCINC_0 (0 << 6) -# define DMA_CFG1_SRCINC_1 (1 << 6) -# define DMA_CFG1_SRCINC_2 (2 << 6) -# define DMA_CFG1_SRCINC_MINUS_1 (3 << 6) - -# define DMA_CFG1_DESTINC_MASK (3 << 4) -# define DMA_CFG1_DESTINC_0 (0 << 4) -# define DMA_CFG1_DESTINC_1 (1 << 4) -# define DMA_CFG1_DESTINC_2 (2 << 4) -# define DMA_CFG1_DESTINC_MINUS_1 (3 << 4) - -# define DMA_CFG1_IRQMASK (1 << 3) -# define DMA_CFG1_M8 (1 << 2) - -# define DMA_CFG1_PRIORITY_MASK (3 << 0) -# define DMA_CFG1_PRIORITY_LOW (0 << 0) -# define DMA_CFG1_PRIORITY_NORMAL (1 << 0) -# define DMA_CFG1_PRIORITY_HIGH (2 << 0) - -/* - * DMAARM - DMA Channel Arm - */ - -__sfr at 0xD6 DMAARM; - -# define DMAARM_ABORT (1 << 7) -# define DMAARM_DMAARM4 (1 << 4) -# define DMAARM_DMAARM3 (1 << 3) -# define DMAARM_DMAARM2 (1 << 2) -# define DMAARM_DMAARM1 (1 << 1) -# define DMAARM_DMAARM0 (1 << 0) - -/* - * DMAREQ - DMA Channel Start Request and Status - */ - -__sfr at 0xD7 DMAREQ; - -# define DMAREQ_DMAREQ4 (1 << 4) -# define DMAREQ_DMAREQ3 (1 << 3) -# define DMAREQ_DMAREQ2 (1 << 2) -# define DMAREQ_DMAREQ1 (1 << 1) -# define DMAREQ_DMAREQ0 (1 << 0) - -/* - * DMA configuration 0 address - */ - -__sfr at 0xD5 DMA0CFGH; -__sfr at 0xD4 DMA0CFGL; - -/* - * DMA configuration 1-4 address - */ - -__sfr at 0xD3 DMA1CFGH; -__sfr at 0xD2 DMA1CFGL; - -/* - * DMAIRQ - DMA Interrupt Flag - */ - -__sfr at 0xD1 DMAIRQ; - -# define DMAIRQ_DMAIF4 (1 << 4) -# define DMAIRQ_DMAIF3 (1 << 3) -# define DMAIRQ_DMAIF2 (1 << 2) -# define DMAIRQ_DMAIF1 (1 << 1) -# define DMAIRQ_DMAIF0 (1 << 0) - -/* - * UART registers - */ - -/* USART config/status registers */ -__sfr at 0x86 U0CSR; -__sfr at 0xF8 U1CSR; - -# define UxCSR_MODE_UART (1 << 7) -# define UxCSR_MODE_SPI (0 << 7) -# define UxCSR_RE (1 << 6) -# define UxCSR_SLAVE (1 << 5) -# define UxCSR_MASTER (0 << 5) -# define UxCSR_FE (1 << 4) -# define UxCSR_ERR (1 << 3) -# define UxCSR_RX_BYTE (1 << 2) -# define UxCSR_TX_BYTE (1 << 1) -# define UxCSR_ACTIVE (1 << 0) - -/* UART configuration registers */ -__sfr at 0xc4 U0UCR; -__sfr at 0xfb U1UCR; - -# define UxUCR_FLUSH (1 << 7) -# define UxUCR_FLOW_DISABLE (0 << 6) -# define UxUCR_FLOW_ENABLE (1 << 6) -# define UxUCR_D9_EVEN_PARITY (0 << 5) -# define UxUCR_D9_ODD_PARITY (1 << 5) -# define UxUCR_BIT9_8_BITS (0 << 4) -# define UxUCR_BIT9_9_BITS (1 << 4) -# define UxUCR_PARITY_DISABLE (0 << 3) -# define UxUCR_PARITY_ENABLE (1 << 3) -# define UxUCR_SPB_1_STOP_BIT (0 << 2) -# define UxUCR_SPB_2_STOP_BITS (1 << 2) -# define UxUCR_STOP_LOW (0 << 1) -# define UxUCR_STOP_HIGH (1 << 1) -# define UxUCR_START_LOW (0 << 0) -# define UxUCR_START_HIGH (1 << 0) - -/* USART General configuration registers (mostly SPI) */ -__sfr at 0xc5 U0GCR; -__sfr at 0xfc U1GCR; - -# define UxGCR_CPOL_NEGATIVE (0 << 7) -# define UxGCR_CPOL_POSITIVE (1 << 7) -# define UxGCR_CPHA_FIRST_EDGE (0 << 6) -# define UxGCR_CPHA_SECOND_EDGE (1 << 6) -# define UxGCR_ORDER_LSB (0 << 5) -# define UxGCR_ORDER_MSB (1 << 5) -# define UxGCR_BAUD_E_MASK (0x1f) -# define UxGCR_BAUD_E_SHIFT 0 - -/* USART data registers */ -__sfr at 0xc1 U0DBUF; -__xdata __at (0xDFC1) volatile uint8_t U0DBUFXADDR; -__sfr at 0xf9 U1DBUF; -__xdata __at (0xDFF9) volatile uint8_t U1DBUFXADDR; - -/* USART baud rate registers, M value */ -__sfr at 0xc2 U0BAUD; -__sfr at 0xfa U1BAUD; - -/* Flash controller */ - -__sfr at 0xAE FCTL; -#define FCTL_BUSY (1 << 7) -#define FCTL_SWBSY (1 << 6) -#define FCTL_CONTRD_ENABLE (1 << 4) -#define FCTL_WRITE (1 << 1) -#define FCTL_ERASE (1 << 0) - -/* Flash write data. Write two bytes here */ -__sfr at 0xAF FWDATA; -__xdata __at (0xDFAF) volatile uint8_t FWDATAXADDR; - -/* Flash write/erase address */ -__sfr at 0xAD FADDRH; -__sfr at 0xAC FADDRL; - -/* Flash timing */ -__sfr at 0xAB FWT; - -/* 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 0x91 RFIM; -#define RFIM_IM_TXUNF (1 << 7) -#define RFIM_IM_RXOVF (1 << 6) -#define RFIM_IM_TIMEOUT (1 << 5) -#define RFIM_IM_DONE (1 << 4) -#define RFIM_IM_CS (1 << 3) -#define RFIM_IM_PQT (1 << 2) -#define RFIM_IM_CCA (1 << 1) -#define RFIM_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/src/cc1111/Makefile.cc1111 b/src/cc1111/Makefile.cc1111 new file mode 100644 index 00000000..8de4a9b2 --- /dev/null +++ b/src/cc1111/Makefile.cc1111 @@ -0,0 +1,27 @@ +CC=sdcc + +CFLAGS=--model-small --debug --opt-code-speed -DCODESIZE=$(CODESIZE) + +CFLAGS += $(PRODUCT_DEF) -I. -I.. -I../core -I../cc1111 -I../driver -I../product + +CODESIZE ?= 0x8000 + +LDFLAGS=--out-fmt-ihx --code-loc 0x0000 --code-size $(CODESIZE) \ + --xram-loc 0xf000 --xram-size 0xda2 --iram-size 0xff + +REL=$(SRC:.c=.rel) ao_product.rel +ADB=$(REL:.rel=.adb) +ASM=$(REL:.rel=.asm) +LNK=$(REL:.rel=.lnk) +LST=$(REL:.rel=.lst) +RST=$(REL:.rel=.rst) +SYM=$(REL:.rel=.sym) + +PCDB=$(PROG:.ihx=.cdb) +PLNK=$(PROG:.ihx=.lnk) +PMAP=$(PROG:.ihx=.map) +PMEM=$(PROG:.ihx=.mem) +PAOM=$(PROG:.ihx=) + +%.rel : %.c $(INC) + $(call quiet,CC,$(PRODUCT_DEF)) $(CFLAGS) -c -o$@ $< diff --git a/src/cc1111/_bp.c b/src/cc1111/_bp.c new file mode 100644 index 00000000..6bf135bc --- /dev/null +++ b/src/cc1111/_bp.c @@ -0,0 +1,26 @@ +/*------------------------------------------------------------------------- + + _bp.c :- just declares bp as a variable + + Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999) + + This library is free software; you can redistribute it and/or modify it + under the terms of the GNU Library General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This library 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 Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! +-------------------------------------------------------------------------*/ + +__data unsigned char bp ; diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c new file mode 100644 index 00000000..786dfd11 --- /dev/null +++ b/src/cc1111/ao_adc.c @@ -0,0 +1,196 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; +#if HAS_ACCEL_REF +volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; +#endif +volatile __data uint8_t ao_adc_head; + +void +ao_adc_poll(void) +{ +#if HAS_ACCEL_REF + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 2; +#else +# ifdef TELENANO_V_0_1 + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 1; +# else + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 0; +# endif +#endif +} + +void +ao_adc_get(__xdata struct ao_adc *packet) +{ + uint8_t i = ao_adc_ring_prev(ao_sample_adc); + memcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); +} + +void +ao_adc_isr(void) __interrupt 1 +{ + uint8_t sequence; + uint8_t __xdata *a; + + sequence = (ADCCON2 & ADCCON2_SCH_MASK) >> ADCCON2_SCH_SHIFT; +#if IGNITE_ON_P2 + /* TeleMetrum readings */ +#if HAS_ACCEL_REF + if (sequence == 2) { + a = (uint8_t __xdata *) (&ao_accel_ref[ao_adc_head]); + sequence = 0; + } else +#endif + { + if (sequence == ADCCON3_ECH_TEMP) + sequence = 2; + a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].accel + sequence); + sequence++; + } +#define GOT_ADC + a[0] = ADCL; + a[1] = ADCH; + if (sequence < 6) { +#if HAS_EXTERNAL_TEMP == 0 + /* start next channel conversion */ + /* v0.2 replaces external temp sensor with internal one */ + if (sequence == 2) + ADCCON3 = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP; + else +#endif + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | sequence; + } +#endif + +#if IGNITE_ON_P0 + /* TeleMini readings */ + a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].pres); +#ifdef TELEMINI_V_1_0 + switch (sequence) { + case 0: + /* pressure */ + a += 0; + sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 1; + break; + case 1: + /* drogue sense */ + a += 6; + sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 2; + break; + case 2: + /* main sense */ + a += 8; + sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 3; + break; + case 3: + /* battery */ + a += 4; + sequence = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP; + break; + case ADCCON3_ECH_TEMP: + a += 2; + sequence = 0; + break; + } +#define GOT_ADC +#endif +#ifdef TELENANO_V_0_1 + switch (sequence) { + case 1: + /* pressure */ + a += 0; + sequence = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | 3; + break; + case 3: + /* battery */ + a += 4; + sequence = ADCCON3_EREF_1_25 | ADCCON3_EDIV_512 | ADCCON3_ECH_TEMP; + break; + case ADCCON3_ECH_TEMP: + a += 2; + sequence = 0; + break; + } +#define GOT_ADC +#endif + a[0] = ADCL; + a[1] = ADCH; + if (sequence) { + /* Start next conversion */ + ADCCON3 = sequence; + } +#endif +#ifndef GOT_ADC +#error No known ADC configuration set +#endif + + else { + /* record this conversion series */ + ao_adc_ring[ao_adc_head].tick = ao_time(); + ao_adc_head = ao_adc_ring_next(ao_adc_head); + ao_wakeup(DATA_TO_XDATA(&ao_adc_head)); + } +} + +static void +ao_adc_dump(void) __reentrant +{ + static __xdata struct ao_adc packet; + ao_adc_get(&packet); + printf("tick: %5u accel: %5d pres: %5d temp: %5d batt: %5d drogue: %5d main: %5d\n", + packet.tick, packet.accel, packet.pres, packet.temp, + packet.v_batt, packet.sense_d, packet.sense_m); +} + +__code struct ao_cmds ao_adc_cmds[] = { + { ao_adc_dump, "a\0Current ADC" }, + { 0, NULL }, +}; + +void +ao_adc_init(void) +{ +#if IGNITE_ON_P2 + /* TeleMetrum configuration */ + ADCCFG = ((1 << 0) | /* acceleration */ + (1 << 1) | /* pressure */ +#if HAS_EXTERNAL_TEMP + (1 << 2) | /* v0.1 temperature */ +#endif + (1 << 3) | /* battery voltage */ + (1 << 4) | /* drogue sense */ + (1 << 5)); /* main sense */ +#endif + +#if IGNITE_ON_P0 + /* TeleMini configuration */ + ADCCFG = ((1 << 0) | /* pressure */ + (1 << 1) | /* drogue sense */ + (1 << 2) | /* main sense */ + (1 << 3)); /* battery voltage */ +#endif + + /* enable interrupts */ + ADCIF = 0; + IEN0 |= IEN0_ADCIE; + ao_cmd_register(&ao_adc_cmds[0]); +} diff --git a/src/cc1111/ao_beep.c b/src/cc1111/ao_beep.c new file mode 100644 index 00000000..3642f4c6 --- /dev/null +++ b/src/cc1111/ao_beep.c @@ -0,0 +1,52 @@ +/* + * 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_beep(uint8_t beep) +{ + if (beep == 0) { + P2_0 = 0; + P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_GPIO; + T4CTL = 0; + } else { + P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_PERIPHERAL; + T4CC0 = beep; + T4CTL = TxCTL_DIV_32 | TxCTL_MODE_MODULO | TxCTL_START; + } +} + +void +ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant +{ + ao_beep(beep); + ao_delay(ticks); + ao_beep(0); +} + +void +ao_beep_init(void) +{ + /* Our beeper is on P2_0, which is hooked to timer 4 using + * configuration alternative 2 + */ + P2_0 = 0; + P2SEL = (P2SEL & ~P2SEL_SELP2_0_MASK) | P2SEL_SELP2_0_GPIO; + PERCFG = (PERCFG & ~PERCFG_T4CFG_ALT_MASK) | PERCFG_T4CFG_ALT_2; + T4CCTL0 = TxCCTLy_CMP_TOGGLE|TxCCTLy_CMP_MODE_ENABLE; +} diff --git a/src/cc1111/ao_dbg.c b/src/cc1111/ao_dbg.c new file mode 100644 index 00000000..d4c9567f --- /dev/null +++ b/src/cc1111/ao_dbg.c @@ -0,0 +1,364 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +static void +ao_dbg_send_bits(uint8_t msk, uint8_t val) __reentrant +{ + DBG_PORT = (DBG_PORT & ~msk) | (val & msk); + _asm + nop + nop + _endasm; +} + +void +ao_dbg_send_byte(uint8_t byte) +{ + __pdata uint8_t b, d; + + DBG_PORT |= DBG_DATA; + DBG_PORT_DIR |= DBG_DATA; + for (b = 0; b < 8; b++) { + d = 0; + if (byte & 0x80) + d = DBG_DATA; + byte <<= 1; + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA, DBG_CLOCK|d); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA, 0 |d); + } + DBG_PORT_DIR &= ~DBG_DATA; +} + +uint8_t +ao_dbg_recv_byte(void) +{ + __pdata uint8_t byte, b; + + byte = 0; + for (b = 0; b < 8; b++) { + byte = byte << 1; + ao_dbg_send_bits(DBG_CLOCK, DBG_CLOCK); + if (DBG_DATA_PIN) + byte |= 1; + ao_dbg_send_bits(DBG_CLOCK, 0); + } + return byte; +} + +/* 8051 instructions + */ +#define NOP 0x00 +#define MOV_direct_data 0x75 +#define LJMP 0x02 +#define MOV_Rn_data(n) (0x78 | (n)) +#define DJNZ_Rn_rel(n) (0xd8 | (n)) +#define MOV_A_direct 0xe5 +#define MOV_direct1_direct2 0x85 +#define MOV_direct_A 0xf5 +#define MOV_DPTR_data16 0x90 +#define MOV_A_data 0x74 +#define MOVX_atDPTR_A 0xf0 +#define MOVX_A_atDPTR 0xe0 +#define INC_DPTR 0xa3 +#define TRAP 0xa5 +#define SJMP 0x80 +#define JB 0x20 + +#define DEBUG_INSTR(l) (0x54 | (l)) + +#define SFR_PSW 0xD0 +#define SFR_DPL0 0x82 +#define SFR_DPH0 0x83 +#define SFR_DPL1 0x84 +#define SFR_DPH1 0x85 + +__pdata uint8_t save_acc; +__pdata uint8_t save_psw; +__pdata uint8_t save_dpl0; +__pdata uint8_t save_dph0; +__pdata uint8_t save_dpl1; +__pdata uint8_t save_dph1; + +static uint8_t +ao_dbg_inst1(uint8_t a) __reentrant +{ + ao_dbg_send_byte(DEBUG_INSTR(1)); + ao_dbg_send_byte(a); + return ao_dbg_recv_byte(); +} + +static uint8_t +ao_dbg_inst2(uint8_t a, uint8_t b) __reentrant +{ + ao_dbg_send_byte(DEBUG_INSTR(2)); + ao_dbg_send_byte(a); + ao_dbg_send_byte(b); + return ao_dbg_recv_byte(); +} + +static uint8_t +ao_dbg_inst3(uint8_t a, uint8_t b, uint8_t c) __reentrant +{ + ao_dbg_send_byte(DEBUG_INSTR(3)); + ao_dbg_send_byte(a); + ao_dbg_send_byte(b); + ao_dbg_send_byte(c); + return ao_dbg_recv_byte(); +} + +void +ao_dbg_start_transfer(uint16_t addr) +{ + save_acc = ao_dbg_inst1(NOP); + save_psw = ao_dbg_inst2(MOV_A_direct, SFR_PSW); + save_dpl0 = ao_dbg_inst2(MOV_A_direct, SFR_DPL0); + save_dph0 = ao_dbg_inst2(MOV_A_direct, SFR_DPH0); + save_dpl1 = ao_dbg_inst2(MOV_A_direct, SFR_DPL1); + save_dph1 = ao_dbg_inst2(MOV_A_direct, SFR_DPH1); + ao_dbg_inst3(MOV_DPTR_data16, addr >> 8, addr); +} + +void +ao_dbg_end_transfer(void) +{ + ao_dbg_inst3(MOV_direct_data, SFR_DPL0, save_dpl0); + ao_dbg_inst3(MOV_direct_data, SFR_DPH0, save_dph0); + ao_dbg_inst3(MOV_direct_data, SFR_DPL1, save_dpl1); + ao_dbg_inst3(MOV_direct_data, SFR_DPH1, save_dph1); + ao_dbg_inst3(MOV_direct_data, SFR_PSW, save_psw); + ao_dbg_inst2(MOV_A_data, save_acc); +} + +void +ao_dbg_write_byte(uint8_t byte) +{ + ao_dbg_inst2(MOV_A_data, byte); + ao_dbg_inst1(MOVX_atDPTR_A); + ao_dbg_inst1(INC_DPTR); +} + +uint8_t +ao_dbg_read_byte(void) +{ + ao_dbg_inst1(MOVX_A_atDPTR); + return ao_dbg_inst1(INC_DPTR); +} + +static void +ao_dbg_set_pins(void) +{ + /* Make the DBG pins GPIOs. On TeleMetrum, this will + * disable the SPI link, so don't expect SPI to work after + * using the debugger. + */ + DBG_PORT_SEL &= ~(DBG_CLOCK|DBG_DATA|DBG_RESET_N); + + /* make DBG_DATA tri-state */ + DBG_PORT_INP |= DBG_DATA; + + /* Raise RESET_N and CLOCK */ + DBG_PORT |= DBG_RESET_N | DBG_CLOCK; + + /* RESET_N and CLOCK are outputs now */ + DBG_PORT_DIR |= DBG_RESET_N | DBG_CLOCK; + DBG_PORT_DIR &= ~DBG_DATA; +} + +static void +ao_dbg_long_delay(void) +{ + uint8_t n; + + for (n = 0; n < 20; n++) + _asm nop _endasm; +} + +#define AO_RESET_LOW_DELAY AO_MS_TO_TICKS(100) +#define AO_RESET_HIGH_DELAY AO_MS_TO_TICKS(100) + +void +ao_dbg_debug_mode(void) +{ + ao_dbg_set_pins(); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); + ao_delay(AO_RESET_LOW_DELAY); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, 0 |DBG_DATA|DBG_RESET_N); + ao_delay(AO_RESET_HIGH_DELAY); +} + +void +ao_dbg_reset(void) +{ + ao_dbg_set_pins(); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_delay(AO_RESET_LOW_DELAY); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA| 0 ); + ao_dbg_long_delay(); + ao_dbg_send_bits(DBG_CLOCK|DBG_DATA|DBG_RESET_N, DBG_CLOCK|DBG_DATA|DBG_RESET_N); + ao_delay(AO_RESET_HIGH_DELAY); +} + +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) +{ + __pdata uint16_t count; + __pdata uint16_t i; + __pdata 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) +{ + __pdata char 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) +{ + __pdata uint16_t count; + __pdata uint16_t addr; + __pdata uint8_t b; + __pdata 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) +{ + __pdata uint16_t count; + __pdata uint16_t addr; + __pdata 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] = { + { debug_enable, "D\0Enable debug" }, + { debug_get, "G \0Get data" }, + { debug_input, "I \0Input at " }, + { debug_output, "O \0Output at " }, + { debug_put, "P ...\0Put data" }, + { debug_reset, "R\0Reset" }, + { 0, NULL }, +}; + +void +ao_dbg_init(void) +{ + ao_cmd_register(&ao_dbg_cmds[0]); +} diff --git a/src/cc1111/ao_dma.c b/src/cc1111/ao_dma.c new file mode 100644 index 00000000..6052964a --- /dev/null +++ b/src/cc1111/ao_dma.c @@ -0,0 +1,131 @@ +/* + * 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" + +#define NUM_DMA 5 + +/* + * The config address for DMA0 is programmed + * separately from that of DMA1-4, but for simplicity, + * we make them all contiguous. + */ + +static __xdata struct cc_dma_channel ao_dma_config[NUM_DMA]; +static __xdata uint8_t * __xdata ao_dma_done[NUM_DMA]; +static __data uint8_t ao_next_dma; + +uint8_t +ao_dma_alloc(__xdata uint8_t *done) +{ + uint8_t id; + + if (ao_next_dma == NUM_DMA) + ao_panic(AO_PANIC_DMA); + id = ao_next_dma++; + ao_dma_done[id] = done; + + /* When the first dma object is allocated, set up the DMA + * controller + */ + if (id == 0) { + DMAIRQ = 0; + DMAIF = 0; + IEN1 |= IEN1_DMAIE; + } + + return id; +} + +void +ao_dma_set_transfer(uint8_t id, + void __xdata *srcaddr, + void __xdata *dstaddr, + uint16_t count, + uint8_t cfg0, + uint8_t cfg1) +{ + if (DMAARM & (1 << id)) + ao_panic(AO_PANIC_DMA); + ao_dma_config[id].src_high = ((uint16_t) srcaddr) >> 8; + ao_dma_config[id].src_low = ((uint16_t) srcaddr); + ao_dma_config[id].dst_high = ((uint16_t) dstaddr) >> 8; + ao_dma_config[id].dst_low = ((uint16_t) dstaddr); + ao_dma_config[id].len_high = count >> 8; + ao_dma_config[id].len_low = count; + ao_dma_config[id].cfg0 = cfg0; + ao_dma_config[id].cfg1 = cfg1 | DMA_CFG1_IRQMASK; + if (id == 0) { + DMA0CFGH = ((uint16_t) (&ao_dma_config[0])) >> 8; + DMA0CFGL = ((uint16_t) (&ao_dma_config[0])); + } else { + DMA1CFGH = ((uint16_t) (&ao_dma_config[1])) >> 8; + DMA1CFGL = ((uint16_t) (&ao_dma_config[1])); + } +} + +#define nop() _asm nop _endasm; + +void +ao_dma_start(uint8_t id) +{ + uint8_t mask = (1 << id); + DMAIRQ &= ~mask; + 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(); +} + +void +ao_dma_trigger(uint8_t id) +{ + DMAREQ |= (1 << id); +} + +void +ao_dma_abort(uint8_t id) +{ + uint8_t mask = (1 << id); + DMAARM = 0x80 | mask; + DMAIRQ &= ~mask; +} + +void +ao_dma_isr(void) __interrupt 8 +{ + uint8_t id, mask; + + /* Find the first DMA channel which is done */ + mask = 1; + for (id = 0; id < ao_next_dma; id++) { + if (DMAIRQ & mask) { + /* Clear CPU interrupt flag */ + DMAIF = 0; + /* Clear the completed ID */ + DMAIRQ = ~mask; + *(ao_dma_done[id]) = 1; + ao_wakeup(ao_dma_done[id]); + break; + } + mask <<= 1; + } +} diff --git a/src/cc1111/ao_ignite.c b/src/cc1111/ao_ignite.c new file mode 100644 index 00000000..5238beb4 --- /dev/null +++ b/src/cc1111/ao_ignite.c @@ -0,0 +1,218 @@ +/* + * 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" + +#if IGNITE_ON_P2 +#define AO_IGNITER_DROGUE P2_3 +#define AO_IGNITER_MAIN P2_4 +#define AO_IGNITER_DIR P2DIR +#define AO_IGNITER_DROGUE_BIT (1 << 3) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +#if IGNITE_ON_P0 +#define AO_IGNITER_DROGUE P0_5 +#define AO_IGNITER_MAIN P0_4 +#define AO_IGNITER_DIR P0DIR +#define AO_IGNITER_DROGUE_BIT (1 << 5) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +/* test these values with real igniters */ +#define AO_IGNITER_OPEN 1000 +#define AO_IGNITER_CLOSED 7000 +#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) +#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) + +struct ao_ignition { + uint8_t request; + uint8_t fired; + uint8_t firing; +}; + +__xdata struct ao_ignition ao_ignition[2]; + +void +ao_ignite(enum ao_igniter igniter) __critical +{ + ao_ignition[igniter].request = 1; + ao_wakeup(&ao_ignition); +} + +enum ao_igniter_status +ao_igniter_status(enum ao_igniter igniter) +{ + __xdata struct ao_adc adc; + __pdata int16_t value; + __pdata uint8_t request, firing, fired; + + __critical { + ao_adc_get(&adc); + request = ao_ignition[igniter].request; + fired = ao_ignition[igniter].fired; + firing = ao_ignition[igniter].firing; + } + if (firing || (request && !fired)) + return ao_igniter_active; + + value = (AO_IGNITER_CLOSED>>1); + switch (igniter) { + case ao_igniter_drogue: + value = adc.sense_d; + break; + case ao_igniter_main: + value = adc.sense_m; + break; + } + if (value < AO_IGNITER_OPEN) + return ao_igniter_open; + else if (value > AO_IGNITER_CLOSED) + return ao_igniter_ready; + else + return ao_igniter_unknown; +} + +void +ao_igniter_fire(enum ao_igniter igniter) __critical +{ + ao_ignition[igniter].firing = 1; + switch(ao_config.ignite_mode) { + case AO_IGNITE_MODE_DUAL: + switch (igniter) { + case ao_igniter_drogue: + AO_IGNITER_DROGUE = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_DROGUE = 0; + break; + case ao_igniter_main: + AO_IGNITER_MAIN = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_MAIN = 0; + break; + } + break; + case AO_IGNITE_MODE_APOGEE: + switch (igniter) { + case ao_igniter_drogue: + AO_IGNITER_DROGUE = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_DROGUE = 0; + ao_delay(AO_IGNITER_CHARGE_TIME); + AO_IGNITER_MAIN = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_MAIN = 0; + break; + } + break; + case AO_IGNITE_MODE_MAIN: + switch (igniter) { + case ao_igniter_main: + AO_IGNITER_DROGUE = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_DROGUE = 0; + ao_delay(AO_IGNITER_CHARGE_TIME); + AO_IGNITER_MAIN = 1; + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_MAIN = 0; + break; + } + break; + } + ao_ignition[igniter].firing = 0; +} + +void +ao_igniter(void) +{ + __xdata enum ao_ignter igniter; + + ao_config_get(); + for (;;) { + ao_sleep(&ao_ignition); + for (igniter = ao_igniter_drogue; igniter <= ao_igniter_main; igniter++) { + if (ao_ignition[igniter].request && !ao_ignition[igniter].fired) { + if (igniter == ao_igniter_drogue && ao_config.apogee_delay) + ao_delay(AO_SEC_TO_TICKS(ao_config.apogee_delay)); + + ao_igniter_fire(igniter); + ao_delay(AO_IGNITER_CHARGE_TIME); + ao_ignition[igniter].fired = 1; + } + } + } +} + +void +ao_ignite_manual(void) +{ + ao_cmd_white(); + if (!ao_match_word("DoIt")) + return; + ao_cmd_white(); + if (ao_cmd_lex_c == 'm') { + if(ao_match_word("main")) + ao_igniter_fire(ao_igniter_main); + } else { + if(ao_match_word("drogue")) + ao_igniter_fire(ao_igniter_drogue); + } +} + +static __code char * __code igniter_status_names[] = { + "unknown", "ready", "active", "open" +}; + +void +ao_ignite_print_status(enum ao_igniter igniter, __code char *name) __reentrant +{ + enum ao_igniter_status status = ao_igniter_status(igniter); + printf("Igniter: %6s Status: %s\n", + name, + igniter_status_names[status]); +} + +void +ao_ignite_test(void) +{ + ao_ignite_print_status(ao_igniter_drogue, "drogue"); + ao_ignite_print_status(ao_igniter_main, "main"); +} + +__code struct ao_cmds ao_ignite_cmds[] = { + { ao_ignite_manual, "i {main|drogue}\0Fire igniter. is doit with D&I" }, + { ao_ignite_test, "t\0Test igniter" }, + { 0, NULL }, +}; + +__xdata struct ao_task ao_igniter_task; + +void +ao_ignite_set_pins(void) +{ + AO_IGNITER_DROGUE = 0; + AO_IGNITER_MAIN = 0; + AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; +} + +void +ao_igniter_init(void) +{ + ao_ignite_set_pins(); + ao_cmd_register(&ao_ignite_cmds[0]); + ao_add_task(&ao_igniter_task, ao_igniter, "igniter"); +} diff --git a/src/cc1111/ao_intflash.c b/src/cc1111/ao_intflash.c new file mode 100644 index 00000000..d76d954e --- /dev/null +++ b/src/cc1111/ao_intflash.c @@ -0,0 +1,209 @@ +/* + * Copyright © 2011 Anthony Towns + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "cc1111.h" + +#define ENDOFCODE (CODESIZE) +#define AO_INTFLASH_BLOCK 1024 +#define AO_INTFLASH_BLOCKS ((0x8000 - ENDOFCODE)/AO_INTFLASH_BLOCK) +#define AO_INTFLASH_SIZE (AO_INTFLASH_BLOCK * AO_INTFLASH_BLOCKS) +#define AO_INTFLASH_LOCATION (0x8000 - AO_INTFLASH_SIZE) + +/* + * 21000 * 24e6 + * FWT = ------------ + * 16e9 + * + * = 31.5 + * + * Round up and use 32 + */ + +#define FLASH_TIMING 0x20 + +#if AO_INTFLASH_BLOCKS < 2 +#error "Too few pages" +#endif + +#if AO_INFTLASH_LOCATION % 1024 != 0 +#error "Pages aren't aligned properly" +#endif + +__xdata __at(AO_INTFLASH_LOCATION) uint8_t ao_intflash[AO_INTFLASH_SIZE]; + +/* Total bytes of available storage */ +__pdata uint32_t ao_storage_total = sizeof(ao_intflash); + +/* Block size - device is erased in these units. */ +__pdata uint32_t ao_storage_block = AO_INTFLASH_BLOCK; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +__pdata uint32_t ao_storage_config = sizeof(ao_intflash) - AO_INTFLASH_BLOCK; + +/* Storage unit size - device reads and writes must be within blocks of this size. */ +__pdata uint16_t ao_storage_unit = AO_INTFLASH_BLOCK; + +__xdata static uint8_t ao_intflash_dma_done; +static uint8_t ao_intflash_dma; + +/* + * The internal flash chip is arranged in 1kB sectors; the + * chip cannot erase in units smaller than that. + * + * Writing happens in units of 2 bytes and + * can only change bits from 1 to 0. So, you can rewrite + * the same contents, or append to an existing page easily enough + */ + +/* + * Erase the specified sector + */ +uint8_t +ao_storage_erase(uint32_t pos) __reentrant +{ + uint16_t addr; + + if (pos >= ao_storage_total || pos + ao_storage_block > ao_storage_total) + return 0; + + addr = ((uint16_t)(ao_intflash + pos) >> 1); + + FADDRH = addr >> 8; + FADDRL = addr; + + __critical { + _asm + .even + orl _FCTL, #FCTL_ERASE; ; FCTL |= FCTL_ERASE + nop ; Required, see datasheet. + _endasm; + } + + return 1; +} + +/* + * Write to flash + */ + +static void +ao_intflash_write_aligned(uint16_t pos, __xdata void *d, uint16_t len) __reentrant +{ + pos = ((uint16_t) ao_intflash + pos) >> 1; + + ao_dma_set_transfer(ao_intflash_dma, + d, + &FWDATAXADDR, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_FLASH, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_HIGH); + + FADDRH = pos >> 8; + FADDRL = pos; + + ao_dma_start(ao_intflash_dma); + + __critical { + _asm + .even + orl _FCTL, #FCTL_WRITE; ; FCTL |= FCTL_WRITE + nop + _endasm; + } +} + +static void +ao_intflash_write_byte(uint16_t pos, uint8_t byte) __reentrant +{ + static __xdata uint8_t b[2]; + + if (pos & 1) { + b[0] = 0xff; + b[1] = byte; + } else { + b[0] = byte; + b[1] = 0xff; + } + ao_intflash_write_aligned(pos, b, 2); +} + +uint8_t +ao_storage_device_write(uint32_t pos32, __xdata void *v, uint16_t len) __reentrant +{ + uint16_t pos = pos32; + __xdata uint8_t *d = v; + uint8_t oddlen; + + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + if (len == 0) + return 1; + + if (pos & 1) { + ao_intflash_write_byte(pos++, *d++); + len--; + } + oddlen = len & 1; + len -= oddlen; + if (len) + ao_intflash_write_aligned(pos, d, len); + if (oddlen) + ao_intflash_write_byte(pos + len, d[len]); + + return 1; +} + +/* + * Read from flash + */ +uint8_t +ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant +{ + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + memcpy(d, ao_intflash+pos, len); + return 1; +} + +void +ao_storage_flush(void) __reentrant +{ +} + +void +ao_storage_setup(void) +{ +} + +void +ao_storage_device_info(void) __reentrant +{ + printf ("Using internal flash, starting at 0x%04x\n", AO_INTFLASH_LOCATION); +} + +void +ao_storage_device_init(void) +{ + ao_intflash_dma = ao_dma_alloc(&ao_intflash_dma_done); + + FWT = FLASH_TIMING; +} diff --git a/src/cc1111/ao_led.c b/src/cc1111/ao_led.c new file mode 100644 index 00000000..5beed58d --- /dev/null +++ b/src/cc1111/ao_led.c @@ -0,0 +1,61 @@ +/* + * 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" + +__pdata uint8_t ao_led_enable; + +void +ao_led_on(uint8_t colors) +{ + P1 |= (colors & ao_led_enable); +} + +void +ao_led_off(uint8_t colors) +{ + P1 &= ~(colors & ao_led_enable); +} + +void +ao_led_set(uint8_t colors) +{ + P1 = (P1 & ~(ao_led_enable)) | (colors & ao_led_enable); +} + +void +ao_led_toggle(uint8_t colors) +{ + P1 ^= (colors & ao_led_enable); +} + +void +ao_led_for(uint8_t colors, uint16_t ticks) __reentrant +{ + ao_led_on(colors); + ao_delay(ticks); + ao_led_off(colors); +} + +void +ao_led_init(uint8_t enable) +{ + ao_led_enable = enable; + P1SEL &= ~enable; + P1 &= ~enable; + P1DIR |= enable; +} diff --git a/src/cc1111/ao_packet.c b/src/cc1111/ao_packet.c new file mode 100644 index 00000000..f627e02b --- /dev/null +++ b/src/cc1111/ao_packet.c @@ -0,0 +1,148 @@ +/* + * 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" + +__xdata struct ao_packet_recv ao_rx_packet; +__xdata struct ao_packet ao_tx_packet; +__pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; + +static __xdata char tx_data[AO_PACKET_MAX]; +static __xdata char rx_data[AO_PACKET_MAX]; +static __pdata uint8_t rx_seq; + +__xdata struct ao_task ao_packet_task; +__xdata uint8_t ao_packet_enable; +__xdata uint8_t ao_packet_master_sleeping; + +void +ao_packet_send(void) +{ + ao_led_on(AO_LED_RED); + /* If any tx data is pending then copy it into the tx packet */ + if (ao_packet_tx_used && ao_tx_packet.len == 0) { + memcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); + ao_tx_packet.len = ao_packet_tx_used; + ao_tx_packet.seq++; + ao_packet_tx_used = 0; + ao_wakeup(&tx_data); + } + ao_radio_send(&ao_tx_packet, sizeof (ao_tx_packet)); + ao_led_off(AO_LED_RED); +} + +uint8_t +ao_packet_recv(void) +{ + uint8_t dma_done; + +#ifdef AO_LED_GREEN + ao_led_on(AO_LED_GREEN); +#endif + dma_done = ao_radio_recv(&ao_rx_packet, sizeof (struct ao_packet_recv)); +#ifdef AO_LED_GREEN + ao_led_off(AO_LED_GREEN); +#endif + + /* Check to see if we got a valid packet */ + if (!dma_done) + return 0; + if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) + return 0; + + /* SYN packets carry no data */ + if (ao_rx_packet.packet.len == AO_PACKET_SYN) { + rx_seq = ao_rx_packet.packet.seq; + ao_tx_packet.seq = ao_rx_packet.packet.ack; + ao_tx_packet.ack = rx_seq; + } else if (ao_rx_packet.packet.len) { + + /* Check for incoming data at the next sequence and + * for an empty data buffer + */ + if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) && + ao_packet_rx_used == ao_packet_rx_len) { + + /* Copy data to the receive data buffer and set up the + * offsets + */ + memcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); + ao_packet_rx_used = 0; + ao_packet_rx_len = ao_rx_packet.packet.len; + + /* Mark the sequence that we've received to + * let the sender know when we return a packet + */ + rx_seq = ao_rx_packet.packet.seq; + ao_tx_packet.ack = rx_seq; + + /* Poke anyone looking for received data */ + ao_wakeup(&ao_stdin_ready); + } + } + + /* If the other side has seen the latest data we queued, + * wake up any task waiting to send data and let them go again + */ + if (ao_rx_packet.packet.ack == ao_tx_packet.seq) { + ao_tx_packet.len = 0; + ao_wakeup(&ao_tx_packet); + } + return 1; +} + +#ifndef PACKET_HAS_MASTER +#define PACKET_HAS_MASTER 1 +#endif + +#if PACKET_HAS_MASTER +void +ao_packet_flush(void) +{ + /* If there is data to send, and this is the master, + * then poke the master to send all queued data + */ + if (ao_packet_tx_used && ao_packet_master_sleeping) + ao_wakeup(&ao_packet_master_sleeping); +} +#endif /* PACKET_HAS_MASTER */ + +void +ao_packet_putchar(char c) __reentrant +{ + while (ao_packet_tx_used == AO_PACKET_MAX && ao_packet_enable) { +#if PACKET_HAS_MASTER + ao_packet_flush(); +#endif + ao_sleep(&tx_data); + } + + if (ao_packet_enable) + tx_data[ao_packet_tx_used++] = c; +} + +char +ao_packet_pollchar(void) __critical +{ + if (!ao_packet_enable) + return AO_READ_AGAIN; + + if (ao_packet_rx_used == ao_packet_rx_len) + return AO_READ_AGAIN; + + return rx_data[ao_packet_rx_used++]; +} diff --git a/src/cc1111/ao_packet_master.c b/src/cc1111/ao_packet_master.c new file mode 100644 index 00000000..b0fdf5a8 --- /dev/null +++ b/src/cc1111/ao_packet_master.c @@ -0,0 +1,144 @@ +/* + * 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" + +static char +ao_packet_getchar(void) __critical +{ + char c; + while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) { + if (!ao_packet_enable) + break; + if (ao_packet_master_sleeping) + ao_wakeup(&ao_packet_master_sleeping); + flush(); + ao_sleep(&ao_stdin_ready); + } + return c; +} + +static void +ao_packet_echo(void) __reentrant +{ + char c; + while (ao_packet_enable) { + c = ao_packet_getchar(); + if (c != AO_READ_AGAIN) + putchar(c); + } + ao_exit(); +} + +static __xdata struct ao_task ao_packet_echo_task; +static __xdata uint16_t ao_packet_master_delay; +static __xdata uint16_t ao_packet_master_time; + +#define AO_PACKET_MASTER_DELAY_SHORT AO_MS_TO_TICKS(100) +#define AO_PACKET_MASTER_DELAY_LONG AO_MS_TO_TICKS(1000) +#define AO_PACKET_MASTER_DELAY_TIMEOUT AO_MS_TO_TICKS(2000) + +static void +ao_packet_master_busy(void) +{ + ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; + ao_packet_master_time = ao_time(); +} + +static void +ao_packet_master_check_busy(void) +{ + int16_t idle; + if (ao_packet_master_delay != AO_PACKET_MASTER_DELAY_SHORT) + return; + idle = (int16_t) (ao_time() - ao_packet_master_time); + + if (idle > AO_PACKET_MASTER_DELAY_TIMEOUT) + ao_packet_master_delay = AO_PACKET_MASTER_DELAY_LONG; +} + +void +ao_packet_master(void) +{ + ao_config_get(); + ao_tx_packet.addr = ao_serial_number; + ao_tx_packet.len = AO_PACKET_SYN; + ao_packet_master_time = ao_time(); + ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; + while (ao_packet_enable) { + memcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN); + ao_packet_send(); + if (ao_tx_packet.len) + ao_packet_master_busy(); + ao_packet_master_check_busy(); + ao_alarm(ao_packet_master_delay); + if (ao_packet_recv()) { + /* if we can transmit data, do so */ + if (ao_packet_tx_used && ao_tx_packet.len == 0) + continue; + if (ao_rx_packet.packet.len) + ao_packet_master_busy(); + ao_packet_master_sleeping = 1; + ao_alarm(ao_packet_master_delay); + ao_sleep(&ao_packet_master_sleeping); + ao_packet_master_sleeping = 0; + } + } + ao_exit(); +} + +static void +ao_packet_forward(void) __reentrant +{ + char c; + ao_packet_enable = 1; + ao_cmd_white(); + + flush(); +#if HAS_MONITOR + ao_set_monitor(0); +#endif + ao_add_task(&ao_packet_task, ao_packet_master, "master"); + ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); + while ((c = getchar()) != '~') { + if (c == '\r') c = '\n'; + ao_packet_putchar(c); + } + + /* Wait for a second if there is any pending data */ + for (c = 0; (ao_packet_tx_used || ao_tx_packet.len) && c < 10; c++) + ao_delay(AO_MS_TO_TICKS(100)); + ao_packet_enable = 0; + while (ao_packet_echo_task.wchan || ao_packet_task.wchan) { + ao_radio_recv_abort(); + ao_wakeup(&ao_stdin_ready); + ao_delay(AO_MS_TO_TICKS(10)); + } +} + + + +__code struct ao_cmds ao_packet_master_cmds[] = { + { ao_packet_forward, "p\0Remote packet link." }, + { 0, NULL }, +}; + +void +ao_packet_master_init(void) +{ + ao_cmd_register(&ao_packet_master_cmds[0]); +} diff --git a/src/cc1111/ao_packet_slave.c b/src/cc1111/ao_packet_slave.c new file mode 100644 index 00000000..9f14052a --- /dev/null +++ b/src/cc1111/ao_packet_slave.c @@ -0,0 +1,64 @@ +/* + * 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_packet_slave(void) +{ + ao_tx_packet.addr = ao_serial_number; + ao_tx_packet.len = AO_PACKET_SYN; + while (ao_packet_enable) { + if (ao_packet_recv()) { + memcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN); +#if HAS_FLIGHT + ao_flight_force_idle = TRUE; +#endif + ao_packet_send(); + } + } + ao_exit(); +} + +void +ao_packet_slave_start(void) +{ + ao_packet_enable = 1; + ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); +} + +void +ao_packet_slave_stop(void) +{ + if (ao_packet_enable) { + ao_packet_enable = 0; + while (ao_packet_task.wchan) { + ao_radio_recv_abort(); + ao_delay(AO_MS_TO_TICKS(10)); + } + } +} + +void +ao_packet_slave_init(uint8_t enable) +{ + ao_add_stdio(ao_packet_pollchar, + ao_packet_putchar, + NULL); + if (enable) + ao_packet_slave_start(); +} diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c new file mode 100644 index 00000000..00816b33 --- /dev/null +++ b/src/cc1111/ao_radio.c @@ -0,0 +1,475 @@ +/* + * 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 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 + +/* + * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone), + * so the DRATE_E and DRATE_M values are: + * + * M is 94 and E is 6 + * + * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes + */ + +#define RDF_DRATE_E 6 +#define RDF_DRATE_M 94 +#define RDF_PACKET_LEN 50 + +/* + * RDF deviation should match the normal NFM value of 5kHz + * + * M is 6 and E is 1 + * + */ + +#define RDF_DEVIATION_M 6 +#define RDF_DEVIATION_E 1 + +/* 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_10_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_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_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, +}; + +static __code uint8_t rdf_setup[] = { + RF_MDMCFG4_OFF, ((CHANBW_E << RF_MDMCFG4_CHANBW_E_SHIFT) | + (CHANBW_M << RF_MDMCFG4_CHANBW_M_SHIFT) | + (RDF_DRATE_E << RF_MDMCFG4_DRATE_E_SHIFT)), + RF_MDMCFG3_OFF, (RDF_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_DIS | + RF_MDMCFG1_NUM_PREAMBLE_2 | + (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), + + RF_DEVIATN_OFF, ((RDF_DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | + (RDF_DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), + + /* packet length is set in-line */ + RF_PKTCTRL1_OFF, ((1 << PKTCTRL1_PQT_SHIFT)| + PKTCTRL1_ADR_CHK_NONE), + RF_PKTCTRL0_OFF, (RF_PKTCTRL0_PKT_FORMAT_NORMAL| + RF_PKTCTRL0_LENGTH_CONFIG_FIXED), +}; + +static __code uint8_t fixed_pkt_setup[] = { + 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_DEVIATN_OFF, ((DEVIATION_E << RF_DEVIATN_DEVIATION_E_SHIFT) | + (DEVIATION_M << RF_DEVIATN_DEVIATION_M_SHIFT)), + + /* max packet length -- now set inline */ + 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), +}; + +__xdata uint8_t ao_radio_dma; +__xdata uint8_t ao_radio_dma_done; +__xdata uint8_t ao_radio_done; +__xdata uint8_t ao_radio_abort; +__xdata uint8_t ao_radio_mutex; + +void +ao_radio_general_isr(void) __interrupt 16 +{ + S1CON &= ~0x03; + if (RFIF & RFIF_IM_TIMEOUT) { + ao_radio_recv_abort(); + RFIF &= ~ RFIF_IM_TIMEOUT; + } else if (RFIF & RFIF_IM_DONE) { + ao_radio_done = 1; + ao_wakeup(&ao_radio_done); + RFIF &= ~RFIF_IM_DONE; + } +} + +void +ao_radio_set_packet(void) +{ + uint8_t i; + for (i = 0; i < sizeof (fixed_pkt_setup); i += 2) + RF[fixed_pkt_setup[i]] = fixed_pkt_setup[i+1]; +} + +void +ao_radio_idle(void) +{ + if (RF_MARCSTATE != RF_MARCSTATE_IDLE) + { + do { + RFST = RFST_SIDLE; + ao_yield(); + } while (RF_MARCSTATE != RF_MARCSTATE_IDLE); + } +} + +void +ao_radio_get(uint8_t len) +{ + ao_config_get(); + ao_mutex_get(&ao_radio_mutex); + ao_radio_idle(); + RF_CHANNR = ao_config.radio_channel; + RF_FREQ2 = (uint8_t) (ao_config.radio_setting >> 16); + RF_FREQ1 = (uint8_t) (ao_config.radio_setting >> 8); + RF_FREQ0 = (uint8_t) (ao_config.radio_setting); + RF_PKTLEN = len; +} + + +void +ao_radio_send(__xdata void *packet, uint8_t size) __reentrant +{ + ao_radio_get(size); + ao_radio_done = 0; + ao_dma_set_transfer(ao_radio_dma, + packet, + &RFDXADDR, + size, + 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; + __critical while (!ao_radio_done) + ao_sleep(&ao_radio_done); + ao_radio_put(); +} + +uint8_t +ao_radio_recv(__xdata void *packet, uint8_t size) __reentrant +{ + ao_radio_abort = 0; + ao_radio_get(size - 2); + ao_dma_set_transfer(ao_radio_dma, + &RFDXADDR, + packet, + size, + 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; + + /* Wait for DMA to be done, for the radio receive process to + * get aborted or for a receive timeout to fire + */ + __critical while (!ao_radio_dma_done && !ao_radio_abort) + if (ao_sleep(&ao_radio_dma_done)) + break; + + /* If recv was aborted, clean up by stopping the DMA engine + * and idling the radio + */ + if (!ao_radio_dma_done) { + ao_dma_abort(ao_radio_dma); + ao_radio_idle(); + } + ao_radio_put(); + return ao_radio_dma_done; +} + +/* + * Wake up a task waiting to receive a radio packet + * and tell them to abort the transfer + */ + +void +ao_radio_recv_abort(void) +{ + ao_radio_abort = 1; + ao_wakeup(&ao_radio_dma_done); +} + +__xdata ao_radio_rdf_value = 0x55; + +void +ao_radio_rdf(int ms) +{ + uint8_t i; + uint8_t pkt_len; + + /* + * Compute the packet length as follows: + * + * 2000 bps (for a 1kHz tone) + * so, for 'ms' milliseconds, we need + * 2 * ms bits, or ms / 4 bytes + */ + if (ms > (255 * 4)) + ms = 255 * 4; + pkt_len = ms >> 2; + + ao_radio_abort = 0; + ao_radio_get(pkt_len); + ao_radio_done = 0; + for (i = 0; i < sizeof (rdf_setup); i += 2) + RF[rdf_setup[i]] = rdf_setup[i+1]; + + ao_dma_set_transfer(ao_radio_dma, + &ao_radio_rdf_value, + &RFDXADDR, + pkt_len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_RADIO, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_HIGH); + ao_dma_start(ao_radio_dma); + RFST = RFST_STX; + __critical while (!ao_radio_done && !ao_radio_abort) + ao_sleep(&ao_radio_done); + if (!ao_radio_done) { + ao_dma_abort(ao_radio_dma); + ao_radio_idle(); + } + ao_radio_set_packet(); + ao_radio_put(); +} + +void +ao_radio_rdf_abort(void) +{ + ao_radio_abort = 1; + ao_wakeup(&ao_radio_done); +} + + +/* Output carrier */ +void +ao_radio_test(void) +{ + uint8_t mode = 2; + static __xdata radio_on; + ao_cmd_white(); + if (ao_cmd_lex_c != '\n') { + ao_cmd_decimal(); + mode = (uint8_t) ao_cmd_lex_u32; + } + mode++; + if ((mode & 2) && !radio_on) { +#if HAS_MONITOR + ao_set_monitor(0); +#endif +#if PACKET_HAS_SLAVE + ao_packet_slave_stop(); +#endif + ao_radio_get(0xff); + RFST = RFST_STX; + radio_on = 1; + } + if (mode == 3) { + printf ("Hit a character to stop..."); flush(); + getchar(); + putchar('\n'); + } + if ((mode & 1) && radio_on) { + ao_radio_idle(); + ao_radio_put(); + radio_on = 0; + } +} + +__code struct ao_cmds ao_radio_cmds[] = { + { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" }, + { 0, NULL }, +}; + +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_set_packet(); + ao_radio_dma_done = 1; + ao_radio_dma = ao_dma_alloc(&ao_radio_dma_done); + RFIF = 0; + RFIM = RFIM_IM_TIMEOUT|RFIM_IM_DONE; + IEN2 |= IEN2_RFIE; + ao_cmd_register(&ao_radio_cmds[0]); +} diff --git a/src/cc1111/ao_reboot.c b/src/cc1111/ao_reboot.c new file mode 100644 index 00000000..8c47b893 --- /dev/null +++ b/src/cc1111/ao_reboot.c @@ -0,0 +1,28 @@ +/* + * 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" + +/* Use the watchdog timer to force a complete reboot + */ +void +ao_reboot(void) +{ + WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_32768; + ao_delay(AO_SEC_TO_TICKS(2)); + ao_panic(AO_PANIC_REBOOT); +} diff --git a/src/cc1111/ao_romconfig.c b/src/cc1111/ao_romconfig.c new file mode 100644 index 00000000..f3fe61b1 --- /dev/null +++ b/src/cc1111/ao_romconfig.c @@ -0,0 +1,32 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +__code __at (0x00a0) uint16_t ao_romconfig_version = AO_ROMCONFIG_VERSION; +__code __at (0x00a2) uint16_t ao_romconfig_check = ~AO_ROMCONFIG_VERSION; +__code __at (0x00a4) uint16_t ao_serial_number = 0; +/* + * For 434.550MHz, the frequency value is: + * + * 434.550e6 / (24e6 / 2**16) = 1186611.2 + * + * This value is stored in a const variable so that + * ao-load can change it during programming for + * devices that have no eeprom for config data. + */ +__code __at (0x00a6) uint32_t ao_radio_cal = 1186611; diff --git a/src/cc1111/ao_serial.c b/src/cc1111/ao_serial.c new file mode 100644 index 00000000..82370c64 --- /dev/null +++ b/src/cc1111/ao_serial.c @@ -0,0 +1,175 @@ +/* + * 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" + +volatile __xdata struct ao_fifo ao_usart1_rx_fifo; +volatile __xdata struct ao_fifo ao_usart1_tx_fifo; + +void +ao_serial_rx1_isr(void) __interrupt 3 +{ + if (!ao_fifo_full(ao_usart1_rx_fifo)) + ao_fifo_insert(ao_usart1_rx_fifo, U1DBUF); + ao_wakeup(&ao_usart1_rx_fifo); +#if USE_SERIAL_STDIN + ao_wakeup(&ao_stdin_ready); +#endif +} + +static __xdata uint8_t ao_serial_tx1_started; + +static void +ao_serial_tx1_start(void) +{ + if (!ao_fifo_empty(ao_usart1_tx_fifo) && + !ao_serial_tx1_started) + { + ao_serial_tx1_started = 1; + ao_fifo_remove(ao_usart1_tx_fifo, U1DBUF); + } +} + +void +ao_serial_tx1_isr(void) __interrupt 14 +{ + UTX1IF = 0; + ao_serial_tx1_started = 0; + ao_serial_tx1_start(); + ao_wakeup(&ao_usart1_tx_fifo); +} + +char +ao_serial_getchar(void) __critical +{ + char c; + while (ao_fifo_empty(ao_usart1_rx_fifo)) + ao_sleep(&ao_usart1_rx_fifo); + ao_fifo_remove(ao_usart1_rx_fifo, c); + return c; +} + +#if USE_SERIAL_STDIN +char +ao_serial_pollchar(void) __critical +{ + char c; + if (ao_fifo_empty(ao_usart1_rx_fifo)) + return AO_READ_AGAIN; + ao_fifo_remove(ao_usart1_rx_fifo,c); + return c; +} +#endif + +void +ao_serial_putchar(char c) __critical +{ + while (ao_fifo_full(ao_usart1_tx_fifo)) + ao_sleep(&ao_usart1_tx_fifo); + ao_fifo_insert(ao_usart1_tx_fifo, c); + ao_serial_tx1_start(); +} + +void +ao_serial_drain(void) __critical +{ + while (!ao_fifo_empty(ao_usart1_tx_fifo)) + ao_sleep(&ao_usart1_tx_fifo); +} + +static __code struct { + uint8_t baud; + uint8_t gcr; +} ao_serial_speeds[] = { + /* [AO_SERIAL_SPEED_4800] = */ { + /* .baud = */ 163, + /* .gcr = */ (7 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB + }, + /* [AO_SERIAL_SPEED_9600] = */ { + /* .baud = */ 163, + /* .gcr = */ (8 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB + }, + /* [AO_SERIAL_SPEED_19200] = */ { + /* .baud = */ 163, + /* .gcr = */ (9 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB + }, + /* [AO_SERIAL_SPEED_57600] = */ { + /* .baud = */ 59, + /* .gcr = */ (11 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB + }, +}; + +void +ao_serial_set_speed(uint8_t speed) +{ + ao_serial_drain(); + if (speed > AO_SERIAL_SPEED_57600) + return; + U1UCR |= UxUCR_FLUSH; + U1BAUD = ao_serial_speeds[speed].baud; + U1GCR = ao_serial_speeds[speed].gcr; +} + +void +ao_serial_init(void) +{ +#if HAS_SERIAL_1_ALT_1 + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_1; + + P2DIR = (P2DIR & ~P2DIR_PRIP0_MASK) | P2DIR_PRIP0_USART1_USART0; + + /* Make the USART pins be controlled by the USART */ + P0SEL |= (1 << 5) | (1 << 4); +#if HAS_SERIAL_1_HW_FLOW + P0SEL |= (1 << 3) | (1 << 2); +#endif +#else + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_2; + + P2SEL = (P2SEL & ~(P2SEL_PRI3P1_MASK | P2SEL_PRI2P1_MASK)) | + (P2SEL_PRI3P1_USART1 | P2SEL_PRI2P1_USART1); + + /* Make the USART pins be controlled by the USART */ + P1SEL |= (1 << 6) | (1 << 7); + P1SEL |= (1 << 5) | (1 << 4); +#endif + + /* UART mode with receiver enabled */ + U1CSR = (UxCSR_MODE_UART | UxCSR_RE); + + /* Pick a 4800 baud rate */ + ao_serial_set_speed(AO_SERIAL_SPEED_4800); + + /* Reasonable serial parameters */ + U1UCR = (UxUCR_FLUSH | +#if HAS_SERIAL_1_HW_FLOW + UxUCR_FLOW_ENABLE | +#else + UxUCR_FLOW_DISABLE | +#endif + UxUCR_D9_EVEN_PARITY | + UxUCR_BIT9_8_BITS | + UxUCR_PARITY_DISABLE | + UxUCR_SPB_1_STOP_BIT | + UxUCR_STOP_HIGH | + UxUCR_START_LOW); + + IEN0 |= IEN0_URX1IE; + IEN2 |= IEN2_UTX1IE; +} diff --git a/src/cc1111/ao_spi.c b/src/cc1111/ao_spi.c new file mode 100644 index 00000000..fbe613c7 --- /dev/null +++ b/src/cc1111/ao_spi.c @@ -0,0 +1,157 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +/* Shared mutex to protect SPI bus, must cover the entire + * operation, from CS low to CS high. This means that any SPI + * user must protect the SPI bus with this mutex + */ +__xdata uint8_t ao_spi_mutex; +__xdata uint8_t ao_spi_dma_in_done; +__xdata uint8_t ao_spi_dma_out_done; + +uint8_t ao_spi_dma_out_id; +uint8_t ao_spi_dma_in_id; + +static __xdata uint8_t ao_spi_const = 0xff; + +/* Send bytes over SPI. + * + * This sets up two DMA engines, one writing the data and another reading + * bytes coming back. We use the bytes coming back to tell when the transfer + * is complete, as the transmit register is double buffered and hence signals + * completion one byte before the transfer is actually complete + */ +void +ao_spi_send(void __xdata *block, uint16_t len) __reentrant +{ + ao_dma_set_transfer(ao_spi_dma_in_id, + &U0DBUFXADDR, + &ao_spi_const, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_URX0, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_set_transfer(ao_spi_dma_out_id, + block, + &U0DBUFXADDR, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_UTX0, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_start(ao_spi_dma_in_id); + ao_dma_start(ao_spi_dma_out_id); + ao_dma_trigger(ao_spi_dma_out_id); + __critical while (!ao_spi_dma_in_done) + ao_sleep(&ao_spi_dma_in_done); +} + +/* Receive bytes over SPI. + * + * This sets up tow DMA engines, one reading the data and another + * writing constant values to the SPI transmitter as that is what + * clocks the data coming in. + */ +void +ao_spi_recv(void __xdata *block, uint16_t len) __reentrant +{ + ao_dma_set_transfer(ao_spi_dma_in_id, + &U0DBUFXADDR, + block, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_URX0, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_1 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_set_transfer(ao_spi_dma_out_id, + &ao_spi_const, + &U0DBUFXADDR, + len, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_UTX0, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_NORMAL); + + ao_dma_start(ao_spi_dma_in_id); + ao_dma_start(ao_spi_dma_out_id); + ao_dma_trigger(ao_spi_dma_out_id); + __critical while (!ao_spi_dma_in_done) + ao_sleep(&ao_spi_dma_in_done); +} + +/* + * Initialize USART0 for SPI using config alt 2 + * + * MO P1_5 + * MI P1_4 + * CLK P1_3 + * + * Chip select is the responsibility of the caller + */ + +void +ao_spi_init(void) +{ + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2; + + /* Ensure that USART0 takes precidence over USART1 for pins that + * they share + */ + P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | P2SEL_PRI3P1_USART0; + + /* Make the SPI pins be controlled by the USART peripheral */ + P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3)); + + /* Set up OUT DMA */ + ao_spi_dma_out_id = ao_dma_alloc(&ao_spi_dma_out_done); + + /* Set up IN DMA */ + ao_spi_dma_in_id = ao_dma_alloc(&ao_spi_dma_in_done); + + /* Set up the USART. + * + * SPI master mode + */ + U0CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_MASTER); + + /* Set the baud rate and signal parameters + * + * The cc1111 is limited to a 24/8 MHz SPI clock. + * Every peripheral I've ever seen goes faster than that, + * so set the clock to 3MHz (BAUD_E 17, BAUD_M 0) + */ + U0BAUD = 0; + U0GCR = (UxGCR_CPOL_NEGATIVE | + UxGCR_CPHA_FIRST_EDGE | + UxGCR_ORDER_MSB | + (17 << UxGCR_BAUD_E_SHIFT)); +} diff --git a/src/cc1111/ao_timer.c b/src/cc1111/ao_timer.c new file mode 100644 index 00000000..c977fbc8 --- /dev/null +++ b/src/cc1111/ao_timer.c @@ -0,0 +1,111 @@ +/* + * 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" + +static volatile __data uint16_t ao_tick_count; + +uint16_t ao_time(void) __critical +{ + return ao_tick_count; +} + +static __xdata uint8_t ao_forever; + +void +ao_delay(uint16_t ticks) +{ + ao_alarm(ticks); + ao_sleep(&ao_forever); +} + +#define T1_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ +#define T1_SAMPLE_TIME 30000 /* 3e6/30000 = 100 */ + +#if HAS_ADC +volatile __data uint8_t ao_adc_interval = 1; +volatile __data uint8_t ao_adc_count; +#endif + +void ao_timer_isr(void) __interrupt 9 +{ + ++ao_tick_count; +#if HAS_ADC + if (++ao_adc_count == ao_adc_interval) { + ao_adc_count = 0; + ao_adc_poll(); + } +#endif +} + +#if HAS_ADC +void +ao_timer_set_adc_interval(uint8_t interval) __critical +{ + ao_adc_interval = interval; + ao_adc_count = 0; +} +#endif + +void +ao_timer_init(void) +{ + /* NOTE: This uses a timer only present on cc1111 architecture. */ + + /* disable timer 1 */ + T1CTL = 0; + + /* set the sample rate */ + T1CC0H = T1_SAMPLE_TIME >> 8; + T1CC0L = (uint8_t) T1_SAMPLE_TIME; + + T1CCTL0 = T1CCTL_MODE_COMPARE; + T1CCTL1 = 0; + T1CCTL2 = 0; + + /* clear timer value */ + T1CNTL = 0; + + /* enable overflow interrupt */ + OVFIM = 1; + /* enable timer 1 interrupt */ + T1IE = 1; + + /* enable timer 1 in module mode, dividing by 8 */ + T1CTL = T1CTL_MODE_MODULO | T1CTL_DIV_8; +} + +/* + * AltOS always cranks the clock to the max frequency + */ +void +ao_clock_init(void) +{ + /* Switch system clock to crystal oscilator */ + CLKCON = (CLKCON & ~CLKCON_OSC_MASK) | (CLKCON_OSC_XTAL); + + while (!(SLEEP & SLEEP_XOSC_STB)) + ; + + /* Crank up the timer tick and system clock speed */ + CLKCON = ((CLKCON & ~(CLKCON_TICKSPD_MASK | CLKCON_CLKSPD_MASK)) | + (CLKCON_TICKSPD_1 | CLKCON_CLKSPD_1)); + + while ((CLKCON & (CLKCON_TICKSPD_MASK|CLKCON_CLKSPD_MASK)) != + (CLKCON_TICKSPD_1 | CLKCON_CLKSPD_1)) + ; +} diff --git a/src/cc1111/ao_usb.c b/src/cc1111/ao_usb.c new file mode 100644 index 00000000..08cb7390 --- /dev/null +++ b/src/cc1111/ao_usb.c @@ -0,0 +1,460 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_usb.h" + +struct ao_task __xdata ao_usb_task; + +static __xdata uint16_t ao_usb_in_bytes; +static __pdata uint16_t ao_usb_in_bytes_last; +static __xdata uint16_t ao_usb_out_bytes; +static __pdata uint8_t ao_usb_iif; +static __pdata uint8_t ao_usb_running; + +static void +ao_usb_set_interrupts(void) +{ + /* IN interrupts on the control an IN endpoints */ + USBIIE = (1 << AO_USB_CONTROL_EP) | (1 << AO_USB_IN_EP); + + /* OUT interrupts on the OUT endpoint */ + USBOIE = (1 << AO_USB_OUT_EP); + + /* Only care about reset */ + USBCIE = USBCIE_RSTIE; +} + +/* This interrupt is shared with port 2, + * so when we hook that up, fix this + */ +void +ao_usb_isr(void) __interrupt 6 +{ + USBIF = 0; + ao_usb_iif |= USBIIF; + if (ao_usb_iif & 1) + ao_wakeup(&ao_usb_task); + if (ao_usb_iif & (1 << AO_USB_IN_EP)) + ao_wakeup(&ao_usb_in_bytes); + + if (USBOIF & (1 << AO_USB_OUT_EP)) + ao_wakeup(&ao_stdin_ready); + + if (USBCIF & USBCIF_RSTIF) + ao_usb_set_interrupts(); +#if HAS_BTM +#if BT_LINK_ON_P2 + ao_btm_isr(); +#endif +#endif +} + +struct ao_usb_setup { + uint8_t dir_type_recip; + uint8_t request; + uint16_t value; + uint16_t index; + uint16_t length; +} __xdata ao_usb_setup; + +__pdata uint8_t ao_usb_ep0_state; +uint8_t * __pdata ao_usb_ep0_in_data; +__pdata uint8_t ao_usb_ep0_in_len; +__pdata uint8_t ao_usb_ep0_in_buf[2]; +__pdata uint8_t ao_usb_ep0_out_len; +__xdata uint8_t *__pdata ao_usb_ep0_out_data; +__pdata uint8_t ao_usb_configuration; + +/* Send an IN data packet */ +static void +ao_usb_ep0_flush(void) +{ + __pdata uint8_t this_len; + __pdata uint8_t cs0; + + /* If the IN packet hasn't been picked up, just return */ + USBINDEX = 0; + cs0 = USBCS0; + if (cs0 & USBCS0_INPKT_RDY) + return; + + this_len = ao_usb_ep0_in_len; + if (this_len > AO_USB_CONTROL_SIZE) + this_len = AO_USB_CONTROL_SIZE; + cs0 = USBCS0_INPKT_RDY; + if (this_len != AO_USB_CONTROL_SIZE) { + cs0 = USBCS0_INPKT_RDY | USBCS0_DATA_END; + ao_usb_ep0_state = AO_USB_EP0_IDLE; + } + ao_usb_ep0_in_len -= this_len; + while (this_len--) + USBFIFO[0] = *ao_usb_ep0_in_data++; + USBINDEX = 0; + USBCS0 = cs0; +} + +__xdata static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; + +/* Walk through the list of descriptors and find a match + */ +static void +ao_usb_get_descriptor(uint16_t value) +{ + __code uint8_t *__pdata descriptor; + __pdata uint8_t type = value >> 8; + __pdata uint8_t index = value; + + descriptor = ao_usb_descriptors; + while (descriptor[0] != 0) { + if (descriptor[1] == type && index-- == 0) { + if (type == AO_USB_DESC_CONFIGURATION) + ao_usb_ep0_in_len = descriptor[2]; + else + ao_usb_ep0_in_len = descriptor[0]; + ao_usb_ep0_in_data = descriptor; + break; + } + descriptor += descriptor[0]; + } +} + +/* Read data from the ep0 OUT fifo + */ +static void +ao_usb_ep0_fill(void) +{ + __pdata uint8_t len; + + USBINDEX = 0; + len = USBCNT0; + if (len > ao_usb_ep0_out_len) + len = ao_usb_ep0_out_len; + ao_usb_ep0_out_len -= len; + while (len--) + *ao_usb_ep0_out_data++ = USBFIFO[0]; +} + +void +ao_usb_ep0_queue_byte(uint8_t a) +{ + ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a; +} + +void +ao_usb_set_address(uint8_t address) +{ + ao_usb_running = 1; + USBADDR = address | 0x80; + while (USBADDR & 0x80) + ; +} + +static void +ao_usb_set_configuration(void) +{ + /* Set the IN max packet size, double buffered */ + USBINDEX = AO_USB_IN_EP; + USBMAXI = AO_USB_IN_SIZE >> 3; + USBCSIH |= USBCSIH_IN_DBL_BUF; + + /* Set the OUT max packet size, double buffered */ + USBINDEX = AO_USB_OUT_EP; + USBMAXO = AO_USB_OUT_SIZE >> 3; + USBCSOH = USBCSOH_OUT_DBL_BUF; +} + +static void +ao_usb_ep0_setup(void) +{ + /* Pull the setup packet out of the fifo */ + ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_setup; + ao_usb_ep0_out_len = 8; + ao_usb_ep0_fill(); + if (ao_usb_ep0_out_len != 0) + return; + + /* Figure out how to ACK the setup packet */ + if (ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) { + if (ao_usb_setup.length) + ao_usb_ep0_state = AO_USB_EP0_DATA_IN; + else + ao_usb_ep0_state = AO_USB_EP0_IDLE; + } else { + if (ao_usb_setup.length) + ao_usb_ep0_state = AO_USB_EP0_DATA_OUT; + else + ao_usb_ep0_state = AO_USB_EP0_IDLE; + } + USBINDEX = 0; + if (ao_usb_ep0_state == AO_USB_EP0_IDLE) + USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END; + else + USBCS0 = USBCS0_CLR_OUTPKT_RDY; + + ao_usb_ep0_in_data = ao_usb_ep0_in_buf; + ao_usb_ep0_in_len = 0; + switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_TYPE_MASK) { + case AO_USB_TYPE_STANDARD: + switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_RECIP_MASK) { + case AO_USB_RECIP_DEVICE: + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + ao_usb_ep0_queue_byte(0); + ao_usb_ep0_queue_byte(0); + break; + case AO_USB_REQ_SET_ADDRESS: + ao_usb_set_address(ao_usb_setup.value); + break; + case AO_USB_REQ_GET_DESCRIPTOR: + ao_usb_get_descriptor(ao_usb_setup.value); + break; + case AO_USB_REQ_GET_CONFIGURATION: + ao_usb_ep0_queue_byte(ao_usb_configuration); + break; + case AO_USB_REQ_SET_CONFIGURATION: + ao_usb_configuration = ao_usb_setup.value; + ao_usb_set_configuration(); + break; + } + 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); + ao_usb_ep0_queue_byte(0); + break; + case AO_USB_REQ_GET_INTERFACE: + ao_usb_ep0_queue_byte(0); + break; + case AO_USB_REQ_SET_INTERFACE: + break; + } + break; + case AO_USB_RECIP_ENDPOINT: + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + ao_usb_ep0_queue_byte(0); + ao_usb_ep0_queue_byte(0); + break; + } + break; + } + break; + case AO_USB_TYPE_CLASS: + switch (ao_usb_setup.request) { + case SET_LINE_CODING: + ao_usb_ep0_out_len = 7; + ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_line_coding; + break; + case GET_LINE_CODING: + ao_usb_ep0_in_len = 7; + ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding; + break; + case SET_CONTROL_LINE_STATE: + break; + } + break; + } + if (ao_usb_ep0_state != AO_USB_EP0_DATA_OUT) { + if (ao_usb_setup.length < ao_usb_ep0_in_len) + ao_usb_ep0_in_len = ao_usb_setup.length; + ao_usb_ep0_flush(); + } +} + +/* End point 0 receives all of the control messages. */ +static void +ao_usb_ep0(void) +{ + __pdata uint8_t cs0; + + ao_usb_ep0_state = AO_USB_EP0_IDLE; + for (;;) { + __critical for (;;) { + if (ao_usb_iif & 1) { + ao_usb_iif &= ~1; + break; + } + ao_sleep(&ao_usb_task); + } + USBINDEX = 0; + cs0 = USBCS0; + if (cs0 & USBCS0_SETUP_END) { + ao_usb_ep0_state = AO_USB_EP0_IDLE; + USBCS0 = USBCS0_CLR_SETUP_END; + } + if (cs0 & USBCS0_SENT_STALL) { + ao_usb_ep0_state = AO_USB_EP0_IDLE; + USBCS0 &= ~USBCS0_SENT_STALL; + } + if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN && + (cs0 & USBCS0_INPKT_RDY) == 0) + { + ao_usb_ep0_flush(); + } + if (cs0 & USBCS0_OUTPKT_RDY) { + switch (ao_usb_ep0_state) { + case AO_USB_EP0_IDLE: + ao_usb_ep0_setup(); + break; + case AO_USB_EP0_DATA_OUT: + ao_usb_ep0_fill(); + if (ao_usb_ep0_out_len == 0) + ao_usb_ep0_state = AO_USB_EP0_IDLE; + USBINDEX = 0; + if (ao_usb_ep0_state == AO_USB_EP0_IDLE) + USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END; + else + USBCS0 = USBCS0_CLR_OUTPKT_RDY; + break; + } + } + } +} + +/* Wait for a free IN buffer */ +static void +ao_usb_in_wait(void) +{ + for (;;) { + USBINDEX = AO_USB_IN_EP; + if ((USBCSIL & USBCSIL_INPKT_RDY) == 0) + break; + ao_sleep(&ao_usb_in_bytes); + } +} + +/* Send the current IN packet */ +static void +ao_usb_in_send(void) +{ + USBINDEX = AO_USB_IN_EP; + USBCSIL |= USBCSIL_INPKT_RDY; + ao_usb_in_bytes_last = ao_usb_in_bytes; + ao_usb_in_bytes = 0; +} + +void +ao_usb_flush(void) __critical +{ + if (!ao_usb_running) + return; + + /* If there are pending bytes, or if the last packet was full, + * send another IN packet + */ + if (ao_usb_in_bytes || (ao_usb_in_bytes_last == AO_USB_IN_SIZE)) { + ao_usb_in_wait(); + ao_usb_in_send(); + } +} + +void +ao_usb_putchar(char c) __critical __reentrant +{ + if (!ao_usb_running) + return; + + ao_usb_in_wait(); + + /* Queue a byte, sending the packet when full */ + USBFIFO[AO_USB_IN_EP << 1] = c; + if (++ao_usb_in_bytes == AO_USB_IN_SIZE) + ao_usb_in_send(); +} + +char +ao_usb_pollchar(void) __critical +{ + char c; + if (ao_usb_out_bytes == 0) { + USBINDEX = AO_USB_OUT_EP; + if ((USBCSOL & USBCSOL_OUTPKT_RDY) == 0) + return AO_READ_AGAIN; + ao_usb_out_bytes = (USBCNTH << 8) | USBCNTL; + if (ao_usb_out_bytes == 0) { + USBINDEX = AO_USB_OUT_EP; + USBCSOL &= ~USBCSOL_OUTPKT_RDY; + return AO_READ_AGAIN; + } + } + --ao_usb_out_bytes; + c = USBFIFO[AO_USB_OUT_EP << 1]; + if (ao_usb_out_bytes == 0) { + USBINDEX = AO_USB_OUT_EP; + USBCSOL &= ~USBCSOL_OUTPKT_RDY; + } + return c; +} + +char +ao_usb_getchar(void) __critical +{ + char c; + + while ((c = ao_usb_pollchar()) == AO_READ_AGAIN) + ao_sleep(&ao_stdin_ready); + return c; +} + +void +ao_usb_enable(void) +{ + /* Turn on the USB controller */ + SLEEP |= SLEEP_USB_EN; + + ao_usb_set_configuration(); + + ao_usb_set_interrupts(); + + /* enable USB interrupts */ + IEN2 |= IEN2_USBIE; + + /* Clear any pending interrupts */ + USBCIF = 0; + USBOIF = 0; + USBIIF = 0; +} + +void +ao_usb_disable(void) +{ + /* Disable USB interrupts */ + USBIIE = 0; + USBOIE = 0; + USBCIE = 0; + IEN2 &= ~IEN2_USBIE; + + /* Clear any pending interrupts */ + USBCIF = 0; + USBOIF = 0; + USBIIF = 0; + + /* Turn off the USB controller */ + SLEEP &= ~SLEEP_USB_EN; +} + +void +ao_usb_init(void) +{ + ao_usb_enable(); + + ao_add_task(&ao_usb_task, ao_usb_ep0, "usb"); + ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); +} diff --git a/src/cc1111/ao_usb.h b/src/cc1111/ao_usb.h new file mode 100644 index 00000000..6633dafc --- /dev/null +++ b/src/cc1111/ao_usb.h @@ -0,0 +1,100 @@ +/* + * 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. + */ + +#ifndef _AO_USB_H_ +#define _AO_USB_H_ + +#define AO_USB_SETUP_DIR_MASK (0x01 << 7) +#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) +#define AO_USB_SETUP_RECIP_MASK (0x1f) + +#define AO_USB_DIR_OUT 0 +#define AO_USB_DIR_IN (1 << 7) + +#define AO_USB_TYPE_STANDARD 0 +#define AO_USB_TYPE_CLASS (1 << 5) +#define AO_USB_TYPE_VENDOR (2 << 5) +#define AO_USB_TYPE_RESERVED (3 << 5) + +#define AO_USB_RECIP_DEVICE 0 +#define AO_USB_RECIP_INTERFACE 1 +#define AO_USB_RECIP_ENDPOINT 2 +#define AO_USB_RECIP_OTHER 3 + +/* standard requests */ +#define AO_USB_REQ_GET_STATUS 0x00 +#define AO_USB_REQ_CLEAR_FEATURE 0x01 +#define AO_USB_REQ_SET_FEATURE 0x03 +#define AO_USB_REQ_SET_ADDRESS 0x05 +#define AO_USB_REQ_GET_DESCRIPTOR 0x06 +#define AO_USB_REQ_SET_DESCRIPTOR 0x07 +#define AO_USB_REQ_GET_CONFIGURATION 0x08 +#define AO_USB_REQ_SET_CONFIGURATION 0x09 +#define AO_USB_REQ_GET_INTERFACE 0x0A +#define AO_USB_REQ_SET_INTERFACE 0x0B +#define AO_USB_REQ_SYNCH_FRAME 0x0C + +#define AO_USB_DESC_DEVICE 1 +#define AO_USB_DESC_CONFIGURATION 2 +#define AO_USB_DESC_STRING 3 +#define AO_USB_DESC_INTERFACE 4 +#define AO_USB_DESC_ENDPOINT 5 +#define AO_USB_DESC_DEVICE_QUALIFIER 6 +#define AO_USB_DESC_OTHER_SPEED 7 +#define AO_USB_DESC_INTERFACE_POWER 8 + +#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) +#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) + +#define AO_USB_CONTROL_EP 0 +#define AO_USB_INT_EP 1 +#define AO_USB_OUT_EP 4 +#define AO_USB_IN_EP 5 +#define AO_USB_CONTROL_SIZE 32 +/* + * Double buffer IN and OUT EPs, so each + * gets half of the available space + * + * Ah, but USB bulk packets can only come in 8, 16, 32 and 64 + * byte sizes, so we'll use 64 for everything + */ +#define AO_USB_IN_SIZE 64 +#define AO_USB_OUT_SIZE 64 + +#define AO_USB_EP0_IDLE 0 +#define AO_USB_EP0_DATA_IN 1 +#define AO_USB_EP0_DATA_OUT 2 + +#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) + +/* CDC definitions */ +#define CS_INTERFACE 0x24 +#define CS_ENDPOINT 0x25 + +#define SET_LINE_CODING 0x20 +#define GET_LINE_CODING 0x21 +#define SET_CONTROL_LINE_STATE 0x22 + +/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ +struct ao_usb_line_coding { + uint32_t rate; + uint8_t char_format; + uint8_t parity; + uint8_t data_bits; +} ; + +#endif /* _AO_USB_H_ */ diff --git a/src/cc1111/cc1111.h b/src/cc1111/cc1111.h new file mode 100644 index 00000000..e52aa79f --- /dev/null +++ b/src/cc1111/cc1111.h @@ -0,0 +1,1306 @@ +/*------------------------------------------------------------------------- + Register Declarations for the ChipCon CC1111 Processor Range + + Copyright © 2008 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. + + Adapted from the Cygnal C8051F12x config file which is: + + Copyright (C) 2003 - Maarten Brock, sourceforge.brock@dse.nl + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +-------------------------------------------------------------------------*/ + +#ifndef _CC1111_H_ +#define _CC1111_H_ +#include +#include + +__sfr __at 0xA8 IEN0; /* Interrupt Enable 0 Register */ + +sbit __at 0xA8 RFTXRXIE; /* RF TX/RX done interrupt enable */ +sbit __at 0xA9 ADCIE; /* ADC interrupt enable */ +sbit __at 0xAA URX0IE; /* USART0 RX interrupt enable */ +sbit __at 0xAB URX1IE; /* USART1 RX interrupt enable (shared with I2S RX) */ +sbit __at 0xAB I2SRXIE; /* I2S RX interrupt enable (shared with USART1 RX) */ +sbit __at 0xAC ENCIE; /* AES encryption/decryption interrupt enable */ +sbit __at 0xAD STIE; /* Sleep Timer interrupt enable */ +sbit __at 0xAF EA; /* Enable All */ + +#define IEN0_EA (1 << 7) +#define IEN0_STIE (1 << 5) +#define IEN0_ENCIE (1 << 4) +#define IEN0_URX1IE (1 << 3) +#define IEN0_I2SRXIE (1 << 3) +#define IEN0_URX0IE (1 << 2) +#define IEN0_ADCIE (1 << 1) +#define IEN0_RFTXRXIE (1 << 0) + +__sfr __at 0xB8 IEN1; /* Interrupt Enable 1 Register */ + +#define IEN1_P0IE (1 << 5) /* Port 0 interrupt enable */ +#define IEN1_T4IE (1 << 4) /* Timer 4 interrupt enable */ +#define IEN1_T3IE (1 << 3) /* Timer 3 interrupt enable */ +#define IEN1_T2IE (1 << 2) /* Timer 2 interrupt enable */ +#define IEN1_T1IE (1 << 1) /* Timer 1 interrupt enable */ +#define IEN1_DMAIE (1 << 0) /* DMA transfer interrupt enable */ + +/* IEN2 */ +__sfr __at 0x9A IEN2; /* Interrupt Enable 2 Register */ + +#define IEN2_WDTIE (1 << 5) /* Watchdog timer interrupt enable */ +#define IEN2_P1IE (1 << 4) /* Port 1 interrupt enable */ +#define IEN2_UTX1IE (1 << 3) /* USART1 TX interrupt enable */ +#define IEN2_I2STXIE (1 << 3) /* I2S TX interrupt enable */ +#define IEN2_UTX0IE (1 << 2) /* USART0 TX interrupt enable */ +#define IEN2_P2IE (1 << 1) /* Port 2 interrupt enable */ +#define IEN2_USBIE (1 << 1) /* USB interrupt enable */ +#define IEN2_RFIE (1 << 0) /* RF general interrupt enable */ + +/* CLKCON 0xC6 */ +__sfr __at 0xC6 CLKCON; /* Clock Control */ + +#define CLKCON_OSC32K_RC (1 << 7) +#define CLKCON_OSC32K_XTAL (0 << 7) +#define CLKCON_OSC32K_MASK (1 << 7) +#define CLKCON_OSC_RC (1 << 6) +#define CLKCON_OSC_XTAL (0 << 6) +#define CLKCON_OSC_MASK (1 << 6) +#define CLKCON_TICKSPD_MASK (7 << 3) +# define CLKCON_TICKSPD_1 (0 << 3) +# define CLKCON_TICKSPD_1_2 (1 << 3) +# define CLKCON_TICKSPD_1_4 (2 << 3) +# define CLKCON_TICKSPD_1_8 (3 << 3) +# define CLKCON_TICKSPD_1_16 (4 << 3) +# define CLKCON_TICKSPD_1_32 (5 << 3) +# define CLKCON_TICKSPD_1_64 (6 << 3) +# define CLKCON_TICKSPD_1_128 (7 << 3) + +#define CLKCON_CLKSPD_MASK (7 << 0) +# define CLKCON_CLKSPD_1 (0 << 0) +# define CLKCON_CLKSPD_1_2 (1 << 0) +# define CLKCON_CLKSPD_1_4 (2 << 0) +# define CLKCON_CLKSPD_1_8 (3 << 0) +# define CLKCON_CLKSPD_1_16 (4 << 0) +# define CLKCON_CLKSPD_1_32 (5 << 0) +# define CLKCON_CLKSPD_1_64 (6 << 0) +# define CLKCON_CLKSPD_1_128 (7 << 0) + +/* SLEEP 0xBE */ +#define SLEEP_USB_EN (1 << 7) +#define SLEEP_XOSC_STB (1 << 6) +#define SLEEP_HFRC_STB (1 << 5) +#define SLEEP_RST_POWER (0 << 3) +#define SLEEP_RST_EXTERNAL (1 << 3) +#define SLEEP_RST_WATCHDOG (2 << 3) +#define SLEEP_RST_MASK (3 << 3) +#define SLEEP_OSC_PD (1 << 2) +#define SLEEP_MODE_PM0 (0 << 0) +#define SLEEP_MODE_PM1 (1 << 0) +#define SLEEP_MODE_PM2 (2 << 0) +#define SLEEP_MODE_PM3 (3 << 0) +#define SLEEP_MODE_MASK (3 << 0) + +/* PCON 0x87 */ +__sfr __at 0x87 PCON; /* Power Mode Control Register */ + +#define PCON_IDLE (1 << 0) + +/* + * TCON + */ +__sfr __at 0x88 TCON; /* CPU Interrupt Flag 1 */ + +sbit __at 0x8F URX1IF; /* USART1 RX interrupt flag. Automatically cleared */ +sbit __at 0x8F I2SRXIF; /* I2S RX interrupt flag. Automatically cleared */ +sbit __at 0x8D ADCIF; /* ADC interrupt flag. Automatically cleared */ +sbit __at 0x8B URX0IF; /* USART0 RX interrupt flag. Automatically cleared */ +sbit __at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically cleared */ + +#define TCON_URX1IF (1 << 7) +#define TCON_I2SRXIF (1 << 7) +#define TCON_ADCIF (1 << 5) +#define TCON_URX0IF (1 << 3) +#define TCON_RFTXRXIF (1 << 1) + +/* + * S0CON + */ +__sfr __at 0x98 S0CON; /* CPU Interrupt Flag 2 */ + +sbit __at 0x98 ENCIF_0; /* AES interrupt 0. */ +sbit __at 0x99 ENCIF_1; /* AES interrupt 1. */ + +#define S0CON_ENCIF_1 (1 << 1) +#define S0CON_ENCIF_0 (1 << 0) + +/* + * S1CON + */ +__sfr __at 0x9B S1CON; /* CPU Interrupt Flag 3 */ + +#define S1CON_RFIF_1 (1 << 1) +#define S1CON_RFIF_0 (1 << 0) + +/* + * IRCON + */ +__sfr __at 0xC0 IRCON; /* CPU Interrupt Flag 4 */ + +sbit __at 0xC0 DMAIF; /* DMA complete interrupt flag */ +sbit __at 0xC1 T1IF; /* Timer 1 interrupt flag. Automatically cleared */ +sbit __at 0xC2 T2IF; /* Timer 2 interrupt flag. Automatically cleared */ +sbit __at 0xC3 T3IF; /* Timer 3 interrupt flag. Automatically cleared */ +sbit __at 0xC4 T4IF; /* Timer 4 interrupt flag. Automatically cleared */ +sbit __at 0xC5 P0IF; /* Port0 interrupt flag */ +sbit __at 0xC7 STIF; /* Sleep Timer interrupt flag */ + +#define IRCON_DMAIF (1 << 0) /* DMA complete interrupt flag */ +#define IRCON_T1IF (1 << 1) /* Timer 1 interrupt flag. Automatically cleared */ +#define IRCON_T2IF (1 << 2) /* Timer 2 interrupt flag. Automatically cleared */ +#define IRCON_T3IF (1 << 3) /* Timer 3 interrupt flag. Automatically cleared */ +#define IRCON_T4IF (1 << 4) /* Timer 4 interrupt flag. Automatically cleared */ +#define IRCON_P0IF (1 << 5) /* Port0 interrupt flag */ +#define IRCON_STIF (1 << 7) /* Sleep Timer interrupt flag */ + +/* + * IRCON2 + */ +__sfr __at 0xE8 IRCON2; /* CPU Interrupt Flag 5 */ + +sbit __at 0xE8 USBIF; /* USB interrupt flag (shared with Port2) */ +sbit __at 0xE8 P2IF; /* Port2 interrupt flag (shared with USB) */ +sbit __at 0xE9 UTX0IF; /* USART0 TX interrupt flag */ +sbit __at 0xEA UTX1IF; /* USART1 TX interrupt flag (shared with I2S TX) */ +sbit __at 0xEA I2STXIF; /* I2S TX interrupt flag (shared with USART1 TX) */ +sbit __at 0xEB P1IF; /* Port1 interrupt flag */ +sbit __at 0xEC WDTIF; /* Watchdog timer interrupt flag */ + +#define IRCON2_USBIF (1 << 0) /* USB interrupt flag (shared with Port2) */ +#define IRCON2_P2IF (1 << 0) /* Port2 interrupt flag (shared with USB) */ +#define IRCON2_UTX0IF (1 << 1) /* USART0 TX interrupt flag */ +#define IRCON2_UTX1IF (1 << 2) /* USART1 TX interrupt flag (shared with I2S TX) */ +#define IRCON2_I2STXIF (1 << 2) /* I2S TX interrupt flag (shared with USART1 TX) */ +#define IRCON2_P1IF (1 << 3) /* Port1 interrupt flag */ +#define IRCON2_WDTIF (1 << 4) /* Watchdog timer interrupt flag */ + +/* + * IP1 - Interrupt Priority 1 + */ + +/* + * Interrupt priority groups: + * + * IPG0 RFTXRX RF DMA + * IPG1 ADC T1 P2INT/USB + * IPG2 URX0 T2 UTX0 + * IPG3 URX1/I2SRX T3 UTX1 / I2STX + * IPG4 ENC T4 P1INT + * IPG5 ST P0INT WDT + * + * Priority = (IP1 << 1) | IP0. Higher priority interrupts served first + */ + +__sfr __at 0xB9 IP1; /* Interrupt Priority 1 */ +__sfr __at 0xA9 IP0; /* Interrupt Priority 0 */ + +#define IP1_IPG5 (1 << 5) +#define IP1_IPG4 (1 << 4) +#define IP1_IPG3 (1 << 3) +#define IP1_IPG2 (1 << 2) +#define IP1_IPG1 (1 << 1) +#define IP1_IPG0 (1 << 0) + +#define IP0_IPG5 (1 << 5) +#define IP0_IPG4 (1 << 4) +#define IP0_IPG3 (1 << 3) +#define IP0_IPG2 (1 << 2) +#define IP0_IPG1 (1 << 1) +#define IP0_IPG0 (1 << 0) + +/* + * Timer 1 + */ +#define T1CTL_MODE_SUSPENDED (0 << 0) +#define T1CTL_MODE_FREE (1 << 0) +#define T1CTL_MODE_MODULO (2 << 0) +#define T1CTL_MODE_UP_DOWN (3 << 0) +#define T1CTL_MODE_MASK (3 << 0) +#define T1CTL_DIV_1 (0 << 2) +#define T1CTL_DIV_8 (1 << 2) +#define T1CTL_DIV_32 (2 << 2) +#define T1CTL_DIV_128 (3 << 2) +#define T1CTL_DIV_MASK (3 << 2) +#define T1CTL_OVFIF (1 << 4) +#define T1CTL_CH0IF (1 << 5) +#define T1CTL_CH1IF (1 << 6) +#define T1CTL_CH2IF (1 << 7) + +#define T1CCTL_NO_CAPTURE (0 << 0) +#define T1CCTL_CAPTURE_RISING (1 << 0) +#define T1CCTL_CAPTURE_FALLING (2 << 0) +#define T1CCTL_CAPTURE_BOTH (3 << 0) +#define T1CCTL_CAPTURE_MASK (3 << 0) + +#define T1CCTL_MODE_CAPTURE (0 << 2) +#define T1CCTL_MODE_COMPARE (1 << 2) + +#define T1CTL_CMP_SET (0 << 3) +#define T1CTL_CMP_CLEAR (1 << 3) +#define T1CTL_CMP_TOGGLE (2 << 3) +#define T1CTL_CMP_SET_CLEAR (3 << 3) +#define T1CTL_CMP_CLEAR_SET (4 << 3) + +#define T1CTL_IM_DISABLED (0 << 6) +#define T1CTL_IM_ENABLED (1 << 6) + +#define T1CTL_CPSEL_NORMAL (0 << 7) +#define T1CTL_CPSEL_RF (1 << 7) + +/* + * Timer 3 and Timer 4 + */ + +/* Timer count */ +__sfr __at 0xCA T3CNT; +__sfr __at 0xEA T4CNT; + +/* Timer control */ + +__sfr __at 0xCB T3CTL; +__sfr __at 0xEB T4CTL; + +#define TxCTL_DIV_1 (0 << 5) +#define TxCTL_DIV_2 (1 << 5) +#define TxCTL_DIV_4 (2 << 5) +#define TxCTL_DIV_8 (3 << 5) +#define TxCTL_DIV_16 (4 << 5) +#define TxCTL_DIV_32 (5 << 5) +#define TxCTL_DIV_64 (6 << 5) +#define TxCTL_DIV_128 (7 << 5) +#define TxCTL_START (1 << 4) +#define TxCTL_OVFIM (1 << 3) +#define TxCTL_CLR (1 << 2) +#define TxCTL_MODE_FREE (0 << 0) +#define TxCTL_MODE_DOWN (1 << 0) +#define TxCTL_MODE_MODULO (2 << 0) +#define TxCTL_MODE_UP_DOWN (3 << 0) + +/* Timer 4 channel 0 compare control */ + +__sfr __at 0xCC T3CCTL0; +__sfr __at 0xCE T3CCTL1; +__sfr __at 0xEC T4CCTL0; +__sfr __at 0xEE T4CCTL1; + +#define TxCCTLy_IM (1 << 6) +#define TxCCTLy_CMP_SET (0 << 3) +#define TxCCTLy_CMP_CLEAR (1 << 3) +#define TxCCTLy_CMP_TOGGLE (2 << 3) +#define TxCCTLy_CMP_SET_UP_CLEAR_DOWN (3 << 3) +#define TxCCTLy_CMP_CLEAR_UP_SET_DOWN (4 << 3) +#define TxCCTLy_CMP_SET_CLEAR_FF (5 << 3) +#define TxCCTLy_CMP_CLEAR_SET_00 (6 << 3) +#define TxCCTLy_CMP_MODE_ENABLE (1 << 2) + +/* Timer compare value */ +__sfr __at 0xCD T3CC0; +__sfr __at 0xCF T3CC1; +__sfr __at 0xED T4CC0; +__sfr __at 0xEF T4CC1; + +/* + * Peripheral control + */ + +__sfr __at 0xf1 PERCFG; +#define PERCFG_T1CFG_ALT_1 (0 << 6) +#define PERCFG_T1CFG_ALT_2 (1 << 6) +#define PERCFG_T1CFG_ALT_MASK (1 << 6) + +#define PERCFG_T3CFG_ALT_1 (0 << 5) +#define PERCFG_T3CFG_ALT_2 (1 << 5) +#define PERCFG_T3CFG_ALT_MASK (1 << 5) + +#define PERCFG_T4CFG_ALT_1 (0 << 4) +#define PERCFG_T4CFG_ALT_2 (1 << 4) +#define PERCFG_T4CFG_ALT_MASK (1 << 4) + +#define PERCFG_U1CFG_ALT_1 (0 << 1) +#define PERCFG_U1CFG_ALT_2 (1 << 1) +#define PERCFG_U1CFG_ALT_MASK (1 << 1) + +#define PERCFG_U0CFG_ALT_1 (0 << 0) +#define PERCFG_U0CFG_ALT_2 (1 << 0) +#define PERCFG_U0CFG_ALT_MASK (1 << 0) + +/* directly addressed USB registers */ +__xdata __at (0xde00) volatile uint8_t USBADDR; +__xdata __at (0xde01) volatile uint8_t USBPOW; +__xdata __at (0xde02) volatile uint8_t USBIIF; + +__xdata __at (0xde04) volatile uint8_t USBOIF; + +__xdata __at (0xde06) volatile uint8_t USBCIF; + +# define USBCIF_SOFIF (1 << 3) +# define USBCIF_RSTIF (1 << 2) +# define USBCIF_RESUMEIF (1 << 1) +# define USBCIF_SUSPENDIF (1 << 0) + +__xdata __at (0xde07) volatile uint8_t USBIIE; + +__xdata __at (0xde09) volatile uint8_t USBOIE; + +__xdata __at (0xde0b) volatile uint8_t USBCIE; + +# define USBCIE_SOFIE (1 << 3) +# define USBCIE_RSTIE (1 << 2) +# define USBCIE_RESUMEIE (1 << 1) +# define USBCIE_SUSPENDIE (1 << 0) + +__xdata __at (0xde0c) volatile uint8_t USBFRML; +__xdata __at (0xde0d) volatile uint8_t USBFRMH; +__xdata __at (0xde0e) volatile uint8_t USBINDEX; + +/* indexed USB registers, must set USBINDEX to 0-5 */ +__xdata __at (0xde10) volatile uint8_t USBMAXI; +__xdata __at (0xde11) volatile uint8_t USBCS0; + +# define USBCS0_CLR_SETUP_END (1 << 7) +# define USBCS0_CLR_OUTPKT_RDY (1 << 6) +# define USBCS0_SEND_STALL (1 << 5) +# define USBCS0_SETUP_END (1 << 4) +# define USBCS0_DATA_END (1 << 3) +# define USBCS0_SENT_STALL (1 << 2) +# define USBCS0_INPKT_RDY (1 << 1) +# define USBCS0_OUTPKT_RDY (1 << 0) + +__xdata __at (0xde11) volatile uint8_t USBCSIL; + +# define USBCSIL_CLR_DATA_TOG (1 << 6) +# define USBCSIL_SENT_STALL (1 << 5) +# define USBCSIL_SEND_STALL (1 << 4) +# define USBCSIL_FLUSH_PACKET (1 << 3) +# define USBCSIL_UNDERRUN (1 << 2) +# define USBCSIL_PKT_PRESENT (1 << 1) +# define USBCSIL_INPKT_RDY (1 << 0) + +__xdata __at (0xde12) volatile uint8_t USBCSIH; + +# define USBCSIH_AUTOSET (1 << 7) +# define USBCSIH_ISO (1 << 6) +# define USBCSIH_FORCE_DATA_TOG (1 << 3) +# define USBCSIH_IN_DBL_BUF (1 << 0) + +__xdata __at (0xde13) volatile uint8_t USBMAXO; +__xdata __at (0xde14) volatile uint8_t USBCSOL; + +# define USBCSOL_CLR_DATA_TOG (1 << 7) +# define USBCSOL_SENT_STALL (1 << 6) +# define USBCSOL_SEND_STALL (1 << 5) +# define USBCSOL_FLUSH_PACKET (1 << 4) +# define USBCSOL_DATA_ERROR (1 << 3) +# define USBCSOL_OVERRUN (1 << 2) +# define USBCSOL_FIFO_FULL (1 << 1) +# define USBCSOL_OUTPKT_RDY (1 << 0) + +__xdata __at (0xde15) volatile uint8_t USBCSOH; + +# define USBCSOH_AUTOCLEAR (1 << 7) +# define USBCSOH_ISO (1 << 6) +# define USBCSOH_OUT_DBL_BUF (1 << 0) + +__xdata __at (0xde16) volatile uint8_t USBCNT0; +__xdata __at (0xde16) volatile uint8_t USBCNTL; +__xdata __at (0xde17) volatile uint8_t USBCNTH; + +__xdata __at (0xde20) volatile uint8_t USBFIFO[12]; + +/* ADC Data register, low and high */ +__sfr at 0xBA ADCL; +__sfr at 0xBB ADCH; +__xdata __at (0xDFBA) volatile uint16_t ADCXDATA; + +/* ADC Control Register 1 */ +__sfr at 0xB4 ADCCON1; + +# define ADCCON1_EOC (1 << 7) /* conversion complete */ +# define ADCCON1_ST (1 << 6) /* start conversion */ + +# define ADCCON1_STSEL_MASK (3 << 4) /* start select */ +# define ADCCON1_STSEL_EXTERNAL (0 << 4) /* P2_0 pin triggers */ +# define ADCCON1_STSEL_FULLSPEED (1 << 4) /* full speed, no waiting */ +# define ADCCON1_STSEL_TIMER1 (2 << 4) /* timer 1 channel 0 */ +# define ADCCON1_STSEL_START (3 << 4) /* set start bit */ + +# define ADCCON1_RCTRL_MASK (3 << 2) /* random number control */ +# define ADCCON1_RCTRL_COMPLETE (0 << 2) /* operation completed */ +# define ADCCON1_RCTRL_CLOCK_LFSR (1 << 2) /* Clock the LFSR once */ + +/* ADC Control Register 2 */ +__sfr at 0xB5 ADCCON2; + +# define ADCCON2_SREF_MASK (3 << 6) /* reference voltage */ +# define ADCCON2_SREF_1_25V (0 << 6) /* internal 1.25V */ +# define ADCCON2_SREF_EXTERNAL (1 << 6) /* external on AIN7 cc1110 */ +# define ADCCON2_SREF_VDD (2 << 6) /* VDD on the AVDD pin */ +# define ADCCON2_SREF_EXTERNAL_DIFF (3 << 6) /* external on AIN6-7 cc1110 */ + +# define ADCCON2_SDIV_MASK (3 << 4) /* decimation rate */ +# define ADCCON2_SDIV_64 (0 << 4) /* 7 bits */ +# define ADCCON2_SDIV_128 (1 << 4) /* 9 bits */ +# define ADCCON2_SDIV_256 (2 << 4) /* 10 bits */ +# define ADCCON2_SDIV_512 (3 << 4) /* 12 bits */ + +# define ADCCON2_SCH_MASK (0xf << 0) /* Sequence channel select */ +# define ADCCON2_SCH_SHIFT 0 +# define ADCCON2_SCH_AIN0 (0 << 0) +# define ADCCON2_SCH_AIN1 (1 << 0) +# define ADCCON2_SCH_AIN2 (2 << 0) +# define ADCCON2_SCH_AIN3 (3 << 0) +# define ADCCON2_SCH_AIN4 (4 << 0) +# define ADCCON2_SCH_AIN5 (5 << 0) +# define ADCCON2_SCH_AIN6 (6 << 0) +# define ADCCON2_SCH_AIN7 (7 << 0) +# define ADCCON2_SCH_AIN0_AIN1 (8 << 0) +# define ADCCON2_SCH_AIN2_AIN3 (9 << 0) +# define ADCCON2_SCH_AIN4_AIN5 (0xa << 0) +# define ADCCON2_SCH_AIN6_AIN7 (0xb << 0) +# define ADCCON2_SCH_GND (0xc << 0) +# define ADCCON2_SCH_VREF (0xd << 0) +# define ADCCON2_SCH_TEMP (0xe << 0) +# define ADCCON2_SCH_VDD_3 (0xf << 0) + + +/* ADC Control Register 3 */ +__sfr at 0xB6 ADCCON3; + +# define ADCCON3_EREF_MASK (3 << 6) /* extra conversion reference */ +# define ADCCON3_EREF_1_25 (0 << 6) /* internal 1.25V */ +# define ADCCON3_EREF_EXTERNAL (1 << 6) /* external AIN7 cc1110 */ +# define ADCCON3_EREF_VDD (2 << 6) /* VDD on the AVDD pin */ +# define ADCCON3_EREF_EXTERNAL_DIFF (3 << 6) /* external AIN6-7 cc1110 */ +# define ADCCON3_EDIV_MASK (3 << 4) /* extral decimation */ +# define ADCCON3_EDIV_64 (0 << 4) /* 7 bits */ +# define ADCCON3_EDIV_128 (1 << 4) /* 9 bits */ +# define ADCCON3_EDIV_256 (2 << 4) /* 10 bits */ +# define ADCCON3_EDIV_512 (3 << 4) /* 12 bits */ +# define ADCCON3_ECH_MASK (0xf << 0) /* Sequence channel select */ +# define ADCCON3_ECH_SHIFT 0 +# define ADCCON3_ECH_AIN0 (0 << 0) +# define ADCCON3_ECH_AIN1 (1 << 0) +# define ADCCON3_ECH_AIN2 (2 << 0) +# define ADCCON3_ECH_AIN3 (3 << 0) +# define ADCCON3_ECH_AIN4 (4 << 0) +# define ADCCON3_ECH_AIN5 (5 << 0) +# define ADCCON3_ECH_AIN6 (6 << 0) +# define ADCCON3_ECH_AIN7 (7 << 0) +# define ADCCON3_ECH_AIN0_AIN1 (8 << 0) +# define ADCCON3_ECH_AIN2_AIN3 (9 << 0) +# define ADCCON3_ECH_AIN4_AIN5 (0xa << 0) +# define ADCCON3_ECH_AIN6_AIN7 (0xb << 0) +# define ADCCON3_ECH_GND (0xc << 0) +# define ADCCON3_ECH_VREF (0xd << 0) +# define ADCCON3_ECH_TEMP (0xe << 0) +# define ADCCON3_ECH_VDD_3 (0xf << 0) + +/* + * ADC configuration register, this selects which + * GPIO pins are to be used as ADC inputs + */ +__sfr at 0xF2 ADCCFG; + +/* + * Watchdog timer + */ + +__sfr at 0xc9 WDCTL; + +#define WDCTL_CLEAR_FIRST (0xa << 4) +#define WDCTL_CLEAR_SECOND (0x5 << 4) +#define WDCTL_EN (1 << 3) +#define WDCTL_MODE_WATCHDOG (0 << 2) +#define WDCTL_MODE_TIMER (1 << 2) +#define WDCTL_MODE_MASK (1 << 2) +#define WDCTL_INT_32768 (0 << 0) +#define WDCTL_INT_8192 (1 << 0) +#define WDCTL_INT_512 (2 << 0) +#define WDCTL_INT_64 (3 << 0) + +/* + * Pin selectors, these set which pins are + * using their peripheral function + */ +__sfr at 0xF3 P0SEL; +__sfr at 0xF4 P1SEL; +__sfr at 0xF5 P2SEL; + +#define P2SEL_PRI3P1_USART0 (0 << 6) +#define P2SEL_PRI3P1_USART1 (1 << 6) +#define P2SEL_PRI3P1_MASK (1 << 6) +#define P2SEL_PRI2P1_USART1 (0 << 5) +#define P2SEL_PRI2P1_TIMER3 (1 << 5) +#define P2SEL_PRI2P1_MASK (1 << 5) +#define P2SEL_PRI1P1_TIMER1 (0 << 4) +#define P2SEL_PRI1P1_TIMER4 (1 << 4) +#define P2SEL_PRI1P1_MASK (1 << 4) +#define P2SEL_PRI0P1_USART0 (0 << 3) +#define P2SEL_PRI0P1_TIMER1 (1 << 3) +#define P2SEL_PRI0P1_MASK (1 << 3) +#define P2SEL_SELP2_4_GPIO (0 << 2) +#define P2SEL_SELP2_4_PERIPHERAL (1 << 2) +#define P2SEL_SELP2_4_MASK (1 << 2) +#define P2SEL_SELP2_3_GPIO (0 << 1) +#define P2SEL_SELP2_3_PERIPHERAL (1 << 1) +#define P2SEL_SELP2_3_MASK (1 << 1) +#define P2SEL_SELP2_0_GPIO (0 << 0) +#define P2SEL_SELP2_0_PERIPHERAL (1 << 0) +#define P2SEL_SELP2_0_MASK (1 << 0) + +/* + * For pins used as GPIOs, these set which are used as outputs + */ +__sfr at 0xFD P0DIR; +__sfr at 0xFE P1DIR; +__sfr at 0xFF P2DIR; + +#define P2DIR_PRIP0_USART0_USART1 (0 << 6) +#define P2DIR_PRIP0_USART1_USART0 (1 << 6) +#define P2DIR_PRIP0_TIMER1_01_USART1 (2 << 6) +#define P2DIR_PRIP0_TIMER1_2_USART0 (3 << 6) +#define P2DIR_PRIP0_MASK (3 << 6) + +__sfr at 0x8F P0INP; + +/* Select between tri-state and pull up/down + * for pins P0_0 - P0_7. + */ +#define P0INP_MDP0_7_PULL (0 << 7) +#define P0INP_MDP0_7_TRISTATE (1 << 7) +#define P0INP_MDP0_6_PULL (0 << 6) +#define P0INP_MDP0_6_TRISTATE (1 << 6) +#define P0INP_MDP0_5_PULL (0 << 5) +#define P0INP_MDP0_5_TRISTATE (1 << 5) +#define P0INP_MDP0_4_PULL (0 << 4) +#define P0INP_MDP0_4_TRISTATE (1 << 4) +#define P0INP_MDP0_3_PULL (0 << 3) +#define P0INP_MDP0_3_TRISTATE (1 << 3) +#define P0INP_MDP0_2_PULL (0 << 2) +#define P0INP_MDP0_2_TRISTATE (1 << 2) +#define P0INP_MDP0_1_PULL (0 << 1) +#define P0INP_MDP0_1_TRISTATE (1 << 1) +#define P0INP_MDP0_0_PULL (0 << 0) +#define P0INP_MDP0_0_TRISTATE (1 << 0) + +__sfr at 0xF6 P1INP; + +/* Select between tri-state and pull up/down + * for pins P1_2 - P1_7. Pins P1_0 and P1_1 are + * always tri-stated + */ +#define P1INP_MDP1_7_PULL (0 << 7) +#define P1INP_MDP1_7_TRISTATE (1 << 7) +#define P1INP_MDP1_6_PULL (0 << 6) +#define P1INP_MDP1_6_TRISTATE (1 << 6) +#define P1INP_MDP1_5_PULL (0 << 5) +#define P1INP_MDP1_5_TRISTATE (1 << 5) +#define P1INP_MDP1_4_PULL (0 << 4) +#define P1INP_MDP1_4_TRISTATE (1 << 4) +#define P1INP_MDP1_3_PULL (0 << 3) +#define P1INP_MDP1_3_TRISTATE (1 << 3) +#define P1INP_MDP1_2_PULL (0 << 2) +#define P1INP_MDP1_2_TRISTATE (1 << 2) + +__sfr at 0xF7 P2INP; +/* P2INP has three extra bits which are used to choose + * between pull-up and pull-down when they are not tri-stated + */ +#define P2INP_PDUP2_PULL_UP (0 << 7) +#define P2INP_PDUP2_PULL_DOWN (1 << 7) +#define P2INP_PDUP1_PULL_UP (0 << 6) +#define P2INP_PDUP1_PULL_DOWN (1 << 6) +#define P2INP_PDUP0_PULL_UP (0 << 5) +#define P2INP_PDUP0_PULL_DOWN (1 << 5) + +/* For the P2 pins, choose between tri-state and pull up/down + * mode + */ +#define P2INP_MDP2_4_PULL (0 << 4) +#define P2INP_MDP2_4_TRISTATE (1 << 4) +#define P2INP_MDP2_3_PULL (0 << 3) +#define P2INP_MDP2_3_TRISTATE (1 << 3) +#define P2INP_MDP2_2_PULL (0 << 2) +#define P2INP_MDP2_2_TRISTATE (1 << 2) +#define P2INP_MDP2_1_PULL (0 << 1) +#define P2INP_MDP2_1_TRISTATE (1 << 1) +#define P2INP_MDP2_0_PULL (0 << 0) +#define P2INP_MDP2_0_TRISTATE (1 << 0) + +/* GPIO interrupt status flags */ +__sfr at 0x89 P0IFG; +__sfr at 0x8A P1IFG; +__sfr at 0x8B P2IFG; + +#define P0IFG_USB_RESUME (1 << 7) + +__sfr at 0x8C PICTL; +#define PICTL_P2IEN (1 << 5) +#define PICTL_P0IENH (1 << 4) +#define PICTL_P0IENL (1 << 3) +#define PICTL_P2ICON (1 << 2) +#define PICTL_P1ICON (1 << 1) +#define PICTL_P0ICON (1 << 0) + +/* GPIO pins */ +__sfr at 0x80 P0; + +sbit at 0x80 P0_0; +sbit at 0x81 P0_1; +sbit at 0x82 P0_2; +sbit at 0x83 P0_3; +sbit at 0x84 P0_4; +sbit at 0x85 P0_5; +sbit at 0x86 P0_6; +sbit at 0x87 P0_7; + +__sfr at 0x90 P1; + +sbit at 0x90 P1_0; +sbit at 0x91 P1_1; +sbit at 0x92 P1_2; +sbit at 0x93 P1_3; +sbit at 0x94 P1_4; +sbit at 0x95 P1_5; +sbit at 0x96 P1_6; +sbit at 0x97 P1_7; + +__sfr at 0xa0 P2; + +sbit at 0xa0 P2_0; +sbit at 0xa1 P2_1; +sbit at 0xa2 P2_2; +sbit at 0xa3 P2_3; +sbit at 0xa4 P2_4; + +/* DMA controller */ +struct cc_dma_channel { + uint8_t src_high; + uint8_t src_low; + uint8_t dst_high; + uint8_t dst_low; + uint8_t len_high; + uint8_t len_low; + uint8_t cfg0; + uint8_t cfg1; +}; + +# define DMA_LEN_HIGH_VLEN_MASK (7 << 5) +# define DMA_LEN_HIGH_VLEN_LEN (0 << 5) +# define DMA_LEN_HIGH_VLEN_PLUS_1 (1 << 5) +# define DMA_LEN_HIGH_VLEN (2 << 5) +# define DMA_LEN_HIGH_VLEN_PLUS_2 (3 << 5) +# define DMA_LEN_HIGH_VLEN_PLUS_3 (4 << 5) +# define DMA_LEN_HIGH_MASK (0x1f) + +# define DMA_CFG0_WORDSIZE_8 (0 << 7) +# define DMA_CFG0_WORDSIZE_16 (1 << 7) +# define DMA_CFG0_TMODE_MASK (3 << 5) +# define DMA_CFG0_TMODE_SINGLE (0 << 5) +# define DMA_CFG0_TMODE_BLOCK (1 << 5) +# define DMA_CFG0_TMODE_REPEATED_SINGLE (2 << 5) +# define DMA_CFG0_TMODE_REPEATED_BLOCK (3 << 5) + +/* + * DMA triggers + */ +# define DMA_CFG0_TRIGGER_NONE 0 +# define DMA_CFG0_TRIGGER_PREV 1 +# define DMA_CFG0_TRIGGER_T1_CH0 2 +# define DMA_CFG0_TRIGGER_T1_CH1 3 +# define DMA_CFG0_TRIGGER_T1_CH2 4 +# define DMA_CFG0_TRIGGER_T2_OVFL 6 +# define DMA_CFG0_TRIGGER_T3_CH0 7 +# define DMA_CFG0_TRIGGER_T3_CH1 8 +# define DMA_CFG0_TRIGGER_T4_CH0 9 +# define DMA_CFG0_TRIGGER_T4_CH1 10 +# define DMA_CFG0_TRIGGER_IOC_0 12 +# define DMA_CFG0_TRIGGER_IOC_1 13 +# define DMA_CFG0_TRIGGER_URX0 14 +# define DMA_CFG0_TRIGGER_UTX0 15 +# define DMA_CFG0_TRIGGER_URX1 16 +# define DMA_CFG0_TRIGGER_UTX1 17 +# define DMA_CFG0_TRIGGER_FLASH 18 +# define DMA_CFG0_TRIGGER_RADIO 19 +# define DMA_CFG0_TRIGGER_ADC_CHALL 20 +# define DMA_CFG0_TRIGGER_ADC_CH0 21 +# define DMA_CFG0_TRIGGER_ADC_CH1 22 +# define DMA_CFG0_TRIGGER_ADC_CH2 23 +# define DMA_CFG0_TRIGGER_ADC_CH3 24 +# define DMA_CFG0_TRIGGER_ADC_CH4 25 +# define DMA_CFG0_TRIGGER_ADC_CH5 26 +# define DMA_CFG0_TRIGGER_ADC_CH6 27 +# define DMA_CFG0_TRIGGER_I2SRX 27 +# define DMA_CFG0_TRIGGER_ADC_CH7 28 +# define DMA_CFG0_TRIGGER_I2STX 28 +# define DMA_CFG0_TRIGGER_ENC_DW 29 +# define DMA_CFG0_TRIGGER_DNC_UP 30 + +# define DMA_CFG1_SRCINC_MASK (3 << 6) +# define DMA_CFG1_SRCINC_0 (0 << 6) +# define DMA_CFG1_SRCINC_1 (1 << 6) +# define DMA_CFG1_SRCINC_2 (2 << 6) +# define DMA_CFG1_SRCINC_MINUS_1 (3 << 6) + +# define DMA_CFG1_DESTINC_MASK (3 << 4) +# define DMA_CFG1_DESTINC_0 (0 << 4) +# define DMA_CFG1_DESTINC_1 (1 << 4) +# define DMA_CFG1_DESTINC_2 (2 << 4) +# define DMA_CFG1_DESTINC_MINUS_1 (3 << 4) + +# define DMA_CFG1_IRQMASK (1 << 3) +# define DMA_CFG1_M8 (1 << 2) + +# define DMA_CFG1_PRIORITY_MASK (3 << 0) +# define DMA_CFG1_PRIORITY_LOW (0 << 0) +# define DMA_CFG1_PRIORITY_NORMAL (1 << 0) +# define DMA_CFG1_PRIORITY_HIGH (2 << 0) + +/* + * DMAARM - DMA Channel Arm + */ + +__sfr at 0xD6 DMAARM; + +# define DMAARM_ABORT (1 << 7) +# define DMAARM_DMAARM4 (1 << 4) +# define DMAARM_DMAARM3 (1 << 3) +# define DMAARM_DMAARM2 (1 << 2) +# define DMAARM_DMAARM1 (1 << 1) +# define DMAARM_DMAARM0 (1 << 0) + +/* + * DMAREQ - DMA Channel Start Request and Status + */ + +__sfr at 0xD7 DMAREQ; + +# define DMAREQ_DMAREQ4 (1 << 4) +# define DMAREQ_DMAREQ3 (1 << 3) +# define DMAREQ_DMAREQ2 (1 << 2) +# define DMAREQ_DMAREQ1 (1 << 1) +# define DMAREQ_DMAREQ0 (1 << 0) + +/* + * DMA configuration 0 address + */ + +__sfr at 0xD5 DMA0CFGH; +__sfr at 0xD4 DMA0CFGL; + +/* + * DMA configuration 1-4 address + */ + +__sfr at 0xD3 DMA1CFGH; +__sfr at 0xD2 DMA1CFGL; + +/* + * DMAIRQ - DMA Interrupt Flag + */ + +__sfr at 0xD1 DMAIRQ; + +# define DMAIRQ_DMAIF4 (1 << 4) +# define DMAIRQ_DMAIF3 (1 << 3) +# define DMAIRQ_DMAIF2 (1 << 2) +# define DMAIRQ_DMAIF1 (1 << 1) +# define DMAIRQ_DMAIF0 (1 << 0) + +/* + * UART registers + */ + +/* USART config/status registers */ +__sfr at 0x86 U0CSR; +__sfr at 0xF8 U1CSR; + +# define UxCSR_MODE_UART (1 << 7) +# define UxCSR_MODE_SPI (0 << 7) +# define UxCSR_RE (1 << 6) +# define UxCSR_SLAVE (1 << 5) +# define UxCSR_MASTER (0 << 5) +# define UxCSR_FE (1 << 4) +# define UxCSR_ERR (1 << 3) +# define UxCSR_RX_BYTE (1 << 2) +# define UxCSR_TX_BYTE (1 << 1) +# define UxCSR_ACTIVE (1 << 0) + +/* UART configuration registers */ +__sfr at 0xc4 U0UCR; +__sfr at 0xfb U1UCR; + +# define UxUCR_FLUSH (1 << 7) +# define UxUCR_FLOW_DISABLE (0 << 6) +# define UxUCR_FLOW_ENABLE (1 << 6) +# define UxUCR_D9_EVEN_PARITY (0 << 5) +# define UxUCR_D9_ODD_PARITY (1 << 5) +# define UxUCR_BIT9_8_BITS (0 << 4) +# define UxUCR_BIT9_9_BITS (1 << 4) +# define UxUCR_PARITY_DISABLE (0 << 3) +# define UxUCR_PARITY_ENABLE (1 << 3) +# define UxUCR_SPB_1_STOP_BIT (0 << 2) +# define UxUCR_SPB_2_STOP_BITS (1 << 2) +# define UxUCR_STOP_LOW (0 << 1) +# define UxUCR_STOP_HIGH (1 << 1) +# define UxUCR_START_LOW (0 << 0) +# define UxUCR_START_HIGH (1 << 0) + +/* USART General configuration registers (mostly SPI) */ +__sfr at 0xc5 U0GCR; +__sfr at 0xfc U1GCR; + +# define UxGCR_CPOL_NEGATIVE (0 << 7) +# define UxGCR_CPOL_POSITIVE (1 << 7) +# define UxGCR_CPHA_FIRST_EDGE (0 << 6) +# define UxGCR_CPHA_SECOND_EDGE (1 << 6) +# define UxGCR_ORDER_LSB (0 << 5) +# define UxGCR_ORDER_MSB (1 << 5) +# define UxGCR_BAUD_E_MASK (0x1f) +# define UxGCR_BAUD_E_SHIFT 0 + +/* USART data registers */ +__sfr at 0xc1 U0DBUF; +__xdata __at (0xDFC1) volatile uint8_t U0DBUFXADDR; +__sfr at 0xf9 U1DBUF; +__xdata __at (0xDFF9) volatile uint8_t U1DBUFXADDR; + +/* USART baud rate registers, M value */ +__sfr at 0xc2 U0BAUD; +__sfr at 0xfa U1BAUD; + +/* Flash controller */ + +__sfr at 0xAE FCTL; +#define FCTL_BUSY (1 << 7) +#define FCTL_SWBSY (1 << 6) +#define FCTL_CONTRD_ENABLE (1 << 4) +#define FCTL_WRITE (1 << 1) +#define FCTL_ERASE (1 << 0) + +/* Flash write data. Write two bytes here */ +__sfr at 0xAF FWDATA; +__xdata __at (0xDFAF) volatile uint8_t FWDATAXADDR; + +/* Flash write/erase address */ +__sfr at 0xAD FADDRH; +__sfr at 0xAC FADDRL; + +/* Flash timing */ +__sfr at 0xAB FWT; + +/* 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 0x91 RFIM; +#define RFIM_IM_TXUNF (1 << 7) +#define RFIM_IM_RXOVF (1 << 6) +#define RFIM_IM_TIMEOUT (1 << 5) +#define RFIM_IM_DONE (1 << 4) +#define RFIM_IM_CS (1 << 3) +#define RFIM_IM_PQT (1 << 2) +#define RFIM_IM_CCA (1 << 1) +#define RFIM_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/src/check-stack b/src/check-stack deleted file mode 100755 index 1e8044e0..00000000 --- a/src/check-stack +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -HEADER=$1 -MEM=$2 - -HEADER_STACK=`awk '/#define AO_STACK_START/ {print strtonum($3)}' $HEADER` -MEM_STACK=`awk '/Stack starts at/ {print strtonum ($4)}' $MEM` - -if [ "$HEADER_STACK" -lt "$MEM_STACK" ]; then - echo $MEM_STACK | awk '{ printf ("Set AO_STACK_START to at least 0x%x\n", $1); }' - exit 1 -else - exit 0 -fi diff --git a/src/core/altitude.h b/src/core/altitude.h new file mode 100644 index 00000000..a278bbc6 --- /dev/null +++ b/src/core/altitude.h @@ -0,0 +1,132 @@ +/*max error 3.197865153490684 at 0.782%. Average error 0.260150920474668*/ +#define NALT 129 +#define ALT_FRAC_BITS 8 + 15835, /* 10.56 kPa 0.000% */ + 15332, /* 11.42 kPa 0.781% */ + 14868, /* 12.29 kPa 1.563% */ + 14435, /* 13.16 kPa 2.344% */ + 14030, /* 14.02 kPa 3.125% */ + 13649, /* 14.90 kPa 3.906% */ + 13290, /* 15.76 kPa 4.688% */ + 12950, /* 16.63 kPa 5.469% */ + 12627, /* 17.50 kPa 6.250% */ + 12320, /* 18.37 kPa 7.031% */ + 12027, /* 19.24 kPa 7.813% */ + 11747, /* 20.10 kPa 8.594% */ + 11479, /* 20.97 kPa 9.375% */ + 11222, /* 21.84 kPa 10.156% */ + 10975, /* 22.71 kPa 10.938% */ + 10736, /* 23.58 kPa 11.719% */ + 10504, /* 24.44 kPa 12.500% */ + 10278, /* 25.31 kPa 13.281% */ + 10059, /* 26.18 kPa 14.063% */ + 9846, /* 27.05 kPa 14.844% */ + 9638, /* 27.91 kPa 15.625% */ + 9435, /* 28.78 kPa 16.406% */ + 9237, /* 29.65 kPa 17.188% */ + 9044, /* 30.52 kPa 17.969% */ + 8855, /* 31.39 kPa 18.750% */ + 8670, /* 32.26 kPa 19.531% */ + 8490, /* 33.13 kPa 20.313% */ + 8313, /* 33.99 kPa 21.094% */ + 8140, /* 34.86 kPa 21.875% */ + 7970, /* 35.73 kPa 22.656% */ + 7803, /* 36.60 kPa 23.438% */ + 7640, /* 37.47 kPa 24.219% */ + 7480, /* 38.33 kPa 25.000% */ + 7322, /* 39.20 kPa 25.781% */ + 7168, /* 40.07 kPa 26.563% */ + 7016, /* 40.94 kPa 27.344% */ + 6867, /* 41.80 kPa 28.125% */ + 6720, /* 42.67 kPa 28.906% */ + 6575, /* 43.54 kPa 29.688% */ + 6433, /* 44.41 kPa 30.469% */ + 6294, /* 45.28 kPa 31.250% */ + 6156, /* 46.15 kPa 32.031% */ + 6020, /* 47.01 kPa 32.813% */ + 5887, /* 47.88 kPa 33.594% */ + 5755, /* 48.75 kPa 34.375% */ + 5625, /* 49.62 kPa 35.156% */ + 5497, /* 50.49 kPa 35.938% */ + 5371, /* 51.35 kPa 36.719% */ + 5247, /* 52.22 kPa 37.500% */ + 5124, /* 53.09 kPa 38.281% */ + 5003, /* 53.96 kPa 39.063% */ + 4883, /* 54.83 kPa 39.844% */ + 4765, /* 55.69 kPa 40.625% */ + 4648, /* 56.56 kPa 41.406% */ + 4533, /* 57.43 kPa 42.188% */ + 4419, /* 58.30 kPa 42.969% */ + 4307, /* 59.17 kPa 43.750% */ + 4196, /* 60.03 kPa 44.531% */ + 4086, /* 60.90 kPa 45.313% */ + 3977, /* 61.77 kPa 46.094% */ + 3870, /* 62.63 kPa 46.875% */ + 3764, /* 63.51 kPa 47.656% */ + 3659, /* 64.38 kPa 48.438% */ + 3555, /* 65.24 kPa 49.219% */ + 3453, /* 66.11 kPa 50.000% */ + 3351, /* 66.98 kPa 50.781% */ + 3250, /* 67.85 kPa 51.563% */ + 3151, /* 68.72 kPa 52.344% */ + 3052, /* 69.58 kPa 53.125% */ + 2955, /* 70.45 kPa 53.906% */ + 2858, /* 71.32 kPa 54.688% */ + 2763, /* 72.19 kPa 55.469% */ + 2668, /* 73.06 kPa 56.250% */ + 2574, /* 73.92 kPa 57.031% */ + 2482, /* 74.79 kPa 57.813% */ + 2390, /* 75.66 kPa 58.594% */ + 2298, /* 76.52 kPa 59.375% */ + 2208, /* 77.40 kPa 60.156% */ + 2119, /* 78.26 kPa 60.938% */ + 2030, /* 79.13 kPa 61.719% */ + 1942, /* 80.00 kPa 62.500% */ + 1855, /* 80.87 kPa 63.281% */ + 1769, /* 81.74 kPa 64.063% */ + 1683, /* 82.60 kPa 64.844% */ + 1598, /* 83.47 kPa 65.625% */ + 1514, /* 84.34 kPa 66.406% */ + 1430, /* 85.21 kPa 67.188% */ + 1347, /* 86.08 kPa 67.969% */ + 1265, /* 86.94 kPa 68.750% */ + 1184, /* 87.81 kPa 69.531% */ + 1103, /* 88.68 kPa 70.313% */ + 1023, /* 89.55 kPa 71.094% */ + 943, /* 90.41 kPa 71.875% */ + 864, /* 91.28 kPa 72.656% */ + 786, /* 92.15 kPa 73.438% */ + 708, /* 93.02 kPa 74.219% */ + 631, /* 93.89 kPa 75.000% */ + 554, /* 94.76 kPa 75.781% */ + 478, /* 95.63 kPa 76.563% */ + 403, /* 96.49 kPa 77.344% */ + 328, /* 97.36 kPa 78.125% */ + 254, /* 98.23 kPa 78.906% */ + 180, /* 99.10 kPa 79.688% */ + 106, /* 99.97 kPa 80.469% */ + 34, /* 100.83 kPa 81.250% */ + -39, /* 101.70 kPa 82.031% */ + -111, /* 102.57 kPa 82.813% */ + -182, /* 103.44 kPa 83.594% */ + -253, /* 104.30 kPa 84.375% */ + -323, /* 105.17 kPa 85.156% */ + -393, /* 106.04 kPa 85.938% */ + -462, /* 106.91 kPa 86.719% */ + -531, /* 107.78 kPa 87.500% */ + -600, /* 108.65 kPa 88.281% */ + -668, /* 109.51 kPa 89.063% */ + -736, /* 110.38 kPa 89.844% */ + -803, /* 111.25 kPa 90.625% */ + -870, /* 112.12 kPa 91.406% */ + -936, /* 112.99 kPa 92.188% */ + -1002, /* 113.85 kPa 92.969% */ + -1068, /* 114.72 kPa 93.750% */ + -1133, /* 115.59 kPa 94.531% */ + -1198, /* 116.46 kPa 95.313% */ + -1262, /* 117.33 kPa 96.094% */ + -1326, /* 118.19 kPa 96.875% */ + -1389, /* 119.06 kPa 97.656% */ + -1453, /* 119.93 kPa 98.438% */ + -1516, /* 120.80 kPa 99.219% */ + -1578, /* 121.67 kPa 100.000% */ diff --git a/src/core/ao.h b/src/core/ao.h new file mode 100644 index 00000000..8ac9ac3d --- /dev/null +++ b/src/core/ao.h @@ -0,0 +1,1610 @@ +/* + * 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. + */ + +#ifndef _AO_H_ +#define _AO_H_ + +#include +#include +#include +#include +#include "cc1111.h" +#include "ao_pins.h" + +#define TRUE 1 +#define FALSE 0 + +/* Convert a __data pointer into an __xdata pointer */ +#define DATA_TO_XDATA(a) ((void __xdata *) ((uint8_t) (a) | 0xff00)) + +/* 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 0x90 +#define AO_STACK_END 0xfe +#define AO_STACK_SIZE (AO_STACK_END - AO_STACK_START + 1) + +/* An AltOS task */ +struct ao_task { + __xdata void *wchan; /* current wait channel (NULL if running) */ + uint16_t alarm; /* abort ao_sleep time */ + uint8_t stack_count; /* amount of saved stack */ + uint8_t task_id; /* unique id */ + __code char *name; /* task name */ + uint8_t stack[AO_STACK_SIZE]; /* saved stack */ +}; + +extern __xdata struct ao_task *__data ao_cur_task; + +#define AO_NUM_TASKS 16 /* maximum number of tasks */ +#define AO_NO_TASK 0 /* no task id */ + +/* + ao_task.c + */ + +/* Suspend the current task until wchan is awoken. + * returns: + * 0 on normal wake + * 1 on alarm + */ +uint8_t +ao_sleep(__xdata void *wchan); + +/* Wake all tasks sleeping on wchan */ +void +ao_wakeup(__xdata void *wchan); + +/* set an alarm to go off in 'delay' ticks */ +void +ao_alarm(uint16_t delay); + +/* Yield the processor to another task */ +void +ao_yield(void) __naked; + +/* Add a task to the run queue */ +void +ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant; + +/* Terminate the current task */ +void +ao_exit(void); + +/* Dump task info to console */ +void +ao_task_info(void); + +/* Start the scheduler. This will not return */ +void +ao_start_scheduler(void); + +/* + * ao_panic.c + */ + +#define AO_PANIC_NO_TASK 1 /* AO_NUM_TASKS is not large enough */ +#define AO_PANIC_DMA 2 /* Attempt to start DMA while active */ +#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 */ +#define AO_PANIC_STDIO 7 /* Too many stdio handlers registered */ +#define AO_PANIC_REBOOT 8 /* Reboot failed */ +#define AO_PANIC_FLASH 9 /* Invalid flash part (or wrong blocksize) */ +#define AO_PANIC_USB 10 /* Trying to send USB packet while busy */ +#define AO_PANIC_BT 11 /* Communications with bluetooth device failed */ + +/* Stop the operating system, beeping and blinking the reason */ +void +ao_panic(uint8_t reason); + +/* + * ao_timer.c + */ + +/* Our timer runs at 100Hz */ +#define AO_HERTZ 100 +#define AO_MS_TO_TICKS(ms) ((ms) / (1000 / AO_HERTZ)) +#define AO_SEC_TO_TICKS(s) ((s) * AO_HERTZ) + +/* Returns the current time in ticks */ +uint16_t +ao_time(void); + +/* Suspend the current task until ticks time has passed */ +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; + +/* Initialize the timer */ +void +ao_timer_init(void); + +/* Initialize the hardware clock. Must be called first */ +void +ao_clock_init(void); + +/* + * One set of samples read from the A/D converter or telemetry + */ +struct ao_adc { + uint16_t tick; /* tick when the sample was read */ + int16_t accel; /* accelerometer */ + int16_t pres; /* pressure sensor */ + int16_t temp; /* temperature sensor */ + int16_t v_batt; /* battery voltage */ + int16_t sense_d; /* drogue continuity sense */ + int16_t sense_m; /* main continuity sense */ +}; + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#if HAS_ADC + +#if HAS_ACCEL +#ifndef HAS_ACCEL_REF +#error Please define HAS_ACCEL_REF +#endif +#else +#define HAS_ACCEL_REF 0 +#endif + +/* + * ao_adc.c + */ + +#define AO_ADC_RING 32 +#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) +#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) + + +/* + * A/D data is stored in a ring, with the next sample to be written + * at ao_adc_head + */ +extern volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; +extern volatile __data uint8_t ao_adc_head; +#if HAS_ACCEL_REF +extern volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; +#endif + +/* Trigger a conversion sequence (called from the timer interrupt) */ +void +ao_adc_poll(void); + +/* Suspend the current task until another A/D sample is converted */ +void +ao_adc_sleep(void); + +/* Get a copy of the last complete A/D sample set */ +void +ao_adc_get(__xdata struct ao_adc *packet); + +/* The A/D interrupt handler */ + +void +ao_adc_isr(void) __interrupt 1; + +/* Initialize the A/D converter */ +void +ao_adc_init(void); + +#endif /* HAS_ADC */ + +/* + * ao_beep.c + */ + +/* + * Various pre-defined beep frequencies + * + * frequency = 1/2 (24e6/32) / beep + */ + +#define AO_BEEP_LOW 150 /* 2500Hz */ +#define AO_BEEP_MID 94 /* 3989Hz */ +#define AO_BEEP_HIGH 75 /* 5000Hz */ +#define AO_BEEP_OFF 0 /* off */ + +#define AO_BEEP_g 240 /* 1562.5Hz */ +#define AO_BEEP_gs 227 /* 1652Hz (1655Hz) */ +#define AO_BEEP_aa 214 /* 1752Hz (1754Hz) */ +#define AO_BEEP_bbf 202 /* 1856Hz (1858Hz) */ +#define AO_BEEP_bb 190 /* 1974Hz (1969Hz) */ +#define AO_BEEP_cc 180 /* 2083Hz (2086Hz) */ +#define AO_BEEP_ccs 170 /* 2205Hz (2210Hz) */ +#define AO_BEEP_dd 160 /* 2344Hz (2341Hz) */ +#define AO_BEEP_eef 151 /* 2483Hz (2480Hz) */ +#define AO_BEEP_ee 143 /* 2622Hz (2628Hz) */ +#define AO_BEEP_ff 135 /* 2778Hz (2784Hz) */ +#define AO_BEEP_ffs 127 /* 2953Hz (2950Hz) */ +#define AO_BEEP_gg 120 /* 3125Hz */ +#define AO_BEEP_ggs 113 /* 3319Hz (3311Hz) */ +#define AO_BEEP_aaa 107 /* 3504Hz (3508Hz) */ +#define AO_BEEP_bbbf 101 /* 3713Hz (3716Hz) */ +#define AO_BEEP_bbb 95 /* 3947Hz (3937Hz) */ +#define AO_BEEP_ccc 90 /* 4167Hz (4171Hz) */ +#define AO_BEEP_cccs 85 /* 4412Hz (4419Hz) */ +#define AO_BEEP_ddd 80 /* 4688Hz (4682Hz) */ +#define AO_BEEP_eeef 76 /* 4934Hz (4961Hz) */ +#define AO_BEEP_eee 71 /* 5282Hz (5256Hz) */ +#define AO_BEEP_fff 67 /* 5597Hz (5568Hz) */ +#define AO_BEEP_fffs 64 /* 5859Hz (5899Hz) */ +#define AO_BEEP_ggg 60 /* 6250Hz */ + +/* Set the beeper to the specified tone */ +void +ao_beep(uint8_t beep); + +/* Turn on the beeper for the specified time */ +void +ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant; + +/* Initialize the beeper */ +void +ao_beep_init(void); + +/* + * ao_led.c + */ + +#define AO_LED_NONE 0 + +/* Turn on the specified LEDs */ +void +ao_led_on(uint8_t colors); + +/* Turn off the specified LEDs */ +void +ao_led_off(uint8_t colors); + +/* Set all of the LEDs to the specified state */ +void +ao_led_set(uint8_t colors); + +/* Toggle the specified LEDs */ +void +ao_led_toggle(uint8_t colors); + +/* Turn on the specified LEDs for the indicated interval */ +void +ao_led_for(uint8_t colors, uint16_t ticks) __reentrant; + +/* Initialize the LEDs */ +void +ao_led_init(uint8_t enable); + +/* + * ao_romconfig.c + */ + +#define AO_ROMCONFIG_VERSION 2 + +extern __code __at (0x00a0) uint16_t ao_romconfig_version; +extern __code __at (0x00a2) uint16_t ao_romconfig_check; +extern __code __at (0x00a4) uint16_t ao_serial_number; +extern __code __at (0x00a6) uint32_t ao_radio_cal; + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + +#if HAS_USB +extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; +#endif + +/* + * ao_usb.c + */ + +/* Put one character to the USB output queue */ +void +ao_usb_putchar(char c); + +/* Get one character from the USB input queue */ +char +ao_usb_getchar(void); + +/* Poll for a charcter on the USB input queue. + * returns AO_READ_AGAIN if none are available + */ +char +ao_usb_pollchar(void); + +/* Flush the USB output queue */ +void +ao_usb_flush(void); + +#if HAS_USB +/* USB interrupt handler */ +void +ao_usb_isr(void) __interrupt 6; +#endif + +/* Enable the USB controller */ +void +ao_usb_enable(void); + +/* Disable the USB controller */ +void +ao_usb_disable(void); + +/* Initialize the USB system */ +void +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 __pdata uint16_t ao_cmd_lex_i; +extern __pdata uint32_t ao_cmd_lex_u32; +extern __pdata char ao_cmd_lex_c; +extern __pdata 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); + +void +ao_cmd_decimal(void); + +uint8_t +ao_match_word(__code char *word); + +struct ao_cmds { + void (*func)(void); + __code char *help; +}; + +void +ao_cmd_register(__code struct ao_cmds *cmds); + +void +ao_cmd_init(void); + +#if HAS_CMD_FILTER +/* + * Provided by an external module to filter raw command lines + */ +uint8_t +ao_cmd_filter(void); +#endif + +/* + * ao_dma.c + */ + +/* Allocate a DMA channel. the 'done' parameter will be set when the + * dma is finished and will be used to wakeup any waiters + */ + +uint8_t +ao_dma_alloc(__xdata uint8_t * done); + +/* Setup a DMA channel */ +void +ao_dma_set_transfer(uint8_t id, + void __xdata *srcaddr, + void __xdata *dstaddr, + uint16_t count, + uint8_t cfg0, + uint8_t cfg1); + +/* Start a DMA channel */ +void +ao_dma_start(uint8_t id); + +/* Manually trigger a DMA channel */ +void +ao_dma_trigger(uint8_t id); + +/* Abort a running DMA transfer */ +void +ao_dma_abort(uint8_t id); + +/* DMA interrupt routine */ +void +ao_dma_isr(void) __interrupt 8; + +/* + * ao_mutex.c + */ + +void +ao_mutex_get(__xdata uint8_t *ao_mutex) __reentrant; + +void +ao_mutex_put(__xdata uint8_t *ao_mutex) __reentrant; + +/* + * Storage interface, provided by one of the eeprom or flash + * drivers + */ + +/* Total bytes of available storage */ +extern __pdata uint32_t ao_storage_total; + +/* Block size - device is erased in these units. At least 256 bytes */ +extern __pdata uint32_t ao_storage_block; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +extern __pdata uint32_t ao_storage_config; + +/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ +extern __pdata uint16_t ao_storage_unit; + +#define AO_STORAGE_ERASE_LOG (ao_storage_config + AO_CONFIG_MAX_SIZE) + +/* Initialize above values. Can only be called once the OS is running */ +void +ao_storage_setup(void) __reentrant; + +/* Write data. Returns 0 on failure, 1 on success */ +uint8_t +ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Read data. Returns 0 on failure, 1 on success */ +uint8_t +ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Erase a block of storage. This always clears ao_storage_block bytes */ +uint8_t +ao_storage_erase(uint32_t pos) __reentrant; + +/* Flush any pending writes to stable storage */ +void +ao_storage_flush(void) __reentrant; + +/* Initialize the storage code */ +void +ao_storage_init(void); + +/* + * Low-level functions wrapped by ao_storage.c + */ + +/* Read data within a storage unit */ +uint8_t +ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Write data within a storage unit */ +uint8_t +ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Initialize low-level device bits */ +void +ao_storage_device_init(void); + +/* Print out information about flash chips */ +void +ao_storage_device_info(void) __reentrant; + +/* + * ao_log.c + */ + +/* We record flight numbers in the first record of + * the log. Tasks may wait for this to be initialized + * by sleeping on this variable. + */ +extern __xdata uint16_t ao_flight_number; + +extern __pdata uint32_t ao_log_current_pos; +extern __pdata uint32_t ao_log_end_pos; +extern __pdata uint32_t ao_log_start_pos; +extern __xdata uint8_t ao_log_running; +extern __pdata enum flight_state ao_log_state; + +/* required functions from the underlying log system */ + +#define AO_LOG_FORMAT_UNKNOWN 0 /* unknown; altosui will have to guess */ +#define AO_LOG_FORMAT_FULL 1 /* 8 byte typed log records */ +#define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */ +#define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */ +#define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ +#define AO_LOG_FORMAT_NONE 127 /* No log at all */ + +extern __code uint8_t ao_log_format; + +/* Return the flight number from the given log slot, 0 if none */ +uint16_t +ao_log_flight(uint8_t slot); + +/* Flush the log */ +void +ao_log_flush(void); + +/* Logging thread main routine */ +void +ao_log(void); + +/* functions provided in ao_log.c */ + +/* Figure out the current flight number */ +void +ao_log_scan(void) __reentrant; + +/* Return the position of the start of the given log slot */ +uint32_t +ao_log_pos(uint8_t slot); + +/* Start logging to eeprom */ +void +ao_log_start(void); + +/* Stop logging */ +void +ao_log_stop(void); + +/* Initialize the logging system */ +void +ao_log_init(void); + +/* Write out the current flight number to the erase log */ +void +ao_log_write_erase(uint8_t pos); + +/* Returns true if there are any logs stored in eeprom */ +uint8_t +ao_log_present(void); + +/* Returns true if there is no more storage space available */ +uint8_t +ao_log_full(void); + +/* + * ao_log_big.c + */ + +/* + * The data log is recorded in the eeprom as a sequence + * of data packets. + * + * Each packet starts with a 4-byte header that has the + * packet type, the packet checksum and the tick count. Then + * they all contain 2 16 bit values which hold packet-specific + * data. + * + * For each flight, the first packet + * is FLIGHT packet, indicating the serial number of the + * device and a unique number marking the number of flights + * recorded by this device. + * + * During flight, data from the accelerometer and barometer + * are recorded in SENSOR packets, using the raw 16-bit values + * read from the A/D converter. + * + * Also during flight, but at a lower rate, the deployment + * sensors are recorded in DEPLOY packets. The goal here is to + * detect failure in the deployment circuits. + * + * STATE packets hold state transitions as the flight computer + * transitions through different stages of the flight. + */ +#define AO_LOG_FLIGHT 'F' +#define AO_LOG_SENSOR 'A' +#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_GPS_SAT 'V' +#define AO_LOG_GPS_DATE 'Y' + +#define AO_LOG_POS_NONE (~0UL) + +struct ao_log_record { + char type; + uint8_t csum; + uint16_t tick; + union { + struct { + int16_t ground_accel; + uint16_t flight; + } flight; + struct { + int16_t accel; + int16_t pres; + } sensor; + struct { + int16_t temp; + int16_t v_batt; + } temp_volt; + struct { + int16_t drogue; + int16_t main; + } deploy; + struct { + uint16_t state; + uint16_t reason; + } state; + struct { + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t flags; + } gps_time; + int32_t gps_latitude; + int32_t gps_longitude; + struct { + int16_t altitude; + uint16_t unused; + } gps_altitude; + struct { + uint16_t svid; + uint8_t unused; + uint8_t c_n; + } gps_sat; + struct { + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t extra; + } gps_date; + struct { + uint16_t d0; + uint16_t d1; + } anon; + } u; +}; + +/* Write a record to the eeprom log */ +uint8_t +ao_log_data(__xdata struct ao_log_record *log) __reentrant; + +/* + * ao_flight.c + */ + +enum ao_flight_state { + ao_flight_startup = 0, + ao_flight_idle = 1, + ao_flight_pad = 2, + ao_flight_boost = 3, + ao_flight_fast = 4, + ao_flight_coast = 5, + ao_flight_drogue = 6, + ao_flight_main = 7, + ao_flight_landed = 8, + ao_flight_invalid = 9 +}; + +extern __pdata enum ao_flight_state ao_flight_state; + +extern __pdata uint16_t ao_launch_time; +extern __pdata uint8_t ao_flight_force_idle; + +/* Flight thread */ +void +ao_flight(void); + +/* Initialize flight thread */ +void +ao_flight_init(void); + +/* + * ao_flight_nano.c + */ + +void +ao_flight_nano_init(void); + +/* + * ao_sample.c + */ + +/* + * Barometer calibration + * + * We directly sample the barometer. The specs say: + * + * Pressure range: 15-115 kPa + * Voltage at 115kPa: 2.82 + * Output scale: 27mV/kPa + * + * If we want to detect launch with the barometer, we need + * a large enough bump to not be fooled by noise. At typical + * launch elevations (0-2000m), a 200Pa pressure change cooresponds + * to about a 20m elevation change. This is 5.4mV, or about 3LSB. + * As all of our calculations are done in 16 bits, we'll actually see a change + * of 16 times this though + * + * 27 mV/kPa * 32767 / 3300 counts/mV = 268.1 counts/kPa + */ + +/* Accelerometer calibration + * + * We're sampling the accelerometer through a resistor divider which + * consists of 5k and 10k resistors. This multiplies the values by 2/3. + * That goes into the cc1111 A/D converter, which is running at 11 bits + * of precision with the bits in the MSB of the 16 bit value. Only positive + * values are used, so values should range from 0-32752 for 0-3.3V. The + * specs say we should see 40mV/g (uncalibrated), multiply by 2/3 for what + * the A/D converter sees (26.67 mV/g). We should see 32752/3300 counts/mV, + * for a final computation of: + * + * 26.67 mV/g * 32767/3300 counts/mV = 264.8 counts/g + * + * Zero g was measured at 16000 (we would expect 16384). + * Note that this value is only require to tell if the + * rocket is standing upright. Once that is determined, + * the value of the accelerometer is averaged for 100 samples + * to find the resting accelerometer value, which is used + * for all further flight computations + */ + +#define GRAVITY 9.80665 + +/* + * Above this height, the baro sensor doesn't work + */ +#define AO_MAX_BARO_HEIGHT 12000 + +/* + * Above this speed, baro measurements are unreliable + */ +#define AO_MAX_BARO_SPEED 200 + +#define ACCEL_NOSE_UP (ao_accel_2g >> 2) + +/* + * Speed and acceleration are scaled by 16 to provide a bit more + * resolution while still having reasonable range. Note that this + * limits speed to 2047m/s (around mach 6) and acceleration to + * 2047m/s² (over 200g) + */ + +#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) +#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) +#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) + +extern __pdata uint16_t ao_sample_tick; /* time of last data */ +extern __pdata int16_t ao_sample_pres; /* most recent pressure sensor reading */ +extern __pdata int16_t ao_sample_alt; /* MSL of ao_sample_pres */ +extern __pdata int16_t ao_sample_height; /* AGL of ao_sample_pres */ +extern __data uint8_t ao_sample_adc; /* Ring position of last processed sample */ + +#if HAS_ACCEL +extern __pdata int16_t ao_sample_accel; /* most recent accel sensor reading */ +#endif + +extern __pdata int16_t ao_ground_pres; /* startup pressure */ +extern __pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ + +#if HAS_ACCEL +extern __pdata int16_t ao_ground_accel; /* startup acceleration */ +extern __pdata int16_t ao_accel_2g; /* factory accel calibration */ +extern __pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +#endif + +void ao_sample_init(void); + +/* returns FALSE in preflight mode, TRUE in flight mode */ +uint8_t ao_sample(void); + +/* + * ao_kalman.c + */ + +#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) +#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) +#define from_fix(x) ((x) >> 16) + +extern __pdata int16_t ao_height; /* meters */ +extern __pdata int16_t ao_speed; /* m/s * 16 */ +extern __pdata int16_t ao_accel; /* m/s² * 16 */ +extern __pdata int16_t ao_max_height; /* max of ao_height */ +extern __pdata int16_t ao_avg_height; /* running average of height */ + +extern __pdata int16_t ao_error_h; +extern __pdata int16_t ao_error_h_sq_avg; + +#if HAS_ACCEL +extern __pdata int16_t ao_error_a; +#endif + +void ao_kalman(void); + +/* + * ao_report.c + */ + +void +ao_report_init(void); + +/* + * ao_convert.c + * + * Given raw data, convert to SI units + */ + +/* pressure from the sensor to altitude in meters */ +int16_t +ao_pres_to_altitude(int16_t pres) __reentrant; + +int16_t +ao_altitude_to_pres(int16_t alt) __reentrant; + +int16_t +ao_temp_to_dC(int16_t temp) __reentrant; + +/* + * ao_dbg.c + * + * debug another telemetrum board + */ + +/* Send a byte to the dbg target */ +void +ao_dbg_send_byte(uint8_t byte); + +/* Receive a byte from the dbg target */ +uint8_t +ao_dbg_recv_byte(void); + +/* Start a bulk transfer to/from dbg target memory */ +void +ao_dbg_start_transfer(uint16_t addr); + +/* End a bulk transfer to/from dbg target memory */ +void +ao_dbg_end_transfer(void); + +/* Write a byte to dbg target memory */ +void +ao_dbg_write_byte(uint8_t byte); + +/* Read a byte from dbg target memory */ +uint8_t +ao_dbg_read_byte(void); + +/* Enable dbg mode, switching use of the pins */ +void +ao_dbg_debug_mode(void); + +/* Reset the dbg target */ +void +ao_dbg_reset(void); + +void +ao_dbg_init(void); + +/* + * ao_serial.c + */ + +#ifndef HAS_SERIAL_1 +#error Please define HAS_SERIAL_1 +#endif + +#if HAS_SERIAL_1 +#ifndef USE_SERIAL_STDIN +#error Please define USE_SERIAL_STDIN +#endif + +void +ao_serial_rx1_isr(void) __interrupt 3; + +void +ao_serial_tx1_isr(void) __interrupt 14; + +char +ao_serial_getchar(void) __critical; + +#if USE_SERIAL_STDIN +char +ao_serial_pollchar(void) __critical; + +void +ao_serial_set_stdin(uint8_t stdin); +#endif + +void +ao_serial_putchar(char c) __critical; + +void +ao_serial_drain(void) __critical; + +#define AO_SERIAL_SPEED_4800 0 +#define AO_SERIAL_SPEED_9600 1 +#define AO_SERIAL_SPEED_19200 2 +#define AO_SERIAL_SPEED_57600 3 + +void +ao_serial_set_speed(uint8_t speed); + +void +ao_serial_init(void); +#endif + +/* + * ao_spi.c + */ + +extern __xdata uint8_t ao_spi_mutex; + +#define ao_spi_get_mask(reg,mask) do {\ + ao_mutex_get(&ao_spi_mutex); \ + (reg) &= ~(mask); \ + } while (0) + +#define ao_spi_put_mask(reg,mask) do { \ + (reg) |= (mask); \ + ao_mutex_put(&ao_spi_mutex); \ + } while (0) + +#define ao_spi_get_bit(bit) do {\ + ao_mutex_get(&ao_spi_mutex); \ + (bit) = 0; \ + } while (0) + +#define ao_spi_put_bit(bit) do { \ + (bit) = 1; \ + ao_mutex_put(&ao_spi_mutex); \ + } while (0) + +/* + * The SPI mutex must be held to call either of these + * functions -- this mutex covers the entire SPI operation, + * from chip select low to chip select high + */ + +void +ao_spi_send(void __xdata *block, uint16_t len) __reentrant; + +void +ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; + +void +ao_spi_init(void); + +/* + * ao_telemetry.c + */ +#define AO_MAX_CALLSIGN 8 +#define AO_MAX_VERSION 8 +#define AO_MAX_TELEMETRY 128 + +struct ao_telemetry_generic { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t payload[27]; /* 5 */ + /* 32 */ +}; + +#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 +#define AO_TELEMETRY_SENSOR_TELEMINI 0x02 +#define AO_TELEMETRY_SENSOR_TELENANO 0x03 + +struct ao_telemetry_sensor { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t state; /* 5 flight state */ + int16_t accel; /* 6 accelerometer (TM only) */ + int16_t pres; /* 8 pressure sensor */ + int16_t temp; /* 10 temperature sensor */ + int16_t v_batt; /* 12 battery voltage */ + int16_t sense_d; /* 14 drogue continuity sense (TM/Tm) */ + int16_t sense_m; /* 16 main continuity sense (TM/Tm) */ + + int16_t acceleration; /* 18 m/s² * 16 */ + int16_t speed; /* 20 m/s * 16 */ + int16_t height; /* 22 m */ + + int16_t ground_pres; /* 24 average pres on pad */ + int16_t ground_accel; /* 26 average accel on pad */ + int16_t accel_plus_g; /* 28 accel calibration at +1g */ + int16_t accel_minus_g; /* 30 accel calibration at -1g */ + /* 32 */ +}; + +#define AO_TELEMETRY_CONFIGURATION 0x04 + +struct ao_telemetry_configuration { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t device; /* 5 device type */ + uint16_t flight; /* 6 flight number */ + uint8_t config_major; /* 8 Config major version */ + uint8_t config_minor; /* 9 Config minor version */ + uint16_t apogee_delay; /* 10 Apogee deploy delay in seconds */ + uint16_t main_deploy; /* 12 Main deploy alt in meters */ + uint16_t flight_log_max; /* 14 Maximum flight log size in kB */ + char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ + char version[AO_MAX_VERSION]; /* 24 Software version */ + /* 32 */ +}; + +#define AO_TELEMETRY_LOCATION 0x05 + +#define AO_GPS_MODE_NOT_VALID 'N' +#define AO_GPS_MODE_AUTONOMOUS 'A' +#define AO_GPS_MODE_DIFFERENTIAL 'D' +#define AO_GPS_MODE_ESTIMATED 'E' +#define AO_GPS_MODE_MANUAL 'M' +#define AO_GPS_MODE_SIMULATED 'S' + +struct ao_telemetry_location { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t flags; /* 5 Number of sats and other flags */ + int16_t altitude; /* 6 GPS reported altitude (m) */ + int32_t latitude; /* 8 latitude (degrees * 10⁷) */ + int32_t longitude; /* 12 longitude (degrees * 10⁷) */ + uint8_t year; /* 16 (- 2000) */ + uint8_t month; /* 17 (1-12) */ + uint8_t day; /* 18 (1-31) */ + uint8_t hour; /* 19 (0-23) */ + uint8_t minute; /* 20 (0-59) */ + uint8_t second; /* 21 (0-59) */ + uint8_t pdop; /* 22 (m * 5) */ + uint8_t hdop; /* 23 (m * 5) */ + uint8_t vdop; /* 24 (m * 5) */ + uint8_t mode; /* 25 */ + uint16_t ground_speed; /* 26 cm/s */ + int16_t climb_rate; /* 28 cm/s */ + uint8_t course; /* 30 degrees / 2 */ + uint8_t unused[1]; /* 31 */ + /* 32 */ +}; + +#define AO_TELEMETRY_SATELLITE 0x06 + +struct ao_telemetry_satellite_info { + uint8_t svid; + uint8_t c_n_1; +}; + +struct ao_telemetry_satellite { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t channels; /* 5 number of reported sats */ + + struct ao_telemetry_satellite_info sats[12]; /* 6 */ + uint8_t unused[2]; /* 30 */ + /* 32 */ +}; + +#define AO_TELEMETRY_COMPANION 0x07 + +#define AO_COMPANION_MAX_CHANNELS 12 + +struct ao_telemetry_companion { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t board_id; /* 5 */ + + uint8_t update_period; /* 6 */ + uint8_t channels; /* 7 */ + uint16_t companion_data[AO_COMPANION_MAX_CHANNELS]; /* 8 */ + /* 32 */ +}; + +union ao_telemetry_all { + struct ao_telemetry_generic generic; + struct ao_telemetry_sensor sensor; + struct ao_telemetry_configuration configuration; + struct ao_telemetry_location location; + struct ao_telemetry_satellite satellite; + struct ao_telemetry_companion companion; +}; + +/* + * ao_gps.c + */ + +#define AO_GPS_NUM_SAT_MASK (0xf << 0) +#define AO_GPS_NUM_SAT_SHIFT (0) + +#define AO_GPS_VALID (1 << 4) +#define AO_GPS_RUNNING (1 << 5) +#define AO_GPS_DATE_VALID (1 << 6) +#define AO_GPS_COURSE_VALID (1 << 7) + +extern __pdata uint16_t ao_gps_tick; +extern __xdata uint8_t ao_gps_mutex; +extern __xdata struct ao_telemetry_location ao_gps_data; +extern __xdata struct ao_telemetry_satellite ao_gps_tracking_data; + +struct ao_gps_orig { + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t flags; + int32_t latitude; /* degrees * 10⁷ */ + int32_t longitude; /* degrees * 10⁷ */ + int16_t altitude; /* m */ + uint16_t ground_speed; /* cm/s */ + uint8_t course; /* degrees / 2 */ + uint8_t hdop; /* * 5 */ + int16_t climb_rate; /* cm/s */ + uint16_t h_error; /* m */ + uint16_t v_error; /* m */ +}; + +struct ao_gps_sat_orig { + uint8_t svid; + uint8_t c_n_1; +}; + +#define AO_MAX_GPS_TRACKING 12 + +struct ao_gps_tracking_orig { + uint8_t channels; + struct ao_gps_sat_orig sats[AO_MAX_GPS_TRACKING]; +}; + +void +ao_gps(void); + +void +ao_gps_print(__xdata struct ao_gps_orig *gps_data); + +void +ao_gps_tracking_print(__xdata struct ao_gps_tracking_orig *gps_tracking_data); + +void +ao_gps_init(void); + +/* + * ao_gps_report.c + */ + +void +ao_gps_report(void); + +void +ao_gps_report_init(void); + +/* + * ao_telemetry_orig.c + */ + +struct ao_telemetry_orig { + uint16_t serial; + uint16_t flight; + uint8_t flight_state; + int16_t accel; + int16_t ground_accel; + union { + struct { + int16_t speed; + int16_t unused; + } k; + int32_t flight_vel; + } u; + int16_t height; + int16_t ground_pres; + int16_t accel_plus_g; + int16_t accel_minus_g; + struct ao_adc adc; + struct ao_gps_orig gps; + char callsign[AO_MAX_CALLSIGN]; + struct ao_gps_tracking_orig gps_tracking; +}; + +struct ao_telemetry_tiny { + uint16_t serial; + uint16_t flight; + uint8_t flight_state; + int16_t height; /* AGL in meters */ + int16_t speed; /* in m/s * 16 */ + int16_t accel; /* in m/s² * 16 */ + int16_t ground_pres; /* sensor units */ + struct ao_adc adc; /* raw ADC readings */ + char callsign[AO_MAX_CALLSIGN]; +}; + +/* + * ao_radio_recv tacks on rssi and status bytes + */ + +struct ao_telemetry_raw_recv { + uint8_t packet[AO_MAX_TELEMETRY + 2]; +}; + +struct ao_telemetry_orig_recv { + struct ao_telemetry_orig telemetry_orig; + int8_t rssi; + uint8_t status; +}; + +struct ao_telemetry_tiny_recv { + struct ao_telemetry_tiny telemetry_tiny; + int8_t rssi; + uint8_t status; +}; + +/* Set delay between telemetry reports (0 to disable) */ + +#define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(1000) +#define AO_TELEMETRY_INTERVAL_FLIGHT AO_MS_TO_TICKS(100) +#define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(1000) + +void +ao_telemetry_set_interval(uint16_t interval); + +void +ao_rdf_set(uint8_t rdf); + +void +ao_telemetry_init(void); + +void +ao_telemetry_orig_init(void); + +void +ao_telemetry_tiny_init(void); + +/* + * ao_radio.c + */ + +extern __xdata uint8_t ao_radio_dma; +extern __xdata uint8_t ao_radio_dma_done; +extern __xdata uint8_t ao_radio_done; +extern __xdata uint8_t ao_radio_mutex; + +void +ao_radio_general_isr(void) __interrupt 16; + +void +ao_radio_get(uint8_t len); + +#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) + +void +ao_radio_set_packet(void); + +void +ao_radio_send(__xdata void *data, uint8_t size) __reentrant; + +uint8_t +ao_radio_recv(__xdata void *data, uint8_t size) __reentrant; + +void +ao_radio_recv_abort(void); + +void +ao_radio_rdf(int ms); + +void +ao_radio_rdf_abort(void); + +void +ao_radio_idle(void); + +void +ao_radio_init(void); + +/* + * ao_monitor.c + */ + +extern const char const * const ao_state_names[]; + +void +ao_monitor(void); + +#define AO_MONITORING_OFF 0 +#define AO_MONITORING_ORIG 1 +#define AO_MONITORING_TINY 2 + +void +ao_set_monitor(uint8_t monitoring); + +void +ao_monitor_init(uint8_t led, uint8_t monitoring) __reentrant; + +/* + * ao_stdio.c + */ + +#define AO_READ_AGAIN ((char) -1) + +struct ao_stdio { + char (*pollchar)(void); + void (*putchar)(char c) __reentrant; + void (*flush)(void); + uint8_t echo; +}; + +extern __xdata struct ao_stdio ao_stdios[]; +extern __pdata int8_t ao_cur_stdio; +extern __pdata int8_t ao_num_stdios; + +void +flush(void); + +extern __xdata uint8_t ao_stdin_ready; + +uint8_t +ao_echo(void); + +int8_t +ao_add_stdio(char (*pollchar)(void), + void (*putchar)(char) __reentrant, + void (*flush)(void)) __reentrant; + +/* + * ao_ignite.c + */ + +enum ao_igniter { + ao_igniter_drogue = 0, + ao_igniter_main = 1 +}; + +void +ao_ignite(enum ao_igniter igniter); + +enum ao_igniter_status { + ao_igniter_unknown, /* unknown status (ambiguous voltage) */ + ao_igniter_ready, /* continuity detected */ + ao_igniter_active, /* igniter firing */ + ao_igniter_open, /* open circuit detected */ +}; + +enum ao_igniter_status +ao_igniter_status(enum ao_igniter igniter); + +void +ao_ignite_set_pins(void); + +void +ao_igniter_init(void); + +/* + * ao_config.c + */ + +#define AO_CONFIG_MAJOR 1 +#define AO_CONFIG_MINOR 8 + +struct ao_config { + uint8_t major; + uint8_t minor; + uint16_t main_deploy; + int16_t accel_plus_g; /* changed for minor version 2 */ + uint8_t radio_channel; + char callsign[AO_MAX_CALLSIGN + 1]; + uint8_t apogee_delay; /* minor version 1 */ + int16_t accel_minus_g; /* minor version 2 */ + uint32_t radio_cal; /* minor version 3 */ + uint32_t flight_log_max; /* minor version 4 */ + uint8_t ignite_mode; /* minor version 5 */ + uint8_t pad_orientation; /* minor version 6 */ + uint32_t radio_setting; /* minor version 7 */ + uint8_t radio_enable; /* minor version 8 */ +}; + +#define AO_IGNITE_MODE_DUAL 0 +#define AO_IGNITE_MODE_APOGEE 1 +#define AO_IGNITE_MODE_MAIN 2 + +#define AO_PAD_ORIENTATION_ANTENNA_UP 0 +#define AO_PAD_ORIENTATION_ANTENNA_DOWN 1 + +extern __xdata struct ao_config ao_config; + +#define AO_CONFIG_MAX_SIZE 128 + +void +ao_config_get(void); + +void +ao_config_put(void); + +void +ao_config_init(void); + +/* + * ao_rssi.c + */ + +void +ao_rssi_set(int rssi_value); + +void +ao_rssi_init(uint8_t rssi_led); + +/* + * ao_product.c + * + * values which need to be defined for + * each instance of a product + */ + +extern const char ao_version[]; +extern const char ao_manufacturer[]; +extern const char ao_product[]; + +/* + * Fifos + */ + +#define AO_FIFO_SIZE 32 + +struct ao_fifo { + uint8_t insert; + uint8_t remove; + char fifo[AO_FIFO_SIZE]; +}; + +#define ao_fifo_insert(f,c) do { \ + (f).fifo[(f).insert] = (c); \ + (f).insert = ((f).insert + 1) & (AO_FIFO_SIZE-1); \ +} while(0) + +#define ao_fifo_remove(f,c) do {\ + c = (f).fifo[(f).remove]; \ + (f).remove = ((f).remove + 1) & (AO_FIFO_SIZE-1); \ +} while(0) + +#define ao_fifo_full(f) ((((f).insert + 1) & (AO_FIFO_SIZE-1)) == (f).remove) +#define ao_fifo_empty(f) ((f).insert == (f).remove) + +/* + * ao_packet.c + * + * Packet-based command interface + */ + +#define AO_PACKET_MAX 64 +#define AO_PACKET_SYN (uint8_t) 0xff + +struct ao_packet { + uint8_t addr; + uint8_t len; + uint8_t seq; + uint8_t ack; + uint8_t d[AO_PACKET_MAX]; + uint8_t callsign[AO_MAX_CALLSIGN]; +}; + +struct ao_packet_recv { + struct ao_packet packet; + int8_t rssi; + uint8_t status; +}; + +extern __xdata struct ao_packet_recv ao_rx_packet; +extern __xdata struct ao_packet ao_tx_packet; +extern __xdata struct ao_task ao_packet_task; +extern __xdata uint8_t ao_packet_enable; +extern __xdata uint8_t ao_packet_master_sleeping; +extern __pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; + +void +ao_packet_send(void); + +uint8_t +ao_packet_recv(void); + +void +ao_packet_flush(void); + +void +ao_packet_putchar(char c) __reentrant; + +char +ao_packet_pollchar(void) __critical; + +/* ao_packet_master.c */ + +void +ao_packet_master_init(void); + +/* ao_packet_slave.c */ + +void +ao_packet_slave_start(void); + +void +ao_packet_slave_stop(void); + +void +ao_packet_slave_init(uint8_t enable); + +/* ao_btm.c */ + +/* If bt_link is on P2, this interrupt is shared by USB, so the USB + * code calls this function. Otherwise, it's a regular ISR. + */ + +void +ao_btm_isr(void) +#if BT_LINK_ON_P1 + __interrupt 15 +#endif + ; + +void +ao_btm_init(void); + +/* ao_companion.c */ + +#define AO_COMPANION_SETUP 1 +#define AO_COMPANION_FETCH 2 +#define AO_COMPANION_NOTIFY 3 + +struct ao_companion_command { + uint8_t command; + uint8_t flight_state; + uint16_t tick; + uint16_t serial; + uint16_t flight; +}; + +struct ao_companion_setup { + uint16_t board_id; + uint16_t board_id_inverse; + uint8_t update_period; + uint8_t channels; +}; + +extern __pdata uint8_t ao_companion_running; +extern __xdata struct ao_companion_setup ao_companion_setup; +extern __xdata uint8_t ao_companion_mutex; +extern __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; + +void +ao_companion_init(void); + +#endif /* _AO_H_ */ diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c new file mode 100644 index 00000000..1442ebea --- /dev/null +++ b/src/core/ao_cmd.c @@ -0,0 +1,320 @@ +/* + * 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" + +__pdata uint16_t ao_cmd_lex_i; +__pdata uint32_t ao_cmd_lex_u32; +__pdata char ao_cmd_lex_c; +__pdata enum ao_cmd_status ao_cmd_status; + +#define CMD_LEN 32 + +static __xdata char cmd_line[CMD_LEN]; +static __pdata uint8_t cmd_len; +static __pdata uint8_t cmd_i; + +static void +put_string(__code char *s) +{ + char c; + while (c = *s++) + putchar(c); +} + +static void +readline(void) +{ + __pdata char c; + if (ao_echo()) + put_string("> "); + cmd_len = 0; + for (;;) { + flush(); + c = getchar(); + /* backspace/delete */ + if (c == '\010' || c == '\177') { + if (cmd_len != 0) { + if (ao_echo()) + put_string("\010 \010"); + --cmd_len; + } + continue; + } + + /* ^U */ + if (c == '\025') { + while (cmd_len != 0) { + if (ao_echo()) + put_string("\010 \010"); + --cmd_len; + } + continue; + } + + /* map CR to NL */ + if (c == '\r') + c = '\n'; + + if (c == '\n') { + if (ao_echo()) + putchar('\n'); + break; + } + + if (cmd_len >= CMD_LEN - 2) { + if (ao_echo()) + putchar('\007'); + continue; + } + cmd_line[cmd_len++] = c; + if (ao_echo()) + putchar(c); + } + cmd_line[cmd_len++] = '\n'; + cmd_line[cmd_len++] = '\0'; + cmd_i = 0; +} + +void +ao_cmd_lex(void) +{ + ao_cmd_lex_c = '\n'; + if (cmd_i < cmd_len) + ao_cmd_lex_c = cmd_line[cmd_i++]; +} + +static void +putnibble(uint8_t v) +{ + if (v < 10) + putchar(v + '0'); + else + putchar(v + ('a' - 10)); +} + +void +ao_cmd_put16(uint16_t v) +{ + ao_cmd_put8(v >> 8); + ao_cmd_put8(v); +} + +void +ao_cmd_put8(uint8_t v) +{ + putnibble((v >> 4) & 0xf); + putnibble(v & 0xf); +} + +void +ao_cmd_white(void) +{ + while (ao_cmd_lex_c == ' ' || ao_cmd_lex_c == '\t') + ao_cmd_lex(); +} + +void +ao_cmd_hex(void) +{ + __pdata uint8_t r = ao_cmd_lex_error; + uint8_t n; + + ao_cmd_lex_i = 0; + ao_cmd_white(); + for(;;) { + if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') + n = (ao_cmd_lex_c - '0'); + else if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f') + n = (ao_cmd_lex_c - 'a' + 10); + else if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F') + n = (ao_cmd_lex_c - 'A' + 10); + else + break; + ao_cmd_lex_i = (ao_cmd_lex_i << 4) | n; + r = ao_cmd_success; + ao_cmd_lex(); + } + if (r != ao_cmd_success) + ao_cmd_status = r; +} + +void +ao_cmd_decimal(void) +{ + __pdata uint8_t r = ao_cmd_lex_error; + + ao_cmd_lex_u32 = 0; + ao_cmd_white(); + for(;;) { + if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') + ao_cmd_lex_u32 = (ao_cmd_lex_u32 * 10) + (ao_cmd_lex_c - '0'); + else + break; + r = ao_cmd_success; + ao_cmd_lex(); + } + if (r != ao_cmd_success) + ao_cmd_status = r; + ao_cmd_lex_i = (uint16_t) ao_cmd_lex_u32; +} + +uint8_t +ao_match_word(__code char *word) +{ + while (*word) { + if (ao_cmd_lex_c != *word) { + ao_cmd_status = ao_cmd_syntax_error; + return 0; + } + word++; + ao_cmd_lex(); + } + return 1; +} + +static void +eol(void) +{ + while (ao_cmd_lex_c != '\n') + ao_cmd_lex(); +} + +static void +echo(void) +{ + ao_cmd_hex(); + if (ao_cmd_status == ao_cmd_success) + ao_stdios[ao_cur_stdio].echo = ao_cmd_lex_i != 0; +} + +static void +ao_reboot(void) +{ + ao_cmd_white(); + if (!ao_match_word("eboot")) + return; + WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; + ao_delay(AO_SEC_TO_TICKS(2)); + ao_panic(AO_PANIC_REBOOT); +} + +static void +version(void) +{ + printf("manufacturer %s\n", ao_manufacturer); + printf("product %s\n", ao_product); + printf("serial-number %u\n", ao_serial_number); +#if HAS_EEPROM + printf("log-format %u\n", ao_log_format); +#endif + printf("software-version %s\n", ao_version); +} + +#define NUM_CMDS 11 + +static __code struct ao_cmds *__xdata (ao_cmds[NUM_CMDS]); +static __pdata uint8_t ao_ncmds; + +static void +help(void) +{ + register uint8_t cmds; + register uint8_t cmd; + register __code struct ao_cmds * cs; + + for (cmds = 0; cmds < ao_ncmds; cmds++) { + cs = ao_cmds[cmds]; + for (cmd = 0; cs[cmd].func; cmd++) + printf("%-45s %s\n", + cs[cmd].help, + cs[cmd].help+1+strlen(cs[cmd].help)); + } +} + +static void +report(void) +{ + 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) +{ + char c; + uint8_t cmd, cmds; + __code struct ao_cmds * __xdata cs; + void (*__xdata func)(void); + + for (;;) { + readline(); + ao_cmd_lex(); + ao_cmd_white(); + c = ao_cmd_lex_c; + ao_cmd_lex(); + if (c == '\r' || c == '\n') + continue; + func = (void (*)(void)) NULL; + for (cmds = 0; cmds < ao_ncmds; cmds++) { + cs = ao_cmds[cmds]; + for (cmd = 0; cs[cmd].func; cmd++) + if (cs[cmd].help[0] == c) { + func = cs[cmd].func; + break; + } + if (func) + break; + } + if (func) + (*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, "?\0Help" }, + { ao_task_info, "T\0Show tasks" }, + { echo, "E <0 off, 1 on>\0Set echo mode" }, + { ao_reboot, "r eboot\0Reboot" }, + { version, "v\0Version" }, + { 0, 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/src/core/ao_config.c b/src/core/ao_config.c new file mode 100644 index 00000000..0c10e608 --- /dev/null +++ b/src/core/ao_config.c @@ -0,0 +1,542 @@ +/* + * 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" + +__xdata struct ao_config ao_config; +__pdata uint8_t ao_config_loaded; +__pdata uint8_t ao_config_dirty; +__xdata uint8_t ao_config_mutex; + +#define AO_CONFIG_DEFAULT_MAIN_DEPLOY 250 +#define AO_CONFIG_DEFAULT_RADIO_CHANNEL 0 +#define AO_CONFIG_DEFAULT_CALLSIGN "N0CALL" +#define AO_CONFIG_DEFAULT_ACCEL_ZERO_G 16000 +#define AO_CONFIG_DEFAULT_APOGEE_DELAY 0 +#define AO_CONFIG_DEFAULT_IGNITE_MODE AO_IGNITE_MODE_DUAL +#define AO_CONFIG_DEFAULT_PAD_ORIENTATION AO_PAD_ORIENTATION_ANTENNA_UP +#if HAS_EEPROM +#ifndef USE_INTERNAL_FLASH +#error Please define USE_INTERNAL_FLASH +#endif +#endif +#if USE_INTERNAL_FLASH +#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_config +#else +#define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 192 * (uint32_t) 1024) +#endif + +#if HAS_EEPROM +static void +_ao_config_put(void) +{ + ao_storage_setup(); + ao_storage_erase(ao_storage_config); + ao_storage_write(ao_storage_config, &ao_config, sizeof (ao_config)); + ao_log_write_erase(0); + ao_storage_flush(); +} + +void +ao_config_put(void) +{ + ao_mutex_get(&ao_config_mutex); + _ao_config_put(); + ao_mutex_put(&ao_config_mutex); +} +#endif + +static void +_ao_config_get(void) +{ + if (ao_config_loaded) + return; +#if HAS_EEPROM + ao_storage_setup(); + ao_storage_read(ao_storage_config, &ao_config, sizeof (ao_config)); +#endif + if (ao_config.major != AO_CONFIG_MAJOR) { + ao_config.major = AO_CONFIG_MAJOR; + ao_config.minor = 0; + ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; + ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; + memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); + memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, + sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); + } + if (ao_config.minor < AO_CONFIG_MINOR) { + /* Fixups for minor version 1 */ + if (ao_config.minor < 1) + ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; + /* Fixups for minor version 2 */ + if (ao_config.minor < 2) { + ao_config.accel_plus_g = 0; + ao_config.accel_minus_g = 0; + } + /* Fixups for minor version 3 */ + if (ao_config.minor < 3) + ao_config.radio_cal = ao_radio_cal; + /* Fixups for minor version 4 */ + if (ao_config.minor < 4) + ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; + /* Fixupes for minor version 5 */ + if (ao_config.minor < 5) + ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; + if (ao_config.minor < 6) + ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; + if (ao_config.minor < 7) + ao_config.radio_setting = ao_config.radio_cal; + if (ao_config.minor < 8) + ao_config.radio_enable = TRUE; + ao_config.minor = AO_CONFIG_MINOR; + ao_config_dirty = 1; + } + ao_config_loaded = 1; +} + +static void +_ao_config_edit_start(void) +{ + ao_mutex_get(&ao_config_mutex); + _ao_config_get(); +} + +static void +_ao_config_edit_finish(void) +{ + ao_config_dirty = 1; + ao_mutex_put(&ao_config_mutex); +} + +void +ao_config_get(void) +{ + _ao_config_edit_start(); + ao_mutex_put(&ao_config_mutex); +} + +void +ao_config_callsign_show(void) +{ + printf ("Callsign: \"%s\"\n", ao_config.callsign); +} + +void +ao_config_callsign_set(void) __reentrant +{ + uint8_t c; + static __xdata char callsign[AO_MAX_CALLSIGN + 1]; + + memset(callsign, '\0', sizeof callsign); + ao_cmd_white(); + c = 0; + while (ao_cmd_lex_c != '\n') { + if (c < AO_MAX_CALLSIGN) + callsign[c++] = ao_cmd_lex_c; + else + ao_cmd_status = ao_cmd_lex_error; + ao_cmd_lex(); + } + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + memcpy(&ao_config.callsign, &callsign, + AO_MAX_CALLSIGN + 1); + _ao_config_edit_finish(); +} + +void +ao_config_radio_channel_show(void) __reentrant +{ + printf("Radio channel: %d\n", + ao_config.radio_channel); +} + +void +ao_config_radio_channel_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.radio_channel = ao_cmd_lex_i; + _ao_config_edit_finish(); + ao_radio_recv_abort(); +} + +#if HAS_ADC + +void +ao_config_main_deploy_show(void) __reentrant +{ + printf("Main deploy: %d meters\n", + ao_config.main_deploy); +} + +void +ao_config_main_deploy_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.main_deploy = ao_cmd_lex_i; + _ao_config_edit_finish(); +} + +#if HAS_ACCEL +void +ao_config_accel_calibrate_show(void) __reentrant +{ + printf("Accel cal +1g: %d -1g: %d\n", + ao_config.accel_plus_g, ao_config.accel_minus_g); +} + +#define ACCEL_CALIBRATE_SAMPLES 1024 +#define ACCEL_CALIBRATE_SHIFT 10 + +static int16_t +ao_config_accel_calibrate_auto(char *orientation) __reentrant +{ + uint16_t i; + int32_t accel_total; + uint8_t cal_adc_ring; + + printf("Orient antenna %s and press a key...", orientation); + flush(); + (void) getchar(); + puts("\r\n"); flush(); + puts("Calibrating..."); flush(); + i = ACCEL_CALIBRATE_SAMPLES; + accel_total = 0; + cal_adc_ring = ao_sample_adc; + while (i) { + ao_sleep(DATA_TO_XDATA(&ao_sample_adc)); + while (i && cal_adc_ring != ao_sample_adc) { + accel_total += (int32_t) ao_adc_ring[cal_adc_ring].accel; + cal_adc_ring = ao_adc_ring_next(cal_adc_ring); + i--; + } + } + return accel_total >> ACCEL_CALIBRATE_SHIFT; +} + +void +ao_config_accel_calibrate_set(void) __reentrant +{ + int16_t up, down; + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + if (ao_cmd_lex_i == 0) { + up = ao_config_accel_calibrate_auto("up"); + down = ao_config_accel_calibrate_auto("down"); + } else { + up = ao_cmd_lex_i; + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + down = ao_cmd_lex_i; + } + if (up >= down) { + printf("Invalid accel: up (%d) down (%d)\n", + up, down); + return; + } + _ao_config_edit_start(); + ao_config.accel_plus_g = up; + ao_config.accel_minus_g = down; + _ao_config_edit_finish(); +} +#endif /* HAS_ACCEL */ + +void +ao_config_apogee_delay_show(void) __reentrant +{ + printf("Apogee delay: %d seconds\n", + ao_config.apogee_delay); +} + +void +ao_config_apogee_delay_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.apogee_delay = ao_cmd_lex_i; + _ao_config_edit_finish(); +} + +#endif /* HAS_ADC */ + +void +ao_config_radio_cal_show(void) __reentrant +{ + printf("Radio cal: %ld\n", ao_config.radio_cal); +} + +void +ao_config_radio_cal_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.radio_setting = ao_config.radio_cal = ao_cmd_lex_u32; + _ao_config_edit_finish(); +} + +#if HAS_EEPROM +void +ao_config_log_show(void) __reentrant +{ + printf("Max flight log: %d kB\n", (int16_t) (ao_config.flight_log_max >> 10)); +} + +void +ao_config_log_set(void) __reentrant +{ + uint16_t block = (uint16_t) (ao_storage_block >> 10); + uint16_t config = (uint16_t) (ao_storage_config >> 10); + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + if (ao_log_present()) + printf("Storage must be empty before changing log size\n"); + else if (block > 1024 && (ao_cmd_lex_i & (block - 1))) + printf("Flight log size must be multiple of %d kB\n", block); + else if (ao_cmd_lex_i > config) + printf("Flight log max %d kB\n", config); + else { + _ao_config_edit_start(); + ao_config.flight_log_max = (uint32_t) ao_cmd_lex_i << 10; + _ao_config_edit_finish(); + } +} +#endif /* HAS_EEPROM */ + +#if HAS_IGNITE +void +ao_config_ignite_mode_show(void) __reentrant +{ + printf("Ignite mode: %d\n", ao_config.ignite_mode); +} + +void +ao_config_ignite_mode_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.ignite_mode = ao_cmd_lex_i; + _ao_config_edit_finish(); +} +#endif + +#if HAS_ACCEL +void +ao_config_pad_orientation_show(void) __reentrant +{ + printf("Pad orientation: %d\n", ao_config.pad_orientation); +} + +void +ao_config_pad_orientation_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_cmd_lex_i &= 1; + if (ao_config.pad_orientation != ao_cmd_lex_i) { + uint16_t t; + t = ao_config.accel_plus_g; + ao_config.accel_plus_g = 0x7fff - ao_config.accel_minus_g; + ao_config.accel_minus_g = 0x7fff - t; + } + ao_config.pad_orientation = ao_cmd_lex_i; + _ao_config_edit_finish(); +} +#endif + +void +ao_config_radio_setting_show(void) __reentrant +{ + printf("Radio setting: %ld\n", ao_config.radio_setting); +} + +void +ao_config_radio_setting_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.radio_setting = ao_cmd_lex_u32; + ao_config.radio_channel = 0; + _ao_config_edit_finish(); + ao_radio_recv_abort(); +} + +void +ao_config_radio_enable_show(void) __reentrant +{ + printf("Radio enable: %d\n", ao_config.radio_enable); +} + +void +ao_config_radio_enable_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.radio_enable = ao_cmd_lex_i; + _ao_config_edit_finish(); +} + +struct ao_config_var { + __code char *str; + void (*set)(void) __reentrant; + void (*show)(void) __reentrant; +}; + +static void +ao_config_help(void) __reentrant; + +static void +ao_config_show(void) __reentrant; + +static void +ao_config_write(void) __reentrant; + +__code struct ao_config_var ao_config_vars[] = { +#if HAS_ADC + { "m \0Main deploy (in meters)", + ao_config_main_deploy_set, ao_config_main_deploy_show, }, + { "d \0Apogee delay (in seconds)", + ao_config_apogee_delay_set, ao_config_apogee_delay_show }, +#endif /* HAS_ADC */ + { "r \0Radio channel (freq = 434.550 + chan * .1)", + ao_config_radio_channel_set, ao_config_radio_channel_show }, + { "c \0Callsign (8 char max)", + ao_config_callsign_set, ao_config_callsign_show }, + { "R \0Radio freq control (freq = 434.550 * setting/cal)", + ao_config_radio_setting_set, ao_config_radio_setting_show }, + { "e <0 disable, 1 enable>\0Enable telemetry and RDF", + ao_config_radio_enable_set, ao_config_radio_enable_show }, +#if HAS_ACCEL + { "a <+g> <-g>\0Accel calib (0 for auto)", + ao_config_accel_calibrate_set,ao_config_accel_calibrate_show }, +#endif /* HAS_ACCEL */ + { "f \0Radio calib (cal = rf/(xtal/2^16))", + ao_config_radio_cal_set, ao_config_radio_cal_show }, +#if HAS_EEPROM + { "l \0Flight log size in kB", + ao_config_log_set, ao_config_log_show }, +#endif +#if HAS_IGNITE + { "i <0 dual, 1 apogee, 2 main>\0Set igniter mode", + ao_config_ignite_mode_set, ao_config_ignite_mode_show }, +#endif +#if HAS_ACCEL + { "o <0 antenna up, 1 antenna down>\0Set pad orientation", + ao_config_pad_orientation_set,ao_config_pad_orientation_show }, +#endif + { "s\0Show", + ao_config_show, 0 }, +#if HAS_EEPROM + { "w\0Write to eeprom", + ao_config_write, 0 }, +#endif + { "?\0Help", + ao_config_help, 0 }, + { 0, 0, 0 } +}; + +void +ao_config_set(void) +{ + char c; + uint8_t cmd; + void (*__xdata func)(void) __reentrant; + + ao_cmd_white(); + c = ao_cmd_lex_c; + ao_cmd_lex(); + func = 0; + for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) + if (ao_config_vars[cmd].str[0] == c) { + (*ao_config_vars[cmd].set)(); + return; + } + ao_cmd_status = ao_cmd_syntax_error; +} + +static void +ao_config_help(void) __reentrant +{ + uint8_t cmd; + for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) + printf("%-20s %s\n", + ao_config_vars[cmd].str, + ao_config_vars[cmd].str+1+strlen(ao_config_vars[cmd].str)); +} + +static void +ao_config_show(void) __reentrant +{ + uint8_t cmd; + printf("Config version: %d.%d\n", + ao_config.major, ao_config.minor); + for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) + if (ao_config_vars[cmd].show) + (*ao_config_vars[cmd].show)(); +} + +#if HAS_EEPROM +static void +ao_config_write(void) __reentrant +{ + uint8_t saved = 0; + ao_mutex_get(&ao_config_mutex); + if (ao_config_dirty) { + _ao_config_put(); + ao_config_dirty = 0; + saved = 1; + } + ao_mutex_put(&ao_config_mutex); + if (saved) + puts("Saved"); + else + puts("Nothing to save"); +} +#endif + +__code struct ao_cmds ao_config_cmds[] = { + { ao_config_set, "c \0Set config variable (? for help, s to show)" }, + { 0, NULL }, +}; + +void +ao_config_init(void) +{ + ao_cmd_register(&ao_config_cmds[0]); +} diff --git a/src/core/ao_convert.c b/src/core/ao_convert.c new file mode 100644 index 00000000..0969f107 --- /dev/null +++ b/src/core/ao_convert.c @@ -0,0 +1,85 @@ +/* + * 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. + */ + +#if !defined(AO_CONVERT_TEST) && !defined(AO_FLIGHT_TEST) +#include "ao.h" +#endif + +static const int16_t altitude_table[] = { +#include "altitude.h" +}; + +#define ALT_FRAC_SCALE (1 << ALT_FRAC_BITS) +#define ALT_FRAC_MASK (ALT_FRAC_SCALE - 1) + +int16_t +ao_pres_to_altitude(int16_t pres) __reentrant +{ + uint8_t o; + int16_t part; + + if (pres < 0) + pres = 0; + o = pres >> ALT_FRAC_BITS; + part = pres & ALT_FRAC_MASK; + + return ((int32_t) altitude_table[o] * (ALT_FRAC_SCALE - part) + + (int32_t) altitude_table[o+1] * part + (ALT_FRAC_SCALE >> 1)) >> ALT_FRAC_BITS; +} + +int16_t +ao_altitude_to_pres(int16_t alt) __reentrant +{ + int16_t span, sub_span; + uint8_t l, h, m; + int32_t pres; + + l = 0; + h = NALT - 1; + while ((h - l) != 1) { + m = (l + h) >> 1; + if (altitude_table[m] < alt) + h = m; + else + l = m; + } + span = altitude_table[l] - altitude_table[h]; + sub_span = altitude_table[l] - alt; + pres = ((((int32_t) l * (span - sub_span) + (int32_t) h * sub_span) << ALT_FRAC_BITS) + (span >> 1)) / span; + if (pres > 32767) + pres = 32767; + if (pres < 0) + pres = 0; + return (int16_t) pres; +} + +int16_t +ao_temp_to_dC(int16_t temp) __reentrant +{ + int16_t ret; + + /* Output voltage at 0°C = 0.755V + * Coefficient = 0.00247V/°C + * Reference voltage = 1.25V + * + * temp = ((value / 32767) * 1.25 - 0.755) / 0.00247 + * = (value - 19791.268) / 32768 * 1.25 / 0.00247 + * ≃ (value - 19791) * 1012 / 65536 + */ + ret = ((temp - 19791) * 1012L) >> 16; + return ret; +} diff --git a/src/core/ao_convert_test.c b/src/core/ao_convert_test.c new file mode 100644 index 00000000..e2c28b73 --- /dev/null +++ b/src/core/ao_convert_test.c @@ -0,0 +1,75 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#define AO_CONVERT_TEST +#include "ao_host.h" +#include "ao_convert.c" + +#define STEP 1 + +static inline i_abs(int i) { return i < 0 ? -i : i; } + +main () +{ + int i; + int16_t p_to_a, p_to_a_to_p; + int16_t a_to_p, a_to_p_to_a; + int max_p_error = 0, max_p_error_p = -1; + int max_a_error = 0, max_a_error_a = -1; + int p_error; + int a_error; + int ret = 0; + + for (i = 0; i < 32767 + STEP; i += STEP) { + if (i > 32767) + i = 32767; + p_to_a = ao_pres_to_altitude(i); + p_to_a_to_p = ao_altitude_to_pres(p_to_a); + p_error = i_abs(p_to_a_to_p - i); + if (p_error > max_p_error) { + max_p_error = p_error; + max_p_error_p = i; + } +// printf ("pres %d alt %d pres %d\n", +// i, p_to_a, p_to_a_to_p); + } + for (i = -1578; i < 15835 + STEP; i += STEP) { + if (i > 15835) + i = 15835; + a_to_p = ao_altitude_to_pres(i); + a_to_p_to_a = ao_pres_to_altitude(a_to_p); + a_error = i_abs(a_to_p_to_a - i); + if (a_error > max_a_error) { + max_a_error = a_error; + max_a_error_a = i; + } +// printf ("alt %d pres %d alt %d\n", +// i, a_to_p, a_to_p_to_a); + } + if (max_p_error > 2) { + printf ("max p error %d at %d\n", max_p_error, + max_p_error_p); + ret++; + } + if (max_a_error > 1) { + printf ("max a error %d at %d\n", max_a_error, + max_a_error_a); + ret++; + } + return ret; +} diff --git a/src/core/ao_ee_fake.c b/src/core/ao_ee_fake.c new file mode 100644 index 00000000..b0c1d61e --- /dev/null +++ b/src/core/ao_ee_fake.c @@ -0,0 +1,37 @@ +/* + * 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" + +/* + * For hardware without eeprom, the config code still + * wants to call these functions + */ +uint8_t +ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant +{ + (void) buf; + (void) len; + return 1; +} + +uint8_t +ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant +{ + memset(buf, '\0', len); + return 1; +} diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c new file mode 100644 index 00000000..85c1825b --- /dev/null +++ b/src/core/ao_flight.c @@ -0,0 +1,315 @@ +/* + * 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. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#endif + +#ifndef HAS_ACCEL +#error Please define HAS_ACCEL +#endif + +#ifndef HAS_GPS +#error Please define HAS_GPS +#endif + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + +/* Main flight thread. */ + +__pdata enum ao_flight_state ao_flight_state; /* current flight state */ +__pdata uint16_t ao_launch_tick; /* time of launch detect */ + +/* + * track min/max data over a long interval to detect + * resting + */ +__pdata uint16_t ao_interval_end; +__pdata int16_t ao_interval_min_height; +__pdata int16_t ao_interval_max_height; +__pdata uint8_t ao_flight_force_idle; + +/* We also have a clock, which can be used to sanity check things in + * case of other failures + */ + +#define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) + +/* Landing is detected by getting constant readings from both pressure and accelerometer + * for a fairly long time (AO_INTERVAL_TICKS) + */ +#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(10) + +#define abs(a) ((a) < 0 ? -(a) : (a)) + +void +ao_flight(void) +{ + ao_sample_init(); + ao_flight_state = ao_flight_startup; + for (;;) { + + /* + * Process ADC samples, just looping + * until the sensors are calibrated. + */ + if (!ao_sample()) + continue; + + switch (ao_flight_state) { + case ao_flight_startup: + + /* Check to see what mode we should go to. + * - Invalid mode if accel cal appears to be out + * - pad mode if we're upright, + * - idle mode otherwise + */ +#if HAS_ACCEL + if (ao_config.accel_plus_g == 0 || + ao_config.accel_minus_g == 0 || + ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || + ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) + { + /* Detected an accel value outside -1.5g to 1.5g + * (or uncalibrated values), so we go into invalid mode + */ + ao_flight_state = ao_flight_invalid; + + } else +#endif + if (!ao_flight_force_idle +#if HAS_ACCEL + && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP +#endif + ) + { + /* Set pad mode - we can fly! */ + ao_flight_state = ao_flight_pad; +#if HAS_USB + /* Disable the USB controller in flight mode + * to save power + */ + ao_usb_disable(); +#endif + + /* Disable packet mode in pad state */ + ao_packet_slave_stop(); + + /* Turn on telemetry system */ + ao_rdf_set(1); + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); + + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } else { + /* Set idle mode */ + ao_flight_state = ao_flight_idle; + + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } + /* wakeup threads due to state change */ + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + + break; + case ao_flight_pad: + + /* pad to boost: + * + * barometer: > 20m vertical motion + * OR + * accelerometer: > 2g AND velocity > 5m/s + * + * The accelerometer should always detect motion before + * the barometer, but we use both to make sure this + * transition is detected. If the device + * doesn't have an accelerometer, then ignore the + * speed and acceleration as they are quite noisy + * on the pad. + */ + if (ao_height > AO_M_TO_HEIGHT(20) +#if HAS_ACCEL + || (ao_accel > AO_MSS_TO_ACCEL(20) && + ao_speed > AO_MS_TO_SPEED(5)) +#endif + ) + { + ao_flight_state = ao_flight_boost; + ao_launch_tick = ao_sample_tick; + + /* start logging data */ + ao_log_start(); + + /* Increase telemetry rate */ + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); + + /* disable RDF beacon */ + ao_rdf_set(0); + +#if HAS_GPS + /* Record current GPS position by waking up GPS log tasks */ + ao_wakeup(&ao_gps_data); + ao_wakeup(&ao_gps_tracking_data); +#endif + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + case ao_flight_boost: + + /* boost to fast: + * + * accelerometer: start to fall at > 1/4 G + * OR + * time: boost for more than 15 seconds + * + * Detects motor burn out by the switch from acceleration to + * deceleration, or by waiting until the maximum burn duration + * (15 seconds) has past. + */ + if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || + (int16_t) (ao_sample_tick - ao_launch_tick) > BOOST_TICKS_MAX) + { +#if HAS_ACCEL + ao_flight_state = ao_flight_fast; +#else + ao_flight_state = ao_flight_coast; +#endif + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; +#if HAS_ACCEL + case ao_flight_fast: + /* + * This is essentially the same as coast, + * but the barometer is being ignored as + * it may be unreliable. + */ + if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) + { + ao_flight_state = ao_flight_coast; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; +#endif + case ao_flight_coast: + + /* apogee detect: coast to drogue deploy: + * + * speed: < 0 + * + * Also make sure the model altitude is tracking + * the measured altitude reasonably closely; otherwise + * we're probably transsonic. + */ + if (ao_speed < 0 +#if !HAS_ACCEL + && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) +#endif + ) + { + /* ignite the drogue charge */ + ao_ignite(ao_igniter_drogue); + + /* slow down the telemetry system */ + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); + + /* Turn the RDF beacon back on */ + ao_rdf_set(1); + + /* and enter drogue state */ + ao_flight_state = ao_flight_drogue; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + + break; + case ao_flight_drogue: + + /* drogue to main deploy: + * + * barometer: reach main deploy altitude + * + * Would like to use the accelerometer for this test, but + * the orientation of the flight computer is unknown after + * drogue deploy, so we ignore it. Could also detect + * high descent rate using the pressure sensor to + * recognize drogue deploy failure and eject the main + * at that point. Perhaps also use the drogue sense lines + * to notice continutity? + */ + if (ao_height <= ao_config.main_deploy) + { + ao_ignite(ao_igniter_main); + + /* + * Start recording min/max height + * to figure out when the rocket has landed + */ + + /* initialize interval values */ + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + + ao_interval_min_height = ao_interval_max_height = ao_avg_height; + + ao_flight_state = ao_flight_main; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + + /* fall through... */ + case ao_flight_main: + + /* main to land: + * + * barometer: altitude stable + */ + + if (ao_avg_height < ao_interval_min_height) + ao_interval_min_height = ao_avg_height; + if (ao_avg_height > ao_interval_max_height) + ao_interval_max_height = ao_avg_height; + + if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { + if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4)) + { + ao_flight_state = ao_flight_landed; + + /* turn off the ADC capture */ + ao_timer_set_adc_interval(0); + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + ao_interval_min_height = ao_interval_max_height = ao_avg_height; + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + } + break; + case ao_flight_landed: + break; + } + } +} + +static __xdata struct ao_task flight_task; + +void +ao_flight_init(void) +{ + ao_flight_state = ao_flight_startup; + ao_add_task(&flight_task, ao_flight, "flight"); +} diff --git a/src/core/ao_flight_nano.c b/src/core/ao_flight_nano.c new file mode 100644 index 00000000..2e332b12 --- /dev/null +++ b/src/core/ao_flight_nano.c @@ -0,0 +1,120 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +/* Main flight thread. */ + +__pdata enum ao_flight_state ao_flight_state; /* current flight state */ +__pdata uint16_t ao_launch_tick; /* time of launch detect */ + +/* + * track min/max data over a long interval to detect + * resting + */ +__pdata uint16_t ao_interval_end; +__pdata int16_t ao_interval_min_height; +__pdata int16_t ao_interval_max_height; + +__pdata uint8_t ao_flight_force_idle; + +/* Landing is detected by getting constant readings from both pressure and accelerometer + * for a fairly long time (AO_INTERVAL_TICKS) + */ +#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(5) + +static void +ao_flight_nano(void) +{ + ao_sample_init(); + ao_flight_state = ao_flight_startup; + + for (;;) { + /* + * Process ADC samples, just looping + * until the sensors are calibrated. + */ + if (!ao_sample()) + continue; + + switch (ao_flight_state) { + case ao_flight_startup: + if (ao_flight_force_idle) { + /* Set idle mode */ + ao_flight_state = ao_flight_idle; + } else { + ao_flight_state = ao_flight_pad; + /* Disable packet mode in pad state */ + ao_packet_slave_stop(); + + /* Turn on telemetry system */ + ao_rdf_set(1); + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); + } + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + + /* wakeup threads due to state change */ + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + break; + case ao_flight_pad: + if (ao_height> AO_M_TO_HEIGHT(20)) { + ao_flight_state = ao_flight_drogue; + ao_launch_tick = ao_sample_tick; + + /* start logging data */ + ao_log_start(); + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + case ao_flight_drogue: + /* drogue/main to land: + * + * barometer: altitude stable + */ + + if (ao_height < ao_interval_min_height) + ao_interval_min_height = ao_height; + if (ao_height > ao_interval_max_height) + ao_interval_max_height = ao_height; + + if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { + if (ao_interval_max_height - ao_interval_min_height < AO_M_TO_HEIGHT(5)) + { + ao_flight_state = ao_flight_landed; + + /* turn off the ADC capture */ + ao_timer_set_adc_interval(0); + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + ao_interval_min_height = ao_interval_max_height = ao_height; + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + } + break; + } + } +} + +static __xdata struct ao_task flight_task; + +void +ao_flight_nano_init(void) +{ + ao_flight_state = ao_flight_startup; + ao_add_task(&flight_task, ao_flight_nano, "flight"); +} diff --git a/src/core/ao_gps_print.c b/src/core/ao_gps_print.c new file mode 100644 index 00000000..fcdedd30 --- /dev/null +++ b/src/core/ao_gps_print.c @@ -0,0 +1,112 @@ +/* + * 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. + */ + +#ifndef AO_GPS_TEST +#include "ao.h" +#endif +#include "ao_telem.h" + +void +ao_gps_print(__xdata struct ao_gps_orig *gps_data) __reentrant +{ + char state; + + if (gps_data->flags & AO_GPS_VALID) + state = AO_TELEM_GPS_STATE_LOCKED; + else if (gps_data->flags & AO_GPS_RUNNING) + state = AO_TELEM_GPS_STATE_UNLOCKED; + else + state = AO_TELEM_GPS_STATE_ERROR; + printf(AO_TELEM_GPS_STATE " %c " + AO_TELEM_GPS_NUM_SAT " %d ", + state, + (gps_data->flags & AO_GPS_NUM_SAT_MASK) >> AO_GPS_NUM_SAT_SHIFT); + if (!(gps_data->flags & AO_GPS_VALID)) + return; + printf(AO_TELEM_GPS_LATITUDE " %ld " + AO_TELEM_GPS_LONGITUDE " %ld " + AO_TELEM_GPS_ALTITUDE " %d ", + gps_data->latitude, + gps_data->longitude, + gps_data->altitude); + + if (gps_data->flags & AO_GPS_DATE_VALID) + printf(AO_TELEM_GPS_YEAR " %d " + AO_TELEM_GPS_MONTH " %d " + AO_TELEM_GPS_DAY " %d ", + gps_data->year, + gps_data->month, + gps_data->day); + + printf(AO_TELEM_GPS_HOUR " %d " + AO_TELEM_GPS_MINUTE " %d " + AO_TELEM_GPS_SECOND " %d ", + gps_data->hour, + gps_data->minute, + gps_data->second); + + printf(AO_TELEM_GPS_HDOP " %d ", + gps_data->hdop * 2); + + if (gps_data->flags & AO_GPS_COURSE_VALID) { + printf(AO_TELEM_GPS_HERROR " %d " + AO_TELEM_GPS_VERROR " %d " + AO_TELEM_GPS_VERTICAL_SPEED " %d " + AO_TELEM_GPS_HORIZONTAL_SPEED " %d " + AO_TELEM_GPS_COURSE " %d ", + gps_data->h_error, + gps_data->v_error, + gps_data->climb_rate, + gps_data->ground_speed, + (int) gps_data->course * 2); + } +} + +void +ao_gps_tracking_print(__xdata struct ao_gps_tracking_orig *gps_tracking_data) __reentrant +{ + uint8_t c, n, v; + __xdata struct ao_gps_sat_orig *sat; + + n = gps_tracking_data->channels; + if (n == 0) + return; + + sat = gps_tracking_data->sats; + v = 0; + for (c = 0; c < n; c++) { + if (sat->svid) + v++; + sat++; + } + + printf (AO_TELEM_SAT_NUM " %d ", + v); + + sat = gps_tracking_data->sats; + v = 0; + for (c = 0; c < n; c++) { + if (sat->svid) { + printf (AO_TELEM_SAT_SVID "%d %d " + AO_TELEM_SAT_C_N_0 "%d %d ", + v, sat->svid, + v, sat->c_n_1); + v++; + } + sat++; + } +} diff --git a/src/core/ao_gps_report.c b/src/core/ao_gps_report.c new file mode 100644 index 00000000..e57f8744 --- /dev/null +++ b/src/core/ao_gps_report.c @@ -0,0 +1,99 @@ +/* + * 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_report(void) +{ + static __xdata struct ao_log_record gps_log; + static __xdata struct ao_telemetry_location gps_data; + uint8_t date_reported = 0; + + for (;;) { + ao_sleep(&ao_gps_data); + ao_mutex_get(&ao_gps_mutex); + memcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); + ao_mutex_put(&ao_gps_mutex); + + if (!(gps_data.flags & AO_GPS_VALID)) + continue; + + gps_log.tick = ao_gps_tick; + gps_log.type = AO_LOG_GPS_TIME; + gps_log.u.gps_time.hour = gps_data.hour; + gps_log.u.gps_time.minute = gps_data.minute; + gps_log.u.gps_time.second = gps_data.second; + gps_log.u.gps_time.flags = gps_data.flags; + ao_log_data(&gps_log); + gps_log.type = AO_LOG_GPS_LAT; + gps_log.u.gps_latitude = gps_data.latitude; + ao_log_data(&gps_log); + gps_log.type = AO_LOG_GPS_LON; + gps_log.u.gps_longitude = gps_data.longitude; + ao_log_data(&gps_log); + gps_log.type = AO_LOG_GPS_ALT; + gps_log.u.gps_altitude.altitude = gps_data.altitude; + gps_log.u.gps_altitude.unused = 0xffff; + ao_log_data(&gps_log); + if (!date_reported && (gps_data.flags & AO_GPS_DATE_VALID)) { + gps_log.type = AO_LOG_GPS_DATE; + gps_log.u.gps_date.year = gps_data.year; + gps_log.u.gps_date.month = gps_data.month; + gps_log.u.gps_date.day = gps_data.day; + gps_log.u.gps_date.extra = 0; + date_reported = ao_log_data(&gps_log); + } + } +} + +void +ao_gps_tracking_report(void) +{ + static __xdata struct ao_log_record gps_log; + static __xdata struct ao_telemetry_satellite gps_tracking_data; + uint8_t c, n; + + for (;;) { + ao_sleep(&ao_gps_tracking_data); + ao_mutex_get(&ao_gps_mutex); + gps_log.tick = ao_gps_tick; + memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); + ao_mutex_put(&ao_gps_mutex); + + if (!(n = gps_tracking_data.channels)) + continue; + + gps_log.type = AO_LOG_GPS_SAT; + for (c = 0; c < n; c++) + if ((gps_log.u.gps_sat.svid = gps_tracking_data.sats[c].svid)) + { + gps_log.u.gps_sat.c_n = gps_tracking_data.sats[c].c_n_1; + ao_log_data(&gps_log); + } + } +} + +__xdata struct ao_task ao_gps_report_task; +__xdata struct ao_task ao_gps_tracking_report_task; + +void +ao_gps_report_init(void) +{ + ao_add_task(&ao_gps_report_task, ao_gps_report, "gps_report"); + ao_add_task(&ao_gps_tracking_report_task, ao_gps_tracking_report, "gps_tracking_report"); +} diff --git a/src/core/ao_host.h b/src/core/ao_host.h new file mode 100644 index 00000000..65c25fe5 --- /dev/null +++ b/src/core/ao_host.h @@ -0,0 +1,127 @@ +/* + * 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 _GNU_SOURCE + +#include +#include +#include +#include +#include + +#define AO_ADC_RING 64 +#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) +#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) + +/* + * One set of samples read from the A/D converter + */ +struct ao_adc { + uint16_t tick; /* tick when the sample was read */ + int16_t accel; /* accelerometer */ + int16_t pres; /* pressure sensor */ + int16_t temp; /* temperature sensor */ + int16_t v_batt; /* battery voltage */ + int16_t sense_d; /* drogue continuity sense */ + int16_t sense_m; /* main continuity sense */ +}; + +#define __pdata +#define __data +#define __xdata +#define __code +#define __reentrant + +enum ao_flight_state { + ao_flight_startup = 0, + ao_flight_idle = 1, + ao_flight_pad = 2, + ao_flight_boost = 3, + ao_flight_fast = 4, + ao_flight_coast = 5, + ao_flight_drogue = 6, + ao_flight_main = 7, + ao_flight_landed = 8, + ao_flight_invalid = 9 +}; + +struct ao_adc ao_adc_ring[AO_ADC_RING]; +uint8_t ao_adc_head; + +#define ao_led_on(l) +#define ao_led_off(l) +#define ao_timer_set_adc_interval(i) +#define ao_wakeup(wchan) ao_dump_state(wchan) +#define ao_cmd_register(c) +#define ao_usb_disable() +#define ao_telemetry_set_interval(x) +#define ao_delay(x) + +enum ao_igniter { + ao_igniter_drogue = 0, + ao_igniter_main = 1 +}; + +void +ao_ignite(enum ao_igniter igniter) +{ + printf ("ignite %s\n", igniter == ao_igniter_drogue ? "drogue" : "main"); +} + +struct ao_task { + int dummy; +}; + +#define ao_add_task(t,f,n) + +#define ao_log_start() +#define ao_log_stop() + +#define AO_MS_TO_TICKS(ms) ((ms) / 10) +#define AO_SEC_TO_TICKS(s) ((s) * 100) + +#define AO_FLIGHT_TEST + +struct ao_adc ao_adc_static; + +FILE *emulator_in; + +void +ao_dump_state(void *wchan); + +void +ao_sleep(void *wchan); + +const char const * const ao_state_names[] = { + "startup", "idle", "pad", "boost", "fast", + "coast", "drogue", "main", "landed", "invalid" +}; + +struct ao_cmds { + void (*func)(void); + const char *help; +}; + + +struct ao_config { + uint16_t main_deploy; + int16_t accel_zero_g; +}; + +#define ao_config_get() + +struct ao_config ao_config = { 250, 16000 }; diff --git a/src/core/ao_kalman.c b/src/core/ao_kalman.c new file mode 100644 index 00000000..ee01949e --- /dev/null +++ b/src/core/ao_kalman.c @@ -0,0 +1,292 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#endif + +#include "ao_kalman.h" + +static __pdata int32_t ao_k_height; +static __pdata int32_t ao_k_speed; +static __pdata int32_t ao_k_accel; + +#define AO_K_STEP_100 to_fix16(0.01) +#define AO_K_STEP_2_2_100 to_fix16(0.00005) + +#define AO_K_STEP_10 to_fix16(0.1) +#define AO_K_STEP_2_2_10 to_fix16(0.005) + +#define AO_K_STEP_1 to_fix16(1) +#define AO_K_STEP_2_2_1 to_fix16(0.5) + +__pdata int16_t ao_height; +__pdata int16_t ao_speed; +__pdata int16_t ao_accel; +__pdata int16_t ao_max_height; +static __pdata int32_t ao_avg_height_scaled; +__pdata int16_t ao_avg_height; + +__pdata int16_t ao_error_h; +__pdata int16_t ao_error_h_sq_avg; + +#if HAS_ACCEL +__pdata int16_t ao_error_a; +#endif + +static void +ao_kalman_predict(void) +{ +#ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 50) { + ao_k_height += ((int32_t) ao_speed * AO_K_STEP_1 + + (int32_t) ao_accel * AO_K_STEP_2_2_1) >> 4; + ao_k_speed += (int32_t) ao_accel * AO_K_STEP_1; + + return; + } + if (ao_sample_tick - ao_sample_prev_tick > 5) { + ao_k_height += ((int32_t) ao_speed * AO_K_STEP_10 + + (int32_t) ao_accel * AO_K_STEP_2_2_10) >> 4; + ao_k_speed += (int32_t) ao_accel * AO_K_STEP_10; + + return; + } + if (ao_flight_debug) { + printf ("predict speed %g + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), ao_accel / 16.0, AO_K_STEP_100 / 65536.0, + (ao_k_speed + (int32_t) ao_accel * AO_K_STEP_100) / (65536.0 * 16.0)); + } +#endif + ao_k_height += ((int32_t) ao_speed * AO_K_STEP_100 + + (int32_t) ao_accel * AO_K_STEP_2_2_100) >> 4; + ao_k_speed += (int32_t) ao_accel * AO_K_STEP_100; +} + +static void +ao_kalman_err_height(void) +{ + int16_t e; + int16_t height_distrust; +#if HAS_ACCEL + int16_t speed_distrust; +#endif + + ao_error_h = ao_sample_height - (int16_t) (ao_k_height >> 16); + + e = ao_error_h; + if (e < 0) + e = -e; + if (e > 127) + e = 127; +#if HAS_ACCEL + ao_error_h_sq_avg -= ao_error_h_sq_avg >> 2; + ao_error_h_sq_avg += (e * e) >> 2; +#else + ao_error_h_sq_avg -= ao_error_h_sq_avg >> 4; + ao_error_h_sq_avg += (e * e) >> 4; +#endif + + if (ao_flight_state >= ao_flight_drogue) + return; + height_distrust = ao_sample_alt - AO_MAX_BARO_HEIGHT; +#if HAS_ACCEL + /* speed is stored * 16, but we need to ramp between 200 and 328, so + * we want to multiply by 2. The result is a shift by 3. + */ + speed_distrust = (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) >> (4 - 1); + if (speed_distrust <= 0) + speed_distrust = 0; + else if (speed_distrust > height_distrust) + height_distrust = speed_distrust; +#endif + if (height_distrust > 0) { +#ifdef AO_FLIGHT_TEST + int old_ao_error_h = ao_error_h; +#endif + if (height_distrust > 0x100) + height_distrust = 0x100; + ao_error_h = (int16_t) (((int32_t) ao_error_h * (0x100 - height_distrust)) >> 8); +#ifdef AO_FLIGHT_TEST + if (ao_flight_debug) { + printf("over height %g over speed %g distrust: %g height: error %d -> %d\n", + (double) (ao_sample_alt - AO_MAX_BARO_HEIGHT), + (ao_speed - AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) / 16.0, + height_distrust / 256.0, + old_ao_error_h, ao_error_h); + } +#endif + } +} + +static void +ao_kalman_correct_baro(void) +{ + ao_kalman_err_height(); +#ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 50) { + ao_k_height += (int32_t) AO_BARO_K0_1 * ao_error_h; + ao_k_speed += (int32_t) AO_BARO_K1_1 * ao_error_h; + ao_k_accel += (int32_t) AO_BARO_K2_1 * ao_error_h; + return; + } + if (ao_sample_tick - ao_sample_prev_tick > 5) { + ao_k_height += (int32_t) AO_BARO_K0_10 * ao_error_h; + ao_k_speed += (int32_t) AO_BARO_K1_10 * ao_error_h; + ao_k_accel += (int32_t) AO_BARO_K2_10 * ao_error_h; + return; + } +#endif + ao_k_height += (int32_t) AO_BARO_K0_100 * ao_error_h; + ao_k_speed += (int32_t) AO_BARO_K1_100 * ao_error_h; + ao_k_accel += (int32_t) AO_BARO_K2_100 * ao_error_h; +} + +#if HAS_ACCEL + +static void +ao_kalman_err_accel(void) +{ + int32_t accel; + + accel = (ao_ground_accel - ao_sample_accel) * ao_accel_scale; + + /* Can't use ao_accel here as it is the pre-prediction value still */ + ao_error_a = (accel - ao_k_accel) >> 16; +} + +static void +ao_kalman_correct_both(void) +{ + ao_kalman_err_height(); + ao_kalman_err_accel(); + +#ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 50) { + if (ao_flight_debug) { + printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), + (double) ao_error_h, AO_BOTH_K10_1 / 65536.0, + (double) ao_error_a, AO_BOTH_K11_1 / 65536.0, + (ao_k_speed + + (int32_t) AO_BOTH_K10_1 * ao_error_h + + (int32_t) AO_BOTH_K11_1 * ao_error_a) / (65536.0 * 16.0)); + } + ao_k_height += + (int32_t) AO_BOTH_K00_1 * ao_error_h + + (int32_t) AO_BOTH_K01_1 * ao_error_a; + ao_k_speed += + (int32_t) AO_BOTH_K10_1 * ao_error_h + + (int32_t) AO_BOTH_K11_1 * ao_error_a; + ao_k_accel += + (int32_t) AO_BOTH_K20_1 * ao_error_h + + (int32_t) AO_BOTH_K21_1 * ao_error_a; + return; + } + if (ao_sample_tick - ao_sample_prev_tick > 5) { + if (ao_flight_debug) { + printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), + (double) ao_error_h, AO_BOTH_K10_10 / 65536.0, + (double) ao_error_a, AO_BOTH_K11_10 / 65536.0, + (ao_k_speed + + (int32_t) AO_BOTH_K10_10 * ao_error_h + + (int32_t) AO_BOTH_K11_10 * ao_error_a) / (65536.0 * 16.0)); + } + ao_k_height += + (int32_t) AO_BOTH_K00_10 * ao_error_h + + (int32_t) AO_BOTH_K01_10 * ao_error_a; + ao_k_speed += + (int32_t) AO_BOTH_K10_10 * ao_error_h + + (int32_t) AO_BOTH_K11_10 * ao_error_a; + ao_k_accel += + (int32_t) AO_BOTH_K20_10 * ao_error_h + + (int32_t) AO_BOTH_K21_10 * ao_error_a; + return; + } + if (ao_flight_debug) { + printf ("correct speed %g + (%g * %g) + (%g * %g) = %g\n", + ao_k_speed / (65536.0 * 16.0), + (double) ao_error_h, AO_BOTH_K10_100 / 65536.0, + (double) ao_error_a, AO_BOTH_K11_100 / 65536.0, + (ao_k_speed + + (int32_t) AO_BOTH_K10_100 * ao_error_h + + (int32_t) AO_BOTH_K11_100 * ao_error_a) / (65536.0 * 16.0)); + } +#endif + ao_k_height += + (int32_t) AO_BOTH_K00_100 * ao_error_h + + (int32_t) AO_BOTH_K01_100 * ao_error_a; + ao_k_speed += + (int32_t) AO_BOTH_K10_100 * ao_error_h + + (int32_t) AO_BOTH_K11_100 * ao_error_a; + ao_k_accel += + (int32_t) AO_BOTH_K20_100 * ao_error_h + + (int32_t) AO_BOTH_K21_100 * ao_error_a; +} + +#ifdef FORCE_ACCEL +static void +ao_kalman_correct_accel(void) +{ + ao_kalman_err_accel(); + + if (ao_sample_tick - ao_sample_prev_tick > 5) { + ao_k_height +=(int32_t) AO_ACCEL_K0_10 * ao_error_a; + ao_k_speed += (int32_t) AO_ACCEL_K1_10 * ao_error_a; + ao_k_accel += (int32_t) AO_ACCEL_K2_10 * ao_error_a; + return; + } + ao_k_height += (int32_t) AO_ACCEL_K0_100 * ao_error_a; + ao_k_speed += (int32_t) AO_ACCEL_K1_100 * ao_error_a; + ao_k_accel += (int32_t) AO_ACCEL_K2_100 * ao_error_a; +} +#endif +#endif /* HAS_ACCEL */ + +void +ao_kalman(void) +{ + ao_kalman_predict(); +#if HAS_ACCEL + if (ao_flight_state <= ao_flight_coast) { +#ifdef FORCE_ACCEL + ao_kalman_correct_accel(); +#else + ao_kalman_correct_both(); +#endif + } else +#endif + ao_kalman_correct_baro(); + ao_height = from_fix(ao_k_height); + ao_speed = from_fix(ao_k_speed); + ao_accel = from_fix(ao_k_accel); + if (ao_height > ao_max_height) + ao_max_height = ao_height; + ao_avg_height_scaled = ao_avg_height_scaled - ao_avg_height + ao_sample_height; +#ifdef AO_FLIGHT_TEST + if (ao_sample_tick - ao_sample_prev_tick > 50) + ao_avg_height = (ao_avg_height_scaled + 1) >> 1; + else if (ao_sample_tick - ao_sample_prev_tick > 5) + ao_avg_height = (ao_avg_height_scaled + 7) >> 4; + else +#endif + ao_avg_height = (ao_avg_height_scaled + 63) >> 7; +#ifdef AO_FLIGHT_TEST + ao_sample_prev_tick = ao_sample_tick; +#endif +} diff --git a/src/core/ao_log.c b/src/core/ao_log.c new file mode 100644 index 00000000..6d3ad535 --- /dev/null +++ b/src/core/ao_log.c @@ -0,0 +1,284 @@ +/* + * 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" + +__pdata uint32_t ao_log_current_pos; +__pdata uint32_t ao_log_end_pos; +__pdata uint32_t ao_log_start_pos; +__xdata uint8_t ao_log_running; +__pdata enum flight_state ao_log_state; +__xdata uint16_t ao_flight_number; + +__code uint8_t ao_log_format = AO_LOG_FORMAT_FULL; + +void +ao_log_flush(void) +{ + ao_storage_flush(); +} + +/* + * When erasing a flight log, make sure the config block + * has an up-to-date version of the current flight number + */ + +struct ao_log_erase { + uint8_t unused; + uint16_t flight; +}; + +static __xdata struct ao_log_erase erase; + +#define LOG_MAX_ERASE 16 + +static uint32_t +ao_log_erase_pos(uint8_t i) +{ + return i * sizeof (struct ao_log_erase) + AO_STORAGE_ERASE_LOG; +} + +void +ao_log_write_erase(uint8_t pos) +{ + erase.unused = 0x00; + erase.flight = ao_flight_number; + ao_storage_write(ao_log_erase_pos(pos), &erase, sizeof (erase)); + ao_storage_flush(); +} + +static void +ao_log_read_erase(uint8_t pos) +{ + ao_storage_read(ao_log_erase_pos(pos), &erase, sizeof (erase)); +} + + +static void +ao_log_erase_mark(void) +{ + uint8_t i; + + for (i = 0; i < LOG_MAX_ERASE; i++) { + ao_log_read_erase(i); + if (erase.unused == 0 && erase.flight == ao_flight_number) + return; + if (erase.unused == 0xff) { + ao_log_write_erase(i); + return; + } + } + ao_config_put(); +} + +static uint8_t +ao_log_slots() +{ + return (uint8_t) (ao_storage_config / ao_config.flight_log_max); +} + +uint32_t +ao_log_pos(uint8_t slot) +{ + return ((slot) * ao_config.flight_log_max); +} + +static uint16_t +ao_log_max_flight(void) +{ + uint8_t log_slot; + uint8_t log_slots; + uint16_t log_flight; + uint16_t max_flight = 0; + + /* Scan the log space looking for the biggest flight number */ + log_slots = ao_log_slots(); + for (log_slot = 0; log_slot < log_slots; log_slot++) { + log_flight = ao_log_flight(log_slot); + if (!log_flight) + continue; + if (max_flight == 0 || (int16_t) (log_flight - max_flight) > 0) + max_flight = log_flight; + } + return max_flight; +} + +void +ao_log_scan(void) __reentrant +{ + uint8_t log_slot; + uint8_t log_slots; + uint8_t log_want; + + ao_config_get(); + + ao_flight_number = ao_log_max_flight(); + if (ao_flight_number) + if (++ao_flight_number == 0) + ao_flight_number = 1; + + /* Now look through the log of flight numbers from erase operations and + * see if the last one is bigger than what we found above + */ + for (log_slot = LOG_MAX_ERASE; log_slot-- > 0;) { + ao_log_read_erase(log_slot); + if (erase.unused == 0) { + if (ao_flight_number == 0 || + (int16_t) (erase.flight - ao_flight_number) > 0) + ao_flight_number = erase.flight; + break; + } + } + if (ao_flight_number == 0) + ao_flight_number = 1; + + /* With a flight number in hand, find a place to write a new log, + * use the target flight number to index the available log slots so + * that we write logs to each spot about the same number of times. + */ + + /* Find a log slot for the next flight, if available */ + ao_log_current_pos = ao_log_end_pos = 0; + log_slots = ao_log_slots(); + log_want = (ao_flight_number - 1) % log_slots; + log_slot = log_want; + do { + if (ao_log_flight(log_slot) == 0) { + ao_log_current_pos = ao_log_pos(log_slot); + ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; + break; + } + if (++log_slot >= log_slots) + log_slot = 0; + } while (log_slot != log_want); + + ao_wakeup(&ao_flight_number); +} + +void +ao_log_start(void) +{ + /* start logging */ + ao_log_running = 1; + ao_wakeup(&ao_log_running); +} + +void +ao_log_stop(void) +{ + ao_log_running = 0; + ao_log_flush(); +} + +uint8_t +ao_log_present(void) +{ + return ao_log_max_flight() != 0; +} + +uint8_t +ao_log_full(void) +{ + return ao_log_current_pos == ao_log_end_pos; +} + +static __xdata struct ao_task ao_log_task; + +void +ao_log_list(void) __reentrant +{ + uint8_t slot; + uint8_t slots; + uint16_t flight; + + slots = ao_log_slots(); + for (slot = 0; slot < slots; slot++) + { + flight = ao_log_flight(slot); + if (flight) + printf ("flight %d start %x end %x\n", + flight, + (uint16_t) (ao_log_pos(slot) >> 8), + (uint16_t) (ao_log_pos(slot+1) >> 8)); + } + printf ("done\n"); +} + +void +ao_log_delete(void) __reentrant +{ + uint8_t slot; + uint8_t slots; + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + + slots = ao_log_slots(); + /* Look for the flight log matching the requested flight */ + if (ao_cmd_lex_i) { + for (slot = 0; slot < slots; slot++) { + if (ao_log_flight(slot) == ao_cmd_lex_i) { + ao_log_erase_mark(); + ao_log_current_pos = ao_log_pos(slot); + ao_log_end_pos = ao_log_current_pos + ao_config.flight_log_max; + while (ao_log_current_pos < ao_log_end_pos) { + uint8_t i; + static __xdata uint8_t b; + + /* + * Check to see if we've reached the end of + * the used memory to avoid re-erasing the same + * memory over and over again + */ + for (i = 0; i < 16; i++) { + if (ao_storage_read(ao_log_current_pos + i, &b, 1)) + if (b != 0xff) + break; + } + if (i == 16) + break; + ao_storage_erase(ao_log_current_pos); + ao_log_current_pos += ao_storage_block; + } + puts("Erased"); + return; + } + } + } + printf("No such flight: %d\n", ao_cmd_lex_i); +} + +__code struct ao_cmds ao_log_cmds[] = { + { ao_log_list, "l\0List flight logs" }, + { ao_log_delete, "d \0Delete flight" }, + { 0, NULL }, +}; + +void +ao_log_init(void) +{ + ao_log_running = 0; + + /* For now, just log the flight starting at the begining of eeprom */ + ao_log_state = ao_flight_invalid; + + ao_cmd_register(&ao_log_cmds[0]); + + /* Create a task to log events to eeprom */ + ao_add_task(&ao_log_task, ao_log, "log"); +} diff --git a/src/core/ao_log_big.c b/src/core/ao_log_big.c new file mode 100644 index 00000000..74d94c4b --- /dev/null +++ b/src/core/ao_log_big.c @@ -0,0 +1,158 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static __xdata uint8_t ao_log_mutex; +static __xdata struct ao_log_record log; + +static uint8_t +ao_log_csum(__xdata uint8_t *b) __reentrant +{ + uint8_t sum = 0x5a; + uint8_t i; + + for (i = 0; i < sizeof (struct ao_log_record); i++) + sum += *b++; + return -sum; +} + +uint8_t +ao_log_data(__xdata struct ao_log_record *log) __reentrant +{ + uint8_t wrote = 0; + /* set checksum */ + log->csum = 0; + log->csum = ao_log_csum((__xdata uint8_t *) log); + ao_mutex_get(&ao_log_mutex); { + if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_stop(); + if (ao_log_running) { + wrote = 1; + ao_storage_write(ao_log_current_pos, + log, + sizeof (struct ao_log_record)); + ao_log_current_pos += sizeof (struct ao_log_record); + } + } ao_mutex_put(&ao_log_mutex); + return wrote; +} + +static uint8_t +ao_log_dump_check_data(void) +{ + if (ao_log_csum((uint8_t *) &log) != 0) + return 0; + return 1; +} + +static __data uint8_t ao_log_adc_pos; + +/* a hack to make sure that ao_log_records fill the eeprom block in even units */ +typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; + +#define AO_SENSOR_INTERVAL_ASCENT 1 +#define AO_SENSOR_INTERVAL_DESCENT 10 +#define AO_OTHER_INTERVAL 32 + +void +ao_log(void) +{ + __pdata uint16_t next_sensor, next_other; + + ao_storage_setup(); + + ao_log_scan(); + + while (!ao_log_running) + ao_sleep(&ao_log_running); + + log.type = AO_LOG_FLIGHT; + log.tick = ao_sample_tick; +#if HAS_ACCEL + log.u.flight.ground_accel = ao_ground_accel; +#endif + log.u.flight.flight = ao_flight_number; + ao_log_data(&log); + + /* Write the whole contents of the ring to the log + * when starting up. + */ + ao_log_adc_pos = ao_adc_ring_next(ao_sample_adc); + next_other = next_sensor = ao_adc_ring[ao_log_adc_pos].tick; + ao_log_state = ao_flight_startup; + for (;;) { + /* Write samples to EEPROM */ + while (ao_log_adc_pos != ao_sample_adc) { + log.tick = ao_adc_ring[ao_log_adc_pos].tick; + if ((int16_t) (log.tick - next_sensor) >= 0) { + log.type = AO_LOG_SENSOR; + log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel; + log.u.sensor.pres = ao_adc_ring[ao_log_adc_pos].pres; + ao_log_data(&log); + if (ao_log_state <= ao_flight_coast) + next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; + else + next_sensor = log.tick + AO_SENSOR_INTERVAL_DESCENT; + } + if ((int16_t) (log.tick - next_other) >= 0) { + log.type = AO_LOG_TEMP_VOLT; + log.u.temp_volt.temp = ao_adc_ring[ao_log_adc_pos].temp; + log.u.temp_volt.v_batt = ao_adc_ring[ao_log_adc_pos].v_batt; + ao_log_data(&log); + log.type = AO_LOG_DEPLOY; + log.u.deploy.drogue = ao_adc_ring[ao_log_adc_pos].sense_d; + log.u.deploy.main = ao_adc_ring[ao_log_adc_pos].sense_m; + ao_log_data(&log); + next_other = log.tick + AO_OTHER_INTERVAL; + } + ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); + } + /* Write state change to EEPROM */ + if (ao_flight_state != ao_log_state) { + ao_log_state = ao_flight_state; + log.type = AO_LOG_STATE; + log.tick = ao_sample_tick; + log.u.state.state = ao_log_state; + log.u.state.reason = 0; + ao_log_data(&log); + + if (ao_log_state == ao_flight_landed) + ao_log_stop(); + } + + /* Wait for a while */ + ao_delay(AO_MS_TO_TICKS(100)); + + /* Stop logging when told to */ + while (!ao_log_running) + ao_sleep(&ao_log_running); + } +} + +uint16_t +ao_log_flight(uint8_t slot) +{ + if (!ao_storage_read(ao_log_pos(slot), + &log, + sizeof (struct ao_log_record))) + return 0; + + if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) + return log.u.flight.flight; + return 0; +} diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c new file mode 100644 index 00000000..1b472efe --- /dev/null +++ b/src/core/ao_log_telem.c @@ -0,0 +1,30 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +void +ao_log_write_erase(uint8_t pos) +{ + (void) pos; +} + +uint8_t +ao_log_present(void) +{ + return 0; +} diff --git a/src/core/ao_log_tiny.c b/src/core/ao_log_tiny.c new file mode 100644 index 00000000..d5a3b99f --- /dev/null +++ b/src/core/ao_log_tiny.c @@ -0,0 +1,161 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static __data uint16_t ao_log_tiny_interval; + +#define AO_LOG_TINY_INTERVAL_DEFAULT AO_MS_TO_TICKS(1000) +#if USE_FAST_ASCENT_LOG +#define AO_LOG_TINY_INTERVAL_ASCENT AO_MS_TO_TICKS(100) +#define AO_PAD_RING 8 +#else +#define AO_LOG_TINY_INTERVAL_ASCENT AO_LOG_TINY_INTERVAL_DEFAULT +#define AO_PAD_RING 2 +#endif + +__code uint8_t ao_log_format = AO_LOG_FORMAT_TINY; + +void +ao_log_tiny_set_interval(uint16_t ticks) +{ + ao_log_tiny_interval = ticks; +} + + +static void ao_log_tiny_data(uint16_t d) +{ + if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_stop(); + if (ao_log_running) { + ao_storage_write(ao_log_current_pos, DATA_TO_XDATA(&d), 2); + ao_log_current_pos += 2; + } +} + +static __xdata uint16_t ao_log_pad_ring[AO_PAD_RING]; +static __pdata uint8_t ao_log_pad_ring_pos; + +#define ao_pad_ring_next(n) (((n) + 1) & (AO_PAD_RING - 1)) + +static void ao_log_tiny_queue(uint16_t d) +{ + ao_log_pad_ring[ao_log_pad_ring_pos] = d; + ao_log_pad_ring_pos = ao_pad_ring_next(ao_log_pad_ring_pos); +} + +static void ao_log_tiny_start(void) +{ + uint8_t p; + uint16_t d; + + ao_log_tiny_data(ao_flight_number); + ao_log_tiny_data(ao_ground_pres); + p = ao_log_pad_ring_pos; + do { + d = ao_log_pad_ring[p]; + /* + * ignore unwritten slots + */ + if (d) + ao_log_tiny_data(d); + p = ao_pad_ring_next(p); + } while (p != ao_log_pad_ring_pos); +} + +void +ao_log(void) +{ + uint16_t last_time; + uint16_t now; + enum ao_flight_state ao_log_tiny_state; + int32_t sum; + int16_t count; + uint8_t ao_log_adc; + uint8_t ao_log_started = 0; + + ao_storage_setup(); + + ao_log_scan(); + + ao_log_tiny_state = ao_flight_invalid; + ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; + sum = 0; + count = 0; + ao_log_adc = ao_sample_adc; + last_time = ao_time(); + for (;;) { + + /* + * Add in pending sample data + */ + ao_sleep(DATA_TO_XDATA(&ao_sample_adc)); + while (ao_log_adc != ao_sample_adc) { + sum += ao_adc_ring[ao_log_adc].pres; + count++; + ao_log_adc = ao_adc_ring_next(ao_log_adc); + } + if (ao_log_running) { + if (!ao_log_started) { + ao_log_tiny_start(); + ao_log_started = 1; + } + if (ao_flight_state != ao_log_tiny_state) { + ao_log_tiny_data(ao_flight_state | 0x8000); + ao_log_tiny_state = ao_flight_state; + ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_DEFAULT; +#if AO_LOG_TINY_INTERVAL_ASCENT != AO_LOG_TINY_INTERVAL_DEFAULT + if (ao_log_tiny_state <= ao_flight_coast) + ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; +#endif + if (ao_log_tiny_state == ao_flight_landed) + ao_log_stop(); + } + } + + /* Stop logging when told to */ + if (!ao_log_running && ao_log_started) + ao_exit(); + + /* + * Write out the sample when finished + */ + now = ao_time(); + if ((int16_t) (now - (last_time + ao_log_tiny_interval)) >= 0 && count) { + count = sum / count; + if (ao_log_started) + ao_log_tiny_data(count); + else + ao_log_tiny_queue(count); + sum = 0; + count = 0; + last_time = now; + } + } +} + +uint16_t +ao_log_flight(uint8_t slot) +{ + static __xdata uint16_t flight; + + (void) slot; + ao_storage_read(0, &flight, 2); + if (flight == 0xffff) + flight = 0; + return flight; +} diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c new file mode 100644 index 00000000..69eb58e8 --- /dev/null +++ b/src/core/ao_monitor.c @@ -0,0 +1,277 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_telem.h" + +#if !HAS_MONITOR +#error Must define HAS_MONITOR to 1 +#endif + +__xdata uint8_t ao_monitoring; +__pdata uint8_t ao_monitor_led; + +#define AO_MONITOR_RING 8 + +__xdata union ao_monitor { + struct ao_telemetry_raw_recv raw; + struct ao_telemetry_orig_recv orig; + struct ao_telemetry_tiny_recv tiny; +} ao_monitor_ring[AO_MONITOR_RING]; + +#define ao_monitor_ring_next(n) (((n) + 1) & (AO_MONITOR_RING - 1)) + +__data uint8_t ao_monitor_head; + +void +ao_monitor_get(void) +{ + uint8_t size; + + for (;;) { + switch (ao_monitoring) { + case 0: + ao_sleep(&ao_monitoring); + continue; + case AO_MONITORING_ORIG: + size = sizeof (struct ao_telemetry_orig_recv); + break; + case AO_MONITORING_TINY: + size = sizeof (struct ao_telemetry_tiny_recv); + break; + default: + if (ao_monitoring > AO_MAX_TELEMETRY) + ao_monitoring = AO_MAX_TELEMETRY; + size = ao_monitoring; + break; + } + if (!ao_radio_recv(&ao_monitor_ring[ao_monitor_head], size + 2)) + continue; + ao_monitor_head = ao_monitor_ring_next(ao_monitor_head); + ao_wakeup(DATA_TO_XDATA(&ao_monitor_head)); + ao_led_toggle(ao_monitor_led); + } +} + +void +ao_monitor_put(void) +{ + __xdata char callsign[AO_MAX_CALLSIGN+1]; + + uint8_t ao_monitor_tail; + uint8_t state; + uint8_t sum, byte; + int16_t rssi; + __xdata union ao_monitor *m; + +#define recv_raw ((m->raw)) +#define recv_orig ((m->orig)) +#define recv_tiny ((m->tiny)) + + ao_monitor_tail = ao_monitor_head; + for (;;) { + while (ao_monitor_tail == ao_monitor_head) + ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); + m = &ao_monitor_ring[ao_monitor_tail]; + ao_monitor_tail = ao_monitor_ring_next(ao_monitor_tail); + switch (ao_monitoring) { + case AO_MONITORING_ORIG: + state = recv_orig.telemetry_orig.flight_state; + + /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ + rssi = (int16_t) (recv_orig.rssi >> 1) - 74; + memcpy(callsign, recv_orig.telemetry_orig.callsign, AO_MAX_CALLSIGN); + if (state > ao_flight_invalid) + state = ao_flight_invalid; + if (recv_orig.status & PKT_APPEND_STATUS_1_CRC_OK) { + + /* General header fields */ + printf(AO_TELEM_VERSION " %d " + AO_TELEM_CALL " %s " + AO_TELEM_SERIAL " %d " + AO_TELEM_FLIGHT " %d " + AO_TELEM_RSSI " %d " + AO_TELEM_STATE " %s " + AO_TELEM_TICK " %d ", + AO_TELEMETRY_VERSION, + callsign, + recv_orig.telemetry_orig.serial, + recv_orig.telemetry_orig.flight, + rssi, + ao_state_names[state], + recv_orig.telemetry_orig.adc.tick); + + /* Raw sensor values */ + printf(AO_TELEM_RAW_ACCEL " %d " + AO_TELEM_RAW_BARO " %d " + AO_TELEM_RAW_THERMO " %d " + AO_TELEM_RAW_BATT " %d " + AO_TELEM_RAW_DROGUE " %d " + AO_TELEM_RAW_MAIN " %d ", + recv_orig.telemetry_orig.adc.accel, + recv_orig.telemetry_orig.adc.pres, + recv_orig.telemetry_orig.adc.temp, + recv_orig.telemetry_orig.adc.v_batt, + recv_orig.telemetry_orig.adc.sense_d, + recv_orig.telemetry_orig.adc.sense_m); + + /* Sensor calibration values */ + printf(AO_TELEM_CAL_ACCEL_GROUND " %d " + AO_TELEM_CAL_BARO_GROUND " %d " + AO_TELEM_CAL_ACCEL_PLUS " %d " + AO_TELEM_CAL_ACCEL_MINUS " %d ", + recv_orig.telemetry_orig.ground_accel, + recv_orig.telemetry_orig.ground_pres, + recv_orig.telemetry_orig.accel_plus_g, + recv_orig.telemetry_orig.accel_minus_g); + + if (recv_orig.telemetry_orig.u.k.unused == 0x8000) { + /* Kalman state values */ + printf(AO_TELEM_KALMAN_HEIGHT " %d " + AO_TELEM_KALMAN_SPEED " %d " + AO_TELEM_KALMAN_ACCEL " %d ", + recv_orig.telemetry_orig.height, + recv_orig.telemetry_orig.u.k.speed, + recv_orig.telemetry_orig.accel); + } else { + /* Ad-hoc flight values */ + printf(AO_TELEM_ADHOC_ACCEL " %d " + AO_TELEM_ADHOC_SPEED " %ld " + AO_TELEM_ADHOC_BARO " %d ", + recv_orig.telemetry_orig.accel, + recv_orig.telemetry_orig.u.flight_vel, + recv_orig.telemetry_orig.height); + } + ao_gps_print(&recv_orig.telemetry_orig.gps); + ao_gps_tracking_print(&recv_orig.telemetry_orig.gps_tracking); + putchar('\n'); + ao_rssi_set(rssi); + } else { + printf("CRC INVALID RSSI %3d\n", rssi); + } + break; + case AO_MONITORING_TINY: + state = recv_tiny.telemetry_tiny.flight_state; + + /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ + rssi = (int16_t) (recv_tiny.rssi >> 1) - 74; + memcpy(callsign, recv_tiny.telemetry_tiny.callsign, AO_MAX_CALLSIGN); + if (state > ao_flight_invalid) + state = ao_flight_invalid; + if (recv_tiny.status & PKT_APPEND_STATUS_1_CRC_OK) { + /* General header fields */ + printf(AO_TELEM_VERSION " %d " + AO_TELEM_CALL " %s " + AO_TELEM_SERIAL " %d " + AO_TELEM_FLIGHT " %d " + AO_TELEM_RSSI " %d " + AO_TELEM_STATE " %s " + AO_TELEM_TICK " %d ", + AO_TELEMETRY_VERSION, + callsign, + recv_tiny.telemetry_tiny.serial, + recv_tiny.telemetry_tiny.flight, + rssi, + ao_state_names[state], + recv_tiny.telemetry_tiny.adc.tick); + + /* Raw sensor values */ + printf(AO_TELEM_RAW_BARO " %d " + AO_TELEM_RAW_THERMO " %d " + AO_TELEM_RAW_BATT " %d " + AO_TELEM_RAW_DROGUE " %d " + AO_TELEM_RAW_MAIN " %d ", + recv_tiny.telemetry_tiny.adc.pres, + recv_tiny.telemetry_tiny.adc.temp, + recv_tiny.telemetry_tiny.adc.v_batt, + recv_tiny.telemetry_tiny.adc.sense_d, + recv_tiny.telemetry_tiny.adc.sense_m); + + /* Sensor calibration values */ + printf(AO_TELEM_CAL_BARO_GROUND " %d ", + recv_tiny.telemetry_tiny.ground_pres); + +#if 1 + /* Kalman state values */ + printf(AO_TELEM_KALMAN_HEIGHT " %d " + AO_TELEM_KALMAN_SPEED " %d " + AO_TELEM_KALMAN_ACCEL " %d\n", + recv_tiny.telemetry_tiny.height, + recv_tiny.telemetry_tiny.speed, + recv_tiny.telemetry_tiny.accel); +#else + /* Ad-hoc flight values */ + printf(AO_TELEM_ADHOC_ACCEL " %d " + AO_TELEM_ADHOC_SPEED " %ld " + AO_TELEM_ADHOC_BARO " %d\n", + recv_tiny.telemetry_tiny.flight_accel, + recv_tiny.telemetry_tiny.flight_vel, + recv_tiny.telemetry_tiny.flight_pres); +#endif + ao_rssi_set(rssi); + } else { + printf("CRC INVALID RSSI %3d\n", rssi); + } + break; + default: + printf ("TELEM %02x", ao_monitoring + 2); + sum = 0x5a; + for (state = 0; state < ao_monitoring + 2; state++) { + byte = recv_raw.packet[state]; + sum += byte; + printf("%02x", byte); + } + printf("%02x\n", sum); + break; + } + ao_usb_flush(); + } +} + +__xdata struct ao_task ao_monitor_get_task; +__xdata struct ao_task ao_monitor_put_task; + +void +ao_set_monitor(uint8_t monitoring) +{ + if (ao_monitoring) + ao_radio_recv_abort(); + ao_monitoring = monitoring; + ao_wakeup(&ao_monitoring); +} + +static void +set_monitor(void) +{ + ao_cmd_hex(); + ao_set_monitor(ao_cmd_lex_i); +} + +__code struct ao_cmds ao_monitor_cmds[] = { + { set_monitor, "m <0 off, 1 full, 2 tiny>\0Enable/disable radio monitoring" }, + { 0, NULL }, +}; + +void +ao_monitor_init(uint8_t monitor_led, uint8_t monitoring) __reentrant +{ + ao_monitor_led = monitor_led; + ao_monitoring = monitoring; + ao_cmd_register(&ao_monitor_cmds[0]); + ao_add_task(&ao_monitor_get_task, ao_monitor_get, "monitor_get"); + ao_add_task(&ao_monitor_put_task, ao_monitor_put, "monitor_put"); +} diff --git a/src/core/ao_mutex.c b/src/core/ao_mutex.c new file mode 100644 index 00000000..c82a7d57 --- /dev/null +++ b/src/core/ao_mutex.c @@ -0,0 +1,41 @@ +/* + * 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_mutex_get(__xdata uint8_t *mutex) __reentrant +{ + if (*mutex == ao_cur_task->task_id) + ao_panic(AO_PANIC_MUTEX); + __critical { + while (*mutex) + ao_sleep(mutex); + *mutex = ao_cur_task->task_id; + } +} + +void +ao_mutex_put(__xdata uint8_t *mutex) __reentrant +{ + if (*mutex != ao_cur_task->task_id) + ao_panic(AO_PANIC_MUTEX); + __critical { + *mutex = 0; + ao_wakeup(mutex); + } +} diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c new file mode 100644 index 00000000..fdada201 --- /dev/null +++ b/src/core/ao_panic.c @@ -0,0 +1,66 @@ +/* + * 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" + +#ifndef HAS_BEEP +#error Please define HAS_BEEP +#endif + +#if !HAS_BEEP +#define ao_beep(x) +#endif + +static void +ao_panic_delay(uint8_t n) +{ + uint8_t i = 0, j = 0; + + while (n--) + while (--j) + while (--i) + _asm nop _endasm; +} + +void +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); + ao_panic_delay(1); + ao_led_off(AO_LED_RED); + ao_beep(AO_BEEP_LOW); + ao_panic_delay(1); + } + 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); + ao_panic_delay(10); + ao_led_off(AO_LED_RED); + ao_beep(AO_BEEP_OFF); + ao_panic_delay(10); + } + } +} diff --git a/src/core/ao_pins.h b/src/core/ao_pins.h new file mode 100644 index 00000000..e1f5459f --- /dev/null +++ b/src/core/ao_pins.h @@ -0,0 +1,408 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#if defined(TELEMETRUM_V_1_0) + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define HAS_ADC 1 + #define USE_SERIAL_STDIN 0 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define HAS_COMPANION 1 + #define COMPANION_CS_ON_P1 1 + #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ + #define COMPANION_CS P1_2 + + #define AO_LED_RED 1 + #define LEDS_AVAILABLE (AO_LED_RED) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL_REF 0 + #define HAS_ACCEL 1 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEMETRUM_V_1_1) + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define HAS_COMPANION 1 + #define COMPANION_CS_ON_P1 1 + #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ + #define COMPANION_CS P1_2 + + #define AO_LED_RED 1 + #define LEDS_AVAILABLE (AO_LED_RED) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL_REF 1 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ + #define M25_MAX_CHIPS 1 + #define HAS_ACCEL 1 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEDONGLE_V_0_2) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 1 + #define AO_LED_GREEN 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_IGNITE 0 + #define HAS_MONITOR 1 +#endif + +#if defined(TELEMINI_V_1_0) + #define HAS_FLIGHT 1 + #define HAS_USB 0 + #define HAS_BEEP 0 + #define HAS_GPS 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 1 + #define HAS_DBG 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 1 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + #define USE_FAST_ASCENT_LOG 1 + + #define AO_LED_GREEN 1 + #define AO_LED_RED 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL 0 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELENANO_V_0_1) + #define HAS_FLIGHT 1 + #define HAS_USB 0 + #define HAS_BEEP 0 + #define HAS_GPS 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 1 + #define HAS_DBG 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 1 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define AO_LED_GREEN 1 + #define AO_LED_RED 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL 0 + #define HAS_IGNITE 0 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEMETRUM_V_0_1) + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_DBG 0 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 1 + #define HAS_ACCEL_REF 0 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_ACCEL 1 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEDONGLE_V_0_1) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 0 + #define HAS_DBG 0 + #define HAS_EEPROM 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 0 + #define SPI_CS_ON_P0 1 + #define HAS_IGNITE 0 + #define HAS_MONITOR 1 +#endif + +#if defined(TIDONGLE) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 + #define LEDS_AVAILABLE (AO_LED_RED) + #define SPI_CS_ON_P1 0 + #define SPI_CS_ON_P0 1 + #define HAS_IGNITE 0 + #define HAS_MONITOR 1 +#endif + +#if defined(TELEBT_V_0_0) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 1 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define HAS_BTM 1 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_IGNITE 0 + #define BT_LINK_ON_P2 1 + #define BT_LINK_ON_P1 0 + #define BT_LINK_PIN_INDEX 7 + #define BT_LINK_PIN P2_1 + #define HAS_MONITOR 1 +#endif + +#if defined(TELEBT_V_0_1) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_SERIAL_1 1 + #define HAS_SERIAL_1_ALT_1 1 + #define HAS_SERIAL_1_ALT_2 0 + #define HAS_SERIAL_1_HW_FLOW 1 + #define USE_SERIAL_STDIN 1 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_BTM 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 1 + #define AO_LED_GREEN 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x04 /* CS0 is P1_2 */ + #define M25_MAX_CHIPS 1 + #define HAS_ACCEL 0 + #define HAS_IGNITE 0 + #define BT_LINK_ON_P2 0 + #define BT_LINK_ON_P1 1 + #define BT_LINK_PIN_INDEX 7 + #define BT_LINK_PIN P1_7 + #define HAS_MONITOR 1 +#endif + +#if DBG_ON_P1 + + #define DBG_CLOCK (1 << 4) /* mi0 */ + #define DBG_DATA (1 << 5) /* mo0 */ + #define DBG_RESET_N (1 << 3) /* c0 */ + + #define DBG_CLOCK_PIN (P1_4) + #define DBG_DATA_PIN (P1_5) + #define DBG_RESET_N_PIN (P1_3) + + #define DBG_PORT_NUM 1 + #define DBG_PORT P1 + #define DBG_PORT_SEL P1SEL + #define DBG_PORT_INP P1INP + #define DBG_PORT_DIR P1DIR + +#endif /* DBG_ON_P1 */ + +#if DBG_ON_P0 + + #define DBG_CLOCK (1 << 3) + #define DBG_DATA (1 << 4) + #define DBG_RESET_N (1 << 5) + + #define DBG_CLOCK_PIN (P0_3) + #define DBG_DATA_PIN (P0_4) + #define DBG_RESET_N_PIN (P0_5) + + #define DBG_PORT_NUM 0 + #define DBG_PORT P0 + #define DBG_PORT_SEL P0SEL + #define DBG_PORT_INP P0INP + #define DBG_PORT_DIR P0DIR + +#endif /* DBG_ON_P0 */ + +#if COMPANION_CS_ON_P1 + #define COMPANION_CS_PORT P1 + #define COMPANION_CS_SEL P1SEL + #define COMPANION_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P1 + #define SPI_CS_PORT P1 + #define SPI_CS_SEL P1SEL + #define SPI_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P0 + #define SPI_CS_PORT P0 + #define SPI_CS_SEL P0SEL + #define SPI_CS_DIR P0DIR +#endif + +#ifndef IGNITE_ON_P2 +#error Please define IGNITE_ON_P2 +#endif + +#ifndef IGNITE_ON_P0 +#error Please define IGNITE_ON_P0 +#endif + +#ifndef HAS_SERIAL_1 +#error Please define HAS_SERIAL_1 +#endif + +#ifndef USE_SERIAL_STDIN +#error Please define USE_SERIAL_STDIN +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#ifndef HAS_EEPROM +#error Please define HAS_EEPROM +#endif + +#if HAS_EEPROM +#ifndef USE_INTERNAL_FLASH +#error Please define USE_INTERNAL_FLASH +#endif +#endif + +#ifndef HAS_DBG +#error Please define HAS_DBG +#endif + +#ifndef HAS_IGNITE +#error Please define HAS_IGNITE +#endif + +#ifndef PACKET_HAS_MASTER +#error Please define PACKET_HAS_MASTER +#endif + +#ifndef PACKET_HAS_SLAVE +#error Please define PACKET_HAS_SLAVE +#endif + +#ifndef HAS_MONITOR +#error Please define HAS_MONITOR +#endif +#endif /* _AO_PINS_H_ */ diff --git a/src/core/ao_product.c b/src/core/ao_product.c new file mode 100644 index 00000000..fb59580b --- /dev/null +++ b/src/core/ao_product.c @@ -0,0 +1,155 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_product.h" + +/* Defines which mark this particular AltOS product */ + +const char ao_version[AO_MAX_VERSION] = AO_iVersion_STRING; +const char ao_manufacturer[] = AO_iManufacturer_STRING; +const char ao_product[] = AO_iProduct_STRING; + +#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) + +#if HAS_USB +#include "ao_usb.h" +/* USB descriptors in one giant block of bytes */ +__code __at(0x00aa) uint8_t ao_usb_descriptors [] = +{ + /* Device descriptor */ + 0x12, + AO_USB_DESC_DEVICE, + LE_WORD(0x0110), /* bcdUSB */ + 0x02, /* bDeviceClass */ + 0x00, /* bDeviceSubClass */ + 0x00, /* bDeviceProtocol */ + AO_USB_CONTROL_SIZE, /* bMaxPacketSize */ + LE_WORD(0xFFFE), /* idVendor */ + LE_WORD(AO_idProduct_NUMBER), /* idProduct */ + LE_WORD(0x0100), /* bcdDevice */ + 0x01, /* iManufacturer */ + 0x02, /* iProduct */ + 0x03, /* iSerialNumber */ + 0x01, /* bNumConfigurations */ + + /* Configuration descriptor */ + 0x09, + AO_USB_DESC_CONFIGURATION, + LE_WORD(67), /* wTotalLength */ + 0x02, /* bNumInterfaces */ + 0x01, /* bConfigurationValue */ + 0x00, /* iConfiguration */ + 0xC0, /* bmAttributes */ + 0x32, /* bMaxPower */ + + /* Control class interface */ + 0x09, + AO_USB_DESC_INTERFACE, + 0x00, /* bInterfaceNumber */ + 0x00, /* bAlternateSetting */ + 0x01, /* bNumEndPoints */ + 0x02, /* bInterfaceClass */ + 0x02, /* bInterfaceSubClass */ + 0x01, /* bInterfaceProtocol, linux requires value of 1 for the cdc_acm module */ + 0x00, /* iInterface */ + + /* Header functional descriptor */ + 0x05, + CS_INTERFACE, + 0x00, /* bDescriptor SubType Header */ + LE_WORD(0x0110), /* CDC version 1.1 */ + + /* Call management functional descriptor */ + 0x05, + CS_INTERFACE, + 0x01, /* bDescriptor SubType Call Management */ + 0x01, /* bmCapabilities = device handles call management */ + 0x01, /* bDataInterface call management interface number */ + + /* ACM functional descriptor */ + 0x04, + CS_INTERFACE, + 0x02, /* bDescriptor SubType Abstract Control Management */ + 0x02, /* bmCapabilities = D1 (Set_line_Coding, Set_Control_Line_State, Get_Line_Coding and Serial_State) */ + + /* Union functional descriptor */ + 0x05, + CS_INTERFACE, + 0x06, /* bDescriptor SubType Union Functional descriptor */ + 0x00, /* bMasterInterface */ + 0x01, /* bSlaveInterface0 */ + + /* Notification EP */ + 0x07, + AO_USB_DESC_ENDPOINT, + AO_USB_INT_EP|0x80, /* bEndpointAddress */ + 0x03, /* bmAttributes = intr */ + LE_WORD(8), /* wMaxPacketSize */ + 0x0A, /* bInterval */ + + /* Data class interface descriptor */ + 0x09, + AO_USB_DESC_INTERFACE, + 0x01, /* bInterfaceNumber */ + 0x00, /* bAlternateSetting */ + 0x02, /* bNumEndPoints */ + 0x0A, /* bInterfaceClass = data */ + 0x00, /* bInterfaceSubClass */ + 0x00, /* bInterfaceProtocol */ + 0x00, /* iInterface */ + + /* Data EP OUT */ + 0x07, + AO_USB_DESC_ENDPOINT, + AO_USB_OUT_EP, /* bEndpointAddress */ + 0x02, /* bmAttributes = bulk */ + LE_WORD(AO_USB_OUT_SIZE),/* wMaxPacketSize */ + 0x00, /* bInterval */ + + /* Data EP in */ + 0x07, + AO_USB_DESC_ENDPOINT, + AO_USB_IN_EP|0x80, /* bEndpointAddress */ + 0x02, /* bmAttributes = bulk */ + LE_WORD(AO_USB_IN_SIZE),/* wMaxPacketSize */ + 0x00, /* bInterval */ + + /* String descriptors */ + 0x04, + AO_USB_DESC_STRING, + LE_WORD(0x0409), + + /* iManufacturer */ + AO_iManufacturer_LEN, + AO_USB_DESC_STRING, + AO_iManufacturer_UCS2, + + /* iProduct */ + AO_iProduct_LEN, + AO_USB_DESC_STRING, + AO_iProduct_UCS2, + + /* iSerial */ + AO_iSerial_LEN, + AO_USB_DESC_STRING, + AO_iSerial_UCS2, + + /* Terminating zero */ + 0 +}; +#endif diff --git a/src/core/ao_report.c b/src/core/ao_report.c new file mode 100644 index 00000000..3cf558e1 --- /dev/null +++ b/src/core/ao_report.c @@ -0,0 +1,180 @@ +/* + * 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" + +#define BIT(i,x) ((x) ? (1 << (i)) : 0) +#define MORSE1(a) (1 | BIT(3,a)) +#define MORSE2(a,b) (2 | BIT(3,a) | BIT(4,b)) +#define MORSE3(a,b,c) (3 | BIT(3,a) | BIT(4,b) | BIT(5,c)) +#define MORSE4(a,b,c,d) (4 | BIT(3,a) | BIT(4,b) | BIT(5,c) | BIT(6,d)) +#define MORSE5(a,b,c,d,e) (5 | BIT(3,a) | BIT(4,b) | BIT(5,c) | BIT(6,d) | BIT(7,e)) + +static const uint8_t flight_reports[] = { + MORSE3(0,0,0), /* startup, 'S' */ + MORSE2(0,0), /* idle 'I' */ + MORSE4(0,1,1,0), /* pad 'P' */ + MORSE4(1,0,0,0), /* boost 'B' */ + MORSE4(0,0,1,0), /* fast 'F' */ + MORSE4(1,0,1,0), /* coast 'C' */ + MORSE3(1,0,0), /* drogue 'D' */ + MORSE2(1,1), /* main 'M' */ + MORSE4(0,1,0,0), /* landed 'L' */ + MORSE4(1,0,0,1), /* invalid 'X' */ +}; + +#if HAS_BEEP +#define low(time) ao_beep_for(AO_BEEP_LOW, time) +#define mid(time) ao_beep_for(AO_BEEP_MID, time) +#define high(time) ao_beep_for(AO_BEEP_HIGH, time) +#else +#define low(time) ao_led_for(AO_LED_GREEN, time) +#define mid(time) ao_led_for(AO_LED_RED, time) +#define high(time) ao_led_for(AO_LED_GREEN|AO_LED_RED, time) +#endif +#define pause(time) ao_delay(time) + +static __pdata enum ao_flight_state ao_report_state; + +static void +ao_report_beep(void) __reentrant +{ + uint8_t r = flight_reports[ao_flight_state]; + uint8_t l = r & 7; + + if (!r) + return; + while (l--) { + if (r & 8) + mid(AO_MS_TO_TICKS(600)); + else + mid(AO_MS_TO_TICKS(200)); + pause(AO_MS_TO_TICKS(200)); + r >>= 1; + } + pause(AO_MS_TO_TICKS(400)); +} + +static void +ao_report_digit(uint8_t digit) __reentrant +{ + if (!digit) { + mid(AO_MS_TO_TICKS(500)); + pause(AO_MS_TO_TICKS(200)); + } else { + while (digit--) { + mid(AO_MS_TO_TICKS(200)); + pause(AO_MS_TO_TICKS(200)); + } + } + pause(AO_MS_TO_TICKS(300)); +} + +static void +ao_report_altitude(void) +{ + __pdata int16_t agl = ao_max_height; + __xdata uint8_t digits[10]; + __pdata uint8_t ndigits, i; + + if (agl < 0) + agl = 0; + ndigits = 0; + do { + digits[ndigits++] = agl % 10; + agl /= 10; + } while (agl); + + for (;;) { + ao_report_beep(); + i = ndigits; + do + ao_report_digit(digits[--i]); + while (i != 0); + pause(AO_SEC_TO_TICKS(5)); + } +} + +#if HAS_IGNITE +static uint8_t +ao_report_igniter_ready(enum ao_igniter igniter) +{ + return ao_igniter_status(igniter) == ao_igniter_ready ? 1 : 0; +} + +static void +ao_report_continuity(void) __reentrant +{ + uint8_t c = (ao_report_igniter_ready(ao_igniter_drogue) | + (ao_report_igniter_ready(ao_igniter_main) << 1)); + if (c) { + while (c--) { + high(AO_MS_TO_TICKS(25)); + pause(AO_MS_TO_TICKS(100)); + } + } else { + c = 10; + while (c--) { + high(AO_MS_TO_TICKS(20)); + low(AO_MS_TO_TICKS(20)); + } + } + if (ao_log_full()) { + pause(AO_MS_TO_TICKS(100)); + c = 2; + while (c--) { + low(AO_MS_TO_TICKS(100)); + mid(AO_MS_TO_TICKS(100)); + high(AO_MS_TO_TICKS(100)); + mid(AO_MS_TO_TICKS(100)); + } + } + c = 50; + while (c-- && ao_flight_state == ao_flight_pad) + pause(AO_MS_TO_TICKS(100)); +} +#endif + +void +ao_report(void) +{ + ao_report_state = ao_flight_state; + for(;;) { + if (ao_flight_state == ao_flight_landed) + ao_report_altitude(); + ao_report_beep(); +#if HAS_IGNITE + if (ao_flight_state == ao_flight_idle) + ao_report_continuity(); + while (ao_flight_state == ao_flight_pad) + ao_report_continuity(); +#endif + __critical { + while (ao_report_state == ao_flight_state) + ao_sleep(DATA_TO_XDATA(&ao_flight_state)); + ao_report_state = ao_flight_state; + } + } +} + +static __xdata struct ao_task ao_report_task; + +void +ao_report_init(void) +{ + ao_add_task(&ao_report_task, ao_report, "report"); +} diff --git a/src/core/ao_rssi.c b/src/core/ao_rssi.c new file mode 100644 index 00000000..e3964d2d --- /dev/null +++ b/src/core/ao_rssi.c @@ -0,0 +1,53 @@ +/* + * 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" + +static __xdata volatile uint16_t ao_rssi_time; +static __pdata volatile uint16_t ao_rssi_delay; +static __pdata uint8_t ao_rssi_led; + +void +ao_rssi(void) +{ + for (;;) { + while ((int16_t) (ao_time() - ao_rssi_time) > AO_SEC_TO_TICKS(3)) + ao_sleep(&ao_rssi_time); + ao_led_for(ao_rssi_led, AO_MS_TO_TICKS(100)); + ao_delay(ao_rssi_delay); + } +} + +void +ao_rssi_set(int rssi_value) +{ + if (rssi_value > 0) + rssi_value = 0; + ao_rssi_delay = AO_MS_TO_TICKS((-rssi_value) * 5); + ao_rssi_time = ao_time(); + ao_wakeup(&ao_rssi_time); +} + +__xdata struct ao_task ao_rssi_task; + +void +ao_rssi_init(uint8_t rssi_led) +{ + ao_rssi_led = rssi_led; + ao_rssi_delay = 0; + ao_add_task(&ao_rssi_task, ao_rssi, "rssi"); +} diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c new file mode 100644 index 00000000..b2b8e9f6 --- /dev/null +++ b/src/core/ao_sample.c @@ -0,0 +1,209 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#endif + +/* + * Current sensor values + */ + +__pdata uint16_t ao_sample_tick; /* time of last data */ +__pdata int16_t ao_sample_pres; +__pdata int16_t ao_sample_alt; +__pdata int16_t ao_sample_height; +#if HAS_ACCEL +__pdata int16_t ao_sample_accel; +#endif + +__data uint8_t ao_sample_adc; + +/* + * Sensor calibration values + */ + +__pdata int16_t ao_ground_pres; /* startup pressure */ +__pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ + +#if HAS_ACCEL +__pdata int16_t ao_ground_accel; /* startup acceleration */ +__pdata int16_t ao_accel_2g; /* factory accel calibration */ +__pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +#endif + +static __pdata uint8_t ao_preflight; /* in preflight mode */ + +static __pdata uint16_t nsamples; +__pdata int32_t ao_sample_pres_sum; +#if HAS_ACCEL +__pdata int32_t ao_sample_accel_sum; +#endif + +static void +ao_sample_preflight(void) +{ + /* startup state: + * + * Collect 512 samples of acceleration and pressure + * data and average them to find the resting values + */ + if (nsamples < 512) { +#if HAS_ACCEL + ao_sample_accel_sum += ao_sample_accel; +#endif + ao_sample_pres_sum += ao_sample_pres; + ++nsamples; + } else { + ao_config_get(); +#if HAS_ACCEL + ao_ground_accel = ao_sample_accel_sum >> 9; + ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; + ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; +#endif + ao_ground_pres = ao_sample_pres_sum >> 9; + ao_ground_height = ao_pres_to_altitude(ao_ground_pres); + ao_preflight = FALSE; + } +} + +uint8_t +ao_sample(void) +{ + ao_wakeup(DATA_TO_XDATA(&ao_sample_adc)); + ao_sleep(DATA_TO_XDATA(&ao_adc_head)); + while (ao_sample_adc != ao_adc_head) { + __xdata struct ao_adc *ao_adc; + + /* Capture a sample */ + ao_adc = &ao_adc_ring[ao_sample_adc]; + ao_sample_tick = ao_adc->tick; + ao_sample_pres = ao_adc->pres; + ao_sample_alt = ao_pres_to_altitude(ao_sample_pres); + ao_sample_height = ao_sample_alt - ao_ground_height; +#if HAS_ACCEL + ao_sample_accel = ao_adc->accel; +#if HAS_ACCEL_REF + /* + * Ok, the math here is a bit tricky. + * + * ao_sample_accel: ADC output for acceleration + * ao_accel_ref: ADC output for the 5V reference. + * ao_cook_accel: Corrected acceleration value + * Vcc: 3.3V supply to the CC1111 + * Vac: 5V supply to the accelerometer + * accel: input voltage to accelerometer ADC pin + * ref: input voltage to 5V reference ADC pin + * + * + * Measured acceleration is ratiometric to Vcc: + * + * ao_sample_accel accel + * ------------ = ----- + * 32767 Vcc + * + * Measured 5v reference is also ratiometric to Vcc: + * + * ao_accel_ref ref + * ------------ = ----- + * 32767 Vcc + * + * + * ao_accel_ref = 32767 * (ref / Vcc) + * + * Acceleration is measured ratiometric to the 5V supply, + * so what we want is: + * + * ao_cook_accel accel + * ------------- = ----- + * 32767 ref + * + * + * accel Vcc + * = ----- * --- + * Vcc ref + * + * ao_sample_accel 32767 + * = ------------ * ------------ + * 32767 ao_accel_ref + * + * Multiply through by 32767: + * + * ao_sample_accel * 32767 + * ao_cook_accel = -------------------- + * ao_accel_ref + * + * Now, the tricky part. Getting this to compile efficiently + * and keeping all of the values in-range. + * + * First off, we need to use a shift of 16 instead of * 32767 as SDCC + * does the obvious optimizations for byte-granularity shifts: + * + * ao_cook_accel = (ao_sample_accel << 16) / ao_accel_ref + * + * Next, lets check our input ranges: + * + * 0 <= ao_sample_accel <= 0x7fff (singled ended ADC conversion) + * 0x7000 <= ao_accel_ref <= 0x7fff (the 5V ref value is close to 0x7fff) + * + * Plugging in our input ranges, we get an output range of 0 - 0x12490, + * which is 17 bits. That won't work. If we take the accel ref and shift + * by a bit, we'll change its range: + * + * 0xe000 <= ao_accel_ref<<1 <= 0xfffe + * + * ao_cook_accel = (ao_sample_accel << 16) / (ao_accel_ref << 1) + * + * Now the output range is 0 - 0x9248, which nicely fits in 16 bits. It + * is, however, one bit too large for our signed computations. So, we + * take the result and shift that by a bit: + * + * ao_cook_accel = ((ao_sample_accel << 16) / (ao_accel_ref << 1)) >> 1 + * + * This finally creates an output range of 0 - 0x4924. As the ADC only + * provides 11 bits of data, we haven't actually lost any precision, + * just dropped a bit of noise off the low end. + */ + ao_sample_accel = (uint16_t) ((((uint32_t) ao_sample_accel << 16) / (ao_accel_ref[ao_sample_adc] << 1))) >> 1; + if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) + ao_sample_accel = 0x7fff - ao_sample_accel; + ao_adc->accel = ao_sample_accel; +#endif +#endif + + if (ao_preflight) + ao_sample_preflight(); + else + ao_kalman(); + ao_sample_adc = ao_adc_ring_next(ao_sample_adc); + } + return !ao_preflight; +} + +void +ao_sample_init(void) +{ + nsamples = 0; + ao_sample_pres_sum = 0; + ao_sample_pres = 0; +#if HAS_ACCEL + ao_sample_accel_sum = 0; + ao_sample_accel = 0; +#endif + ao_sample_adc = ao_adc_head; + ao_preflight = TRUE; +} diff --git a/src/core/ao_state.c b/src/core/ao_state.c new file mode 100644 index 00000000..ed197aa5 --- /dev/null +++ b/src/core/ao_state.c @@ -0,0 +1,23 @@ +/* + * 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" + +const char const * const ao_state_names[] = { + "startup", "idle", "pad", "boost", "fast", + "coast", "drogue", "main", "landed", "invalid" +}; diff --git a/src/core/ao_stdio.c b/src/core/ao_stdio.c new file mode 100644 index 00000000..c0138a30 --- /dev/null +++ b/src/core/ao_stdio.c @@ -0,0 +1,84 @@ +/* + * 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 + */ + +#define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) + +__xdata struct ao_stdio ao_stdios[AO_NUM_STDIOS]; +__pdata int8_t ao_cur_stdio; +__pdata int8_t ao_num_stdios; + +void +putchar(char c) +{ + if (c == '\n') + (*ao_stdios[ao_cur_stdio].putchar)('\r'); + (*ao_stdios[ao_cur_stdio].putchar)(c); +} + +void +flush(void) +{ + if (ao_stdios[ao_cur_stdio].flush) + ao_stdios[ao_cur_stdio].flush(); +} + +__xdata uint8_t ao_stdin_ready; + +char +getchar(void) __reentrant __critical +{ + char c; + int8_t stdio = ao_cur_stdio; + + for (;;) { + c = ao_stdios[stdio].pollchar(); + if (c != AO_READ_AGAIN) + break; + if (++stdio == ao_num_stdios) + stdio = 0; + if (stdio == ao_cur_stdio) + ao_sleep(&ao_stdin_ready); + } + ao_cur_stdio = stdio; + return c; +} + +uint8_t +ao_echo(void) +{ + return ao_stdios[ao_cur_stdio].echo; +} + +int8_t +ao_add_stdio(char (*pollchar)(void), + void (*putchar)(char), + void (*flush)(void)) __reentrant +{ + if (ao_num_stdios == AO_NUM_STDIOS) + ao_panic(AO_PANIC_STDIO); + ao_stdios[ao_num_stdios].pollchar = pollchar; + ao_stdios[ao_num_stdios].putchar = putchar; + ao_stdios[ao_num_stdios].flush = flush; + ao_stdios[ao_num_stdios].echo = 1; + return ao_num_stdios++; +} diff --git a/src/core/ao_storage.c b/src/core/ao_storage.c new file mode 100644 index 00000000..6ffca0e5 --- /dev/null +++ b/src/core/ao_storage.c @@ -0,0 +1,184 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +uint8_t +ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +{ + uint16_t this_len; + uint16_t this_off; + + ao_storage_setup(); + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + while (len) { + + /* Compute portion of transfer within + * a single block + */ + this_off = (uint16_t) pos & (ao_storage_unit - 1); + this_len = ao_storage_unit - this_off; + if (this_len > len) + this_len = len; + + if (!ao_storage_device_read(pos, buf, this_len)) + return 0; + + /* See how much is left */ + buf += this_len; + len -= this_len; + pos += this_len; + } + return 1; +} + +uint8_t +ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +{ + uint16_t this_len; + uint16_t this_off; + + ao_storage_setup(); + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + while (len) { + + /* Compute portion of transfer within + * a single block + */ + this_off = (uint16_t) pos & (ao_storage_unit - 1); + this_len = ao_storage_unit - this_off; + if (this_len > len) + this_len = len; + + if (!ao_storage_device_write(pos, buf, this_len)) + return 0; + + /* See how much is left */ + buf += this_len; + len -= this_len; + pos += this_len; + } + return 1; +} + +static __xdata uint8_t storage_data[8]; + +static void +ao_storage_dump(void) __reentrant +{ + uint8_t i, j; + + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + for (i = 0; ; i += 8) { + if (ao_storage_read(((uint32_t) (ao_cmd_lex_i) << 8) + i, + storage_data, + 8)) { + ao_cmd_put16((uint16_t) i); + for (j = 0; j < 8; j++) { + putchar(' '); + ao_cmd_put8(storage_data[j]); + } + putchar ('\n'); + } + if (i == 248) + break; + } +} + +#if 0 + +/* not enough space for this today + */ +static void +ao_storage_store(void) __reentrant +{ + uint16_t block; + uint8_t i; + uint16_t len; + static __xdata uint8_t b; + 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_storage_write(addr, &b, 1); + addr++; + } +} +#endif + +void +ao_storage_zap(void) __reentrant +{ + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_storage_erase((uint32_t) ao_cmd_lex_i << 8); +} + +void +ao_storage_zapall(void) __reentrant +{ + uint32_t pos; + + ao_cmd_white(); + if (!ao_match_word("DoIt")) + return; + for (pos = 0; pos < ao_storage_config; pos += ao_storage_block) + ao_storage_erase(pos); +} + +void +ao_storage_info(void) __reentrant +{ + printf("Storage size: %ld\n", ao_storage_total); + printf("Storage erase unit: %ld\n", ao_storage_block); + ao_storage_device_info(); +} + +__code struct ao_cmds ao_storage_cmds[] = { + { ao_storage_info, "f\0Show storage" }, + { ao_storage_dump, "e \0Dump flash" }, +#ifdef HAS_STORAGE_DBG + { ao_storage_store, "w ...\0Write data to flash" }, +#endif + { ao_storage_zap, "z \0Erase " }, + { ao_storage_zapall,"Z \0Erase all. is doit with D&I" }, + { 0, NULL }, +}; + +void +ao_storage_init(void) +{ + ao_storage_device_init(); + ao_cmd_register(&ao_storage_cmds[0]); +} diff --git a/src/core/ao_task.c b/src/core/ao_task.c new file mode 100644 index 00000000..f5850fa4 --- /dev/null +++ b/src/core/ao_task.c @@ -0,0 +1,275 @@ +/* + * 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" + +#define AO_NO_TASK_INDEX 0xff + +__xdata struct ao_task * __xdata ao_tasks[AO_NUM_TASKS]; +__data uint8_t ao_num_tasks; +__data uint8_t ao_cur_task_index; +__xdata struct ao_task *__data ao_cur_task; + +void +ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant +{ + uint8_t __xdata *stack; + uint8_t task_id; + uint8_t t; + if (ao_num_tasks == AO_NUM_TASKS) + ao_panic(AO_PANIC_NO_TASK); + for (task_id = 1; task_id != 0; task_id++) { + for (t = 0; t < ao_num_tasks; t++) + if (ao_tasks[t]->task_id == task_id) + break; + if (t == ao_num_tasks) + break; + } + ao_tasks[ao_num_tasks++] = task; + task->task_id = task_id; + task->name = name; + /* + * Construct a stack frame so that it will 'return' + * to the start of the task + */ + stack = task->stack; + + *stack++ = ((uint16_t) start); /* 0 */ + *stack++ = ((uint16_t) start) >> 8; /* 1 */ + + /* and the stuff saved by ao_switch */ + *stack++ = 0; /* 2 acc */ + *stack++ = 0x80; /* 3 IE */ + + /* 4 DPL + * 5 DPH + * 6 B + * 7 R2 + * 8 R3 + * 9 R4 + * 10 R5 + * 11 R6 + * 12 R7 + * 13 R0 + * 14 R1 + * 15 PSW + * 16 BP + */ + for (t = 0; t < 13; t++) + *stack++ = 0; + + task->stack_count = 17; + task->wchan = NULL; +} + +/* Task switching function. This must not use any stack variables */ +void +ao_yield(void) __naked +{ + + /* Save current context */ + _asm + /* Push ACC first, as when restoring the context it must be restored + * last (it is used to set the IE register). */ + push ACC + /* Store the IE register then enable interrupts. */ + push _IEN0 + setb _EA + push DPL + push DPH + push b + push ar2 + push ar3 + push ar4 + push ar5 + push ar6 + push ar7 + push ar0 + push ar1 + push PSW + _endasm; + PSW = 0; + _asm + push _bp + _endasm; + + if (ao_cur_task_index == AO_NO_TASK_INDEX) + ao_cur_task_index = ao_num_tasks-1; + else + { + uint8_t stack_len; + __data uint8_t *stack_ptr; + __xdata uint8_t *save_ptr; + /* Save the current stack */ + stack_len = SP - (AO_STACK_START - 1); + ao_cur_task->stack_count = stack_len; + stack_ptr = (uint8_t __data *) AO_STACK_START; + save_ptr = (uint8_t __xdata *) ao_cur_task->stack; + do + *save_ptr++ = *stack_ptr++; + while (--stack_len); + } + + /* Empty the stack; might as well let interrupts have the whole thing */ + SP = AO_STACK_START - 1; + + /* Find a task to run. If there isn't any runnable task, + * this loop will run forever, which is just fine + */ + { + __pdata uint8_t ao_next_task_index = ao_cur_task_index; + for (;;) { + ++ao_next_task_index; + if (ao_next_task_index == ao_num_tasks) + ao_next_task_index = 0; + + ao_cur_task = ao_tasks[ao_next_task_index]; + if (ao_cur_task->wchan == NULL) { + ao_cur_task_index = ao_next_task_index; + break; + } + + /* Check if the alarm is set for a time which has passed */ + if (ao_cur_task->alarm && + (int16_t) (ao_time() - ao_cur_task->alarm) >= 0) { + ao_cur_task_index = ao_next_task_index; + break; + } + + /* Enter lower power mode when there isn't anything to do */ + if (ao_next_task_index == ao_cur_task_index) + PCON = PCON_IDLE; + } + } + + { + uint8_t stack_len; + __data uint8_t *stack_ptr; + __xdata uint8_t *save_ptr; + + /* Restore the old stack */ + stack_len = ao_cur_task->stack_count; + SP = AO_STACK_START - 1 + stack_len; + + stack_ptr = (uint8_t __data *) AO_STACK_START; + save_ptr = (uint8_t __xdata *) ao_cur_task->stack; + do + *stack_ptr++ = *save_ptr++; + while (--stack_len); + } + + _asm + pop _bp + pop PSW + pop ar1 + pop ar0 + pop ar7 + pop ar6 + pop ar5 + pop ar4 + pop ar3 + pop ar2 + pop b + pop DPH + pop DPL + /* The next byte of the stack is the IE register. Only the global + enable bit forms part of the task context. Pop off the IE then set + the global enable bit to match that of the stored IE register. */ + pop ACC + JB ACC.7,0098$ + CLR _EA + LJMP 0099$ + 0098$: + SETB _EA + 0099$: + /* Finally pop off the ACC, which was the first register saved. */ + pop ACC + ret + _endasm; +} + +uint8_t +ao_sleep(__xdata void *wchan) +{ + __critical { + ao_cur_task->wchan = wchan; + } + ao_yield(); + ao_cur_task->alarm = 0; + if (ao_cur_task->wchan) { + ao_cur_task->wchan = NULL; + return 1; + } + return 0; +} + +void +ao_wakeup(__xdata void *wchan) +{ + uint8_t i; + + for (i = 0; i < ao_num_tasks; i++) + if (ao_tasks[i]->wchan == wchan) + ao_tasks[i]->wchan = NULL; +} + +void +ao_alarm(uint16_t delay) +{ + /* Make sure we sleep *at least* delay ticks, which means adding + * one to account for the fact that we may be close to the next tick + */ + if (!(ao_cur_task->alarm = ao_time() + delay + 1)) + ao_cur_task->alarm = 1; +} + +void +ao_exit(void) __critical +{ + uint8_t i; + ao_num_tasks--; + for (i = ao_cur_task_index; i < ao_num_tasks; i++) + ao_tasks[i] = ao_tasks[i+1]; + ao_cur_task_index = AO_NO_TASK_INDEX; + ao_yield(); + /* we'll never get back here */ +} + +void +ao_task_info(void) +{ + uint8_t i; + uint8_t pc_loc; + __xdata struct ao_task *task; + + for (i = 0; i < ao_num_tasks; i++) { + task = ao_tasks[i]; + pc_loc = task->stack_count - 17; + printf("%12s: wchan %04x pc %04x\n", + task->name, + (int16_t) task->wchan, + (task->stack[pc_loc]) | (task->stack[pc_loc+1] << 8)); + } +} + +void +ao_start_scheduler(void) +{ + ao_cur_task_index = AO_NO_TASK_INDEX; + ao_cur_task = NULL; + ao_yield(); +} diff --git a/src/core/ao_telem.h b/src/core/ao_telem.h new file mode 100644 index 00000000..1a8da291 --- /dev/null +++ b/src/core/ao_telem.h @@ -0,0 +1,172 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_TELEM_H_ +#define _AO_TELEM_H_ + +#define AO_TELEMETRY_VERSION 4 + +/* + * Telemetry version 4 and higher format: + * + * General header fields + * + * Name Value + * + * VERSION Telemetry version number (4 or more). Must be first. + * c Callsign (string, no spaces allowed) + * n Flight unit serial number (integer) + * f Flight number (integer) + * r Packet RSSI value (integer) + * s Flight computer state (string, no spaces allowed) + * t Flight computer clock (integer in centiseconds) + */ + +#define AO_TELEM_VERSION "VERSION" +#define AO_TELEM_CALL "c" +#define AO_TELEM_SERIAL "n" +#define AO_TELEM_FLIGHT "f" +#define AO_TELEM_RSSI "r" +#define AO_TELEM_STATE "s" +#define AO_TELEM_TICK "t" + +/* + * Raw sensor values + * + * Name Value + * r_a Accelerometer reading (integer) + * r_b Barometer reading (integer) + * r_t Thermometer reading (integer) + * r_v Battery reading (integer) + * r_d Drogue continuity (integer) + * r_m Main continuity (integer) + */ + +#define AO_TELEM_RAW_ACCEL "r_a" +#define AO_TELEM_RAW_BARO "r_b" +#define AO_TELEM_RAW_THERMO "r_t" +#define AO_TELEM_RAW_BATT "r_v" +#define AO_TELEM_RAW_DROGUE "r_d" +#define AO_TELEM_RAW_MAIN "r_m" + +/* + * Sensor calibration values + * + * Name Value + * c_a Ground accelerometer reading (integer) + * c_b Ground barometer reading (integer) + * c_p Accelerometer reading for +1g + * c_m Accelerometer reading for -1g + */ + +#define AO_TELEM_CAL_ACCEL_GROUND "c_a" +#define AO_TELEM_CAL_BARO_GROUND "c_b" +#define AO_TELEM_CAL_ACCEL_PLUS "c_p" +#define AO_TELEM_CAL_ACCEL_MINUS "c_m" + +/* + * Kalman state values + * + * Name Value + * k_h Height above pad (integer, meters) + * k_s Vertical speeed (integer, m/s * 16) + * k_a Vertical acceleration (integer, m/s² * 16) + */ + +#define AO_TELEM_KALMAN_HEIGHT "k_h" +#define AO_TELEM_KALMAN_SPEED "k_s" +#define AO_TELEM_KALMAN_ACCEL "k_a" + +/* + * Ad-hoc flight values + * + * Name Value + * a_a Acceleration (integer, sensor units) + * a_s Speed (integer, integrated acceleration value) + * a_b Barometer reading (integer, sensor units) + */ + +#define AO_TELEM_ADHOC_ACCEL "a_a" +#define AO_TELEM_ADHOC_SPEED "a_s" +#define AO_TELEM_ADHOC_BARO "a_b" + +/* + * GPS values + * + * Name Value + * g GPS state (string): + * l locked + * u unlocked + * e error (missing or broken) + * g_n Number of sats used in solution + * g_ns Latitude (degrees * 10e7) + * g_ew Longitude (degrees * 10e7) + * g_a Altitude (integer meters) + * g_Y GPS year (integer) + * g_M GPS month (integer - 1-12) + * g_D GPS day (integer - 1-31) + * g_h GPS hour (integer - 0-23) + * g_m GPS minute (integer - 0-59) + * g_s GPS second (integer - 0-59) + * g_v GPS vertical speed (integer, cm/sec) + * g_g GPS horizontal speed (integer, cm/sec) + * g_c GPS course (integer, 0-359) + * g_hd GPS hdop (integer * 10) + * g_vd GPS vdop (integer * 10) + * g_he GPS h error (integer) + * g_ve GPS v error (integer) + */ + +#define AO_TELEM_GPS_STATE "g" +#define AO_TELEM_GPS_STATE_LOCKED 'l' +#define AO_TELEM_GPS_STATE_UNLOCKED 'u' +#define AO_TELEM_GPS_STATE_ERROR 'e' +#define AO_TELEM_GPS_NUM_SAT "g_n" +#define AO_TELEM_GPS_LATITUDE "g_ns" +#define AO_TELEM_GPS_LONGITUDE "g_ew" +#define AO_TELEM_GPS_ALTITUDE "g_a" +#define AO_TELEM_GPS_YEAR "g_Y" +#define AO_TELEM_GPS_MONTH "g_M" +#define AO_TELEM_GPS_DAY "g_D" +#define AO_TELEM_GPS_HOUR "g_h" +#define AO_TELEM_GPS_MINUTE "g_m" +#define AO_TELEM_GPS_SECOND "g_s" +#define AO_TELEM_GPS_VERTICAL_SPEED "g_v" +#define AO_TELEM_GPS_HORIZONTAL_SPEED "g_g" +#define AO_TELEM_GPS_COURSE "g_c" +#define AO_TELEM_GPS_HDOP "g_hd" +#define AO_TELEM_GPS_VDOP "g_vd" +#define AO_TELEM_GPS_HERROR "g_he" +#define AO_TELEM_GPS_VERROR "g_ve" + +/* + * GPS satellite values + * + * Name Value + * s_n Number of satellites reported (integer) + * s_v0 Space vehicle ID (integer) for report 0 + * s_c0 C/N0 number (integer) for report 0 + * s_v1 Space vehicle ID (integer) for report 1 + * s_c1 C/N0 number (integer) for report 1 + * ... + */ + +#define AO_TELEM_SAT_NUM "s_n" +#define AO_TELEM_SAT_SVID "s_v" +#define AO_TELEM_SAT_C_N_0 "s_c" + +#endif /* _AO_TELEM_H_ */ diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c new file mode 100644 index 00000000..c7338a58 --- /dev/null +++ b/src/core/ao_telemetry.c @@ -0,0 +1,270 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_product.h" + +static __pdata uint16_t ao_telemetry_interval; +static __pdata int8_t ao_telemetry_config_max; +static __pdata int8_t ao_telemetry_config_cur; +#if HAS_GPS +static __pdata int8_t ao_telemetry_loc_cur; +static __pdata int8_t ao_telemetry_sat_cur; +#endif +#if HAS_COMPANION +static __pdata int8_t ao_telemetry_companion_max; +static __pdata int8_t ao_telemetry_companion_cur; +#endif +static __pdata uint8_t ao_rdf = 0; +static __pdata uint16_t ao_rdf_time; + +#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) +#define AO_RDF_LENGTH_MS 500 + +#if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) +#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMETRUM +#endif + +#if defined(TELEMINI_V_1_0) +#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMINI +#endif + +#if defined(TELENANO_V_0_1) +#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELENANO +#endif + +static __xdata union ao_telemetry_all telemetry; + +/* Send sensor packet */ +static void +ao_send_sensor(void) +{ + uint8_t sample; + sample = ao_sample_adc; + + telemetry.generic.tick = ao_adc_ring[sample].tick; + telemetry.generic.type = AO_TELEMETRY_SENSOR; + + telemetry.sensor.state = ao_flight_state; +#if HAS_ACCEL + telemetry.sensor.accel = ao_adc_ring[sample].accel; +#else + telemetry.sensor.accel = 0; +#endif + telemetry.sensor.pres = ao_adc_ring[sample].pres; + telemetry.sensor.temp = ao_adc_ring[sample].temp; + telemetry.sensor.v_batt = ao_adc_ring[sample].v_batt; +#if HAS_IGNITE + telemetry.sensor.sense_d = ao_adc_ring[sample].sense_d; + telemetry.sensor.sense_m = ao_adc_ring[sample].sense_m; +#else + telemetry.sensor.sense_d = 0; + telemetry.sensor.sense_m = 0; +#endif + + telemetry.sensor.acceleration = ao_accel; + telemetry.sensor.speed = ao_speed; + telemetry.sensor.height = ao_height; + + telemetry.sensor.ground_pres = ao_ground_pres; +#if HAS_ACCEL + telemetry.sensor.ground_accel = ao_ground_accel; + telemetry.sensor.accel_plus_g = ao_config.accel_plus_g; + telemetry.sensor.accel_minus_g = ao_config.accel_minus_g; +#else + telemetry.sensor.ground_accel = 0; + telemetry.sensor.accel_plus_g = 0; + telemetry.sensor.accel_minus_g = 0; +#endif + + ao_radio_send(&telemetry, sizeof (telemetry)); +} + +static void +ao_send_configuration(void) +{ + if (--ao_telemetry_config_cur <= 0) + { + telemetry.generic.type = AO_TELEMETRY_CONFIGURATION; + telemetry.configuration.device = AO_idProduct_NUMBER; + telemetry.configuration.flight = ao_log_full() ? 0 : ao_flight_number; + telemetry.configuration.config_major = AO_CONFIG_MAJOR; + telemetry.configuration.config_minor = AO_CONFIG_MINOR; + telemetry.configuration.apogee_delay = ao_config.apogee_delay; + telemetry.configuration.main_deploy = ao_config.main_deploy; + telemetry.configuration.flight_log_max = ao_config.flight_log_max >> 10; + memcpy (telemetry.configuration.callsign, + ao_config.callsign, + AO_MAX_CALLSIGN); + memcpy (telemetry.configuration.version, + ao_version, + AO_MAX_VERSION); + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_config_cur = ao_telemetry_config_max; + } +} + +#if HAS_GPS +static void +ao_send_location(void) +{ + if (--ao_telemetry_loc_cur <= 0) + { + telemetry.generic.type = AO_TELEMETRY_LOCATION; + ao_mutex_get(&ao_gps_mutex); + memcpy(&telemetry.location.flags, + &ao_gps_data.flags, + 26); + ao_mutex_put(&ao_gps_mutex); + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_loc_cur = ao_telemetry_config_max; + } +} + +static void +ao_send_satellite(void) +{ + if (--ao_telemetry_sat_cur <= 0) + { + telemetry.generic.type = AO_TELEMETRY_SATELLITE; + ao_mutex_get(&ao_gps_mutex); + telemetry.satellite.channels = ao_gps_tracking_data.channels; + memcpy(&telemetry.satellite.sats, + &ao_gps_tracking_data.sats, + AO_MAX_GPS_TRACKING * sizeof (struct ao_telemetry_satellite_info)); + ao_mutex_put(&ao_gps_mutex); + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_sat_cur = ao_telemetry_config_max; + } +} +#endif + +#if HAS_COMPANION +static void +ao_send_companion(void) +{ + if (--ao_telemetry_companion_cur <= 0) { + telemetry.generic.type = AO_TELEMETRY_COMPANION; + telemetry.companion.board_id = ao_companion_setup.board_id; + telemetry.companion.update_period = ao_companion_setup.update_period; + telemetry.companion.channels = ao_companion_setup.channels; + ao_mutex_get(&ao_companion_mutex); + memcpy(&telemetry.companion.companion_data, + ao_companion_data, + ao_companion_setup.channels * 2); + ao_mutex_put(&ao_companion_mutex); + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_companion_cur = ao_telemetry_companion_max; + } +} +#endif + +void +ao_telemetry(void) +{ + uint16_t time; + int16_t delay; + + ao_config_get(); + if (!ao_config.radio_enable) + ao_exit(); + while (!ao_flight_number) + ao_sleep(&ao_flight_number); + + telemetry.generic.serial = ao_serial_number; + for (;;) { + while (ao_telemetry_interval == 0) + ao_sleep(&telemetry); + time = ao_rdf_time = ao_time(); + while (ao_telemetry_interval) { + + + ao_send_sensor(); +#if HAS_COMPANION + if (ao_companion_running) + ao_send_companion(); +#endif + ao_send_configuration(); +#if HAS_GPS + ao_send_location(); + ao_send_satellite(); +#endif + if (ao_rdf && + (int16_t) (ao_time() - ao_rdf_time) >= 0) + { + ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; + ao_radio_rdf(AO_RDF_LENGTH_MS); + } + time += ao_telemetry_interval; + delay = time - ao_time(); + if (delay > 0) + ao_delay(delay); + else + time = ao_time(); + } + } +} + +void +ao_telemetry_set_interval(uint16_t interval) +{ + ao_telemetry_interval = interval; + +#if HAS_COMPANION + if (!ao_companion_setup.update_period) + ao_companion_setup.update_period = AO_SEC_TO_TICKS(1); + ao_telemetry_companion_max = ao_companion_setup.update_period / interval; + ao_telemetry_companion_cur = 1; +#endif + + ao_telemetry_config_max = AO_SEC_TO_TICKS(1) / interval; +#if HAS_COMPANION + ao_telemetry_config_cur = ao_telemetry_companion_cur; + if (ao_telemetry_config_max > ao_telemetry_config_cur) + ao_telemetry_config_cur++; +#else + ao_telemetry_config_cur = 1; +#endif + +#if HAS_GPS + ao_telemetry_loc_cur = ao_telemetry_config_cur; + if (ao_telemetry_config_max > ao_telemetry_loc_cur) + ao_telemetry_loc_cur++; + ao_telemetry_sat_cur = ao_telemetry_loc_cur; + if (ao_telemetry_config_max > ao_telemetry_sat_cur) + ao_telemetry_sat_cur++; +#endif + ao_wakeup(&telemetry); +} + +void +ao_rdf_set(uint8_t rdf) +{ + ao_rdf = rdf; + if (rdf == 0) + ao_radio_rdf_abort(); + else + ao_rdf_time = ao_time(); +} + +__xdata struct ao_task ao_telemetry_task; + +void +ao_telemetry_init() +{ + ao_add_task(&ao_telemetry_task, ao_telemetry, "telemetry"); +} diff --git a/src/drivers/ao_25lc1024.c b/src/drivers/ao_25lc1024.c new file mode 100644 index 00000000..738f8ce6 --- /dev/null +++ b/src/drivers/ao_25lc1024.c @@ -0,0 +1,241 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_25lc1024.h" + +#define EE_BLOCK_SIZE ((uint16_t) (256)) +#define EE_BLOCK_SHIFT 8 +#define EE_DEVICE_SIZE ((uint32_t) 128 * (uint32_t) 1024) + +/* Total bytes of available storage */ +__pdata uint32_t ao_storage_total; + +/* Block size - device is erased in these units. At least 256 bytes */ +__pdata uint32_t ao_storage_block; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +__pdata uint32_t ao_storage_config; + +/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ +__pdata uint16_t ao_storage_unit; + +/* + * Using SPI on USART 0, with P1_2 as the chip select + */ + +#define EE_CS P1_2 +#define EE_CS_INDEX 2 + +static __xdata uint8_t ao_ee_mutex; + +#define ao_ee_delay() do { \ + _asm nop _endasm; \ + _asm nop _endasm; \ + _asm nop _endasm; \ +} while(0) + +#define ao_ee_cs_low() ao_spi_get_bit(EE_CS) + +#define ao_ee_cs_high() ao_spi_put_bit(EE_CS) + +struct ao_ee_instruction { + uint8_t instruction; + uint8_t address[3]; +} __xdata ao_ee_instruction; + +static void +ao_ee_write_enable(void) +{ + ao_ee_cs_low(); + ao_ee_instruction.instruction = EE_WREN; + ao_spi_send(&ao_ee_instruction, 1); + ao_ee_cs_high(); +} + +static uint8_t +ao_ee_rdsr(void) +{ + ao_ee_cs_low(); + ao_ee_instruction.instruction = EE_RDSR; + ao_spi_send(&ao_ee_instruction, 1); + ao_spi_recv(&ao_ee_instruction, 1); + ao_ee_cs_high(); + return ao_ee_instruction.instruction; +} + +static void +ao_ee_wrsr(uint8_t status) +{ + ao_ee_cs_low(); + ao_ee_instruction.instruction = EE_WRSR; + ao_ee_instruction.address[0] = status; + ao_spi_send(&ao_ee_instruction, 2); + ao_ee_cs_high(); +} + +#define EE_BLOCK_NONE 0xffff + +static __xdata uint8_t ao_ee_data[EE_BLOCK_SIZE]; +static __pdata uint16_t ao_ee_block = EE_BLOCK_NONE; +static __pdata uint8_t ao_ee_block_dirty; + +/* Write the current block to the EEPROM */ +static void +ao_ee_write_block(void) +{ + uint8_t status; + + status = ao_ee_rdsr(); + if (status & (EE_STATUS_BP0|EE_STATUS_BP1|EE_STATUS_WPEN)) { + status &= ~(EE_STATUS_BP0|EE_STATUS_BP1|EE_STATUS_WPEN); + ao_ee_wrsr(status); + } + ao_ee_write_enable(); + ao_ee_cs_low(); + ao_ee_instruction.instruction = EE_WRITE; + ao_ee_instruction.address[0] = ao_ee_block >> 8; + ao_ee_instruction.address[1] = ao_ee_block; + ao_ee_instruction.address[2] = 0; + ao_spi_send(&ao_ee_instruction, 4); + ao_spi_send(ao_ee_data, EE_BLOCK_SIZE); + ao_ee_cs_high(); + for (;;) { + uint8_t status = ao_ee_rdsr(); + if ((status & EE_STATUS_WIP) == 0) + break; + } +} + +/* Read the current block from the EEPROM */ +static void +ao_ee_read_block(void) +{ + ao_ee_cs_low(); + ao_ee_instruction.instruction = EE_READ; + ao_ee_instruction.address[0] = ao_ee_block >> 8; + ao_ee_instruction.address[1] = ao_ee_block; + ao_ee_instruction.address[2] = 0; + ao_spi_send(&ao_ee_instruction, 4); + ao_spi_recv(ao_ee_data, EE_BLOCK_SIZE); + ao_ee_cs_high(); +} + +static void +ao_ee_flush_internal(void) +{ + if (ao_ee_block_dirty) { + ao_ee_write_block(); + ao_ee_block_dirty = 0; + } +} + +static void +ao_ee_fill(uint16_t block) +{ + if (block != ao_ee_block) { + ao_ee_flush_internal(); + ao_ee_block = block; + ao_ee_read_block(); + } +} + +uint8_t +ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +{ + uint16_t block = (uint16_t) (pos >> EE_BLOCK_SHIFT); + + /* Transfer the data */ + ao_mutex_get(&ao_ee_mutex); { + if (len != EE_BLOCK_SIZE) + ao_ee_fill(block); + else { + ao_ee_flush_internal(); + ao_ee_block = block; + } + memcpy(ao_ee_data + (uint16_t) (pos & 0xff), buf, len); + ao_ee_block_dirty = 1; + } ao_mutex_put(&ao_ee_mutex); + return 1; +} + +uint8_t +ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +{ + uint16_t block = (uint16_t) (pos >> EE_BLOCK_SHIFT); + + /* Transfer the data */ + ao_mutex_get(&ao_ee_mutex); { + ao_ee_fill(block); + memcpy(buf, ao_ee_data + (uint16_t) (pos & 0xff), len); + } ao_mutex_put(&ao_ee_mutex); + return 1; +} + +void +ao_storage_flush(void) __reentrant +{ + ao_mutex_get(&ao_ee_mutex); { + ao_ee_flush_internal(); + } ao_mutex_put(&ao_ee_mutex); +} + +uint8_t +ao_storage_erase(uint32_t pos) __reentrant +{ + ao_mutex_get(&ao_ee_mutex); { + ao_ee_flush_internal(); + ao_ee_block = (uint16_t) (pos >> EE_BLOCK_SHIFT); + memset(ao_ee_data, 0xff, EE_BLOCK_SIZE); + ao_ee_block_dirty = 1; + } ao_mutex_put(&ao_ee_mutex); + return 1; +} + +static void +ee_store(void) __reentrant +{ +} + +void +ao_storage_setup(void) +{ + if (ao_storage_total == 0) { + ao_storage_total = EE_DEVICE_SIZE; + ao_storage_block = EE_BLOCK_SIZE; + ao_storage_config = EE_DEVICE_SIZE - EE_BLOCK_SIZE; + ao_storage_unit = EE_BLOCK_SIZE; + } +} + +void +ao_storage_device_info(void) __reentrant +{ +} + +/* + * To initialize the chip, set up the CS line and + * the SPI interface + */ +void +ao_storage_device_init(void) +{ + /* set up CS */ + EE_CS = 1; + P1DIR |= (1 << EE_CS_INDEX); + P1SEL &= ~(1 << EE_CS_INDEX); +} diff --git a/src/drivers/ao_25lc1024.h b/src/drivers/ao_25lc1024.h new file mode 100644 index 00000000..44e52387 --- /dev/null +++ b/src/drivers/ao_25lc1024.h @@ -0,0 +1,41 @@ +/* + * 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. + */ + +/* Defines for the 25LC1024 1Mbit SPI Bus Serial EEPROM */ + +#ifndef _25LC1024_H_ +#define _25LC1024_H_ + +#define EE_READ 0x03 +#define EE_WRITE 0x02 +#define EE_WREN 0x06 +#define EE_WRDI 0x04 +#define EE_RDSR 0x05 +#define EE_WRSR 0x01 +#define EE_PE 0x42 +#define EE_SE 0xd8 +#define EE_CE 0xc7 +#define EE_RDID 0xab +#define EE_DPD 0xb9 + +#define EE_STATUS_WIP (1 << 0) +#define EE_STATUS_WEL (1 << 1) +#define EE_STATUS_BP0 (1 << 2) +#define EE_STATUS_BP1 (1 << 3) +#define EE_STATUS_WPEN (1 << 7) + +#endif /* _25LC1024_H_ */ diff --git a/src/drivers/ao_at45db161d.c b/src/drivers/ao_at45db161d.c new file mode 100644 index 00000000..aee9877a --- /dev/null +++ b/src/drivers/ao_at45db161d.c @@ -0,0 +1,318 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_at45db161d.h" + +/* Total bytes of available storage */ +__pdata uint32_t ao_storage_total; + +/* Block size - device is erased in these units. At least 256 bytes */ +__pdata uint32_t ao_storage_block; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +__pdata uint32_t ao_storage_config; + +/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ +__pdata uint16_t ao_storage_unit; + +#define FLASH_CS P1_1 +#define FLASH_CS_INDEX 1 + +#define FLASH_BLOCK_SIZE_MAX 512 + +__xdata uint8_t ao_flash_mutex; + +#define ao_flash_delay() do { \ + _asm nop _endasm; \ + _asm nop _endasm; \ + _asm nop _endasm; \ +} while(0) + +#define ao_flash_cs_low() ao_spi_get_bit(FLASH_CS) + +#define ao_flash_cs_high() ao_spi_put_bit(FLASH_CS) + +struct ao_flash_instruction { + uint8_t instruction; + uint8_t address[3]; +} __xdata ao_flash_instruction; + +static void +ao_flash_set_pagesize_512(void) +{ + ao_flash_cs_low(); + ao_flash_instruction.instruction = FLASH_SET_CONFIG; + ao_flash_instruction.address[0] = FLASH_SET_512_BYTE_0; + ao_flash_instruction.address[1] = FLASH_SET_512_BYTE_1; + ao_flash_instruction.address[2] = FLASH_SET_512_BYTE_2; + ao_spi_send(&ao_flash_instruction, 4); + ao_flash_cs_high(); +} + + +static uint8_t +ao_flash_read_status(void) +{ + ao_flash_cs_low(); + ao_flash_instruction.instruction = FLASH_READ_STATUS; + ao_spi_send(&ao_flash_instruction, 1); + ao_spi_recv(&ao_flash_instruction, 1); + ao_flash_cs_high(); + return ao_flash_instruction.instruction; +} + +#define FLASH_BLOCK_NONE 0xffff + +static __xdata uint8_t ao_flash_data[FLASH_BLOCK_SIZE_MAX]; +static __pdata uint16_t ao_flash_block = FLASH_BLOCK_NONE; +static __pdata uint8_t ao_flash_block_dirty; +static __pdata uint8_t ao_flash_write_pending; +static __pdata uint8_t ao_flash_setup_done; +static __pdata uint8_t ao_flash_block_shift; +static __pdata uint16_t ao_flash_block_size; +static __pdata uint16_t ao_flash_block_mask; + +void +ao_storage_setup(void) __reentrant +{ + uint8_t status; + + if (ao_flash_setup_done) + return; + + ao_mutex_get(&ao_flash_mutex); + if (ao_flash_setup_done) { + ao_mutex_put(&ao_flash_mutex); + return; + } + + /* On first use, check to see if the flash chip has + * been programmed to use 512 byte pages. If not, do so. + * And then, because the flash part must be power cycled + * for that change to take effect, panic. + */ + status = ao_flash_read_status(); + + if (!(status & FLASH_STATUS_PAGESIZE_512)) { + ao_flash_set_pagesize_512(); + ao_panic(AO_PANIC_FLASH); + } + + switch (status & 0x3c) { + + /* AT45DB321D */ + case 0x34: + ao_flash_block_shift = 9; + ao_storage_total = ((uint32_t) 4 * (uint32_t) 1024 * (uint32_t) 1024); + break; + + /* AT45DB161D */ + case 0x2c: + ao_flash_block_shift = 9; + ao_storage_total = ((uint32_t) 2 * (uint32_t) 1024 * (uint32_t) 1024); + break; + + /* AT45DB081D */ + case 0x24: + ao_flash_block_shift = 8; + ao_storage_total = ((uint32_t) 1024 * (uint32_t) 1024); + break; + + /* AT45DB041D */ + case 0x1c: + ao_flash_block_shift = 8; + ao_storage_total = ((uint32_t) 512 * (uint32_t) 1024); + break; + + /* AT45DB021D */ + case 0x14: + ao_flash_block_shift = 8; + ao_storage_total = ((uint32_t) 256 * (uint32_t) 1024); + break; + + /* AT45DB011D */ + case 0x0c: + ao_flash_block_shift = 8; + ao_storage_total = ((uint32_t) 128 * (uint32_t) 1024); + break; + + default: + ao_panic(AO_PANIC_FLASH); + } + ao_flash_block_size = 1 << ao_flash_block_shift; + ao_flash_block_mask = ao_flash_block_size - 1; + + ao_storage_block = ao_flash_block_size; + ao_storage_config = ao_storage_total - ao_storage_block; + ao_storage_unit = ao_flash_block_size; + + ao_flash_setup_done = 1; + ao_mutex_put(&ao_flash_mutex); +} + +static void +ao_flash_wait_write(void) +{ + if (ao_flash_write_pending) { + for (;;) { + uint8_t status = ao_flash_read_status(); + if ((status & FLASH_STATUS_RDY)) + break; + } + ao_flash_write_pending = 0; + } +} + +/* Write the current block to the FLASHPROM */ +static void +ao_flash_write_block(void) +{ + ao_flash_wait_write(); + ao_flash_cs_low(); + ao_flash_instruction.instruction = FLASH_WRITE; + + /* 13/14 block bits + 9/8 byte bits (always 0) */ + ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift); + ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); + ao_flash_instruction.address[2] = 0; + ao_spi_send(&ao_flash_instruction, 4); + ao_spi_send(ao_flash_data, ao_storage_block); + ao_flash_cs_high(); + ao_flash_write_pending = 1; +} + +/* Read the current block from the FLASHPROM */ +static void +ao_flash_read_block(void) +{ + ao_flash_wait_write(); + ao_flash_cs_low(); + ao_flash_instruction.instruction = FLASH_READ; + + /* 13/14 block bits + 9/8 byte bits (always 0) */ + ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift); + ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); + ao_flash_instruction.address[2] = 0; + ao_spi_send(&ao_flash_instruction, 4); + ao_spi_recv(ao_flash_data, ao_flash_block_size); + ao_flash_cs_high(); +} + +static void +ao_flash_flush_internal(void) +{ + if (ao_flash_block_dirty) { + ao_flash_write_block(); + ao_flash_block_dirty = 0; + } +} + +static void +ao_flash_fill(uint16_t block) +{ + if (block != ao_flash_block) { + ao_flash_flush_internal(); + ao_flash_block = block; + ao_flash_read_block(); + } +} + +uint8_t +ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +{ + uint16_t block = (uint16_t) (pos >> ao_flash_block_shift); + + /* Transfer the data */ + ao_mutex_get(&ao_flash_mutex); { + if (len != ao_flash_block_size) + ao_flash_fill(block); + else { + ao_flash_flush_internal(); + ao_flash_block = block; + } + memcpy(ao_flash_data + (uint16_t) (pos & ao_flash_block_mask), + buf, + len); + ao_flash_block_dirty = 1; + } ao_mutex_put(&ao_flash_mutex); + return 1; +} + +uint8_t +ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +{ + uint16_t block = (uint16_t) (pos >> ao_flash_block_shift); + + /* Transfer the data */ + ao_mutex_get(&ao_flash_mutex); { + ao_flash_fill(block); + memcpy(buf, + ao_flash_data + (uint16_t) (pos & ao_flash_block_mask), + len); + } ao_mutex_put(&ao_flash_mutex); + return 1; +} + +void +ao_storage_flush(void) __reentrant +{ + ao_mutex_get(&ao_flash_mutex); { + ao_flash_flush_internal(); + } ao_mutex_put(&ao_flash_mutex); +} + +uint8_t +ao_storage_erase(uint32_t pos) __reentrant +{ + ao_mutex_get(&ao_flash_mutex); { + ao_flash_flush_internal(); + ao_flash_block = (uint16_t) (pos >> ao_flash_block_shift); + memset(ao_flash_data, 0xff, ao_flash_block_size); + ao_flash_block_dirty = 1; + } ao_mutex_put(&ao_flash_mutex); + return 1; +} + +void +ao_storage_device_info(void) __reentrant +{ + uint8_t status; + + ao_storage_setup(); + ao_mutex_get(&ao_flash_mutex); { + status = ao_flash_read_status(); + printf ("Flash status: 0x%02x\n", status); + printf ("Flash block shift: %d\n", ao_flash_block_shift); + printf ("Flash block size: %d\n", ao_flash_block_size); + printf ("Flash block mask: %d\n", ao_flash_block_mask); + printf ("Flash device size: %ld\n", ao_storage_total); + } ao_mutex_put(&ao_flash_mutex); +} + +/* + * To initialize the chip, set up the CS line and + * the SPI interface + */ +void +ao_storage_device_init(void) +{ + /* set up CS */ + FLASH_CS = 1; + P1DIR |= (1 << FLASH_CS_INDEX); + P1SEL &= ~(1 << FLASH_CS_INDEX); +} diff --git a/src/drivers/ao_at45db161d.h b/src/drivers/ao_at45db161d.h new file mode 100644 index 00000000..9ee6f1b6 --- /dev/null +++ b/src/drivers/ao_at45db161d.h @@ -0,0 +1,45 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +/* Defines for the Atmel AT45DB161D 16Mbit SPI Bus DataFlash® */ + +#ifndef _AT45DB161D_H_ +#define _AT45DB161D_H_ + +/* + * We reserve the last block on the device for + * configuration space. Writes and reads in this + * area return errors. + */ + + +#define FLASH_READ 0x03 +#define FLASH_WRITE 0x82 +#define FLASH_PAGE_ERASE 0x81 +#define FLASH_READ_STATUS 0xd7 +#define FLASH_SET_CONFIG 0x3d + +#define FLASH_SET_512_BYTE_0 0x2a +#define FLASH_SET_512_BYTE_1 0x80 +#define FLASH_SET_512_BYTE_2 0xa6 + +#define FLASH_STATUS_RDY (1 << 7) +#define FLASH_STATUS_COMP (1 << 6) +#define FLASH_STATUS_PROTECT (1 << 1) +#define FLASH_STATUS_PAGESIZE_512 (1 << 0) + +#endif /* _AT45DB161D_H_ */ diff --git a/src/drivers/ao_btm.c b/src/drivers/ao_btm.c new file mode 100644 index 00000000..44155ec1 --- /dev/null +++ b/src/drivers/ao_btm.c @@ -0,0 +1,302 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +int8_t ao_btm_stdio; +__xdata uint8_t ao_btm_connected; + +#define AO_BTM_MAX_REPLY 16 +__xdata char ao_btm_reply[AO_BTM_MAX_REPLY]; + +extern volatile __xdata struct ao_fifo ao_usart1_rx_fifo; + +/* + * Read a line of data from the serial port, truncating + * it after a few characters. + */ + +uint8_t +ao_btm_get_line(void) +{ + uint8_t ao_btm_reply_len = 0; + char c; + + for (;;) { + + while ((c = ao_serial_pollchar()) != AO_READ_AGAIN) { + if (ao_btm_reply_len < sizeof (ao_btm_reply)) + ao_btm_reply[ao_btm_reply_len++] = c; + if (c == '\r' || c == '\n') + goto done; + } + for (c = 0; c < 10; c++) { + ao_delay(AO_MS_TO_TICKS(10)); + if (!ao_fifo_empty(ao_usart1_rx_fifo)) + break; + } + if (c == 10) + goto done; + } +done: + for (c = ao_btm_reply_len; c < sizeof (ao_btm_reply);) + ao_btm_reply[c++] = '\0'; + return ao_btm_reply_len; +} + +/* + * Drain the serial port completely + */ +void +ao_btm_drain() +{ + while (ao_btm_get_line()) + ; +} + +/* + * Set the stdio echo for the bluetooth link + */ +void +ao_btm_echo(uint8_t echo) +{ + ao_stdios[ao_btm_stdio].echo = echo; +} + +/* + * Delay between command charaters; the BT module + * can't keep up with 57600 baud + */ + +void +ao_btm_putchar(char c) +{ + ao_serial_putchar(c); + ao_delay(1); +} + +/* + * Wait for the bluetooth device to return + * status from the previously executed command + */ +uint8_t +ao_btm_wait_reply(void) +{ + for (;;) { + ao_btm_get_line(); + if (!strncmp(ao_btm_reply, "OK", 2)) + return 1; + if (!strncmp(ao_btm_reply, "ERROR", 5)) + return -1; + if (ao_btm_reply[0] == '\0') + return 0; + } +} + +void +ao_btm_string(__code char *cmd) +{ + char c; + + while (c = *cmd++) + ao_btm_putchar(c); +} + +uint8_t +ao_btm_cmd(__code char *cmd) +{ + ao_btm_drain(); + ao_btm_string(cmd); + return ao_btm_wait_reply(); +} + +uint8_t +ao_btm_set_name(void) +{ + char sn[8]; + char *s = sn + 8; + char c; + int n; + ao_btm_string("ATN=TeleBT-"); + *--s = '\0'; + *--s = '\r'; + n = ao_serial_number; + do { + *--s = '0' + n % 10; + } while (n /= 10); + while ((c = *s++)) + ao_btm_putchar(c); + return ao_btm_wait_reply(); +} + +uint8_t +ao_btm_try_speed(uint8_t speed) +{ + ao_serial_set_speed(speed); + ao_btm_drain(); + (void) ao_btm_cmd("\rATE0\rATQ0\r"); + if (ao_btm_cmd("AT\r") == 1) + return 1; + return 0; +} + +/* + * A thread to initialize the bluetooth device and + * hang around to blink the LED when connected + */ +void +ao_btm(void) +{ + /* + * Wait for the bluetooth device to boot + */ + ao_delay(AO_SEC_TO_TICKS(3)); + +#if HAS_BEEP + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); +#endif + + /* + * The first time we connect, the BTM-180 comes up at 19200 baud. + * After that, it will remember and come up at 57600 baud. So, see + * if it is already running at 57600 baud, and if that doesn't work + * then tell it to switch to 57600 from 19200 baud. + */ + while (!ao_btm_try_speed(AO_SERIAL_SPEED_57600)) { + ao_delay(AO_SEC_TO_TICKS(1)); + if (ao_btm_try_speed(AO_SERIAL_SPEED_19200)) + ao_btm_cmd("ATL4\r"); + ao_delay(AO_SEC_TO_TICKS(1)); + } + + /* Disable echo */ + ao_btm_cmd("ATE0\r"); + + /* Enable flow control */ + ao_btm_cmd("ATC1\r"); + + /* Set the reported name to something we can find on the host */ + ao_btm_set_name(); + + /* Turn off status reporting */ + ao_btm_cmd("ATQ1\r"); + + ao_btm_stdio = ao_add_stdio(ao_serial_pollchar, + ao_serial_putchar, + NULL); + ao_btm_echo(0); + + for (;;) { + while (!ao_btm_connected) + ao_sleep(&ao_btm_connected); + while (ao_btm_connected) { + ao_led_for(AO_LED_GREEN, AO_MS_TO_TICKS(20)); + ao_delay(AO_SEC_TO_TICKS(3)); + } + } +} + +__xdata struct ao_task ao_btm_task; + +#if BT_LINK_ON_P2 +#define BT_PICTL_ICON PICTL_P2ICON +#define BT_PIFG P2IFG +#define BT_PDIR P2DIR +#define BT_PINP P2INP +#define BT_IEN2_PIE IEN2_P2IE +#endif +#if BT_LINK_ON_P1 +#define BT_PICTL_ICON PICTL_P1ICON +#define BT_PIFG P1IFG +#define BT_PDIR P1DIR +#define BT_PINP P1INP +#define BT_IEN2_PIE IEN2_P1IE +#endif + +void +ao_btm_check_link() __critical +{ + /* Check the pin and configure the interrupt detector to wait for the + * pin to flip the other way + */ + if (BT_LINK_PIN) { + ao_btm_connected = 0; + PICTL |= BT_PICTL_ICON; + } else { + ao_btm_connected = 1; + PICTL &= ~BT_PICTL_ICON; + } +} + +void +ao_btm_isr(void) +#if BT_LINK_ON_P1 + __interrupt 15 +#endif +{ +#if BT_LINK_ON_P1 + P1IF = 0; +#endif + if (BT_PIFG & (1 << BT_LINK_PIN_INDEX)) { + ao_btm_check_link(); + ao_wakeup(&ao_btm_connected); + } + BT_PIFG = 0; +} + +void +ao_btm_init (void) +{ + ao_serial_init(); + ao_serial_set_speed(AO_SERIAL_SPEED_19200); + +#if BT_LINK_ON_P1 + /* + * Configure ser reset line + */ + + P1_6 = 0; + P1DIR |= (1 << 6); +#endif + + /* + * Configure link status line + */ + + /* Set pin to input */ + BT_PDIR &= ~(1 << BT_LINK_PIN_INDEX); + + /* Set pin to tri-state */ + BT_PINP |= (1 << BT_LINK_PIN_INDEX); + + /* Enable interrupts */ + IEN2 |= BT_IEN2_PIE; + + /* Check current pin state */ + ao_btm_check_link(); + +#if BT_LINK_ON_P2 + /* Eable the pin interrupt */ + PICTL |= PICTL_P2IEN; +#endif +#if BT_LINK_ON_P1 + /* Enable pin interrupt */ + P1IEN |= (1 << BT_LINK_PIN_INDEX); +#endif + + ao_add_task(&ao_btm_task, ao_btm, "bt"); +} diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c new file mode 100644 index 00000000..4c8f4269 --- /dev/null +++ b/src/drivers/ao_companion.c @@ -0,0 +1,132 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +#define ao_spi_slow() (U0GCR = (UxGCR_CPOL_NEGATIVE | \ + UxGCR_CPHA_FIRST_EDGE | \ + UxGCR_ORDER_MSB | \ + (13 << UxGCR_BAUD_E_SHIFT))) + +#define ao_spi_fast() (U0GCR = (UxGCR_CPOL_NEGATIVE | \ + UxGCR_CPHA_FIRST_EDGE | \ + UxGCR_ORDER_MSB | \ + (17 << UxGCR_BAUD_E_SHIFT))) + +#define COMPANION_SELECT() do { ao_spi_get_bit(COMPANION_CS); ao_spi_slow(); } while (0) +#define COMPANION_DESELECT() do { ao_spi_fast(); ao_spi_put_bit(COMPANION_CS); } while (0) + +static __xdata struct ao_companion_command ao_companion_command; +__xdata struct ao_companion_setup ao_companion_setup; + +__xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; +__pdata uint8_t ao_companion_running; +__xdata uint8_t ao_companion_mutex; + +static void +ao_companion_send_command(uint8_t command) +{ + ao_companion_command.command = command; + ao_companion_command.flight_state = ao_flight_state; + ao_companion_command.tick = ao_time(); + ao_companion_command.serial = ao_serial_number; + ao_companion_command.flight = ao_flight_number; + ao_spi_send(&ao_companion_command, sizeof (ao_companion_command)); +} + +static uint8_t +ao_companion_get_setup(void) +{ + COMPANION_SELECT(); + ao_companion_send_command(AO_COMPANION_SETUP); + ao_spi_recv(&ao_companion_setup, sizeof (ao_companion_setup)); + COMPANION_DESELECT(); + return (ao_companion_setup.board_id == + ~ao_companion_setup.board_id_inverse); +} + +static void +ao_companion_get_data(void) +{ + COMPANION_SELECT(); + ao_companion_send_command(AO_COMPANION_FETCH); + ao_mutex_get(&ao_companion_mutex); + ao_spi_recv(&ao_companion_data, ao_companion_setup.channels * 2); + ao_mutex_put(&ao_companion_mutex); + COMPANION_DESELECT(); +} + +static void +ao_companion_notify(void) +{ + COMPANION_SELECT(); + ao_companion_send_command(AO_COMPANION_NOTIFY); + COMPANION_DESELECT(); +} + +void +ao_companion(void) +{ + uint8_t i; + while (!ao_flight_number) + ao_sleep(&ao_flight_number); + for (i = 0; i < 10; i++) { + ao_delay(AO_SEC_TO_TICKS(1)); + if ((ao_companion_running = ao_companion_get_setup())) + break; + } + while (ao_companion_running) { + ao_alarm(ao_companion_setup.update_period); + if (ao_sleep(DATA_TO_XDATA(&ao_flight_state))) + ao_companion_get_data(); + else + ao_companion_notify(); + } + ao_exit(); +} + +void +ao_companion_status(void) __reentrant +{ + uint8_t i; + printf("Companion running: %d\n", ao_companion_running); + printf("device: %d\n", ao_companion_setup.board_id); + printf("update period: %d\n", ao_companion_setup.update_period); + printf("channels: %d\n", ao_companion_setup.channels); + printf("data:"); + for(i = 0; i < ao_companion_setup.channels; i++) + printf(" %5u", ao_companion_data[i]); + printf("\n"); +} + +__code struct ao_cmds ao_companion_cmds[] = { + { ao_companion_status, "L\0Companion link status" }, + { 0, NULL }, +}; + +static __xdata struct ao_task ao_companion_task; + +void +ao_companion_init(void) +{ + COMPANION_CS_PORT |= COMPANION_CS_MASK; /* raise all CS pins */ + COMPANION_CS_DIR |= COMPANION_CS_MASK; /* set CS pins as outputs */ + COMPANION_CS_SEL &= ~COMPANION_CS_MASK; /* set CS pins as GPIO */ + + ao_cmd_register(&ao_companion_cmds[0]); + ao_add_task(&ao_companion_task, ao_companion, "companion"); +} diff --git a/src/drivers/ao_gps_sirf.c b/src/drivers/ao_gps_sirf.c new file mode 100644 index 00000000..f2abbf84 --- /dev/null +++ b/src/drivers/ao_gps_sirf.c @@ -0,0 +1,442 @@ +/* + * 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. + */ + +#ifndef AO_GPS_TEST +#include "ao.h" +#endif + +__xdata uint8_t ao_gps_mutex; +__pdata uint16_t ao_gps_tick; +__xdata struct ao_telemetry_location ao_gps_data; +__xdata struct ao_telemetry_satellite ao_gps_tracking_data; + +static const char ao_gps_set_nmea[] = "\r\n$PSRF100,0,57600,8,1,0*37\r\n"; + +const char ao_gps_config[] = { + + 0xa0, 0xa2, 0x00, 0x0e, /* length: 14 bytes */ + 136, /* mode control */ + 0, 0, /* reserved */ + 0, /* degraded mode (allow 1-SV navigation) */ + 0, 0, /* reserved */ + 0, 0, /* user specified altitude */ + 2, /* alt hold mode (disabled, require 3d fixes) */ + 0, /* alt hold source (use last computed altitude) */ + 0, /* reserved */ + 10, /* Degraded time out (10 sec) */ + 10, /* Dead Reckoning time out (10 sec) */ + 0, /* Track smoothing (disabled) */ + 0x00, 0x8e, 0xb0, 0xb3, + + 0xa0, 0xa2, 0x00, 0x08, /* length: 8 bytes */ + 166, /* Set message rate */ + 2, /* enable/disable all messages */ + 0, /* message id (ignored) */ + 0, /* update rate (0 = disable) */ + 0, 0, 0, 0, /* reserved */ + 0x00, 0xa8, 0xb0, 0xb3, + + 0xa0, 0xa2, 0x00, 0x02, /* length: 2 bytes */ + 143, /* static navigation */ + 0, /* disable */ + 0x00, 0x8f, 0xb0, 0xb3, +}; + +#define NAV_TYPE_GPS_FIX_TYPE_MASK (7 << 0) +#define NAV_TYPE_NO_FIX (0 << 0) +#define NAV_TYPE_SV_KF (1 << 0) +#define NAV_TYPE_2_SV_KF (2 << 0) +#define NAV_TYPE_3_SV_KF (3 << 0) +#define NAV_TYPE_4_SV_KF (4 << 0) +#define NAV_TYPE_2D_LEAST_SQUARES (5 << 0) +#define NAV_TYPE_3D_LEAST_SQUARES (6 << 0) +#define NAV_TYPE_DR (7 << 0) +#define NAV_TYPE_TRICKLE_POWER (1 << 3) +#define NAV_TYPE_ALTITUDE_HOLD_MASK (3 << 4) +#define NAV_TYPE_ALTITUDE_HOLD_NONE (0 << 4) +#define NAV_TYPE_ALTITUDE_HOLD_KF (1 << 4) +#define NAV_TYPE_ALTITUDE_HOLD_USER (2 << 4) +#define NAV_TYPE_ALTITUDE_HOLD_ALWAYS (3 << 4) +#define NAV_TYPE_DOP_LIMIT_EXCEEDED (1 << 6) +#define NAV_TYPE_DGPS_APPLIED (1 << 7) +#define NAV_TYPE_SENSOR_DR (1 << 8) +#define NAV_TYPE_OVERDETERMINED (1 << 9) +#define NAV_TYPE_DR_TIMEOUT_EXCEEDED (1 << 10) +#define NAV_TYPE_FIX_MI_EDIT (1 << 11) +#define NAV_TYPE_INVALID_VELOCITY (1 << 12) +#define NAV_TYPE_ALTITUDE_HOLD_DISABLED (1 << 13) +#define NAV_TYPE_DR_ERROR_STATUS_MASK (3 << 14) +#define NAV_TYPE_DR_ERROR_STATUS_GPS_ONLY (0 << 14) +#define NAV_TYPE_DR_ERROR_STATUS_DR_FROM_GPS (1 << 14) +#define NAV_TYPE_DR_ERROR_STATUS_DR_SENSOR_ERROR (2 << 14) +#define NAV_TYPE_DR_ERROR_STATUS_DR_IN_TEST (3 << 14) + +struct sirf_geodetic_nav_data { + uint16_t nav_type; + uint16_t utc_year; + uint8_t utc_month; + uint8_t utc_day; + uint8_t utc_hour; + uint8_t utc_minute; + uint16_t utc_second; + int32_t lat; + int32_t lon; + int32_t alt_msl; + uint16_t ground_speed; + uint16_t course; + int16_t climb_rate; + uint32_t h_error; + uint32_t v_error; + uint8_t num_sv; + uint8_t hdop; +}; + +static __xdata struct sirf_geodetic_nav_data ao_sirf_data; + +struct sirf_measured_sat_data { + uint8_t svid; + uint8_t c_n_1; +}; + +struct sirf_measured_tracker_data { + int16_t gps_week; + uint32_t gps_tow; + uint8_t channels; + struct sirf_measured_sat_data sats[12]; +}; + +static __xdata struct sirf_measured_tracker_data ao_sirf_tracker_data; + +static __pdata uint16_t ao_sirf_cksum; +static __pdata uint16_t ao_sirf_len; + +#define ao_sirf_byte() ((uint8_t) ao_serial_getchar()) + +static uint8_t data_byte(void) +{ + uint8_t c = ao_sirf_byte(); + --ao_sirf_len; + ao_sirf_cksum += c; + return c; +} + +static char __xdata *sirf_target; + +static void sirf_u16(uint8_t offset) +{ + uint16_t __xdata *ptr = (uint16_t __xdata *) (sirf_target + offset); + uint16_t val; + + val = data_byte() << 8; + val |= data_byte (); + *ptr = val; +} + +static void sirf_u8(uint8_t offset) +{ + uint8_t __xdata *ptr = (uint8_t __xdata *) (sirf_target + offset); + uint8_t val; + + val = data_byte (); + *ptr = val; +} + +static void sirf_u32(uint8_t offset) __reentrant +{ + uint32_t __xdata *ptr = (uint32_t __xdata *) (sirf_target + offset); + uint32_t val; + + val = ((uint32_t) data_byte ()) << 24; + val |= ((uint32_t) data_byte ()) << 16; + val |= ((uint32_t) data_byte ()) << 8; + val |= ((uint32_t) data_byte ()); + *ptr = val; +} + +static void sirf_discard(uint8_t len) +{ + while (len--) + data_byte(); +} + +#define SIRF_END 0 +#define SIRF_DISCARD 1 +#define SIRF_U8 2 +#define SIRF_U16 3 +#define SIRF_U32 4 +#define SIRF_U8X10 5 + +struct sirf_packet_parse { + uint8_t type; + uint8_t offset; +}; + +static void +ao_sirf_parse(void __xdata *target, const struct sirf_packet_parse *parse) __reentrant +{ + uint8_t i, offset, j; + + sirf_target = target; + for (i = 0; ; i++) { + offset = parse[i].offset; + switch (parse[i].type) { + case SIRF_END: + return; + case SIRF_DISCARD: + sirf_discard(offset); + break; + case SIRF_U8: + sirf_u8(offset); + break; + case SIRF_U16: + sirf_u16(offset); + break; + case SIRF_U32: + sirf_u32(offset); + break; + case SIRF_U8X10: + for (j = 10; j--;) + sirf_u8(offset++); + break; + } + } +} + +static const struct sirf_packet_parse geodetic_nav_data_packet[] = { + { SIRF_DISCARD, 2 }, /* 1 nav valid */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, nav_type) }, /* 3 */ + { SIRF_DISCARD, 6 }, /* 5 week number, time of week */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, utc_year) }, /* 11 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_month) }, /* 13 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_day) }, /* 14 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_hour) }, /* 15 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, utc_minute) }, /* 16 */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, utc_second) }, /* 17 */ + { SIRF_DISCARD, 4 }, /* satellite id list */ /* 19 */ + { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, lat) }, /* 23 */ + { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, lon) }, /* 27 */ + { SIRF_DISCARD, 4 }, /* altitude from ellipsoid */ /* 31 */ + { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, alt_msl) }, /* 35 */ + { SIRF_DISCARD, 1 }, /* map datum */ /* 39 */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, ground_speed) }, /* 40 */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, course) }, /* 42 */ + { SIRF_DISCARD, 2 }, /* magnetic variation */ /* 44 */ + { SIRF_U16, offsetof(struct sirf_geodetic_nav_data, climb_rate) }, /* 46 */ + { SIRF_DISCARD, 2 }, /* turn rate */ /* 48 */ + { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, h_error) }, /* 50 */ + { SIRF_U32, offsetof(struct sirf_geodetic_nav_data, v_error) }, /* 54 */ + { SIRF_DISCARD, 30 }, /* time error, h_vel error, clock_bias, + clock bias error, clock drift, + clock drift error, distance, + distance error, heading error */ /* 58 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, num_sv) }, /* 88 */ + { SIRF_U8, offsetof(struct sirf_geodetic_nav_data, hdop) }, /* 89 */ + { SIRF_DISCARD, 1 }, /* additional mode info */ /* 90 */ + { SIRF_END, 0 }, /* 91 */ +}; + +static void +ao_sirf_parse_41(void) __reentrant +{ + ao_sirf_parse(&ao_sirf_data, geodetic_nav_data_packet); +} + +static const struct sirf_packet_parse measured_tracker_data_packet[] = { + { SIRF_U16, offsetof (struct sirf_measured_tracker_data, gps_week) }, /* 1 week */ + { SIRF_U32, offsetof (struct sirf_measured_tracker_data, gps_tow) }, /* 3 time of week */ + { SIRF_U8, offsetof (struct sirf_measured_tracker_data, channels) }, /* 7 channels */ + { SIRF_END, 0 }, +}; + +static const struct sirf_packet_parse measured_sat_data_packet[] = { + { SIRF_U8, offsetof (struct sirf_measured_sat_data, svid) }, /* 0 SV id */ + { SIRF_DISCARD, 4 }, /* 1 azimuth, 2 elevation, 3 state */ + { SIRF_U8, offsetof (struct sirf_measured_sat_data, c_n_1) }, /* C/N0 1 */ + { SIRF_DISCARD, 9 }, /* C/N0 2-10 */ + { SIRF_END, 0 }, +}; + +static void +ao_sirf_parse_4(void) __reentrant +{ + uint8_t i; + ao_sirf_parse(&ao_sirf_tracker_data, measured_tracker_data_packet); + for (i = 0; i < 12; i++) + ao_sirf_parse(&ao_sirf_tracker_data.sats[i], measured_sat_data_packet); +} + +static void +ao_gps_setup(void) __reentrant +{ + uint8_t i, k; + ao_serial_set_speed(AO_SERIAL_SPEED_4800); + for (i = 0; i < 64; i++) + ao_serial_putchar(0x00); + for (k = 0; k < 3; k++) + for (i = 0; i < sizeof (ao_gps_set_nmea); i++) + ao_serial_putchar(ao_gps_set_nmea[i]); + ao_serial_set_speed(AO_SERIAL_SPEED_57600); + for (i = 0; i < 64; i++) + ao_serial_putchar(0x00); +} + +static const char ao_gps_set_message_rate[] = { + 0xa0, 0xa2, 0x00, 0x08, + 166, + 0, +}; + +void +ao_sirf_set_message_rate(uint8_t msg, uint8_t rate) __reentrant +{ + uint16_t cksum = 0x00a6; + uint8_t i; + + for (i = 0; i < sizeof (ao_gps_set_message_rate); i++) + ao_serial_putchar(ao_gps_set_message_rate[i]); + ao_serial_putchar(msg); + ao_serial_putchar(rate); + cksum = 0xa6 + msg + rate; + for (i = 0; i < 4; i++) + ao_serial_putchar(0); + ao_serial_putchar((cksum >> 8) & 0x7f); + ao_serial_putchar(cksum & 0xff); + ao_serial_putchar(0xb0); + ao_serial_putchar(0xb3); +} + +static const uint8_t sirf_disable[] = { + 2, + 9, + 10, + 27, + 50, + 52, +}; + +void +ao_gps(void) __reentrant +{ + uint8_t i, k; + uint16_t cksum; + + ao_gps_setup(); + for (k = 0; k < 5; k++) + { + for (i = 0; i < sizeof (ao_gps_config); i++) + ao_serial_putchar(ao_gps_config[i]); + for (i = 0; i < sizeof (sirf_disable); i++) + ao_sirf_set_message_rate(sirf_disable[i], 0); + ao_sirf_set_message_rate(41, 1); + ao_sirf_set_message_rate(4, 1); + } + for (;;) { + /* Locate the begining of the next record */ + while (ao_sirf_byte() != (uint8_t) 0xa0) + ; + if (ao_sirf_byte() != (uint8_t) 0xa2) + continue; + + /* Length */ + ao_sirf_len = ao_sirf_byte() << 8; + ao_sirf_len |= ao_sirf_byte(); + if (ao_sirf_len > 1023) + continue; + + ao_sirf_cksum = 0; + + /* message ID */ + i = data_byte (); /* 0 */ + + switch (i) { + case 41: + if (ao_sirf_len < 90) + break; + ao_sirf_parse_41(); + break; + case 4: + if (ao_sirf_len < 187) + break; + ao_sirf_parse_4(); + break; + } + if (ao_sirf_len != 0) + continue; + + /* verify checksum and end sequence */ + ao_sirf_cksum &= 0x7fff; + cksum = ao_sirf_byte() << 8; + cksum |= ao_sirf_byte(); + if (ao_sirf_cksum != cksum) + continue; + if (ao_sirf_byte() != (uint8_t) 0xb0) + continue; + if (ao_sirf_byte() != (uint8_t) 0xb3) + continue; + + switch (i) { + case 41: + ao_mutex_get(&ao_gps_mutex); + ao_gps_tick = ao_time(); + ao_gps_data.hour = ao_sirf_data.utc_hour; + ao_gps_data.minute = ao_sirf_data.utc_minute; + ao_gps_data.second = ao_sirf_data.utc_second / 1000; + ao_gps_data.flags = ((ao_sirf_data.num_sv << AO_GPS_NUM_SAT_SHIFT) & AO_GPS_NUM_SAT_MASK) | AO_GPS_RUNNING; + if ((ao_sirf_data.nav_type & NAV_TYPE_GPS_FIX_TYPE_MASK) >= NAV_TYPE_4_SV_KF) + ao_gps_data.flags |= AO_GPS_VALID; + ao_gps_data.latitude = ao_sirf_data.lat; + ao_gps_data.longitude = ao_sirf_data.lon; + ao_gps_data.altitude = ao_sirf_data.alt_msl / 100; + ao_gps_data.ground_speed = ao_sirf_data.ground_speed; + ao_gps_data.course = ao_sirf_data.course / 200; + ao_gps_data.hdop = ao_sirf_data.hdop; + ao_gps_data.climb_rate = ao_sirf_data.climb_rate; + ao_gps_data.flags |= AO_GPS_COURSE_VALID; +#if 0 + if (ao_sirf_data.h_error > 6553500) + ao_gps_data.h_error = 65535; + else + ao_gps_data.h_error = ao_sirf_data.h_error / 100; + if (ao_sirf_data.v_error > 6553500) + ao_gps_data.v_error = 65535; + else + ao_gps_data.v_error = ao_sirf_data.v_error / 100; +#endif + ao_mutex_put(&ao_gps_mutex); + ao_wakeup(&ao_gps_data); + break; + case 4: + ao_mutex_get(&ao_gps_mutex); + ao_gps_tracking_data.channels = ao_sirf_tracker_data.channels; + for (i = 0; i < 12; i++) { + ao_gps_tracking_data.sats[i].svid = ao_sirf_tracker_data.sats[i].svid; + ao_gps_tracking_data.sats[i].c_n_1 = ao_sirf_tracker_data.sats[i].c_n_1; + } + ao_mutex_put(&ao_gps_mutex); + ao_wakeup(&ao_gps_tracking_data); + break; + } + } +} + +__xdata struct ao_task ao_gps_task; + +void +ao_gps_init(void) +{ + ao_add_task(&ao_gps_task, ao_gps, "gps"); +} diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c new file mode 100644 index 00000000..7ac26946 --- /dev/null +++ b/src/drivers/ao_gps_skytraq.c @@ -0,0 +1,490 @@ +/* + * 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. + */ + +#ifndef AO_GPS_TEST +#include "ao.h" +#endif + +#define AO_GPS_LEADER 2 + +static __code char ao_gps_header[] = "GP"; + +__xdata uint8_t ao_gps_mutex; +static __data char ao_gps_char; +static __pdata uint8_t ao_gps_cksum; +static __pdata uint8_t ao_gps_error; + +__pdata uint16_t ao_gps_tick; +__xdata struct ao_telemetry_location ao_gps_data; +__xdata struct ao_telemetry_satellite ao_gps_tracking_data; + +static __pdata uint16_t ao_gps_next_tick; +static __xdata struct ao_telemetry_location ao_gps_next; +static __pdata uint8_t ao_gps_date_flags; +static __xdata struct ao_telemetry_satellite ao_gps_tracking_next; + +#define STQ_S 0xa0, 0xa1 +#define STQ_E 0x0d, 0x0a +#define SKYTRAQ_MSG_2(id,a,b) \ + STQ_S, 0, 3, id, a,b, (id^a^b), STQ_E +#define SKYTRAQ_MSG_3(id,a,b,c) \ + STQ_S, 0, 4, id, a,b,c, (id^a^b^c), STQ_E +#define SKYTRAQ_MSG_8(id,a,b,c,d,e,f,g,h) \ + STQ_S, 0, 9, id, a,b,c,d,e,f,g,h, (id^a^b^c^d^e^f^g^h), STQ_E +#define SKYTRAQ_MSG_14(id,a,b,c,d,e,f,g,h,i,j,k,l,m,n) \ + STQ_S, 0,15, id, a,b,c,d,e,f,g,h,i,j,k,l,m,n, \ + (id^a^b^c^d^e^f^g^h^i^j^k^l^m^n), STQ_E + +static __code uint8_t ao_gps_config[] = { + SKYTRAQ_MSG_8(0x08, 1, 1, 1, 1, 1, 1, 1, 0), /* configure nmea */ + /* gga interval */ + /* gsa interval */ + /* gsv interval */ + /* gll interval */ + /* rmc interval */ + /* vtg interval */ + /* zda interval */ + /* attributes (0 = update to sram, 1 = update flash too) */ + + SKYTRAQ_MSG_2(0x3c, 0x00, 0x00), /* configure navigation mode */ + /* 0 = car, 1 = pedestrian */ + /* 0 = update to sram, 1 = update sram + flash */ +}; + +static void +ao_gps_lexchar(void) +{ + if (ao_gps_error) + ao_gps_char = '\n'; + else + ao_gps_char = ao_serial_getchar(); + ao_gps_cksum ^= ao_gps_char; +} + +void +ao_gps_skip_field(void) +{ + while (ao_gps_char != ',' && ao_gps_char != '*' && ao_gps_char != '\n') + ao_gps_lexchar(); +} + +void +ao_gps_skip_sep(void) +{ + if (ao_gps_char == ',' || ao_gps_char == '.' || ao_gps_char == '*') + ao_gps_lexchar(); +} + +__pdata static uint8_t ao_gps_num_width; + +static int16_t +ao_gps_decimal(uint8_t max_width) +{ + int16_t v; + __pdata uint8_t neg = 0; + + ao_gps_skip_sep(); + if (ao_gps_char == '-') { + neg = 1; + ao_gps_lexchar(); + } + v = 0; + ao_gps_num_width = 0; + while (ao_gps_num_width < max_width) { + if (ao_gps_char < '0' || '9' < ao_gps_char) + break; + v = v * (int16_t) 10 + ao_gps_char - '0'; + ao_gps_num_width++; + ao_gps_lexchar(); + } + if (neg) + v = -v; + return v; +} + +static uint8_t +ao_gps_hex(uint8_t max_width) +{ + uint8_t v, d; + + ao_gps_skip_sep(); + v = 0; + ao_gps_num_width = 0; + while (ao_gps_num_width < max_width) { + if ('0' <= ao_gps_char && ao_gps_char <= '9') + d = ao_gps_char - '0'; + else if ('A' <= ao_gps_char && ao_gps_char <= 'F') + d = ao_gps_char - 'A' + 10; + else if ('a' <= ao_gps_char && ao_gps_char <= 'f') + d = ao_gps_char - 'a' + 10; + else + break; + v = (v << 4) | d; + ao_gps_num_width++; + ao_gps_lexchar(); + } + return v; +} + +static int32_t +ao_gps_parse_pos(uint8_t deg_width) __reentrant +{ + int32_t d; + int32_t m; + int32_t f; + + d = ao_gps_decimal(deg_width); + m = ao_gps_decimal(2); + if (ao_gps_char == '.') { + f = ao_gps_decimal(4); + while (ao_gps_num_width < 4) { + f *= 10; + ao_gps_num_width++; + } + } else { + f = 0; + if (ao_gps_char != ',') + ao_gps_error = 1; + } + d = d * 10000000l; + m = m * 10000l + f; + d = d + m * 50 / 3; + return d; +} + +static uint8_t +ao_gps_parse_flag(char no_c, char yes_c) __reentrant +{ + uint8_t ret = 0; + ao_gps_skip_sep(); + if (ao_gps_char == yes_c) + ret = 1; + else if (ao_gps_char == no_c) + ret = 0; + else + ao_gps_error = 1; + ao_gps_lexchar(); + return ret; +} + +static void +ao_nmea_gga() +{ + uint8_t i; + + /* Now read the data into the gps data record + * + * $GPGGA,025149.000,4528.1723,N,12244.2480,W,1,05,2.0,103.5,M,-19.5,M,,0000*66 + * + * Essential fix data + * + * 025149.000 time (02:51:49.000 GMT) + * 4528.1723,N Latitude 45°28.1723' N + * 12244.2480,W Longitude 122°44.2480' W + * 1 Fix quality: + * 0 = invalid + * 1 = GPS fix (SPS) + * 2 = DGPS fix + * 3 = PPS fix + * 4 = Real Time Kinematic + * 5 = Float RTK + * 6 = estimated (dead reckoning) + * 7 = Manual input mode + * 8 = Simulation mode + * 05 Number of satellites (5) + * 2.0 Horizontal dilution + * 103.5,M Altitude, 103.5M above msl + * -19.5,M Height of geoid above WGS84 ellipsoid + * ? time in seconds since last DGPS update + * 0000 DGPS station ID + * *66 checksum + */ + + ao_gps_next_tick = ao_time(); + ao_gps_next.flags = AO_GPS_RUNNING | ao_gps_date_flags; + ao_gps_next.hour = ao_gps_decimal(2); + ao_gps_next.minute = ao_gps_decimal(2); + ao_gps_next.second = ao_gps_decimal(2); + ao_gps_skip_field(); /* skip seconds fraction */ + + ao_gps_next.latitude = ao_gps_parse_pos(2); + if (ao_gps_parse_flag('N', 'S')) + ao_gps_next.latitude = -ao_gps_next.latitude; + ao_gps_next.longitude = ao_gps_parse_pos(3); + if (ao_gps_parse_flag('E', 'W')) + ao_gps_next.longitude = -ao_gps_next.longitude; + + i = ao_gps_decimal(0xff); + if (i == 1) + ao_gps_next.flags |= AO_GPS_VALID; + + i = ao_gps_decimal(0xff) << AO_GPS_NUM_SAT_SHIFT; + if (i > AO_GPS_NUM_SAT_MASK) + i = AO_GPS_NUM_SAT_MASK; + ao_gps_next.flags |= i; + + ao_gps_lexchar(); + i = ao_gps_decimal(0xff); + if (i <= 50) { + i = (uint8_t) 5 * i; + if (ao_gps_char == '.') + i = (i + ((uint8_t) ao_gps_decimal(1) >> 1)); + } else + i = 255; + ao_gps_next.hdop = i; + ao_gps_skip_field(); + + ao_gps_next.altitude = ao_gps_decimal(0xff); + ao_gps_skip_field(); /* skip any fractional portion */ + + /* Skip remaining fields */ + while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { + ao_gps_lexchar(); + ao_gps_skip_field(); + } + if (ao_gps_char == '*') { + uint8_t cksum = ao_gps_cksum ^ '*'; + if (cksum != ao_gps_hex(2)) + ao_gps_error = 1; + } else + ao_gps_error = 1; + if (!ao_gps_error) { + ao_mutex_get(&ao_gps_mutex); + ao_gps_tick = ao_gps_next_tick; + memcpy(&ao_gps_data, &ao_gps_next, sizeof (ao_gps_data)); + ao_mutex_put(&ao_gps_mutex); + ao_wakeup(&ao_gps_data); + } +} + +static void +ao_nmea_gsv(void) +{ + char c; + uint8_t i; + uint8_t done; + /* Now read the data into the GPS tracking data record + * + * $GPGSV,3,1,12,05,54,069,45,12,44,061,44,21,07,184,46,22,78,289,47*72 + * + * Satellites in view data + * + * 3 Total number of GSV messages + * 1 Sequence number of current GSV message + * 12 Total sats in view (0-12) + * 05 SVID + * 54 Elevation + * 069 Azimuth + * 45 C/N0 in dB + * ... other SVIDs + * 72 checksum + */ + c = ao_gps_decimal(1); /* total messages */ + i = ao_gps_decimal(1); /* message sequence */ + if (i == 1) { + ao_gps_tracking_next.channels = 0; + } + done = (uint8_t) c == i; + ao_gps_lexchar(); + ao_gps_skip_field(); /* sats in view */ + while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { + i = ao_gps_tracking_next.channels; + c = ao_gps_decimal(2); /* SVID */ + if (i < AO_MAX_GPS_TRACKING) + ao_gps_tracking_next.sats[i].svid = c; + ao_gps_lexchar(); + ao_gps_skip_field(); /* elevation */ + ao_gps_lexchar(); + ao_gps_skip_field(); /* azimuth */ + c = ao_gps_decimal(2); /* C/N0 */ + if (i < AO_MAX_GPS_TRACKING) { + if ((ao_gps_tracking_next.sats[i].c_n_1 = c) != 0) + ao_gps_tracking_next.channels = i + 1; + } + } + if (ao_gps_char == '*') { + uint8_t cksum = ao_gps_cksum ^ '*'; + if (cksum != ao_gps_hex(2)) + ao_gps_error = 1; + } + else + ao_gps_error = 1; + if (ao_gps_error) + ao_gps_tracking_next.channels = 0; + else if (done) { + ao_mutex_get(&ao_gps_mutex); + memcpy(&ao_gps_tracking_data, &ao_gps_tracking_next, + sizeof(ao_gps_tracking_data)); + ao_mutex_put(&ao_gps_mutex); + ao_wakeup(&ao_gps_tracking_data); + } +} + +static void +ao_nmea_rmc(void) +{ + char a, c; + uint8_t i; + /* Parse the RMC record to read out the current date */ + + /* $GPRMC,111636.932,A,2447.0949,N,12100.5223,E,000.0,000.0,030407,,,A*61 + * + * Recommended Minimum Specific GNSS Data + * + * 111636.932 UTC time 11:16:36.932 + * A Data Valid (V = receiver warning) + * 2447.0949 Latitude + * N North/south indicator + * 12100.5223 Longitude + * E East/west indicator + * 000.0 Speed over ground + * 000.0 Course over ground + * 030407 UTC date (ddmmyy format) + * A Mode indicator: + * N = data not valid + * A = autonomous mode + * D = differential mode + * E = estimated (dead reckoning) mode + * M = manual input mode + * S = simulator mode + * 61 checksum + */ + ao_gps_skip_field(); + for (i = 0; i < 8; i++) { + ao_gps_lexchar(); + ao_gps_skip_field(); + } + a = ao_gps_decimal(2); + c = ao_gps_decimal(2); + i = ao_gps_decimal(2); + /* Skip remaining fields */ + while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { + ao_gps_lexchar(); + ao_gps_skip_field(); + } + if (ao_gps_char == '*') { + uint8_t cksum = ao_gps_cksum ^ '*'; + if (cksum != ao_gps_hex(2)) + ao_gps_error = 1; + } else + ao_gps_error = 1; + if (!ao_gps_error) { + ao_gps_next.year = i; + ao_gps_next.month = c; + ao_gps_next.day = a; + ao_gps_date_flags = AO_GPS_DATE_VALID; + } +} + +#define ao_skytraq_sendstruct(s) ao_skytraq_sendbytes((s), sizeof(s)) + +static void +ao_skytraq_sendbytes(__code uint8_t *b, uint8_t l) +{ + while (l--) { + uint8_t c = *b++; + if (c == 0xa0) + ao_delay(AO_MS_TO_TICKS(500)); + ao_serial_putchar(c); + } +} + +static void +ao_gps_nmea_parse(void) +{ + uint8_t a, b, c; + + ao_gps_cksum = 0; + ao_gps_error = 0; + + for (a = 0; a < AO_GPS_LEADER; a++) { + ao_gps_lexchar(); + if (ao_gps_char != ao_gps_header[a]) + return; + } + + ao_gps_lexchar(); + a = ao_gps_char; + ao_gps_lexchar(); + b = ao_gps_char; + ao_gps_lexchar(); + c = ao_gps_char; + ao_gps_lexchar(); + + if (ao_gps_char != ',') + return; + + if (a == (uint8_t) 'G' && b == (uint8_t) 'G' && c == (uint8_t) 'A') { + ao_nmea_gga(); + } else if (a == (uint8_t) 'G' && b == (uint8_t) 'S' && c == (uint8_t) 'V') { + ao_nmea_gsv(); + } else if (a == (uint8_t) 'R' && b == (uint8_t) 'M' && c == (uint8_t) 'C') { + ao_nmea_rmc(); + } +} + +void +ao_gps(void) __reentrant +{ + ao_serial_set_speed(AO_SERIAL_SPEED_9600); + + /* give skytraq time to boot in case of cold start */ + ao_delay(AO_MS_TO_TICKS(2000)); + + ao_skytraq_sendstruct(ao_gps_config); + + for (;;) { + /* Locate the begining of the next record */ + if (ao_serial_getchar() == '$') { + ao_gps_nmea_parse(); + } + + } +} + +__xdata struct ao_task ao_gps_task; + +static void +gps_dump(void) __reentrant +{ + uint8_t i; + ao_mutex_get(&ao_gps_mutex); + printf ("Date: %02d/%02d/%02d\n", ao_gps_data.year, ao_gps_data.month, ao_gps_data.day); + printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second); + printf ("Lat/Lon: %ld %ld\n", ao_gps_data.latitude, ao_gps_data.longitude); + printf ("Alt: %d\n", ao_gps_data.altitude); + printf ("Flags: 0x%x\n", ao_gps_data.flags); + printf ("Sats: %d", ao_gps_tracking_data.channels); + for (i = 0; i < ao_gps_tracking_data.channels; i++) + printf (" %d %d", + ao_gps_tracking_data.sats[i].svid, + ao_gps_tracking_data.sats[i].c_n_1); + printf ("\ndone\n"); + ao_mutex_put(&ao_gps_mutex); +} + +__code struct ao_cmds ao_gps_cmds[] = { + { gps_dump, "g\0Display GPS" }, + { 0, NULL }, +}; + +void +ao_gps_init(void) +{ + ao_add_task(&ao_gps_task, ao_gps, "gps"); + ao_cmd_register(&ao_gps_cmds[0]); +} diff --git a/src/drivers/ao_m25.c b/src/drivers/ao_m25.c new file mode 100644 index 00000000..d7208273 --- /dev/null +++ b/src/drivers/ao_m25.c @@ -0,0 +1,380 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +/* Total bytes of available storage */ +__pdata uint32_t ao_storage_total; + +/* Block size - device is erased in these units. At least 256 bytes */ +__pdata uint32_t ao_storage_block; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +__pdata uint32_t ao_storage_config; + +/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ +__pdata uint16_t ao_storage_unit; + +/* + * Each flash chip is arranged in 64kB sectors; the + * chip cannot erase in units smaller than that. + * + * Writing happens in units of 256 byte pages and + * can only change bits from 1 to 0. So, you can rewrite + * the same contents, or append to an existing page easily enough + */ + +#define M25_WREN 0x06 /* Write Enable */ +#define M25_WRDI 0x04 /* Write Disable */ +#define M25_RDID 0x9f /* Read Identification */ +#define M25_RDSR 0x05 /* Read Status Register */ +#define M25_WRSR 0x01 /* Write Status Register */ +#define M25_READ 0x03 /* Read Data Bytes */ +#define M25_FAST_READ 0x0b /* Read Data Bytes at Higher Speed */ +#define M25_PP 0x02 /* Page Program */ +#define M25_SE 0xd8 /* Sector Erase */ +#define M25_BE 0xc7 /* Bulk Erase */ +#define M25_DP 0xb9 /* Deep Power-down */ + +/* RDID response */ +#define M25_MANUF_OFFSET 0 +#define M25_MEMORY_TYPE_OFFSET 1 +#define M25_CAPACITY_OFFSET 2 +#define M25_UID_OFFSET 3 +#define M25_CFI_OFFSET 4 +#define M25_RDID_LEN 4 /* that's all we need */ + +#define M25_CAPACITY_128KB 0x11 +#define M25_CAPACITY_256KB 0x12 +#define M25_CAPACITY_512KB 0x13 +#define M25_CAPACITY_1MB 0x14 +#define M25_CAPACITY_2MB 0x15 + +/* + * Status register bits + */ + +#define M25_STATUS_SRWD (1 << 7) /* Status register write disable */ +#define M25_STATUS_BP_MASK (7 << 2) /* Block protect bits */ +#define M25_STATUS_BP_SHIFT (2) +#define M25_STATUS_WEL (1 << 1) /* Write enable latch */ +#define M25_STATUS_WIP (1 << 0) /* Write in progress */ + +/* + * On teleterra, the m25 chip select pins are + * wired on P0_0 through P0_3. + */ + +#if M25_MAX_CHIPS > 1 +static uint8_t ao_m25_size[M25_MAX_CHIPS]; /* number of sectors in each chip */ +static uint8_t ao_m25_pin[M25_MAX_CHIPS]; /* chip select pin for each chip */ +static uint8_t ao_m25_numchips; /* number of chips detected */ +#endif +static uint8_t ao_m25_total; /* total sectors available */ +static uint8_t ao_m25_wip; /* write in progress */ + +static __xdata uint8_t ao_m25_mutex; + +/* + * This little array is abused to send and receive data. A particular + * caution -- the read and write addresses are written into the last + * three bytes of the array by ao_m25_set_page_address and then the + * first byte is used by ao_m25_wait_wip and ao_m25_write_enable, neither + * of which touch those last three bytes. + */ + +static __xdata uint8_t ao_m25_instruction[4]; + +#define M25_SELECT(cs) ao_spi_get_mask(SPI_CS_PORT,cs) +#define M25_DESELECT(cs) ao_spi_put_mask(SPI_CS_PORT,cs) + +#define M25_BLOCK_SHIFT 16 +#define M25_BLOCK 65536L +#define M25_POS_TO_SECTOR(pos) ((uint8_t) ((pos) >> M25_BLOCK_SHIFT)) +#define M25_SECTOR_TO_POS(sector) (((uint32_t) (sector)) << M25_BLOCK_SHIFT) + +/* + * Block until the specified chip is done writing + */ +static void +ao_m25_wait_wip(uint8_t cs) +{ + if (ao_m25_wip & cs) { + M25_SELECT(cs); + ao_m25_instruction[0] = M25_RDSR; + ao_spi_send(ao_m25_instruction, 1); + do { + ao_spi_recv(ao_m25_instruction, 1); + } while (ao_m25_instruction[0] & M25_STATUS_WIP); + M25_DESELECT(cs); + ao_m25_wip &= ~cs; + } +} + +/* + * Set the write enable latch so that page program and sector + * erase commands will work. Also mark the chip as busy writing + * so that future operations will block until the WIP bit goes off + */ +static void +ao_m25_write_enable(uint8_t cs) +{ + M25_SELECT(cs); + ao_m25_instruction[0] = M25_WREN; + ao_spi_send(&ao_m25_instruction, 1); + M25_DESELECT(cs); + ao_m25_wip |= cs; +} + + +/* + * Returns the number of 64kB sectors + */ +static uint8_t +ao_m25_read_capacity(uint8_t cs) +{ + uint8_t capacity; + M25_SELECT(cs); + ao_m25_instruction[0] = M25_RDID; + ao_spi_send(ao_m25_instruction, 1); + ao_spi_recv(ao_m25_instruction, M25_RDID_LEN); + M25_DESELECT(cs); + + /* Check to see if the chip is present */ + if (ao_m25_instruction[0] == 0xff) + return 0; + capacity = ao_m25_instruction[M25_CAPACITY_OFFSET]; + + /* Sanity check capacity number */ + if (capacity < 0x11 || 0x1f < capacity) + return 0; + return 1 << (capacity - 0x10); +} + +static uint8_t +ao_m25_set_address(uint32_t pos) +{ + uint8_t chip; +#if M25_MAX_CHIPS > 1 + uint8_t size; + + for (chip = 0; chip < ao_m25_numchips; chip++) { + size = ao_m25_size[chip]; + if (M25_POS_TO_SECTOR(pos) < size) + break; + pos -= M25_SECTOR_TO_POS(size); + } + if (chip == ao_m25_numchips) + return 0xff; + + chip = ao_m25_pin[chip]; +#else + chip = M25_CS_MASK; +#endif + ao_m25_wait_wip(chip); + + ao_m25_instruction[1] = pos >> 16; + ao_m25_instruction[2] = pos >> 8; + ao_m25_instruction[3] = pos; + return chip; +} + +/* + * Scan the possible chip select lines + * to see which flash chips are connected + */ +static uint8_t +ao_m25_scan(void) +{ +#if M25_MAX_CHIPS > 1 + uint8_t pin, size; +#endif + + if (ao_m25_total) + return 1; + +#if M25_MAX_CHIPS > 1 + ao_m25_numchips = 0; + for (pin = 1; pin != 0; pin <<= 1) { + if (M25_CS_MASK & pin) { + size = ao_m25_read_capacity(pin); + if (size != 0) { + ao_m25_size[ao_m25_numchips] = size; + ao_m25_pin[ao_m25_numchips] = pin; + ao_m25_total += size; + ao_m25_numchips++; + } + } + } +#else + ao_m25_total = ao_m25_read_capacity(M25_CS_MASK); +#endif + if (!ao_m25_total) + return 0; + ao_storage_total = M25_SECTOR_TO_POS(ao_m25_total); + ao_storage_block = M25_BLOCK; + ao_storage_config = ao_storage_total - M25_BLOCK; + ao_storage_unit = 256; + return 1; +} + +/* + * Erase the specified sector + */ +uint8_t +ao_storage_erase(uint32_t pos) __reentrant +{ + uint8_t cs; + + if (pos >= ao_storage_total || pos + ao_storage_block > ao_storage_total) + return 0; + + ao_mutex_get(&ao_m25_mutex); + ao_m25_scan(); + + cs = ao_m25_set_address(pos); + + ao_m25_wait_wip(cs); + ao_m25_write_enable(cs); + + ao_m25_instruction[0] = M25_SE; + M25_SELECT(cs); + ao_spi_send(ao_m25_instruction, 4); + M25_DESELECT(cs); + ao_m25_wip |= cs; + + ao_mutex_put(&ao_m25_mutex); + return 1; +} + +/* + * Write to flash + */ +uint8_t +ao_storage_device_write(uint32_t pos, __xdata void *d, uint16_t len) __reentrant +{ + uint8_t cs; + + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + + ao_mutex_get(&ao_m25_mutex); + ao_m25_scan(); + + cs = ao_m25_set_address(pos); + ao_m25_write_enable(cs); + + ao_m25_instruction[0] = M25_PP; + M25_SELECT(cs); + ao_spi_send(ao_m25_instruction, 4); + ao_spi_send(d, len); + M25_DESELECT(cs); + + ao_mutex_put(&ao_m25_mutex); + return 1; +} + +/* + * Read from flash + */ +uint8_t +ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant +{ + uint8_t cs; + + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + ao_mutex_get(&ao_m25_mutex); + ao_m25_scan(); + + cs = ao_m25_set_address(pos); + + /* No need to use the FAST_READ as we're running at only 8MHz */ + ao_m25_instruction[0] = M25_READ; + M25_SELECT(cs); + ao_spi_send(ao_m25_instruction, 4); + ao_spi_recv(d, len); + M25_DESELECT(cs); + + ao_mutex_put(&ao_m25_mutex); + return 1; +} + +void +ao_storage_flush(void) __reentrant +{ +} + +void +ao_storage_setup(void) +{ + ao_mutex_get(&ao_m25_mutex); + ao_m25_scan(); + ao_mutex_put(&ao_m25_mutex); +} + +void +ao_storage_device_info(void) __reentrant +{ + uint8_t cs; +#if M25_MAX_CHIPS > 1 + uint8_t chip; +#endif + + ao_mutex_get(&ao_m25_mutex); + ao_m25_scan(); + ao_mutex_put(&ao_m25_mutex); + +#if M25_MAX_CHIPS > 1 + printf ("Detected chips %d size %d\n", ao_m25_numchips, ao_m25_total); + for (chip = 0; chip < ao_m25_numchips; chip++) + printf ("Flash chip %d select %02x size %d\n", + chip, ao_m25_pin[chip], ao_m25_size[chip]); +#else + printf ("Detected chips 1 size %d\n", ao_m25_total); +#endif + + printf ("Available chips:\n"); + for (cs = 1; cs != 0; cs <<= 1) { + if ((M25_CS_MASK & cs) == 0) + continue; + + ao_mutex_get(&ao_m25_mutex); + M25_SELECT(cs); + ao_m25_instruction[0] = M25_RDID; + ao_spi_send(ao_m25_instruction, 1); + ao_spi_recv(ao_m25_instruction, M25_RDID_LEN); + M25_DESELECT(cs); + + printf ("Select %02x manf %02x type %02x cap %02x uid %02x\n", + cs, + ao_m25_instruction[M25_MANUF_OFFSET], + ao_m25_instruction[M25_MEMORY_TYPE_OFFSET], + ao_m25_instruction[M25_CAPACITY_OFFSET], + ao_m25_instruction[M25_UID_OFFSET]); + ao_mutex_put(&ao_m25_mutex); + } +} + +void +ao_storage_device_init(void) +{ + /* Set up chip select wires */ + SPI_CS_PORT |= M25_CS_MASK; /* raise all CS pins */ + SPI_CS_DIR |= M25_CS_MASK; /* set CS pins as outputs */ + SPI_CS_SEL &= ~M25_CS_MASK; /* set CS pins as GPIO */ +} diff --git a/src/gps-cksum b/src/gps-cksum deleted file mode 100755 index a08153bf..00000000 --- a/src/gps-cksum +++ /dev/null @@ -1,17 +0,0 @@ -#!/usr/bin/env nickle - -int checksum(string a) -{ - int c = 0; - for (int i = 0; i < String::length(a); i++) - c ^= a[i]; - return c; -} - -void main() -{ - for (int i = 1; i < dim(argv); i++) - printf ("$%s*%02x\n", argv[i], checksum(argv[i])); -} - -main(); diff --git a/src/make-altitude b/src/make-altitude deleted file mode 100644 index 716aa8a8..00000000 --- a/src/make-altitude +++ /dev/null @@ -1,283 +0,0 @@ -#!/usr/bin/nickle -f -/* - * Pressure Sensor Model, version 1.1 - * - * written by Holly Grimes - * - * Uses the International Standard Atmosphere as described in - * "A Quick Derivation relating altitude to air pressure" (version 1.03) - * from the Portland State Aerospace Society, except that the atmosphere - * is divided into layers with each layer having a different lapse rate. - * - * Lapse rate data for each layer was obtained from Wikipedia on Sept. 1, 2007 - * at site MAXIMUM_ALTITUDE) /* FIX ME: use sensor data to improve model */ - return 0; - - /* calculate the base temperature and pressure for the atmospheric layer - associated with the inputted altitude */ - for(layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1 && altitude > base_altitude[layer_number + 1]; layer_number++) { - delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; - if (lapse_rate[layer_number] == 0.0) { - exponent = GRAVITATIONAL_ACCELERATION * delta_z - / AIR_GAS_CONSTANT / base_temperature; - base_pressure *= exp(exponent); - } - else { - base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; - exponent = GRAVITATIONAL_ACCELERATION / - (AIR_GAS_CONSTANT * lapse_rate[layer_number]); - base_pressure *= pow(base, exponent); - } - base_temperature += delta_z * lapse_rate[layer_number]; - } - - /* calculate the pressure at the inputted altitude */ - delta_z = altitude - base_altitude[layer_number]; - if (lapse_rate[layer_number] == 0.0) { - exponent = GRAVITATIONAL_ACCELERATION * delta_z - / AIR_GAS_CONSTANT / base_temperature; - pressure = base_pressure * exp(exponent); - } - else { - base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; - exponent = GRAVITATIONAL_ACCELERATION / - (AIR_GAS_CONSTANT * lapse_rate[layer_number]); - pressure = base_pressure * pow(base, exponent); - } - - return pressure; -} - - -/* outputs the altitude associated with the given pressure. the altitude - returned is measured with respect to the mean sea level */ -real pressure_to_altitude(real pressure) { - - real next_base_temperature = LAYER0_BASE_TEMPERATURE; - real next_base_pressure = LAYER0_BASE_PRESSURE; - - real altitude; - real base_pressure; - real base_temperature; - real base; /* base for function to determine base pressure of next layer */ - real exponent; /* exponent for function to determine base pressure - of next layer */ - real coefficient; - int layer_number; /* identifies layer in the atmosphere */ - int delta_z; /* difference between two altitudes */ - - if (pressure < 0) /* illegal pressure */ - return -1; - if (pressure < MINIMUM_PRESSURE) /* FIX ME: use sensor data to improve model */ - return MAXIMUM_ALTITUDE; - - /* calculate the base temperature and pressure for the atmospheric layer - associated with the inputted pressure. */ - layer_number = -1; - do { - layer_number++; - base_pressure = next_base_pressure; - base_temperature = next_base_temperature; - delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; - if (lapse_rate[layer_number] == 0.0) { - exponent = GRAVITATIONAL_ACCELERATION * delta_z - / AIR_GAS_CONSTANT / base_temperature; - next_base_pressure *= exp(exponent); - } - else { - base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; - exponent = GRAVITATIONAL_ACCELERATION / - (AIR_GAS_CONSTANT * lapse_rate[layer_number]); - next_base_pressure *= pow(base, exponent); - } - next_base_temperature += delta_z * lapse_rate[layer_number]; - } - while(layer_number < NUMBER_OF_LAYERS - 1 && pressure < next_base_pressure); - - /* calculate the altitude associated with the inputted pressure */ - if (lapse_rate[layer_number] == 0.0) { - coefficient = (AIR_GAS_CONSTANT / GRAVITATIONAL_ACCELERATION) - * base_temperature; - altitude = base_altitude[layer_number] - + coefficient * log(pressure / base_pressure); - } - else { - base = pressure / base_pressure; - exponent = AIR_GAS_CONSTANT * lapse_rate[layer_number] - / GRAVITATIONAL_ACCELERATION; - coefficient = base_temperature / lapse_rate[layer_number]; - altitude = base_altitude[layer_number] - + coefficient * (pow(base, exponent) - 1); - } - - return altitude; -} - -real feet_to_meters(real feet) -{ - return feet * (12 * 2.54 / 100); -} - -real meters_to_feet(real meters) -{ - return meters / (12 * 2.54 / 100); -} - -/* - * Values for our MP3H6115A pressure sensor - * - * From the data sheet: - * - * Pressure range: 15-115 kPa - * Voltage at 115kPa: 2.82 - * Output scale: 27mV/kPa - * - * - * 27 mV/kPa * 2047 / 3300 counts/mV = 16.75 counts/kPa - * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa - */ - -real counts_per_kPa = 27 * 2047 / 3300; -real counts_at_101_3kPa = 1674; - -real fraction_to_kPa(real fraction) -{ - return (fraction + 0.095) / 0.009; -} - - -real count_to_kPa(real count) = fraction_to_kPa(count / 2047); - -typedef struct { - real m, b; - int m_i, b_i; -} line_t; - -line_t best_fit(real[] values, int first, int last) { - real sum_x = 0, sum_x2 = 0, sum_y = 0, sum_xy = 0; - int n = last - first + 1; - real m, b; - int m_i, b_i; - - for (int i = first; i <= last; i++) { - sum_x += i; - sum_x2 += i**2; - sum_y += values[i]; - sum_xy += values[i] * i; - } - m = (n*sum_xy - sum_y*sum_x) / (n*sum_x2 - sum_x**2); - b = sum_y/n - m*(sum_x/n); - return (line_t) { m = m, b = b }; -} - -real count_to_altitude(real count) { - return pressure_to_altitude(count_to_kPa(count) * 1000); -} - -real fraction_to_altitude(real frac) = pressure_to_altitude(fraction_to_kPa(frac) * 1000); - -int num_samples = 1024; - -real[num_samples] alt = { [n] = fraction_to_altitude(n/(num_samples - 1)) }; - -int num_part = 128; -int seg_len = num_samples / num_part; - -line_t [dim(alt) / seg_len] fit = { - [n] = best_fit(alt, n * seg_len, n * seg_len + seg_len - 1) -}; - -int[num_samples/seg_len + 1] alt_part; - -alt_part[0] = floor (fit[0].b + 0.5); -alt_part[dim(fit)] = floor(fit[dim(fit)-1].m * dim(fit) * seg_len + fit[dim(fit)-1].b + 0.5); - -for (int i = 0; i < dim(fit) - 1; i++) { - real here, there; - here = fit[i].m * (i+1) * seg_len + fit[i].b; - there = fit[i+1].m * (i+1) * seg_len + fit[i+1].b; - alt_part[i+1] = floor ((here + there) / 2 + 0.5); -} - -real count_to_fit_altitude(int count) { - int sub = count // seg_len; - int off = count % seg_len; - line_t l = fit[sub]; - real r_v; - real i_v; - - r_v = count * l.m + l.b; - i_v = (alt_part[sub] * (seg_len - off) + alt_part[sub+1] * off) / seg_len; - return i_v; -} - -real max_error = 0; -int max_error_count = 0; -real total_error = 0; - -for (int count = 0; count < num_samples; count++) { - real kPa = fraction_to_kPa(count / (num_samples - 1)); - real meters = pressure_to_altitude(kPa * 1000); - - real meters_approx = count_to_fit_altitude(count); - real error = abs(meters - meters_approx); - - total_error += error; - if (error > max_error) { - max_error = error; - max_error_count = count; - } -# printf (" %7d, /* %6.2g kPa %5d count approx %d */\n", -# floor (meters + 0.5), kPa, count, floor(count_to_fit_altitude(count) + 0.5)); -} - -printf ("/*max error %f at %7.3f%%. Average error %f*/\n", max_error, max_error_count / (num_samples - 1) * 100, total_error / num_samples); - -printf ("#define NALT %d\n", dim(alt_part)); -printf ("#define ALT_FRAC_BITS %d\n", floor (log2(32768/(dim(alt_part)-1)) + 0.1)); - -for (int i = 0; i < dim(alt_part); i++) { - real fraction = i / (dim(alt_part) - 1); - real kPa = fraction_to_kPa(fraction); - printf ("%9d, /* %6.2f kPa %7.3f%% */\n", - alt_part[i], kPa, fraction * 100); -} diff --git a/src/make-kalman b/src/make-kalman deleted file mode 100644 index 9ac35134..00000000 --- a/src/make-kalman +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh - -cd ../kalman - -SIGMA_BOTH="-M 2 -H 6 -A 2" -SIGMA_BARO="-M 2 -H 6 -A 2" -SIGMA_ACCEL="-M 2 -H 4 -A 4" - -nickle kalman.5c -p AO_BOTH -c both -t 0.01 $SIGMA_BOTH -nickle kalman.5c -p AO_BOTH -c both -t 0.1 $SIGMA_BOTH -nickle kalman.5c -p AO_BOTH -c both -t 1 $SIGMA_BOTH - -nickle kalman.5c -p AO_ACCEL -c accel -t 0.01 $SIGMA_ACCEL -nickle kalman.5c -p AO_ACCEL -c accel -t 0.1 $SIGMA_ACCEL -nickle kalman.5c -p AO_ACCEL -c accel -t 1 $SIGMA_ACCEL - -nickle kalman.5c -p AO_BARO -c baro -t 0.01 $SIGMA_BARO -nickle kalman.5c -p AO_BARO -c baro -t 0.1 $SIGMA_BARO -nickle kalman.5c -p AO_BARO -c baro -t 1 $SIGMA_BARO diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt new file mode 100644 index 00000000..99730b9f --- /dev/null +++ b/src/product/Makefile.telebt @@ -0,0 +1,97 @@ +# +# TeleBT build file +# +# Define TELEBT_VER, TELEBT_DEF, TELEBT_INC and TELEBT_SRC +# and include this file + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + ao_product.h \ + $(TELEBT_INC) + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_gps_print.c \ + ao_monitor.c \ + ao_mutex.c \ + ao_panic.c \ + ao_rssi.c \ + ao_state.c \ + ao_stdio.c \ + ao_task.c + +CC1111_SRC = \ + ao_dbg.c \ + ao_dma.c \ + ao_led.c \ + ao_packet.c \ + ao_packet_master.c \ + ao_radio.c \ + ao_romconfig.c \ + ao_serial.c \ + ao_timer.c \ + ao_usb.c \ + _bp.c + +DRIVER_SRC = \ + ao_btm.c + +PRODUCT_SRC = \ + ao_telebt.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) \ + $(TELEBT_SRC) + +PROG = telebt-v$(TELEBT_VER)-$(VERSION).ihx +PRODUCT=TeleBT-v$(TELEBT_VER) +PRODUCT_DEF=-DTELEBT_V_$(TELEBT_DEF) +IDPRODUCT=0x000e + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle new file mode 100644 index 00000000..f32c037f --- /dev/null +++ b/src/product/Makefile.teledongle @@ -0,0 +1,96 @@ +# +# TeleDongle build file +# +# The various teledongle versions differ only +# in minor pin variations +# so the per-board makefiles simply define +# TD_VER, TD_DEF and include +# this file + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + ao_product.h + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_gps_print.c \ + ao_monitor.c \ + ao_mutex.c \ + ao_panic.c \ + ao_rssi.c \ + ao_state.c \ + ao_stdio.c \ + ao_task.c + +CC1111_SRC = \ + ao_dbg.c \ + ao_dma.c \ + ao_led.c \ + ao_packet.c \ + ao_packet_master.c \ + ao_radio.c \ + ao_romconfig.c \ + ao_timer.c \ + ao_usb.c \ + _bp.c + +DRIVER_SRC = + +PRODUCT_SRC = \ + ao_teledongle.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROG = teledongle-v$(TD_VER)-$(VERSION).ihx +PRODUCT=TeleDongle-v$(TD_VER) +PRODUCT_DEF=-DTELEDONGLE_V_$(TD_DEF) +IDPRODUCT=0x000c + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum new file mode 100644 index 00000000..fd958aea --- /dev/null +++ b/src/product/Makefile.telemetrum @@ -0,0 +1,111 @@ +# +# TeleMetrum build file +# +# The various telemetrum versions differ only +# in which flash and GPS drivers are included, +# so the per-board makefiles simply define +# TM_VER, TM_DEF, TM_INC and TM_SRC and include +# this file + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + altitude.h \ + ao_kalman.h \ + ao_product.h \ + $(TM_INC) + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_convert.c \ + ao_gps_report.c \ + ao_mutex.c \ + ao_panic.c \ + ao_stdio.c \ + ao_storage.c \ + ao_task.c \ + ao_flight.c \ + ao_sample.c \ + ao_kalman.c \ + ao_log.c \ + ao_log_big.c \ + ao_report.c \ + ao_telemetry.c + +CC1111_SRC = \ + ao_adc.c \ + ao_beep.c \ + ao_dbg.c \ + ao_dma.c \ + ao_ignite.c \ + ao_led.c \ + ao_packet.c \ + ao_packet_slave.c \ + ao_radio.c \ + ao_romconfig.c \ + ao_serial.c \ + ao_spi.c \ + ao_timer.c \ + ao_usb.c \ + _bp.c + +DRIVER_SRC = \ + $(TM_SRC) + +PRODUCT_SRC = \ + ao_telemetrum.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROG = telemetrum-v$(TM_VER)-$(VERSION).ihx +PRODUCT=TeleMetrum-v$(TM_VER) +PRODUCT_DEF=-DTELEMETRUM_V_$(TM_DEF) +IDPRODUCT=0x000b + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini new file mode 100644 index 00000000..3bd14226 --- /dev/null +++ b/src/product/Makefile.telemini @@ -0,0 +1,100 @@ +# +# TeleMini build file +# +# Define TELEMINI_VER and TELEMINI_DEF and then +# include this file + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + ao_product.h + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_convert.c \ + ao_flight.c \ + ao_kalman.c \ + ao_log.c \ + ao_log_tiny.c \ + ao_mutex.c \ + ao_panic.c \ + ao_report.c \ + ao_sample.c \ + ao_stdio.c \ + ao_storage.c \ + ao_task.c \ + ao_telemetry.c + +CC1111_SRC = \ + ao_adc.c \ + ao_dma.c \ + ao_ignite.c \ + ao_intflash.c \ + ao_led.c \ + ao_packet.c \ + ao_packet_slave.c \ + ao_radio.c \ + ao_romconfig.c \ + ao_timer.c \ + _bp.c + +DRIVER_SRC = + +PRODUCT_SRC = \ + ao_telemini.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROG = telemini-v$(TELEMINI_VER)-$(VERSION).ihx +PRODUCT=TeleMini-v$(TELEMINI_VER) +PRODUCT_DEF=-DTELEMINI_V_$(TELEMINI_DEF) +IDPRODUCT=0x000a +CODESIZE=0x6700 + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano new file mode 100644 index 00000000..72043044 --- /dev/null +++ b/src/product/Makefile.telenano @@ -0,0 +1,99 @@ +# +# TeleNano build file +# +# Define TELENANO_VER and TELENANO_DEF and then +# include this file + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + ao_product.h + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_convert.c \ + ao_flight_nano.c \ + ao_kalman.c \ + ao_log.c \ + ao_log_tiny.c \ + ao_mutex.c \ + ao_panic.c \ + ao_report.c \ + ao_sample.c \ + ao_stdio.c \ + ao_storage.c \ + ao_task.c \ + ao_telemetry.c + +CC1111_SRC = \ + ao_adc.c \ + ao_dma.c \ + ao_intflash.c \ + ao_led.c \ + ao_packet.c \ + ao_packet_slave.c \ + ao_radio.c \ + ao_romconfig.c \ + ao_timer.c \ + _bp.c + +DRIVER_SRC = + +PRODUCT_SRC = \ + ao_telenano.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROG = telenano-v$(TELENANO_VER)-$(VERSION).ihx +PRODUCT=TeleNano-v$(TELENANO_VER) +PRODUCT_DEF=-DTELENANO_V_$(TELENANO_DEF) +IDPRODUCT=0x000a +CODESIZE=0x6700 + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c new file mode 100644 index 00000000..85565172 --- /dev/null +++ b/src/product/ao_telebt.c @@ -0,0 +1,50 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +__code uint8_t ao_log_format = AO_LOG_FORMAT_NONE; /* until we actually log stuff */ + +void +main(void) +{ + ao_clock_init(); + + /* Turn on the LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + ao_timer_init(); +#if HAS_BEEP + ao_beep_init(); +#endif + ao_cmd_init(); +#if HAS_EEPROM + ao_spi_init(); + ao_storage_init(); +#endif + ao_usb_init(); + ao_monitor_init(AO_LED_GREEN, TRUE); + ao_rssi_init(AO_LED_RED); + ao_radio_init(); + ao_packet_master_init(); + ao_btm_init(); +#if HAS_DBG + ao_dbg_init(); +#endif + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/product/ao_teledongle.c b/src/product/ao_teledongle.c new file mode 100644 index 00000000..008b200a --- /dev/null +++ b/src/product/ao_teledongle.c @@ -0,0 +1,40 @@ +/* + * 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) +{ + ao_clock_init(); + + /* Turn on the LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + ao_timer_init(); + ao_cmd_init(); + ao_usb_init(); + ao_monitor_init(AO_LED_GREEN, TRUE); + ao_rssi_init(AO_LED_RED); + ao_radio_init(); + ao_packet_master_init(); +#if HAS_DBG + ao_dbg_init(); +#endif + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/product/ao_telemetrum.c b/src/product/ao_telemetrum.c new file mode 100644 index 00000000..f560740a --- /dev/null +++ b/src/product/ao_telemetrum.c @@ -0,0 +1,70 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +void +main(void) +{ + /* + * Reduce the transient on the ignite pins at startup by + * pulling the pins low as soon as possible at power up + */ + ao_ignite_set_pins(); + + ao_clock_init(); + + /* Turn on the red LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + + /* A hack -- look at the SPI clock pin, if it's sitting at + * ground, then we force the computer to idle mode instead of + * flight mode + */ + if (P1_3 == 0) { + ao_flight_force_idle = 1; + while (P1_3 == 0) + ; + } + ao_timer_init(); + ao_adc_init(); + ao_beep_init(); + ao_cmd_init(); + ao_spi_init(); + ao_storage_init(); + ao_flight_init(); + ao_log_init(); + ao_report_init(); + ao_usb_init(); + ao_serial_init(); + ao_gps_init(); + ao_gps_report_init(); + ao_telemetry_init(); + ao_radio_init(); + ao_packet_slave_init(TRUE); + ao_igniter_init(); +#if HAS_DBG + ao_dbg_init(); +#endif +#if HAS_COMPANION + ao_companion_init(); +#endif + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/product/ao_telemini.c b/src/product/ao_telemini.c new file mode 100644 index 00000000..fa23de01 --- /dev/null +++ b/src/product/ao_telemini.c @@ -0,0 +1,49 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +void +main(void) +{ + /* + * Reduce the transient on the ignite pins at startup by + * pulling the pins low as soon as possible at power up + */ + ao_ignite_set_pins(); + + ao_clock_init(); + + /* Turn on the red LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + + ao_timer_init(); + ao_adc_init(); + ao_cmd_init(); + ao_storage_init(); + ao_flight_init(); + ao_log_init(); + ao_report_init(); + ao_telemetry_init(); + ao_radio_init(); + ao_packet_slave_init(TRUE); + ao_igniter_init(); + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/product/ao_telenano.c b/src/product/ao_telenano.c new file mode 100644 index 00000000..d91983d0 --- /dev/null +++ b/src/product/ao_telenano.c @@ -0,0 +1,43 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +void +main(void) +{ + ao_clock_init(); + + + /* Turn on the red LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + + ao_timer_init(); + ao_adc_init(); + ao_cmd_init(); + ao_storage_init(); + ao_flight_nano_init(); + ao_log_init(); + ao_report_init(); + ao_telemetry_init(); + ao_radio_init(); + ao_packet_slave_init(TRUE); + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/product/ao_teleterra.c b/src/product/ao_teleterra.c new file mode 100644 index 00000000..d696b914 --- /dev/null +++ b/src/product/ao_teleterra.c @@ -0,0 +1,38 @@ +/* + * 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_ADC_ISR 1 +#include "ao.h" + +void +main(void) +{ + ao_clock_init(); + + /* Turn on the red LED until the system is stable */ + ao_led_init(AO_LED_RED|AO_LED_GREEN); + ao_led_on(AO_LED_RED); + ao_timer_init(); + ao_beep_init(); + ao_cmd_init(); + ao_usb_init(); + ao_serial_init(); + ao_monitor_init(AO_LED_GREEN, TRUE); + ao_radio_init(); + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/product/ao_test.c b/src/product/ao_test.c new file mode 100644 index 00000000..14c2eb75 --- /dev/null +++ b/src/product/ao_test.c @@ -0,0 +1,117 @@ +/* + * 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" + +struct ao_task __xdata blink_0_task; +struct ao_task __xdata blink_1_task; +struct ao_task __xdata wakeup_task; +struct ao_task __xdata beep_task; +struct ao_task __xdata echo_task; + +void delay(int n) __reentrant +{ + uint8_t j = 0; + while (--n) + while (--j) + ao_yield(); +} + +static __xdata uint8_t blink_chan; + +void +blink_0(void) +{ + uint8_t b = 0; + for (;;) { + b = 1 - b; + if (b) + ao_led_on(AO_LED_GREEN); + else + ao_led_off(AO_LED_GREEN); + ao_sleep(&blink_chan); + } +} + +void +blink_1(void) +{ + static __xdata struct ao_adc adc; + + for (;;) { + ao_sleep(&ao_adc_head); + ao_adc_get(&adc); + if (adc.accel < 15900) + ao_led_on(AO_LED_RED); + else + ao_led_off(AO_LED_RED); + } +} + +void +wakeup(void) +{ + for (;;) { + ao_delay(AO_MS_TO_TICKS(100)); + ao_wakeup(&blink_chan); + } +} + +void +beep(void) +{ + static __xdata struct ao_adc adc; + + for (;;) { + ao_delay(AO_SEC_TO_TICKS(1)); + ao_adc_get(&adc); + if (adc.temp > 7400) + ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(50)); + } +} + +void +echo(void) +{ + char c; + for (;;) { + ao_usb_flush(); + c = ao_usb_getchar(); + ao_usb_putchar(c); + if (c == '\r') + ao_usb_putchar('\n'); + } +} + +void +main(void) +{ + ao_clock_init(); + +// ao_add_task(&blink_0_task, blink_0); +// ao_add_task(&blink_1_task, blink_1); +// ao_add_task(&wakeup_task, wakeup); +// ao_add_task(&beep_task, beep); + ao_add_task(&echo_task, echo); + ao_timer_init(); + ao_adc_init(); + ao_beep_init(); + ao_led_init(); + ao_usb_init(); + + ao_start_scheduler(); +} diff --git a/src/product/ao_tidongle.c b/src/product/ao_tidongle.c new file mode 100644 index 00000000..3b7c2733 --- /dev/null +++ b/src/product/ao_tidongle.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. + */ + +#define AO_NO_SERIAL_ISR 1 +#define AO_NO_ADC_ISR 1 +#include "ao.h" + +void +main(void) +{ + ao_clock_init(); + + /* Turn on the LED until the system is stable */ + ao_led_init(AO_LED_RED); + ao_led_on(AO_LED_RED); + ao_timer_init(); + ao_cmd_init(); + ao_usb_init(); + ao_monitor_init(AO_LED_RED, TRUE); + ao_rssi_init(AO_LED_RED); + ao_radio_init(); + ao_dbg_init(); + ao_config_init(); + /* Bring up the USB link */ + P1DIR |= 1; + P1 |= 1; + ao_start_scheduler(); +} diff --git a/src/sirf-cksum b/src/sirf-cksum deleted file mode 100755 index b905f318..00000000 --- a/src/sirf-cksum +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env nickle - -int checksum(int[] msg) -{ - int sum = 0; - for (int i = 0; i < dim(msg); i++) { - sum += msg[i]; - sum &= 0x7fff; - } - return sum; -} - -void main() -{ - string[...] input; - int[...] msg; - - setdim(input, 0); - while (!File::end(stdin)) { - input[dim(input)] = gets(); - } - - setdim(msg, 0); - for (int i = 0; i < dim(input); i++) { - string[*] words = String::wordsplit(input[i], " ,\t"); - for (int j = 0; j < dim(words); j++) { - if (words[j] == "/" + "*") - break; - if (String::length(words[j]) > 0 && - Ctype::isdigit(words[j][0])) { - msg[dim(msg)] = string_to_integer(words[j]); - } - } - } - printf("\t0xa0, 0xa2, 0x%02x, 0x%02x,\t/* length: %d bytes */\n", - dim(msg) >> 8, dim(msg) & 0xff, dim(msg)); - for (int i = 0; i < dim(input); i++) - printf("%s\n", input[i]); - int csum = checksum(msg); - printf ("\t0x%02x, 0x%02x, 0xb0, 0xb3,\n", - csum >> 8, csum & 0xff); -} - -main(); diff --git a/src/skytraq-cksum b/src/skytraq-cksum deleted file mode 100644 index ab0464a7..00000000 --- a/src/skytraq-cksum +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env nickle - -int checksum(int[] msg) -{ - int sum = 0; - for (int i = 0; i < dim(msg); i++) { - sum ^= msg[i]; - sum &= 0xff; - } - return sum; -} - -void main() -{ - string[...] input; - int[...] msg; - - setdim(input, 0); - while (!File::end(stdin)) { - input[dim(input)] = gets(); - } - - setdim(msg, 0); - for (int i = 0; i < dim(input); i++) { - string[*] words = String::wordsplit(input[i], " ,\t"); - for (int j = 0; j < dim(words); j++) { - if (words[j] == "/" + "*") - break; - if (String::length(words[j]) > 0 && - Ctype::isdigit(words[j][0])) { - msg[dim(msg)] = string_to_integer(words[j]); - } - } - } - printf("\t0xa0, 0xa1, 0x%02x, 0x%02x,\t\t/* length: %d bytes */\n", - dim(msg) >> 8, dim(msg) & 0xff, dim(msg)); - for (int i = 0; i < dim(input); i++) - printf("%s\n", input[i]); - int csum = checksum(msg); - printf ("\t0x%02x, 0x0d, 0x0a,\n", - csum); -} - -main(); diff --git a/src/telebt-v0.0/Makefile b/src/telebt-v0.0/Makefile index d8867b19..e89639ab 100644 --- a/src/telebt-v0.0/Makefile +++ b/src/telebt-v0.0/Makefile @@ -1 +1,9 @@ -include ../Makefile.proto +# +# TeleBT v0.0 build +# + +TELEBT_VER=0.0 +TELEBT_DEF=0_0 + +include ../product/Makefile.telebt + diff --git a/src/telebt-v0.0/Makefile.defs b/src/telebt-v0.0/Makefile.defs deleted file mode 100644 index f0bb5e0c..00000000 --- a/src/telebt-v0.0/Makefile.defs +++ /dev/null @@ -1,8 +0,0 @@ -PROG = telebt-v0.0-$(VERSION).ihx - -SRC = \ - $(TBT_BASE_SRC) - -PRODUCT=TeleBT-v0.0 -PRODUCT_DEF=-DTELEBT_V_0_0 -IDPRODUCT=0x000e diff --git a/src/telebt-v0.1/Makefile b/src/telebt-v0.1/Makefile index d8867b19..a34e8912 100644 --- a/src/telebt-v0.1/Makefile +++ b/src/telebt-v0.1/Makefile @@ -1 +1,19 @@ -include ../Makefile.proto +# +# TeleBT v0.1 build +# + +TELEBT_VER=0.1 +TELEBT_DEF=0_1 + +TELEBT_INC = \ + ao_25lc1024.h + +TELEBT_SRC = \ + ao_beep.c \ + ao_log_telem.c \ + ao_spi.c \ + ao_storage.c \ + ao_m25.c + +include ../product/Makefile.telebt + diff --git a/src/telebt-v0.1/Makefile.defs b/src/telebt-v0.1/Makefile.defs deleted file mode 100644 index 50657c83..00000000 --- a/src/telebt-v0.1/Makefile.defs +++ /dev/null @@ -1,8 +0,0 @@ -PROG = telebt-v0.1-$(VERSION).ihx - -SRC = \ - $(TBT_V_0_1_SRC) - -PRODUCT=TeleBT-v0.1 -PRODUCT_DEF=-DTELEBT_V_0_1 -IDPRODUCT=0x000e diff --git a/src/teledongle-v0.1/Makefile b/src/teledongle-v0.1/Makefile index d8867b19..48425107 100644 --- a/src/teledongle-v0.1/Makefile +++ b/src/teledongle-v0.1/Makefile @@ -1 +1,8 @@ -include ../Makefile.proto +# +# TeleDongle v0.2 build +# + +TD_VER=0.1 +TD_DEF=0_1 + +include ../product/Makefile.teledongle diff --git a/src/teledongle-v0.1/Makefile.defs b/src/teledongle-v0.1/Makefile.defs deleted file mode 100644 index ceb80b7a..00000000 --- a/src/teledongle-v0.1/Makefile.defs +++ /dev/null @@ -1,9 +0,0 @@ -PROG = teledongle-v0.1-$(VERSION).ihx - -SRC = \ - $(TD_SRC) \ - $(DBG_SRC) - -PRODUCT=TeleDongle-v0.1 -PRODUCT_DEF=-DTELEDONGLE_V_0_1 -IDPRODUCT=0x000c diff --git a/src/teledongle-v0.2/Makefile b/src/teledongle-v0.2/Makefile index d8867b19..ce4ab437 100644 --- a/src/teledongle-v0.2/Makefile +++ b/src/teledongle-v0.2/Makefile @@ -1 +1,8 @@ -include ../Makefile.proto +# +# TeleDongle v0.2 build +# + +TD_VER=0.2 +TD_DEF=0_2 + +include ../product/Makefile.teledongle \ No newline at end of file diff --git a/src/teledongle-v0.2/Makefile.defs b/src/teledongle-v0.2/Makefile.defs deleted file mode 100644 index ea9713b6..00000000 --- a/src/teledongle-v0.2/Makefile.defs +++ /dev/null @@ -1,9 +0,0 @@ -PROG = teledongle-v0.2-$(VERSION).ihx - -SRC = \ - $(TD_SRC) \ - $(DBG_SRC) - -PRODUCT=TeleDongle-v0.2 -PRODUCT_DEF=-DTELEDONGLE_V_0_2 -IDPRODUCT=0x000c diff --git a/src/telemetrum-v0.1-sirf/Makefile b/src/telemetrum-v0.1-sirf/Makefile index d8867b19..00cdc9c5 100644 --- a/src/telemetrum-v0.1-sirf/Makefile +++ b/src/telemetrum-v0.1-sirf/Makefile @@ -1 +1,16 @@ -include ../Makefile.proto +# +# TeleMetrum v0.1 with SkyTraq GPS build +# + +TM_VER=0.1 +TM_DEF=0_1 + +TM_INC = \ + ao_25lc1024.h + +TM_SRC = \ + ao_gps_sirf.c \ + ao_25lc1024.c + +include ../product/Makefile.telemetrum + diff --git a/src/telemetrum-v0.1-sirf/Makefile.defs b/src/telemetrum-v0.1-sirf/Makefile.defs deleted file mode 100644 index ac8dcdb9..00000000 --- a/src/telemetrum-v0.1-sirf/Makefile.defs +++ /dev/null @@ -1,12 +0,0 @@ -PROG = telemetrum-v0.1-sirf-$(VERSION).ihx - -SRC = \ - $(TM_BASE_SRC) \ - $(SPI_DRIVER_SRC) \ - $(EE_DRIVER_SRC) \ - $(SIRF_DRIVER_SRC) \ - $(DBG_SRC) - -PRODUCT=TeleMetrum-v0.1-SiRF -PRODUCT_DEF=-DTELEMETRUM_V_0_1 -IDPRODUCT=0x000b diff --git a/src/telemetrum-v0.1-sky/Makefile b/src/telemetrum-v0.1-sky/Makefile index d8867b19..e3c61db6 100644 --- a/src/telemetrum-v0.1-sky/Makefile +++ b/src/telemetrum-v0.1-sky/Makefile @@ -1 +1,16 @@ -include ../Makefile.proto +# +# TeleMetrum v0.1 with SkyTraq GPS build +# + +TM_VER=0.1 +TM_DEF=0_1 + +TM_INC = \ + ao_25lc1024.h + +TM_SRC = \ + ao_gps_skytraq.c \ + ao_25lc1024.c + +include ../product/Makefile.telemetrum + diff --git a/src/telemetrum-v0.1-sky/Makefile.defs b/src/telemetrum-v0.1-sky/Makefile.defs deleted file mode 100644 index e032d1eb..00000000 --- a/src/telemetrum-v0.1-sky/Makefile.defs +++ /dev/null @@ -1,12 +0,0 @@ -PROG = telemetrum-v0.1-sky-$(VERSION).ihx - -SRC = \ - $(TM_BASE_SRC) \ - $(SPI_DRIVER_SRC) \ - $(EE_DRIVER_SRC) \ - $(SKY_DRIVER_SRC) \ - $(DBG_SRC) - -PRODUCT=TeleMetrum-v0.1 -PRODUCT_DEF=-DTELEMETRUM_V_0_1 -IDPRODUCT=0x000b diff --git a/src/telemetrum-v1.0/Makefile b/src/telemetrum-v1.0/Makefile index d8867b19..4aae84c8 100644 --- a/src/telemetrum-v1.0/Makefile +++ b/src/telemetrum-v1.0/Makefile @@ -1 +1,16 @@ -include ../Makefile.proto +# +# TeleMetrum v1.0 build +# + +TM_VER=1.0 +TM_DEF=1_0 + +TM_INC = \ + ao_at45db161d.h + +TM_SRC = \ + ao_companion.c \ + ao_gps_skytraq.c \ + ao_at45db161d.c + +include ../product/Makefile.telemetrum diff --git a/src/telemetrum-v1.0/Makefile.defs b/src/telemetrum-v1.0/Makefile.defs deleted file mode 100644 index 5eefc392..00000000 --- a/src/telemetrum-v1.0/Makefile.defs +++ /dev/null @@ -1,13 +0,0 @@ -PROG = telemetrum-v1.0-$(VERSION).ihx - -SRC = \ - $(TM_BASE_SRC) \ - $(SPI_DRIVER_SRC) \ - $(FLASH_DRIVER_SRC) \ - $(SKY_DRIVER_SRC) \ - $(COMPANION_SRC) \ - $(DBG_SRC) - -PRODUCT=TeleMetrum-v1.0 -PRODUCT_DEF=-DTELEMETRUM_V_1_0 -IDPRODUCT=0x000b diff --git a/src/telemetrum-v1.1/Makefile b/src/telemetrum-v1.1/Makefile index d8867b19..4bea03db 100644 --- a/src/telemetrum-v1.1/Makefile +++ b/src/telemetrum-v1.1/Makefile @@ -1 +1,16 @@ -include ../Makefile.proto +# +# AltOS build +# +# + +TM_VER=1.1 +TM_DEF=1_1 + +TM_INC = + +TM_SRC = \ + ao_companion.c \ + ao_gps_skytraq.c \ + ao_m25.c + +include ../product/Makefile.telemetrum diff --git a/src/telemetrum-v1.1/Makefile.defs b/src/telemetrum-v1.1/Makefile.defs deleted file mode 100644 index 3c8b8793..00000000 --- a/src/telemetrum-v1.1/Makefile.defs +++ /dev/null @@ -1,13 +0,0 @@ -PROG = telemetrum-v1.1-$(VERSION).ihx - -SRC = \ - $(TM_BASE_SRC) \ - $(SPI_DRIVER_SRC) \ - $(M25_DRIVER_SRC) \ - $(SKY_DRIVER_SRC) \ - $(COMPANION_SRC) \ - $(DBG_SRC) - -PRODUCT=TeleMetrum-v1.1 -PRODUCT_DEF=-DTELEMETRUM_V_1_1 -IDPRODUCT=0x000b diff --git a/src/telemini-v1.0/Makefile b/src/telemini-v1.0/Makefile index d8867b19..4f1c8b51 100644 --- a/src/telemini-v1.0/Makefile +++ b/src/telemini-v1.0/Makefile @@ -1 +1,8 @@ -include ../Makefile.proto +# +# TeleMini build file +# + +TELEMINI_VER=1.0 +TELEMINI_DEF=1_0 + +include ../product/Makefile.telemini diff --git a/src/telemini-v1.0/Makefile.defs b/src/telemini-v1.0/Makefile.defs deleted file mode 100644 index 0e91f2fc..00000000 --- a/src/telemini-v1.0/Makefile.defs +++ /dev/null @@ -1,9 +0,0 @@ -PROG = telemini-v1.0-$(VERSION).ihx - -SRC = \ - $(TMINI_BASE_SRC) - -PRODUCT=TeleMini-v1.0 -PRODUCT_DEF=-DTELEMINI_V_1_0 -IDPRODUCT=0x000a -CODESIZE=0x6700 diff --git a/src/telenano-v0.1/Makefile b/src/telenano-v0.1/Makefile index d8867b19..2714c1e9 100644 --- a/src/telenano-v0.1/Makefile +++ b/src/telenano-v0.1/Makefile @@ -1 +1,9 @@ -include ../Makefile.proto +# +# TeleNano build file +# + +TELENANO_VER=0.1 +TELENANO_DEF=0_1 + +include ../product/Makefile.telenano + diff --git a/src/telenano-v0.1/Makefile.defs b/src/telenano-v0.1/Makefile.defs deleted file mode 100644 index 34cf69d1..00000000 --- a/src/telenano-v0.1/Makefile.defs +++ /dev/null @@ -1,9 +0,0 @@ -PROG = telenano-v0.1-$(VERSION).ihx - -SRC = \ - $(TNANO_BASE_SRC) - -PRODUCT=TeleNano-v0.1 -PRODUCT_DEF=-DTELENANO_V_0_1 -IDPRODUCT=0x000a -CODESIZE=0x6700 diff --git a/src/test/Makefile b/src/test/Makefile index 33203ffd..333850e4 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,9 +1,8 @@ -vpath % .. -vpath % ../kalman +vpath % ..:../core:../drivers PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_gps_test ao_gps_test_skytraq ao_convert_test -CFLAGS=-I.. -I. +CFLAGS=-I.. -I. -I../core -I../drivers -O0 -g all: $(PROGS) @@ -13,22 +12,19 @@ clean: install: ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h - cc -g -o $@ $< + cc $(CFLAGS) -o $@ $< ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h - cc -g -o $@ -DHAS_ACCEL=0 ../ao_flight_test.c + cc $(CFLAGS) -o $@ -DHAS_ACCEL=0 ao_flight_test.c ao_flight_test_accel: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h - cc -g -o $@ -DFORCE_ACCEL=1 ../ao_flight_test.c + cc $(CFLAGS) -o $@ -DFORCE_ACCEL=1 ao_flight_test.c ao_gps_test: ao_gps_test.c ao_gps_sirf.c ao_gps_print.c ao_host.h - cc -g -o $@ $< + cc $(CFLAGS) -o $@ $< ao_gps_test_skytraq: ao_gps_test_skytraq.c ao_gps_skytraq.c ao_gps_print.c ao_host.h - cc -g -o $@ $< + cc $(CFLAGS) -o $@ $< ao_convert_test: ao_convert_test.c ao_convert.c altitude.h - cc -g -o $@ $< - -../ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c - sh $< > $@ + cc $(CFLAGS) -o $@ $< diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c new file mode 100644 index 00000000..56733c89 --- /dev/null +++ b/src/test/ao_flight_test.c @@ -0,0 +1,716 @@ +/* + * 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 _GNU_SOURCE + +#include +#include +#include +#include +#include +#include + +#define AO_HERTZ 100 + +#define AO_ADC_RING 64 +#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) +#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) + +#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) +#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) +#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) + +/* + * One set of samples read from the A/D converter + */ +struct ao_adc { + uint16_t tick; /* tick when the sample was read */ + int16_t accel; /* accelerometer */ + int16_t pres; /* pressure sensor */ + int16_t pres_real; /* unclipped */ + int16_t temp; /* temperature sensor */ + int16_t v_batt; /* battery voltage */ + int16_t sense_d; /* drogue continuity sense */ + int16_t sense_m; /* main continuity sense */ +}; + +#define __pdata +#define __data +#define __xdata +#define __code +#define __reentrant + +#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) +#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) +#define from_fix(x) ((x) >> 16) + +/* + * Above this height, the baro sensor doesn't work + */ +#define AO_MAX_BARO_HEIGHT 12000 +#define AO_BARO_SATURATE 13000 +#define AO_MIN_BARO_VALUE ao_altitude_to_pres(AO_BARO_SATURATE) + +/* + * Above this speed, baro measurements are unreliable + */ +#define AO_MAX_BARO_SPEED 200 + +#define ACCEL_NOSE_UP (ao_accel_2g >> 2) + +enum ao_flight_state { + ao_flight_startup = 0, + ao_flight_idle = 1, + ao_flight_pad = 2, + ao_flight_boost = 3, + ao_flight_fast = 4, + ao_flight_coast = 5, + ao_flight_drogue = 6, + ao_flight_main = 7, + ao_flight_landed = 8, + ao_flight_invalid = 9 +}; + +extern enum ao_flight_state ao_flight_state; + +#define FALSE 0 +#define TRUE 1 + +struct ao_adc ao_adc_ring[AO_ADC_RING]; +uint8_t ao_adc_head; +int ao_summary = 0; + +#define ao_led_on(l) +#define ao_led_off(l) +#define ao_timer_set_adc_interval(i) +#define ao_wakeup(wchan) ao_dump_state() +#define ao_cmd_register(c) +#define ao_usb_disable() +#define ao_telemetry_set_interval(x) +#define ao_rdf_set(rdf) +#define ao_packet_slave_start() +#define ao_packet_slave_stop() + +enum ao_igniter { + ao_igniter_drogue = 0, + ao_igniter_main = 1 +}; + +struct ao_adc ao_adc_static; + +int drogue_height; +double drogue_time; +int main_height; +double main_time; + +int tick_offset; + +static int32_t ao_k_height; + +void +ao_ignite(enum ao_igniter igniter) +{ + double time = (double) (ao_adc_static.tick + tick_offset) / 100; + + if (igniter == ao_igniter_drogue) { + drogue_time = time; + drogue_height = ao_k_height >> 16; + } else { + main_time = time; + main_height = ao_k_height >> 16; + } +} + +struct ao_task { + int dummy; +}; + +#define ao_add_task(t,f,n) + +#define ao_log_start() +#define ao_log_stop() + +#define AO_MS_TO_TICKS(ms) ((ms) / 10) +#define AO_SEC_TO_TICKS(s) ((s) * 100) + +#define AO_FLIGHT_TEST + +int ao_flight_debug; + +FILE *emulator_in; +char *emulator_app; +char *emulator_name; +double emulator_error_max = 4; +double emulator_height_error_max = 20; /* noise in the baro sensor */ + +void +ao_dump_state(void); + +void +ao_sleep(void *wchan); + +const char const * const ao_state_names[] = { + "startup", "idle", "pad", "boost", "fast", + "coast", "drogue", "main", "landed", "invalid" +}; + +struct ao_cmds { + void (*func)(void); + const char *help; +}; + +#include "ao_convert.c" + +struct ao_config { + uint16_t main_deploy; + int16_t accel_plus_g; + int16_t accel_minus_g; + uint8_t pad_orientation; +}; + +#define AO_PAD_ORIENTATION_ANTENNA_UP 0 +#define AO_PAD_ORIENTATION_ANTENNA_DOWN 1 + +#define ao_config_get() + +struct ao_config ao_config; + +#define DATA_TO_XDATA(x) (x) + +#define HAS_FLIGHT 1 +#define HAS_ADC 1 +#define HAS_USB 1 +#define HAS_GPS 1 +#ifndef HAS_ACCEL +#define HAS_ACCEL 1 +#define HAS_ACCEL_REF 0 +#endif + +#define GRAVITY 9.80665 +extern int16_t ao_ground_accel, ao_flight_accel; +extern int16_t ao_accel_2g; + +extern uint16_t ao_sample_tick; + +extern int16_t ao_sample_height; +extern int16_t ao_sample_accel; +extern int32_t ao_accel_scale; +extern int16_t ao_ground_height; +extern int16_t ao_sample_alt; + +int ao_sample_prev_tick; +uint16_t prev_tick; + +#include "ao_kalman.c" +#include "ao_sample.c" +#include "ao_flight.c" + +#define to_double(f) ((f) / 65536.0) + +static int ao_records_read = 0; +static int ao_eof_read = 0; +static int ao_flight_ground_accel; +static int ao_flight_started = 0; +static int ao_test_max_height; +static double ao_test_max_height_time; +static int ao_test_main_height; +static double ao_test_main_height_time; +static double ao_test_landed_time; +static double ao_test_landed_height; +static double ao_test_landed_time; +static int landed_set; +static double landed_time; +static double landed_height; + +void +ao_test_exit(void) +{ + double drogue_error; + double main_error; + double landed_error; + double landed_time_error; + + if (!ao_test_main_height_time) { + ao_test_main_height_time = ao_test_max_height_time; + ao_test_main_height = ao_test_max_height; + } + drogue_error = fabs(ao_test_max_height_time - drogue_time); + main_error = fabs(ao_test_main_height_time - main_time); + landed_error = fabs(ao_test_landed_height - landed_height); + landed_time_error = ao_test_landed_time - landed_time; + if (drogue_error > emulator_error_max || main_error > emulator_error_max || + landed_time_error > emulator_error_max || landed_error > emulator_height_error_max) { + printf ("%s %s\n", + emulator_app, emulator_name); + printf ("\tApogee error %g\n", drogue_error); + printf ("\tMain error %g\n", main_error); + printf ("\tLanded height error %g\n", landed_error); + printf ("\tLanded time error %g\n", landed_time_error); + printf ("\tActual: apogee: %d at %7.2f main: %d at %7.2f landed %7.2f at %7.2f\n", + ao_test_max_height, ao_test_max_height_time, + ao_test_main_height, ao_test_main_height_time, + ao_test_landed_height, ao_test_landed_time); + printf ("\tComputed: apogee: %d at %7.2f main: %d at %7.2f landed %7.2f at %7.2f\n", + drogue_height, drogue_time, main_height, main_time, + landed_height, landed_time); + exit (1); + } + exit(0); +} + +void +ao_insert(void) +{ + double time; + + ao_adc_ring[ao_adc_head] = ao_adc_static; + ao_adc_head = ao_adc_ring_next(ao_adc_head); + if (ao_flight_state != ao_flight_startup) { + double height = ao_pres_to_altitude(ao_adc_static.pres_real) - ao_ground_height; + double accel = ((ao_flight_ground_accel - ao_adc_static.accel) * GRAVITY * 2.0) / + (ao_config.accel_minus_g - ao_config.accel_plus_g); + + if (!tick_offset) + tick_offset = -ao_adc_static.tick; + if ((prev_tick - ao_adc_static.tick) > 0x400) + tick_offset += 65536; + prev_tick = ao_adc_static.tick; + time = (double) (ao_adc_static.tick + tick_offset) / 100; + + if (ao_test_max_height < height) { + ao_test_max_height = height; + ao_test_max_height_time = time; + ao_test_landed_height = height; + ao_test_landed_time = time; + } + if (height > ao_config.main_deploy) { + ao_test_main_height_time = time; + ao_test_main_height = height; + } + + if (ao_test_landed_height > height) { + ao_test_landed_height = height; + ao_test_landed_time = time; + } + + if (ao_flight_state == ao_flight_landed && !landed_set) { + landed_set = 1; + landed_time = time; + landed_height = height; + } + + if (!ao_summary) { + printf("%7.2f height %8.2f accel %8.3f state %-8.8s k_height %8.2f k_speed %8.3f k_accel %8.3f avg_height %5d drogue %4d main %4d error %5d\n", + time, + height, + accel, + ao_state_names[ao_flight_state], + ao_k_height / 65536.0, + ao_k_speed / 65536.0 / 16.0, + ao_k_accel / 65536.0 / 16.0, + ao_avg_height, + drogue_height, + main_height, + ao_error_h_sq_avg); + +// if (ao_flight_state == ao_flight_landed) +// ao_test_exit(); + } + } +} + +#define AO_MAX_CALLSIGN 8 +#define AO_MAX_VERSION 8 +#define AO_MAX_TELEMETRY 128 + +struct ao_telemetry_generic { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t payload[27]; /* 5 */ + /* 32 */ +}; + +#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 +#define AO_TELEMETRY_SENSOR_TELEMINI 0x02 +#define AO_TELEMETRY_SENSOR_TELENANO 0x03 + +struct ao_telemetry_sensor { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t state; /* 5 flight state */ + int16_t accel; /* 6 accelerometer (TM only) */ + int16_t pres; /* 8 pressure sensor */ + int16_t temp; /* 10 temperature sensor */ + int16_t v_batt; /* 12 battery voltage */ + int16_t sense_d; /* 14 drogue continuity sense (TM/Tm) */ + int16_t sense_m; /* 16 main continuity sense (TM/Tm) */ + + int16_t acceleration; /* 18 m/s² * 16 */ + int16_t speed; /* 20 m/s * 16 */ + int16_t height; /* 22 m */ + + int16_t ground_pres; /* 24 average pres on pad */ + int16_t ground_accel; /* 26 average accel on pad */ + int16_t accel_plus_g; /* 28 accel calibration at +1g */ + int16_t accel_minus_g; /* 30 accel calibration at -1g */ + /* 32 */ +}; + +#define AO_TELEMETRY_CONFIGURATION 0x04 + +struct ao_telemetry_configuration { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t device; /* 5 device type */ + uint16_t flight; /* 6 flight number */ + uint8_t config_major; /* 8 Config major version */ + uint8_t config_minor; /* 9 Config minor version */ + uint16_t apogee_delay; /* 10 Apogee deploy delay in seconds */ + uint16_t main_deploy; /* 12 Main deploy alt in meters */ + uint16_t flight_log_max; /* 14 Maximum flight log size in kB */ + char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ + char version[AO_MAX_VERSION]; /* 24 Software version */ + /* 32 */ +}; + +#define AO_TELEMETRY_LOCATION 0x05 + +#define AO_GPS_MODE_NOT_VALID 'N' +#define AO_GPS_MODE_AUTONOMOUS 'A' +#define AO_GPS_MODE_DIFFERENTIAL 'D' +#define AO_GPS_MODE_ESTIMATED 'E' +#define AO_GPS_MODE_MANUAL 'M' +#define AO_GPS_MODE_SIMULATED 'S' + +struct ao_telemetry_location { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t flags; /* 5 Number of sats and other flags */ + int16_t altitude; /* 6 GPS reported altitude (m) */ + int32_t latitude; /* 8 latitude (degrees * 10⁷) */ + int32_t longitude; /* 12 longitude (degrees * 10⁷) */ + uint8_t year; /* 16 (- 2000) */ + uint8_t month; /* 17 (1-12) */ + uint8_t day; /* 18 (1-31) */ + uint8_t hour; /* 19 (0-23) */ + uint8_t minute; /* 20 (0-59) */ + uint8_t second; /* 21 (0-59) */ + uint8_t pdop; /* 22 (m * 5) */ + uint8_t hdop; /* 23 (m * 5) */ + uint8_t vdop; /* 24 (m * 5) */ + uint8_t mode; /* 25 */ + uint16_t ground_speed; /* 26 cm/s */ + int16_t climb_rate; /* 28 cm/s */ + uint8_t course; /* 30 degrees / 2 */ + uint8_t unused[1]; /* 31 */ + /* 32 */ +}; + +#define AO_TELEMETRY_SATELLITE 0x06 + +struct ao_telemetry_satellite_info { + uint8_t svid; + uint8_t c_n_1; +}; + +struct ao_telemetry_satellite { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t channels; /* 5 number of reported sats */ + + struct ao_telemetry_satellite_info sats[12]; /* 6 */ + uint8_t unused[2]; /* 30 */ + /* 32 */ +}; + +union ao_telemetry_all { + struct ao_telemetry_generic generic; + struct ao_telemetry_sensor sensor; + struct ao_telemetry_configuration configuration; + struct ao_telemetry_location location; + struct ao_telemetry_satellite satellite; +}; + +uint16_t +uint16(uint8_t *bytes, int off) +{ + off++; + return (uint16_t) bytes[off] | (((uint16_t) bytes[off+1]) << 8); +} + +int16_t +int16(uint8_t *bytes, int off) +{ + return (int16_t) uint16(bytes, off); +} + +void +ao_sleep(void *wchan) +{ + if (wchan == &ao_adc_head) { + char type; + uint16_t tick; + uint16_t a, b; + int ret; + uint8_t bytes[1024]; + union ao_telemetry_all telem; + char line[1024]; + char *saveptr; + char *l; + char *words[64]; + int nword; + + for (;;) { + if (ao_records_read > 2 && ao_flight_state == ao_flight_startup) + { + ao_adc_static.accel = ao_flight_ground_accel; + ao_insert(); + return; + } + + if (!fgets(line, sizeof (line), emulator_in)) { + if (++ao_eof_read >= 1000) { + if (!ao_summary) + printf ("no more data, exiting simulation\n"); + ao_test_exit(); + } + ao_adc_static.tick += 10; + ao_insert(); + return; + } + l = line; + for (nword = 0; nword < 64; nword++) { + words[nword] = strtok_r(l, " \t\n", &saveptr); + l = NULL; + if (words[nword] == NULL) + break; + } + if (nword == 4) { + type = words[0][0]; + tick = strtoul(words[1], NULL, 16); + a = strtoul(words[2], NULL, 16); + b = strtoul(words[3], NULL, 16); + if (type == 'P') + type = 'A'; + } else if (nword >= 6 && strcmp(words[0], "Accel") == 0) { + ao_config.accel_plus_g = atoi(words[3]); + ao_config.accel_minus_g = atoi(words[5]); + } else if (nword >= 4 && strcmp(words[0], "Main") == 0) { + ao_config.main_deploy = atoi(words[2]); + } else if (nword >= 36 && strcmp(words[0], "CALL") == 0) { + tick = atoi(words[10]); + if (!ao_flight_started) { + type = 'F'; + a = atoi(words[26]); + ao_flight_started = 1; + } else { + type = 'A'; + a = atoi(words[12]); + b = atoi(words[14]); + } + } else if (nword == 3 && strcmp(words[0], "BARO") == 0) { + tick = strtol(words[1], NULL, 16); + a = 16384 - 328; + b = strtol(words[2], NULL, 10); + type = 'A'; + if (!ao_flight_started) { + ao_flight_ground_accel = 16384 - 328; + ao_config.accel_plus_g = 16384 - 328; + ao_config.accel_minus_g = 16384 + 328; + ao_flight_started = 1; + } + } else if (nword == 2 && strcmp(words[0], "TELEM") == 0) { + char *hex = words[1]; + char elt[3]; + int i, len; + uint8_t sum; + + len = strlen(hex); + if (len > sizeof (bytes) * 2) { + len = sizeof (bytes)*2; + hex[len] = '\0'; + } + for (i = 0; i < len; i += 2) { + elt[0] = hex[i]; + elt[1] = hex[i+1]; + elt[2] = '\0'; + bytes[i/2] = (uint8_t) strtol(elt, NULL, 16); + } + len = i/2; + if (bytes[0] != len - 2) { + printf ("bad length %d != %d\n", bytes[0], len - 2); + continue; + } + sum = 0x5a; + for (i = 1; i < len-1; i++) + sum += bytes[i]; + if (sum != bytes[len-1]) { + printf ("bad checksum\n"); + continue; + } + if ((bytes[len-2] & 0x80) == 0) { + continue; + } + if (len == 36) { + memcpy(&telem, bytes + 1, 32); + tick = telem.generic.tick; + switch (telem.generic.type) { + case AO_TELEMETRY_SENSOR_TELEMETRUM: + case AO_TELEMETRY_SENSOR_TELEMINI: + case AO_TELEMETRY_SENSOR_TELENANO: + if (!ao_flight_started) { + ao_flight_ground_accel = telem.sensor.ground_accel; + ao_config.accel_plus_g = telem.sensor.accel_plus_g; + ao_config.accel_minus_g = telem.sensor.accel_minus_g; + ao_flight_started = 1; + } + type = 'A'; + a = telem.sensor.accel; + b = telem.sensor.pres; + break; + } + } else if (len == 99) { + ao_flight_started = 1; + tick = uint16(bytes, 21); + ao_flight_ground_accel = int16(bytes, 7); + ao_config.accel_plus_g = int16(bytes, 17); + ao_config.accel_minus_g = int16(bytes, 19); + type = 'A'; + a = int16(bytes, 23); + b = int16(bytes, 25); + } else if (len == 98) { + ao_flight_started = 1; + tick = uint16(bytes, 20); + ao_flight_ground_accel = int16(bytes, 6); + ao_config.accel_plus_g = int16(bytes, 16); + ao_config.accel_minus_g = int16(bytes, 18); + type = 'A'; + a = int16(bytes, 22); + b = int16(bytes, 24); + } else { + printf("unknown len %d\n", len); + continue; + } + } + if (type != 'F' && !ao_flight_started) + continue; + + switch (type) { + case 'F': + ao_flight_ground_accel = a; + if (ao_config.accel_plus_g == 0) { + ao_config.accel_plus_g = a; + ao_config.accel_minus_g = a + 530; + } + if (ao_config.main_deploy == 0) + ao_config.main_deploy = 250; + ao_flight_started = 1; + break; + case 'S': + break; + case 'A': + ao_adc_static.tick = tick; + ao_adc_static.accel = a; + ao_adc_static.pres_real = b; + if (b < AO_MIN_BARO_VALUE) + b = AO_MIN_BARO_VALUE; + ao_adc_static.pres = b; + ao_records_read++; + ao_insert(); + return; + case 'T': + ao_adc_static.tick = tick; + ao_adc_static.temp = a; + ao_adc_static.v_batt = b; + break; + case 'D': + case 'G': + case 'N': + case 'W': + case 'H': + break; + } + } + + } +} +#define COUNTS_PER_G 264.8 + +void +ao_dump_state(void) +{ +} + +static const struct option options[] = { + { .name = "summary", .has_arg = 0, .val = 's' }, + { .name = "debug", .has_arg = 0, .val = 'd' }, + { 0, 0, 0, 0}, +}; + +void run_flight_fixed(char *name, FILE *f, int summary) +{ + emulator_name = name; + emulator_in = f; + ao_summary = summary; + ao_flight_init(); + ao_flight(); +} + +int +main (int argc, char **argv) +{ + int summary = 0; + int c; + int i; + +#if HAS_ACCEL + emulator_app="full"; +#else + emulator_app="baro"; +#endif + while ((c = getopt_long(argc, argv, "sd", options, NULL)) != -1) { + switch (c) { + case 's': + summary = 1; + break; + case 'd': + ao_flight_debug = 1; + break; + } + } + + if (optind == argc) + run_flight_fixed("", stdin, summary); + else + for (i = optind; i < argc; i++) { + FILE *f = fopen(argv[i], "r"); + if (!f) { + perror(argv[i]); + continue; + } + run_flight_fixed(argv[i], f, summary); + fclose(f); + } +} diff --git a/src/test/ao_gps_test.c b/src/test/ao_gps_test.c new file mode 100644 index 00000000..93d7a9ab --- /dev/null +++ b/src/test/ao_gps_test.c @@ -0,0 +1,508 @@ +/* + * 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_GPS_TEST +#include "ao_host.h" +#include +#include +#include +#include +#include +#define AO_GPS_NUM_SAT_MASK (0xf << 0) +#define AO_GPS_NUM_SAT_SHIFT (0) + +#define AO_GPS_VALID (1 << 4) +#define AO_GPS_RUNNING (1 << 5) +#define AO_GPS_DATE_VALID (1 << 6) +#define AO_GPS_COURSE_VALID (1 << 7) + +struct ao_gps_orig { + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t flags; + int32_t latitude; /* degrees * 10⁷ */ + int32_t longitude; /* degrees * 10⁷ */ + int16_t altitude; /* m */ + uint16_t ground_speed; /* cm/s */ + uint8_t course; /* degrees / 2 */ + uint8_t hdop; /* * 5 */ + int16_t climb_rate; /* cm/s */ + uint16_t h_error; /* m */ + uint16_t v_error; /* m */ +}; + +#define SIRF_SAT_STATE_ACQUIRED (1 << 0) +#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) +#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) +#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) +#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) +#define SIRF_SAT_CODE_LOCKED (1 << 5) +#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) +#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) + +struct ao_gps_sat_orig { + uint8_t svid; + uint8_t c_n_1; +}; + +#define AO_MAX_GPS_TRACKING 12 + +struct ao_gps_tracking_orig { + uint8_t channels; + struct ao_gps_sat_orig sats[AO_MAX_GPS_TRACKING]; +}; + +#define ao_telemetry_location ao_gps_orig +#define ao_telemetry_satellite ao_gps_tracking_orig +#define ao_telemetry_satellite_info ao_gps_sat_orig + +void +ao_mutex_get(uint8_t *mutex) +{ +} + +void +ao_mutex_put(uint8_t *mutex) +{ +} + +static int +ao_gps_fd; + +static void +ao_dbg_char(char c) +{ + char line[128]; + line[0] = '\0'; + if (c < ' ') { + if (c == '\n') + sprintf (line, "\n"); + else + sprintf (line, "\\%02x", ((int) c) & 0xff); + } else { + sprintf (line, "%c", c); + } + write(1, line, strlen(line)); +} + +#define QUEUE_LEN 4096 + +static char input_queue[QUEUE_LEN]; +int input_head, input_tail; + +#include + +int +get_millis(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +} + +static void +check_sirf_message(char *from, uint8_t *msg, int len) +{ + uint16_t encoded_len, encoded_cksum; + uint16_t cksum; + uint8_t id; + int i; + + if (msg[0] != 0xa0 || msg[1] != 0xa2) { + printf ("bad header\n"); + return; + } + if (len < 7) { + printf("short\n"); + return; + } + if (msg[len-1] != 0xb3 || msg[len-2] != 0xb0) { + printf ("bad trailer\n"); + return; + } + encoded_len = (msg[2] << 8) | msg[3]; + id = msg[4]; +/* printf ("%9d: %3d\n", get_millis(), id); */ + if (encoded_len != len - 8) { + if (id != 52) + printf ("length mismatch (got %d, wanted %d)\n", + len - 8, encoded_len); + return; + } + encoded_cksum = (msg[len - 4] << 8) | msg[len-3]; + cksum = 0; + for (i = 4; i < len - 4; i++) + cksum = (cksum + msg[i]) & 0x7fff; + if (encoded_cksum != cksum) { + printf ("cksum mismatch (got %04x wanted %04x)\n", + cksum, encoded_cksum); + return; + } + id = msg[4]; + switch (id) { + case 41:{ + int off = 4; + + uint8_t id; + uint16_t nav_valid; + uint16_t nav_type; + uint16_t week; + uint32_t tow; + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint16_t second; + uint32_t sat_list; + int32_t lat; + int32_t lon; + int32_t alt_ell; + int32_t alt_msl; + int8_t datum; + uint16_t sog; + uint16_t cog; + int16_t mag_var; + int16_t climb_rate; + int16_t heading_rate; + uint32_t h_error; + uint32_t v_error; + uint32_t t_error; + uint16_t h_v_error; + +#define get_u8(u) u = (msg[off]); off+= 1 +#define get_u16(u) u = (msg[off] << 8) | (msg[off + 1]); off+= 2 +#define get_u32(u) u = (msg[off] << 24) | (msg[off + 1] << 16) | (msg[off+2] << 8) | (msg[off+3]); off+= 4 + + get_u8(id); + get_u16(nav_valid); + get_u16(nav_type); + get_u16(week); + get_u32(tow); + get_u16(year); + get_u8(month); + get_u8(day); + get_u8(hour); + get_u8(minute); + get_u16(second); + get_u32(sat_list); + get_u32(lat); + get_u32(lon); + get_u32(alt_ell); + get_u32(alt_msl); + get_u8(datum); + get_u16(sog); + get_u16(cog); + get_u16(mag_var); + get_u16(climb_rate); + get_u16(heading_rate); + get_u32(h_error); + get_u32(v_error); + get_u32(t_error); + get_u16(h_v_error); + + + printf ("Geodetic Navigation Data (41):\n"); + printf ("\tNav valid %04x\n", nav_valid); + printf ("\tNav type %04x\n", nav_type); + printf ("\tWeek %5d", week); + printf (" TOW %9d", tow); + printf (" %4d-%2d-%2d %02d:%02d:%07.4f\n", + year, month, day, + hour, minute, second / 1000.0); + printf ("\tsats: %08x\n", sat_list); + printf ("\tlat: %g", lat / 1.0e7); + printf (" lon: %g", lon / 1.0e7); + printf (" alt_ell: %g", alt_ell / 100.0); + printf (" alt_msll: %g", alt_msl / 100.0); + printf (" datum: %d\n", datum); + printf ("\tground speed: %g", sog / 100.0); + printf (" course: %g", cog / 100.0); + printf (" climb: %g", climb_rate / 100.0); + printf (" heading rate: %g\n", heading_rate / 100.0); + printf ("\th error: %g", h_error / 100.0); + printf (" v error: %g", v_error / 100.0); + printf (" t error: %g", t_error / 100.0); + printf (" h vel error: %g\n", h_v_error / 100.0); + break; + } + case 4: { + int off = 4; + uint8_t id; + int16_t gps_week; + uint32_t gps_tow; + uint8_t channels; + int j, k; + + get_u8(id); + get_u16(gps_week); + get_u32(gps_tow); + get_u8(channels); + + printf ("Measured Tracker Data (4):\n"); + printf ("GPS week: %d\n", gps_week); + printf ("GPS time of week: %d\n", gps_tow); + printf ("channels: %d\n", channels); + for (j = 0; j < 12; j++) { + uint8_t svid, azimuth, elevation; + uint16_t state; + uint8_t c_n[10]; + get_u8(svid); + get_u8(azimuth); + get_u8(elevation); + get_u16(state); + for (k = 0; k < 10; k++) { + get_u8(c_n[k]); + } + printf ("Sat %3d:", svid); + printf (" aziumuth: %6.1f", azimuth * 1.5); + printf (" elevation: %6.1f", elevation * 0.5); + printf (" state: 0x%02x", state); + printf (" c_n:"); + for (k = 0; k < 10; k++) + printf(" %3d", c_n[k]); + if (state & SIRF_SAT_STATE_ACQUIRED) + printf(" acq,"); + if (state & SIRF_SAT_STATE_CARRIER_PHASE_VALID) + printf(" car,"); + if (state & SIRF_SAT_BIT_SYNC_COMPLETE) + printf(" bit,"); + if (state & SIRF_SAT_SUBFRAME_SYNC_COMPLETE) + printf(" sub,"); + if (state & SIRF_SAT_CARRIER_PULLIN_COMPLETE) + printf(" pullin,"); + if (state & SIRF_SAT_CODE_LOCKED) + printf(" code,"); + if (state & SIRF_SAT_ACQUISITION_FAILED) + printf(" fail,"); + if (state & SIRF_SAT_EPHEMERIS_AVAILABLE) + printf(" ephem,"); + printf ("\n"); + } + break; + } + default: + return; + printf ("%s %4d:", from, encoded_len); + for (i = 4; i < len - 4; i++) { + if (((i - 4) & 0xf) == 0) + printf("\n "); + printf (" %3d", msg[i]); + } + printf ("\n"); + } +} + +static uint8_t sirf_message[4096]; +static int sirf_message_len; +static uint8_t sirf_in_message[4096]; +static int sirf_in_len; + +char +ao_serial_getchar(void) +{ + char c; + uint8_t uc; + + while (input_head == input_tail) { + for (;;) { + input_tail = read(ao_gps_fd, input_queue, QUEUE_LEN); + if (input_tail < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + perror ("getchar"); + exit (1); + } + input_head = 0; + break; + } + } + c = input_queue[input_head]; + input_head = (input_head + 1) % QUEUE_LEN; + uc = c; + if (sirf_in_len || uc == 0xa0) { + if (sirf_in_len < 4096) + sirf_in_message[sirf_in_len++] = uc; + if (uc == 0xb3) { + check_sirf_message("recv", sirf_in_message, sirf_in_len); + sirf_in_len = 0; + } + } + return c; +} + + +void +ao_serial_putchar(char c) +{ + int i; + uint8_t uc = (uint8_t) c; + + if (sirf_message_len || uc == 0xa0) { + if (sirf_message_len < 4096) + sirf_message[sirf_message_len++] = uc; + if (uc == 0xb3) { + check_sirf_message("send", sirf_message, sirf_message_len); + sirf_message_len = 0; + } + } + for (;;) { + i = write(ao_gps_fd, &c, 1); + if (i == 1) { + if ((uint8_t) c == 0xb3 || c == '\r') { + static const struct timespec delay = { + .tv_sec = 0, + .tv_nsec = 100 * 1000 * 1000 + }; + tcdrain(ao_gps_fd); +// nanosleep(&delay, NULL); + } + break; + } + if (i < 0 && (errno == EINTR || errno == EAGAIN)) + continue; + perror("putchar"); + exit(1); + } +} + +#define AO_SERIAL_SPEED_4800 0 +#define AO_SERIAL_SPEED_57600 1 + +static void +ao_serial_set_speed(uint8_t speed) +{ + int fd = ao_gps_fd; + struct termios termios; + + tcdrain(fd); + tcgetattr(fd, &termios); + switch (speed) { + case AO_SERIAL_SPEED_4800: + cfsetspeed(&termios, B4800); + break; + case AO_SERIAL_SPEED_57600: + cfsetspeed(&termios, B57600); + break; + } + tcsetattr(fd, TCSAFLUSH, &termios); + tcflush(fd, TCIFLUSH); +} + +#define ao_time() 0 + +#include "ao_gps_print.c" +#include "ao_gps_sirf.c" + +void +ao_dump_state(void *wchan) +{ + double lat, lon; + int i; + if (wchan == &ao_gps_data) + ao_gps_print(&ao_gps_data); + else + ao_gps_tracking_print(&ao_gps_tracking_data); + putchar('\n'); + return; + printf ("%02d:%02d:%02d", + ao_gps_data.hour, ao_gps_data.minute, + ao_gps_data.second); + printf (" nsat %d %svalid", + ao_gps_data.flags & AO_GPS_NUM_SAT_MASK, + ao_gps_data.flags & AO_GPS_VALID ? "" : "not "); + printf (" lat %g lon %g alt %d", + ao_gps_data.latitude / 1.0e7, + ao_gps_data.longitude / 1.0e7, + ao_gps_data.altitude); + printf (" speed %g climb %g course %d", + ao_gps_data.ground_speed / 100.0, + ao_gps_data.climb_rate / 100.0, + ao_gps_data.course * 2); + printf (" hdop %g h_error %d v_error %d", + ao_gps_data.hdop / 5.0, + ao_gps_data.h_error, ao_gps_data.v_error); + printf("\n"); + printf ("\t"); + for (i = 0; i < 12; i++) + printf (" %2d(%02d)", + ao_gps_tracking_data.sats[i].svid, + ao_gps_tracking_data.sats[i].c_n_1); + printf ("\n"); +} + +int +ao_gps_open(const char *tty) +{ + struct termios termios; + int fd; + + fd = open (tty, O_RDWR); + if (fd < 0) + return -1; + + tcgetattr(fd, &termios); + cfmakeraw(&termios); + cfsetspeed(&termios, B4800); + tcsetattr(fd, TCSAFLUSH, &termios); + + tcdrain(fd); + tcflush(fd, TCIFLUSH); + return fd; +} + +#include + +static const struct option options[] = { + { .name = "tty", .has_arg = 1, .val = 'T' }, + { 0, 0, 0, 0}, +}; + +static void usage(char *program) +{ + fprintf(stderr, "usage: %s [--tty ]\n", program); + exit(1); +} + +int +main (int argc, char **argv) +{ + char *tty = "/dev/ttyUSB0"; + int c; + + while ((c = getopt_long(argc, argv, "T:", options, NULL)) != -1) { + switch (c) { + case 'T': + tty = optarg; + break; + default: + usage(argv[0]); + break; + } + } + ao_gps_fd = ao_gps_open(tty); + if (ao_gps_fd < 0) { + perror (tty); + exit (1); + } + ao_gps_setup(); + ao_gps(); +} diff --git a/src/test/ao_gps_test_skytraq.c b/src/test/ao_gps_test_skytraq.c new file mode 100644 index 00000000..a78fae0f --- /dev/null +++ b/src/test/ao_gps_test_skytraq.c @@ -0,0 +1,490 @@ +/* + * 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_GPS_TEST +#include "ao_host.h" +#include +#include +#include +#include +#include +#define AO_GPS_NUM_SAT_MASK (0xf << 0) +#define AO_GPS_NUM_SAT_SHIFT (0) + +#define AO_GPS_VALID (1 << 4) +#define AO_GPS_RUNNING (1 << 5) +#define AO_GPS_DATE_VALID (1 << 6) +#define AO_GPS_COURSE_VALID (1 << 7) + +struct ao_gps_orig { + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t flags; + int32_t latitude; /* degrees * 10⁷ */ + int32_t longitude; /* degrees * 10⁷ */ + int16_t altitude; /* m */ + uint16_t ground_speed; /* cm/s */ + uint8_t course; /* degrees / 2 */ + uint8_t hdop; /* * 5 */ + int16_t climb_rate; /* cm/s */ + uint16_t h_error; /* m */ + uint16_t v_error; /* m */ +}; + +#define SIRF_SAT_STATE_ACQUIRED (1 << 0) +#define SIRF_SAT_STATE_CARRIER_PHASE_VALID (1 << 1) +#define SIRF_SAT_BIT_SYNC_COMPLETE (1 << 2) +#define SIRF_SAT_SUBFRAME_SYNC_COMPLETE (1 << 3) +#define SIRF_SAT_CARRIER_PULLIN_COMPLETE (1 << 4) +#define SIRF_SAT_CODE_LOCKED (1 << 5) +#define SIRF_SAT_ACQUISITION_FAILED (1 << 6) +#define SIRF_SAT_EPHEMERIS_AVAILABLE (1 << 7) + +struct ao_gps_sat_orig { + uint8_t svid; + uint8_t c_n_1; +}; + +#define AO_MAX_GPS_TRACKING 12 + +struct ao_gps_tracking_orig { + uint8_t channels; + struct ao_gps_sat_orig sats[AO_MAX_GPS_TRACKING]; +}; + +#define ao_telemetry_location ao_gps_orig +#define ao_telemetry_satellite ao_gps_tracking_orig +#define ao_telemetry_satellite_info ao_gps_sat_orig + +void +ao_mutex_get(uint8_t *mutex) +{ +} + +void +ao_mutex_put(uint8_t *mutex) +{ +} + +static int +ao_gps_fd; + +static void +ao_dbg_char(char c) +{ + char line[128]; + line[0] = '\0'; + if (c < ' ') { + if (c == '\n') + sprintf (line, "\n"); + else + sprintf (line, "\\%02x", ((int) c) & 0xff); + } else { + sprintf (line, "%c", c); + } + write(1, line, strlen(line)); +} + +#define QUEUE_LEN 4096 + +static char input_queue[QUEUE_LEN]; +int input_head, input_tail; + +#include + +int +get_millis(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec * 1000 + tv.tv_usec / 1000; +} + +static void +check_skytraq_message(char *from, uint8_t *msg, int len) +{ + uint16_t encoded_len, encoded_cksum; + uint16_t cksum; + uint8_t id; + int i; + +// fwrite(msg, 1, len, stdout); + return; + if (msg[0] != 0xa0 || msg[1] != 0xa2) { + printf ("bad header\n"); + return; + } + if (len < 7) { + printf("short\n"); + return; + } + if (msg[len-1] != 0xb3 || msg[len-2] != 0xb0) { + printf ("bad trailer\n"); + return; + } + encoded_len = (msg[2] << 8) | msg[3]; + id = msg[4]; +/* printf ("%9d: %3d\n", get_millis(), id); */ + if (encoded_len != len - 8) { + if (id != 52) + printf ("length mismatch (got %d, wanted %d)\n", + len - 8, encoded_len); + return; + } + encoded_cksum = (msg[len - 4] << 8) | msg[len-3]; + cksum = 0; + for (i = 4; i < len - 4; i++) + cksum = (cksum + msg[i]) & 0x7fff; + if (encoded_cksum != cksum) { + printf ("cksum mismatch (got %04x wanted %04x)\n", + cksum, encoded_cksum); + return; + } + id = msg[4]; + switch (id) { + case 41:{ + int off = 4; + + uint8_t id; + uint16_t nav_valid; + uint16_t nav_type; + uint16_t week; + uint32_t tow; + uint16_t year; + uint8_t month; + uint8_t day; + uint8_t hour; + uint8_t minute; + uint16_t second; + uint32_t sat_list; + int32_t lat; + int32_t lon; + int32_t alt_ell; + int32_t alt_msl; + int8_t datum; + uint16_t sog; + uint16_t cog; + int16_t mag_var; + int16_t climb_rate; + int16_t heading_rate; + uint32_t h_error; + uint32_t v_error; + uint32_t t_error; + uint16_t h_v_error; + +#define get_u8(u) u = (msg[off]); off+= 1 +#define get_u16(u) u = (msg[off] << 8) | (msg[off + 1]); off+= 2 +#define get_u32(u) u = (msg[off] << 24) | (msg[off + 1] << 16) | (msg[off+2] << 8) | (msg[off+3]); off+= 4 + + get_u8(id); + get_u16(nav_valid); + get_u16(nav_type); + get_u16(week); + get_u32(tow); + get_u16(year); + get_u8(month); + get_u8(day); + get_u8(hour); + get_u8(minute); + get_u16(second); + get_u32(sat_list); + get_u32(lat); + get_u32(lon); + get_u32(alt_ell); + get_u32(alt_msl); + get_u8(datum); + get_u16(sog); + get_u16(cog); + get_u16(mag_var); + get_u16(climb_rate); + get_u16(heading_rate); + get_u32(h_error); + get_u32(v_error); + get_u32(t_error); + get_u16(h_v_error); + + + printf ("Geodetic Navigation Data (41):\n"); + printf ("\tNav valid %04x\n", nav_valid); + printf ("\tNav type %04x\n", nav_type); + printf ("\tWeek %5d", week); + printf (" TOW %9d", tow); + printf (" %4d-%2d-%2d %02d:%02d:%07.4f\n", + year, month, day, + hour, minute, second / 1000.0); + printf ("\tsats: %08x\n", sat_list); + printf ("\tlat: %g", lat / 1.0e7); + printf (" lon: %g", lon / 1.0e7); + printf (" alt_ell: %g", alt_ell / 100.0); + printf (" alt_msll: %g", alt_msl / 100.0); + printf (" datum: %d\n", datum); + printf ("\tground speed: %g", sog / 100.0); + printf (" course: %g", cog / 100.0); + printf (" climb: %g", climb_rate / 100.0); + printf (" heading rate: %g\n", heading_rate / 100.0); + printf ("\th error: %g", h_error / 100.0); + printf (" v error: %g", v_error / 100.0); + printf (" t error: %g", t_error / 100.0); + printf (" h vel error: %g\n", h_v_error / 100.0); + break; + } + case 4: { + int off = 4; + uint8_t id; + int16_t gps_week; + uint32_t gps_tow; + uint8_t channels; + int j, k; + + get_u8(id); + get_u16(gps_week); + get_u32(gps_tow); + get_u8(channels); + + printf ("Measured Tracker Data (4):\n"); + printf ("GPS week: %d\n", gps_week); + printf ("GPS time of week: %d\n", gps_tow); + printf ("channels: %d\n", channels); + for (j = 0; j < 12; j++) { + uint8_t svid, azimuth, elevation; + uint16_t state; + uint8_t c_n[10]; + get_u8(svid); + get_u8(azimuth); + get_u8(elevation); + get_u16(state); + for (k = 0; k < 10; k++) { + get_u8(c_n[k]); + } + printf ("Sat %3d:", svid); + printf (" aziumuth: %6.1f", azimuth * 1.5); + printf (" elevation: %6.1f", elevation * 0.5); + printf (" state: 0x%02x", state); + printf (" c_n:"); + for (k = 0; k < 10; k++) + printf(" %3d", c_n[k]); + if (state & SIRF_SAT_STATE_ACQUIRED) + printf(" acq,"); + if (state & SIRF_SAT_STATE_CARRIER_PHASE_VALID) + printf(" car,"); + if (state & SIRF_SAT_BIT_SYNC_COMPLETE) + printf(" bit,"); + if (state & SIRF_SAT_SUBFRAME_SYNC_COMPLETE) + printf(" sub,"); + if (state & SIRF_SAT_CARRIER_PULLIN_COMPLETE) + printf(" pullin,"); + if (state & SIRF_SAT_CODE_LOCKED) + printf(" code,"); + if (state & SIRF_SAT_ACQUISITION_FAILED) + printf(" fail,"); + if (state & SIRF_SAT_EPHEMERIS_AVAILABLE) + printf(" ephem,"); + printf ("\n"); + } + break; + } + default: + return; + printf ("%s %4d:", from, encoded_len); + for (i = 4; i < len - 4; i++) { + if (((i - 4) & 0xf) == 0) + printf("\n "); + printf (" %3d", msg[i]); + } + printf ("\n"); + } +} + +static uint8_t skytraq_message[4096]; +static int skytraq_message_len; +static uint8_t skytraq_in_message[4096]; +static int skytraq_in_len; + +char +ao_serial_getchar(void) +{ + char c; + uint8_t uc; + + while (input_head == input_tail) { + for (;;) { + input_tail = read(ao_gps_fd, input_queue, QUEUE_LEN); + if (input_tail < 0) { + if (errno == EINTR || errno == EAGAIN) + continue; + perror ("getchar"); + exit (1); + } + input_head = 0; + break; + } + } + c = input_queue[input_head]; + input_head = (input_head + 1) % QUEUE_LEN; + uc = c; +// printf ("c: %02x %c\n", uc, uc); + if (skytraq_in_len || uc == '$') { + if (skytraq_in_len < 4096) + skytraq_in_message[skytraq_in_len++] = uc; + if (uc == 0x0a) { + check_skytraq_message("recv", skytraq_in_message, skytraq_in_len); + skytraq_in_len = 0; + } + } + return c; +} + + +void +ao_serial_putchar(char c) +{ + int i; + uint8_t uc = (uint8_t) c; + + if (skytraq_message_len || uc == 0xa0) { + if (skytraq_message_len < 4096) + skytraq_message[skytraq_message_len++] = uc; + if (uc == 0x0a) { + check_skytraq_message("send", skytraq_message, skytraq_message_len); + skytraq_message_len = 0; + } + } + for (;;) { + i = write(ao_gps_fd, &c, 1); + if (i == 1) { + if ((uint8_t) c == 0xb3 || c == '\r') { + static const struct timespec delay = { + .tv_sec = 0, + .tv_nsec = 100 * 1000 * 1000 + }; + tcdrain(ao_gps_fd); +// nanosleep(&delay, NULL); + } + break; + } + if (i < 0 && (errno == EINTR || errno == EAGAIN)) + continue; + perror("putchar"); + exit(1); + } +} + +#define AO_SERIAL_SPEED_4800 0 +#define AO_SERIAL_SPEED_9600 1 +#define AO_SERIAL_SPEED_57600 2 + +static void +ao_serial_set_speed(uint8_t speed) +{ + int fd = ao_gps_fd; + struct termios termios; + + tcdrain(fd); + tcgetattr(fd, &termios); + switch (speed) { + case AO_SERIAL_SPEED_4800: + cfsetspeed(&termios, B4800); + break; + case AO_SERIAL_SPEED_9600: + cfsetspeed(&termios, B38400); + break; + case AO_SERIAL_SPEED_57600: + cfsetspeed(&termios, B57600); + break; + } + tcsetattr(fd, TCSAFLUSH, &termios); + tcflush(fd, TCIFLUSH); +} + +#define ao_time() 0 + +#include "ao_gps_print.c" +#include "ao_gps_skytraq.c" + +void +ao_dump_state(void *wchan) +{ + double lat, lon; + int i; + if (wchan == &ao_gps_data) + ao_gps_print(&ao_gps_data); + else + ao_gps_tracking_print(&ao_gps_tracking_data); + putchar('\n'); + return; +} + +int +ao_gps_open(const char *tty) +{ + struct termios termios; + int fd; + + fd = open (tty, O_RDWR); + if (fd < 0) + return -1; + + tcgetattr(fd, &termios); + cfmakeraw(&termios); + cfsetspeed(&termios, B4800); + tcsetattr(fd, TCSAFLUSH, &termios); + + tcdrain(fd); + tcflush(fd, TCIFLUSH); + return fd; +} + +#include + +static const struct option options[] = { + { .name = "tty", .has_arg = 1, .val = 'T' }, + { 0, 0, 0, 0}, +}; + +static void usage(char *program) +{ + fprintf(stderr, "usage: %s [--tty ]\n", program); + exit(1); +} + +int +main (int argc, char **argv) +{ + char *tty = "/dev/ttyUSB0"; + int c; + + while ((c = getopt_long(argc, argv, "T:", options, NULL)) != -1) { + switch (c) { + case 'T': + tty = optarg; + break; + default: + usage(argv[0]); + break; + } + } + ao_gps_fd = ao_gps_open(tty); + if (ao_gps_fd < 0) { + perror (tty); + exit (1); + } + ao_gps(); +} diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile index d8867b19..fc8df1f4 100644 --- a/src/tidongle/Makefile +++ b/src/tidongle/Makefile @@ -1 +1,92 @@ -include ../Makefile.proto +# +# TIDongle build file +# + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + ao_product.h + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_gps_print.c \ + ao_monitor.c \ + ao_mutex.c \ + ao_panic.c \ + ao_rssi.c \ + ao_state.c \ + ao_stdio.c \ + ao_task.c + +CC1111_SRC = \ + ao_dbg.c \ + ao_dma.c \ + ao_led.c \ + ao_packet.c \ + ao_packet_master.c \ + ao_radio.c \ + ao_romconfig.c \ + ao_timer.c \ + ao_usb.c \ + _bp.c + +DRIVER_SRC = + +PRODUCT_SRC = \ + ao_tidongle.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROG = tidongle-$(VERSION).ihx +PRODUCT=TIDongle +PRODUCT_DEF=-DTIDONGLE +IDPRODUCT=0x000a + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: + diff --git a/src/tidongle/Makefile.defs b/src/tidongle/Makefile.defs deleted file mode 100644 index 0e13cb20..00000000 --- a/src/tidongle/Makefile.defs +++ /dev/null @@ -1,9 +0,0 @@ -PROG = tidongle-$(VERSION).ihx - -SRC = \ - $(TI_SRC) - -PRODUCT=TIDongle - -PRODUCT_DEF=-DTIDONGLE -IDPRODUCT=0x000a diff --git a/src/util/ao-make-product.5c b/src/util/ao-make-product.5c new file mode 100644 index 00000000..5f2eb8e8 --- /dev/null +++ b/src/util/ao-make-product.5c @@ -0,0 +1,103 @@ +#!/bin/sh + +autoimport ParseArgs; + +void +write_ucs2(string a, string description) +{ + int len = String::length(a); + + printf("/* %s */\n", description); + printf("#define AO_%s_LEN 0x%02x\n", description, len * 2 + 2); + printf("#define AO_%s_STRING \"%s\"\n", description, a); + printf("#define AO_%s_UCS2", description); + for (int i = 0; i < len; i++) { + int c = a[i]; + if (i > 0) + printf(","); + if (0x20 <= c && c < 128) + printf(" '%c', 0", c); + else + printf(" LE_WORD(0x%04x),", c); + } + printf("\n\n"); +} + +void +write_string(string a, string description) +{ + printf ("/* %s */\n", description); + printf ("#define AO_%s_STRING \"%s\"\n", description, a); +} + +void +write_int(int a, string description) +{ + printf ("/* %s */\n", description); + printf ("#define AO_%s_NUMBER %d\n\n", description, a); +} + +void +write_hex(int a, string description) +{ + printf ("/* %s */\n", description); + printf ("#define AO_%s_NUMBER 0x%04x\n\n", description, a); +} + +string manufacturer = "altusmetrum.org"; +string product = "TeleMetrum"; +string version = "0.0"; +int serial = 1; +int user_argind = 0; +int id_product = 0x000a; + +argdesc argd = { + .args = { + { + .var = { .arg_string = &manufacturer }, + .abbr = 'm', + .name = "manufacturer", + .expr_name = "manf", + .desc = "Manufacturer name." }, + { + .var = { .arg_string = &product }, + .abbr = 'p', + .name = "product", + .expr_name = "prod", + .desc = "Product name." }, + { + .var = { .arg_int = &id_product }, + .abbr = 'i', + .name = "id_product", + .expr_name = "id_p", + .desc = "Product ID." }, + { + .var = { .arg_int = &serial }, + .abbr = 's', + .name = "serial", + .expr_name = "number", + .desc = "Serial number." }, + { + .var = { .arg_string = &version }, + .abbr = 'v', + .name = "version", + .expr_name = "string", + .desc = "Program version." }, + }, + .prog_name = "usb descriptors", +}; + +void +main() +{ + string[dim(argv)-1] nargv = {[n] = argv[n+1]}; + parseargs(&argd, &nargv); + write_ucs2(manufacturer, "iManufacturer"); + write_ucs2(product, "iProduct"); + write_ucs2(sprintf("%06d", serial), "iSerial"); + write_int(serial, "iSerial"); + write_hex(id_product, "idProduct"); + write_string(version, "iVersion"); +} + +main(); diff --git a/src/util/check-stack b/src/util/check-stack new file mode 100755 index 00000000..1e8044e0 --- /dev/null +++ b/src/util/check-stack @@ -0,0 +1,13 @@ +#!/bin/sh +HEADER=$1 +MEM=$2 + +HEADER_STACK=`awk '/#define AO_STACK_START/ {print strtonum($3)}' $HEADER` +MEM_STACK=`awk '/Stack starts at/ {print strtonum ($4)}' $MEM` + +if [ "$HEADER_STACK" -lt "$MEM_STACK" ]; then + echo $MEM_STACK | awk '{ printf ("Set AO_STACK_START to at least 0x%x\n", $1); }' + exit 1 +else + exit 0 +fi diff --git a/src/util/gps-cksum b/src/util/gps-cksum new file mode 100755 index 00000000..a08153bf --- /dev/null +++ b/src/util/gps-cksum @@ -0,0 +1,17 @@ +#!/usr/bin/env nickle + +int checksum(string a) +{ + int c = 0; + for (int i = 0; i < String::length(a); i++) + c ^= a[i]; + return c; +} + +void main() +{ + for (int i = 1; i < dim(argv); i++) + printf ("$%s*%02x\n", argv[i], checksum(argv[i])); +} + +main(); diff --git a/src/util/make-altitude b/src/util/make-altitude new file mode 100644 index 00000000..716aa8a8 --- /dev/null +++ b/src/util/make-altitude @@ -0,0 +1,283 @@ +#!/usr/bin/nickle -f +/* + * Pressure Sensor Model, version 1.1 + * + * written by Holly Grimes + * + * Uses the International Standard Atmosphere as described in + * "A Quick Derivation relating altitude to air pressure" (version 1.03) + * from the Portland State Aerospace Society, except that the atmosphere + * is divided into layers with each layer having a different lapse rate. + * + * Lapse rate data for each layer was obtained from Wikipedia on Sept. 1, 2007 + * at site MAXIMUM_ALTITUDE) /* FIX ME: use sensor data to improve model */ + return 0; + + /* calculate the base temperature and pressure for the atmospheric layer + associated with the inputted altitude */ + for(layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1 && altitude > base_altitude[layer_number + 1]; layer_number++) { + delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + base_pressure *= exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + base_pressure *= pow(base, exponent); + } + base_temperature += delta_z * lapse_rate[layer_number]; + } + + /* calculate the pressure at the inputted altitude */ + delta_z = altitude - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + pressure = base_pressure * exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + pressure = base_pressure * pow(base, exponent); + } + + return pressure; +} + + +/* outputs the altitude associated with the given pressure. the altitude + returned is measured with respect to the mean sea level */ +real pressure_to_altitude(real pressure) { + + real next_base_temperature = LAYER0_BASE_TEMPERATURE; + real next_base_pressure = LAYER0_BASE_PRESSURE; + + real altitude; + real base_pressure; + real base_temperature; + real base; /* base for function to determine base pressure of next layer */ + real exponent; /* exponent for function to determine base pressure + of next layer */ + real coefficient; + int layer_number; /* identifies layer in the atmosphere */ + int delta_z; /* difference between two altitudes */ + + if (pressure < 0) /* illegal pressure */ + return -1; + if (pressure < MINIMUM_PRESSURE) /* FIX ME: use sensor data to improve model */ + return MAXIMUM_ALTITUDE; + + /* calculate the base temperature and pressure for the atmospheric layer + associated with the inputted pressure. */ + layer_number = -1; + do { + layer_number++; + base_pressure = next_base_pressure; + base_temperature = next_base_temperature; + delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + next_base_pressure *= exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + next_base_pressure *= pow(base, exponent); + } + next_base_temperature += delta_z * lapse_rate[layer_number]; + } + while(layer_number < NUMBER_OF_LAYERS - 1 && pressure < next_base_pressure); + + /* calculate the altitude associated with the inputted pressure */ + if (lapse_rate[layer_number] == 0.0) { + coefficient = (AIR_GAS_CONSTANT / GRAVITATIONAL_ACCELERATION) + * base_temperature; + altitude = base_altitude[layer_number] + + coefficient * log(pressure / base_pressure); + } + else { + base = pressure / base_pressure; + exponent = AIR_GAS_CONSTANT * lapse_rate[layer_number] + / GRAVITATIONAL_ACCELERATION; + coefficient = base_temperature / lapse_rate[layer_number]; + altitude = base_altitude[layer_number] + + coefficient * (pow(base, exponent) - 1); + } + + return altitude; +} + +real feet_to_meters(real feet) +{ + return feet * (12 * 2.54 / 100); +} + +real meters_to_feet(real meters) +{ + return meters / (12 * 2.54 / 100); +} + +/* + * Values for our MP3H6115A pressure sensor + * + * From the data sheet: + * + * Pressure range: 15-115 kPa + * Voltage at 115kPa: 2.82 + * Output scale: 27mV/kPa + * + * + * 27 mV/kPa * 2047 / 3300 counts/mV = 16.75 counts/kPa + * 2.82V * 2047 / 3.3 counts/V = 1749 counts/115 kPa + */ + +real counts_per_kPa = 27 * 2047 / 3300; +real counts_at_101_3kPa = 1674; + +real fraction_to_kPa(real fraction) +{ + return (fraction + 0.095) / 0.009; +} + + +real count_to_kPa(real count) = fraction_to_kPa(count / 2047); + +typedef struct { + real m, b; + int m_i, b_i; +} line_t; + +line_t best_fit(real[] values, int first, int last) { + real sum_x = 0, sum_x2 = 0, sum_y = 0, sum_xy = 0; + int n = last - first + 1; + real m, b; + int m_i, b_i; + + for (int i = first; i <= last; i++) { + sum_x += i; + sum_x2 += i**2; + sum_y += values[i]; + sum_xy += values[i] * i; + } + m = (n*sum_xy - sum_y*sum_x) / (n*sum_x2 - sum_x**2); + b = sum_y/n - m*(sum_x/n); + return (line_t) { m = m, b = b }; +} + +real count_to_altitude(real count) { + return pressure_to_altitude(count_to_kPa(count) * 1000); +} + +real fraction_to_altitude(real frac) = pressure_to_altitude(fraction_to_kPa(frac) * 1000); + +int num_samples = 1024; + +real[num_samples] alt = { [n] = fraction_to_altitude(n/(num_samples - 1)) }; + +int num_part = 128; +int seg_len = num_samples / num_part; + +line_t [dim(alt) / seg_len] fit = { + [n] = best_fit(alt, n * seg_len, n * seg_len + seg_len - 1) +}; + +int[num_samples/seg_len + 1] alt_part; + +alt_part[0] = floor (fit[0].b + 0.5); +alt_part[dim(fit)] = floor(fit[dim(fit)-1].m * dim(fit) * seg_len + fit[dim(fit)-1].b + 0.5); + +for (int i = 0; i < dim(fit) - 1; i++) { + real here, there; + here = fit[i].m * (i+1) * seg_len + fit[i].b; + there = fit[i+1].m * (i+1) * seg_len + fit[i+1].b; + alt_part[i+1] = floor ((here + there) / 2 + 0.5); +} + +real count_to_fit_altitude(int count) { + int sub = count // seg_len; + int off = count % seg_len; + line_t l = fit[sub]; + real r_v; + real i_v; + + r_v = count * l.m + l.b; + i_v = (alt_part[sub] * (seg_len - off) + alt_part[sub+1] * off) / seg_len; + return i_v; +} + +real max_error = 0; +int max_error_count = 0; +real total_error = 0; + +for (int count = 0; count < num_samples; count++) { + real kPa = fraction_to_kPa(count / (num_samples - 1)); + real meters = pressure_to_altitude(kPa * 1000); + + real meters_approx = count_to_fit_altitude(count); + real error = abs(meters - meters_approx); + + total_error += error; + if (error > max_error) { + max_error = error; + max_error_count = count; + } +# printf (" %7d, /* %6.2g kPa %5d count approx %d */\n", +# floor (meters + 0.5), kPa, count, floor(count_to_fit_altitude(count) + 0.5)); +} + +printf ("/*max error %f at %7.3f%%. Average error %f*/\n", max_error, max_error_count / (num_samples - 1) * 100, total_error / num_samples); + +printf ("#define NALT %d\n", dim(alt_part)); +printf ("#define ALT_FRAC_BITS %d\n", floor (log2(32768/(dim(alt_part)-1)) + 0.1)); + +for (int i = 0; i < dim(alt_part); i++) { + real fraction = i / (dim(alt_part) - 1); + real kPa = fraction_to_kPa(fraction); + printf ("%9d, /* %6.2f kPa %7.3f%% */\n", + alt_part[i], kPa, fraction * 100); +} diff --git a/src/util/make-kalman b/src/util/make-kalman new file mode 100644 index 00000000..f78f30a9 --- /dev/null +++ b/src/util/make-kalman @@ -0,0 +1,19 @@ +#!/bin/sh + +cd $1 >&/dev/null + +SIGMA_BOTH="-M 2 -H 6 -A 2" +SIGMA_BARO="-M 2 -H 6 -A 2" +SIGMA_ACCEL="-M 2 -H 4 -A 4" + +nickle kalman.5c -p AO_BOTH -c both -t 0.01 $SIGMA_BOTH +nickle kalman.5c -p AO_BOTH -c both -t 0.1 $SIGMA_BOTH +nickle kalman.5c -p AO_BOTH -c both -t 1 $SIGMA_BOTH + +nickle kalman.5c -p AO_ACCEL -c accel -t 0.01 $SIGMA_ACCEL +nickle kalman.5c -p AO_ACCEL -c accel -t 0.1 $SIGMA_ACCEL +nickle kalman.5c -p AO_ACCEL -c accel -t 1 $SIGMA_ACCEL + +nickle kalman.5c -p AO_BARO -c baro -t 0.01 $SIGMA_BARO +nickle kalman.5c -p AO_BARO -c baro -t 0.1 $SIGMA_BARO +nickle kalman.5c -p AO_BARO -c baro -t 1 $SIGMA_BARO diff --git a/src/util/sirf-cksum b/src/util/sirf-cksum new file mode 100755 index 00000000..b905f318 --- /dev/null +++ b/src/util/sirf-cksum @@ -0,0 +1,44 @@ +#!/usr/bin/env nickle + +int checksum(int[] msg) +{ + int sum = 0; + for (int i = 0; i < dim(msg); i++) { + sum += msg[i]; + sum &= 0x7fff; + } + return sum; +} + +void main() +{ + string[...] input; + int[...] msg; + + setdim(input, 0); + while (!File::end(stdin)) { + input[dim(input)] = gets(); + } + + setdim(msg, 0); + for (int i = 0; i < dim(input); i++) { + string[*] words = String::wordsplit(input[i], " ,\t"); + for (int j = 0; j < dim(words); j++) { + if (words[j] == "/" + "*") + break; + if (String::length(words[j]) > 0 && + Ctype::isdigit(words[j][0])) { + msg[dim(msg)] = string_to_integer(words[j]); + } + } + } + printf("\t0xa0, 0xa2, 0x%02x, 0x%02x,\t/* length: %d bytes */\n", + dim(msg) >> 8, dim(msg) & 0xff, dim(msg)); + for (int i = 0; i < dim(input); i++) + printf("%s\n", input[i]); + int csum = checksum(msg); + printf ("\t0x%02x, 0x%02x, 0xb0, 0xb3,\n", + csum >> 8, csum & 0xff); +} + +main(); diff --git a/src/util/skytraq-cksum b/src/util/skytraq-cksum new file mode 100644 index 00000000..ab0464a7 --- /dev/null +++ b/src/util/skytraq-cksum @@ -0,0 +1,44 @@ +#!/usr/bin/env nickle + +int checksum(int[] msg) +{ + int sum = 0; + for (int i = 0; i < dim(msg); i++) { + sum ^= msg[i]; + sum &= 0xff; + } + return sum; +} + +void main() +{ + string[...] input; + int[...] msg; + + setdim(input, 0); + while (!File::end(stdin)) { + input[dim(input)] = gets(); + } + + setdim(msg, 0); + for (int i = 0; i < dim(input); i++) { + string[*] words = String::wordsplit(input[i], " ,\t"); + for (int j = 0; j < dim(words); j++) { + if (words[j] == "/" + "*") + break; + if (String::length(words[j]) > 0 && + Ctype::isdigit(words[j][0])) { + msg[dim(msg)] = string_to_integer(words[j]); + } + } + } + printf("\t0xa0, 0xa1, 0x%02x, 0x%02x,\t\t/* length: %d bytes */\n", + dim(msg) >> 8, dim(msg) & 0xff, dim(msg)); + for (int i = 0; i < dim(input); i++) + printf("%s\n", input[i]); + int csum = checksum(msg); + printf ("\t0x%02x, 0x0d, 0x0a,\n", + csum); +} + +main(); -- cgit v1.2.3 From a588092a7d76dab92e4ab11e0fdb457d2ddc9025 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Aug 2011 21:10:56 -0700 Subject: altos: AVR changes - create ao_arch.h files, define ao_arch_reboot Start pulling changes needed for avr port; architecture-specific code will live in /ao_arch.h. This first change defines the ao_arch_reboot macro to reboot the microcontroller. Signed-off-by: Keith Packard --- src/avr/ao_arch.h | 36 ++++++++++++++++++++++++++++++++++++ src/cc1111/ao_arch.h | 32 ++++++++++++++++++++++++++++++++ src/core/ao.h | 2 +- src/core/ao_cmd.c | 13 +++---------- 4 files changed, 72 insertions(+), 11 deletions(-) create mode 100644 src/avr/ao_arch.h create mode 100644 src/cc1111/ao_arch.h (limited to 'src') diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h new file mode 100644 index 00000000..2b566814 --- /dev/null +++ b/src/avr/ao_arch.h @@ -0,0 +1,36 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_ARCH_H_ +#define _AO_ARCH_H_ + +#include "avr.h" + + +/* + * AVR definitions and code fragments for AltOS + */ + +#define AO_STACK_SIZE 128 + +/* Various definitions to make GCC look more like SDCC */ + +#define __naked __attribute__((naked)) + +#define ao_arch_reboot() /* XXX */ + +#endif /* _AO_ARCH_H_ */ diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h new file mode 100644 index 00000000..585fffe5 --- /dev/null +++ b/src/cc1111/ao_arch.h @@ -0,0 +1,32 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +/* + * CC1111 definitions and code fragments for AltOS + */ + +#ifndef _AO_ARCH_H_ +#define _AO_ARCH_H_ + +#include "cc1111.h" + +#define ao_arch_reboot() do { \ + WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; \ + ao_delay(AO_SEC_TO_TICKS(2)); \ + } while (0) + +#endif /* _AO_ARCH_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index 8ac9ac3d..0f1a24ad 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -22,7 +22,7 @@ #include #include #include -#include "cc1111.h" +#include #include "ao_pins.h" #define TRUE 1 diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 1442ebea..7663d875 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -32,7 +32,7 @@ static void put_string(__code char *s) { char c; - while (c = *s++) + while ((c = *s++)) putchar(c); } @@ -187,13 +187,6 @@ ao_match_word(__code char *word) return 1; } -static void -eol(void) -{ - while (ao_cmd_lex_c != '\n') - ao_cmd_lex(); -} - static void echo(void) { @@ -208,8 +201,7 @@ ao_reboot(void) ao_cmd_white(); if (!ao_match_word("eboot")) return; - WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; - ao_delay(AO_SEC_TO_TICKS(2)); + ao_arch_reboot(); ao_panic(AO_PANIC_REBOOT); } @@ -254,6 +246,7 @@ report(void) case ao_cmd_syntax_error: puts("Syntax error"); ao_cmd_status = 0; + default: break; } } -- cgit v1.2.3 From e9fab7dc99a0e7c22b511c5919adf7df85213252 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Aug 2011 22:04:36 -0700 Subject: altos: add GCC/SDCC compat macros, init_stack, save_context and GCC stdio hooks More arch-indepdency bits. GCC stdio is different from SDCC, so create suitable code in avr/ao_avr_stdio.c Create macros to initialize the task stack frame and save the task context. Add GCC/SDCC type definition compatibility macros Signed-off-by: Keith Packard --- src/avr-demo/Makefile | 102 ++++++++++ src/avr/ao_arch.h | 67 ++++++- src/avr/ao_avr_stdio.c | 52 +++++ src/avr/ao_pins.h | 31 +++ src/cc1111/ao_arch.h | 99 ++++++++++ src/cc1111/ao_pins.h | 425 ++++++++++++++++++++++++++++++++++++++++ src/core/ao.h | 76 ++----- src/core/ao_panic.c | 2 +- src/core/ao_pins.h | 408 -------------------------------------- src/core/ao_task.c | 60 +----- src/product/Makefile.telebt | 2 +- src/product/Makefile.teledongle | 2 +- src/product/Makefile.telemetrum | 2 +- src/product/Makefile.telemini | 2 +- src/product/Makefile.telenano | 2 +- src/tidongle/Makefile | 2 +- 16 files changed, 805 insertions(+), 529 deletions(-) create mode 100644 src/avr-demo/Makefile create mode 100644 src/avr/ao_avr_stdio.c create mode 100644 src/avr/ao_pins.h create mode 100644 src/cc1111/ao_pins.h delete mode 100644 src/core/ao_pins.h (limited to 'src') diff --git a/src/avr-demo/Makefile b/src/avr-demo/Makefile new file mode 100644 index 00000000..ea356654 --- /dev/null +++ b/src/avr-demo/Makefile @@ -0,0 +1,102 @@ +# +# AltOS build +# +# +vpath % ..:../core:../product:../driver +vpath make-altitude .. +vpath make-kalman .. +vpath kalman.5c ../kalman +vpath kalman_filter.5c ../kalman +vpath load_csv.5c ../kalman +vpath matrix.5c ../kalman +vpath ao-make-product.5c ../util + +MCU=atmega32u4 +DUDECPUTYPE=m32u4 +#PROGRAMMER=stk500v2 -P usb +PROGRAMMER=usbtiny +LOADCMD=avrdude +LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: +CC=avr-gcc +OBJCOPY=avr-objcopy + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + altitude.h \ + ao_kalman.h + +# +# Common AltOS sources +# +ALTOS_SRC = \ + ao_cmd.c \ + ao_mutex.c \ + ao_panic.c \ + ao_product.c \ + ao_serial_avr.c \ + ao_avr_stdio.c \ + ao_stdio.c \ + ao_task.c \ + ao_timer.c \ + ao_led.c + +PRODUCT=AvrDemo-v0.0 +MCU=atmega32u4 +PRODUCT_DEF=-DAVR_DEMO +IDPRODUCT=0x000a +CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../core -I.. +CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -Os -mcall-prologues + +NICKLE=nickle + +PROG=avr-demo + +SRC=$(ALTOS_SRC) ao_demo.c ao_debug_avr.c +OBJ=$(SRC:.c=.o) + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: $(PROG) + +$(PROG): Makefile $(OBJ) + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) + +$(PROG).hex: $(PROG) + avr-size $(PROG) + $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@ + + +load: $(PROG).hex + $(LOADCMD) $(LOADARG)$(PROG).hex + +../altitude.h: make-altitude + nickle $< > $@ + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +ao_product.rel: ao_product.c ao_product.h + $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< + +distclean: clean + +clean: + rm -f $(OBJ) + rm -f ao_product.h + +install: + +uninstall: + +$(OBJ): ao.h ao_product.h \ No newline at end of file diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index 2b566814..51a65880 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -18,8 +18,18 @@ #ifndef _AO_ARCH_H_ #define _AO_ARCH_H_ -#include "avr.h" +#include +#include +#ifdef AVR_DEMO +#define TEENSY 1 +#endif + +#if TEENSY +#define F_CPU 16000000UL // 16 MHz +#else +#define F_CPU 8000000UL // 8 MHz +#endif /* * AVR definitions and code fragments for AltOS @@ -29,8 +39,61 @@ /* Various definitions to make GCC look more like SDCC */ -#define __naked __attribute__((naked)) +#define ao_arch_naked_declare __attribute__((naked)) +#define ao_arch_naked_define +#define __pdata +#define __data +#define __xdata +#define __code const +#define __reentrant +#define __critical +#define __interrupt(n) #define ao_arch_reboot() /* XXX */ +#define ao_arch_nop() asm("nop") + +#define ao_arch_interrupt(n) /* nothing */ + +#undef putchar +#undef getchar +#define putchar(c) ao_putchar(c) +#define getchar ao_getchar + +extern void putchar(char c); +extern char getchar(void); + +extern int ao_serial_number; + +#define ao_arch_init_stack(task, start) do { \ + uint8_t *sp = task->stack + AO_STACK_SIZE - 1; \ + uint16_t a = (uint16_t) start; \ + int i; \ + \ + /* Return address */ \ + PUSH8(sp, a); \ + PUSH8(sp, (a >> 8)); \ + \ + /* Clear register values */ \ + i = 32; \ + while (i--) \ + PUSH8(sp, 0); \ + \ + /* SREG with interrupts enabled */ \ + PUSH8(sp, 0x80); \ + task->sp = sp; \ +} while (0); + +#define ao_arch_save_context() do { \ + asm("push r31" "\n\t" "push r30"); \ + asm("push r29" "\n\t" "push r28" "\n\t" "push r27" "\n\t" "push r26" "\n\t" "push r25"); \ + asm("push r24" "\n\t" "push r23" "\n\t" "push r22" "\n\t" "push r21" "\n\t" "push r20"); \ + asm("push r19" "\n\t" "push r18" "\n\t" "push r17" "\n\t" "push r16" "\n\t" "push r15"); \ + asm("push r14" "\n\t" "push r13" "\n\t" "push r12" "\n\t" "push r11" "\n\t" "push r10"); \ + asm("push r9" "\n\t" "push r8" "\n\t" "push r7" "\n\t" "push r6" "\n\t" "push r5"); \ + asm("push r4" "\n\t" "push r3" "\n\t" "push r2" "\n\t" "push r1" "\n\t" "push r0"); \ + asm("in r0, __SREG__" "\n\t" "push r0"); \ + sei(); \ + } while (0) + #endif /* _AO_ARCH_H_ */ diff --git a/src/avr/ao_avr_stdio.c b/src/avr/ao_avr_stdio.c new file mode 100644 index 00000000..2f358eb5 --- /dev/null +++ b/src/avr/ao_avr_stdio.c @@ -0,0 +1,52 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +int +stdio_put(char c, FILE *stream) +{ + if (ao_cur_task && ao_num_stdios) + putchar(c); + else + { + if (c == '\n') + stdio_put('\r', stream); + loop_until_bit_is_set(UCSR1A, UDRE1); + UDR1 = c; + } + + return 0; +} + +int +stdio_get(FILE *stream) +{ + return (int) getchar() & 0xff; +} + +static FILE mystdout = FDEV_SETUP_STREAM(stdio_put, NULL, _FDEV_SETUP_WRITE); + +static FILE mystdin = FDEV_SETUP_STREAM(NULL, stdio_get, _FDEV_SETUP_READ); + +void +ao_stdio_init(void) +{ + stdout = &mystdout; + stdin = &mystdin; + printf("%d stdios registered\n", ao_num_stdios); +} diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h new file mode 100644 index 00000000..ef41b59c --- /dev/null +++ b/src/avr/ao_pins.h @@ -0,0 +1,31 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#ifdef AVR_DEMO + #define AO_LED_RED (1<<7) + #define LEDS_AVAILABLE (AO_LED_RED) + #define USE_SERIAL_STDIN 1 + #define HAS_USB 0 + #define PACKET_HAS_SLAVE 0 + #define HAS_SERIAL_1 1 + #define HAS_BEEP 0 +#endif + +#endif /* _AO_PINS_H_ */ diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 585fffe5..35fd66f8 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -24,9 +24,108 @@ #include "cc1111.h" +/* Convert a __data pointer into an __xdata pointer */ +#define DATA_TO_XDATA(a) ((void __xdata *) ((uint8_t) (a) | 0xff00)) + +/* 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 0x90 +#define AO_STACK_END 0xfe +#define AO_STACK_SIZE (AO_STACK_END - AO_STACK_START + 1) + #define ao_arch_reboot() do { \ WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; \ ao_delay(AO_SEC_TO_TICKS(2)); \ } while (0) +#define ao_arch_nop() _asm nop _endasm +#define ao_arch_interrupt(n) __interrupt n + +#define ao_arch_naked_declare __naked +#define ao_arch_naked_define __naked + +/* CC1111-specific drivers */ + +/* + * ao_romconfig.c + */ + +#define AO_ROMCONFIG_VERSION 2 + +extern __code __at (0x00a0) uint16_t ao_romconfig_version; +extern __code __at (0x00a2) uint16_t ao_romconfig_check; +extern __code __at (0x00a4) uint16_t ao_serial_number; +extern __code __at (0x00a6) uint32_t ao_radio_cal; + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + +#if HAS_USB +extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; +#endif + +/* Initialize stack */ +#define ao_arch_init_stack(task, start) { \ + uint8_t __xdata *stack = task->stack; \ + uint8_t t; \ + *stack++ = ((uint16_t) start); /* 0 */ \ + *stack++ = ((uint16_t) start) >> 8; /* 1 */ \ + \ + /* and the stuff saved by ao_switch */ \ + *stack++ = 0; /* 2 acc */ \ + *stack++ = 0x80; /* 3 IE */ \ + \ + /* 4 DPL \ + * 5 DPH \ + * 6 B \ + * 7 R2 \ + * 8 R3 \ + * 9 R4 \ + * 10 R5 \ + * 11 R6 \ + * 12 R7 \ + * 13 R0 \ + * 14 R1 \ + * 15 PSW \ + * 16 BP \ + */ \ + for (t = 0; t < 13; t++) \ + *stack++ = 0; \ + task->stack_count = 17; \ + } + + + +/* Save current context */ + +#define ao_arch_save_context() \ + _asm \ + /* Push ACC first, as when restoring the context it must be restored \ + * last (it is used to set the IE register). */ \ + push ACC \ + /* Store the IE register then enable interrupts. */ \ + push _IEN0 \ + setb _EA \ + push DPL \ + push DPH \ + push b \ + push ar2 \ + push ar3 \ + push ar4 \ + push ar5 \ + push ar6 \ + push ar7 \ + push ar0 \ + push ar1 \ + push PSW \ + _endasm; \ + PSW = 0; \ + _asm \ + push _bp \ + _endasm + + + #endif /* _AO_ARCH_H_ */ diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h new file mode 100644 index 00000000..4ac6a84b --- /dev/null +++ b/src/cc1111/ao_pins.h @@ -0,0 +1,425 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#if defined(TELEMETRUM_V_1_0) + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define HAS_ADC 1 + #define USE_SERIAL_STDIN 0 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define HAS_COMPANION 1 + #define COMPANION_CS_ON_P1 1 + #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ + #define COMPANION_CS P1_2 + + #define AO_LED_RED 1 + #define LEDS_AVAILABLE (AO_LED_RED) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL_REF 0 + #define HAS_ACCEL 1 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEMETRUM_V_1_1) + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define HAS_COMPANION 1 + #define COMPANION_CS_ON_P1 1 + #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ + #define COMPANION_CS P1_2 + + #define AO_LED_RED 1 + #define LEDS_AVAILABLE (AO_LED_RED) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL_REF 1 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ + #define M25_MAX_CHIPS 1 + #define HAS_ACCEL 1 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEDONGLE_V_0_2) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 1 + #define AO_LED_GREEN 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_IGNITE 0 + #define HAS_MONITOR 1 +#endif + +#if defined(TELEMINI_V_1_0) + #define HAS_FLIGHT 1 + #define HAS_USB 0 + #define HAS_BEEP 0 + #define HAS_GPS 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 1 + #define HAS_DBG 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 1 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + #define USE_FAST_ASCENT_LOG 1 + + #define AO_LED_GREEN 1 + #define AO_LED_RED 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL 0 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELENANO_V_0_1) + #define HAS_FLIGHT 1 + #define HAS_USB 0 + #define HAS_BEEP 0 + #define HAS_GPS 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 1 + #define HAS_DBG 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 1 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define AO_LED_GREEN 1 + #define AO_LED_RED 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL 0 + #define HAS_IGNITE 0 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEMETRUM_V_0_1) + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_DBG 0 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 1 + #define HAS_ACCEL_REF 0 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_ACCEL 1 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + +#if defined(TELEDONGLE_V_0_1) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 0 + #define HAS_DBG 0 + #define HAS_EEPROM 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 0 + #define SPI_CS_ON_P0 1 + #define HAS_IGNITE 0 + #define HAS_MONITOR 1 +#endif + +#if defined(TIDONGLE) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 0 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 + #define LEDS_AVAILABLE (AO_LED_RED) + #define SPI_CS_ON_P1 0 + #define SPI_CS_ON_P0 1 + #define HAS_IGNITE 0 + #define HAS_MONITOR 1 +#endif + +#if defined(TELEBT_V_0_0) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 1 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define HAS_BTM 1 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_IGNITE 0 + #define BT_LINK_ON_P2 1 + #define BT_LINK_ON_P1 0 + #define BT_LINK_PIN_INDEX 7 + #define BT_LINK_PIN P2_1 + #define HAS_MONITOR 1 +#endif + +#if defined(TELEBT_V_0_1) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_SERIAL_1 1 + #define HAS_SERIAL_1_ALT_1 1 + #define HAS_SERIAL_1_ALT_2 0 + #define HAS_SERIAL_1_HW_FLOW 1 + #define USE_SERIAL_STDIN 1 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_BTM 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 1 + #define AO_LED_GREEN 2 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x04 /* CS0 is P1_2 */ + #define M25_MAX_CHIPS 1 + #define HAS_ACCEL 0 + #define HAS_IGNITE 0 + #define BT_LINK_ON_P2 0 + #define BT_LINK_ON_P1 1 + #define BT_LINK_PIN_INDEX 7 + #define BT_LINK_PIN P1_7 + #define HAS_MONITOR 1 +#endif + +#if DBG_ON_P1 + + #define DBG_CLOCK (1 << 4) /* mi0 */ + #define DBG_DATA (1 << 5) /* mo0 */ + #define DBG_RESET_N (1 << 3) /* c0 */ + + #define DBG_CLOCK_PIN (P1_4) + #define DBG_DATA_PIN (P1_5) + #define DBG_RESET_N_PIN (P1_3) + + #define DBG_PORT_NUM 1 + #define DBG_PORT P1 + #define DBG_PORT_SEL P1SEL + #define DBG_PORT_INP P1INP + #define DBG_PORT_DIR P1DIR + +#endif /* DBG_ON_P1 */ + +#if DBG_ON_P0 + + #define DBG_CLOCK (1 << 3) + #define DBG_DATA (1 << 4) + #define DBG_RESET_N (1 << 5) + + #define DBG_CLOCK_PIN (P0_3) + #define DBG_DATA_PIN (P0_4) + #define DBG_RESET_N_PIN (P0_5) + + #define DBG_PORT_NUM 0 + #define DBG_PORT P0 + #define DBG_PORT_SEL P0SEL + #define DBG_PORT_INP P0INP + #define DBG_PORT_DIR P0DIR + +#endif /* DBG_ON_P0 */ + +#if COMPANION_CS_ON_P1 + #define COMPANION_CS_PORT P1 + #define COMPANION_CS_SEL P1SEL + #define COMPANION_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P1 + #define SPI_CS_PORT P1 + #define SPI_CS_SEL P1SEL + #define SPI_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P0 + #define SPI_CS_PORT P0 + #define SPI_CS_SEL P0SEL + #define SPI_CS_DIR P0DIR +#endif + +#ifndef IGNITE_ON_P2 +#error Please define IGNITE_ON_P2 +#endif + +#ifndef IGNITE_ON_P0 +#error Please define IGNITE_ON_P0 +#endif + +#ifndef HAS_SERIAL_1 +#error Please define HAS_SERIAL_1 +#endif + +#ifndef USE_SERIAL_STDIN +#error Please define USE_SERIAL_STDIN +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#ifndef HAS_EEPROM +#error Please define HAS_EEPROM +#endif + +#if HAS_EEPROM +#ifndef USE_INTERNAL_FLASH +#error Please define USE_INTERNAL_FLASH +#endif +#endif + +#ifndef HAS_DBG +#error Please define HAS_DBG +#endif + +#ifndef HAS_IGNITE +#error Please define HAS_IGNITE +#endif + +#ifndef PACKET_HAS_MASTER +#error Please define PACKET_HAS_MASTER +#endif + +#ifndef PACKET_HAS_SLAVE +#error Please define PACKET_HAS_SLAVE +#endif + +#ifndef HAS_MONITOR +#error Please define HAS_MONITOR +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#if HAS_ADC + +#if HAS_ACCEL +#ifndef HAS_ACCEL_REF +#error Please define HAS_ACCEL_REF +#endif +#else +#define HAS_ACCEL_REF 0 +#endif + +#endif /* HAS_ADC */ + +#endif /* _AO_PINS_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index 0f1a24ad..9b0bb545 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -22,21 +22,16 @@ #include #include #include -#include #include "ao_pins.h" +#include #define TRUE 1 #define FALSE 0 /* Convert a __data pointer into an __xdata pointer */ -#define DATA_TO_XDATA(a) ((void __xdata *) ((uint8_t) (a) | 0xff00)) - -/* 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 0x90 -#define AO_STACK_END 0xfe -#define AO_STACK_SIZE (AO_STACK_END - AO_STACK_START + 1) +#ifndef DATA_TO_XDATA +#define DATA_TO_XDATA(a) (a) +#endif /* An AltOS task */ struct ao_task { @@ -75,7 +70,7 @@ ao_alarm(uint16_t delay); /* Yield the processor to another task */ void -ao_yield(void) __naked; +ao_yield(void) ao_arch_naked_declare; /* Add a task to the run queue */ void @@ -136,7 +131,7 @@ ao_timer_set_adc_interval(uint8_t interval) __critical; /* Timer interrupt */ void -ao_timer_isr(void) __interrupt 9; +ao_timer_isr(void) ao_arch_interrupt(9); /* Initialize the timer */ void @@ -159,20 +154,8 @@ struct ao_adc { int16_t sense_m; /* main continuity sense */ }; -#ifndef HAS_ADC -#error Please define HAS_ADC -#endif - #if HAS_ADC -#if HAS_ACCEL -#ifndef HAS_ACCEL_REF -#error Please define HAS_ACCEL_REF -#endif -#else -#define HAS_ACCEL_REF 0 -#endif - /* * ao_adc.c */ @@ -207,7 +190,7 @@ ao_adc_get(__xdata struct ao_adc *packet); /* The A/D interrupt handler */ void -ao_adc_isr(void) __interrupt 1; +ao_adc_isr(void) ao_arch_interrupt(1); /* Initialize the A/D converter */ void @@ -298,25 +281,6 @@ ao_led_for(uint8_t colors, uint16_t ticks) __reentrant; void ao_led_init(uint8_t enable); -/* - * ao_romconfig.c - */ - -#define AO_ROMCONFIG_VERSION 2 - -extern __code __at (0x00a0) uint16_t ao_romconfig_version; -extern __code __at (0x00a2) uint16_t ao_romconfig_check; -extern __code __at (0x00a4) uint16_t ao_serial_number; -extern __code __at (0x00a6) uint32_t ao_radio_cal; - -#ifndef HAS_USB -#error Please define HAS_USB -#endif - -#if HAS_USB -extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; -#endif - /* * ao_usb.c */ @@ -342,7 +306,7 @@ ao_usb_flush(void); #if HAS_USB /* USB interrupt handler */ void -ao_usb_isr(void) __interrupt 6; +ao_usb_isr(void) ao_arch_interrupt(6); #endif /* Enable the USB controller */ @@ -446,7 +410,7 @@ ao_dma_abort(uint8_t id); /* DMA interrupt routine */ void -ao_dma_isr(void) __interrupt 8; +ao_dma_isr(void) ao_arch_interrupt(8); /* * ao_mutex.c @@ -927,10 +891,10 @@ ao_dbg_init(void); #endif void -ao_serial_rx1_isr(void) __interrupt 3; +ao_serial_rx1_isr(void) ao_arch_interrupt(3); void -ao_serial_tx1_isr(void) __interrupt 14; +ao_serial_tx1_isr(void) ao_arch_interrupt(14); char ao_serial_getchar(void) __critical; @@ -1251,14 +1215,6 @@ struct ao_telemetry_tiny { char callsign[AO_MAX_CALLSIGN]; }; -/* - * ao_radio_recv tacks on rssi and status bytes - */ - -struct ao_telemetry_raw_recv { - uint8_t packet[AO_MAX_TELEMETRY + 2]; -}; - struct ao_telemetry_orig_recv { struct ao_telemetry_orig telemetry_orig; int8_t rssi; @@ -1271,6 +1227,14 @@ struct ao_telemetry_tiny_recv { uint8_t status; }; +/* + * ao_radio_recv tacks on rssi and status bytes + */ + +struct ao_telemetry_raw_recv { + uint8_t packet[AO_MAX_TELEMETRY + 2]; +}; + /* Set delay between telemetry reports (0 to disable) */ #define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(1000) @@ -1302,7 +1266,7 @@ extern __xdata uint8_t ao_radio_done; extern __xdata uint8_t ao_radio_mutex; void -ao_radio_general_isr(void) __interrupt 16; +ao_radio_general_isr(void) ao_arch_interrupt(16); void ao_radio_get(uint8_t len); diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c index fdada201..cbfdf399 100644 --- a/src/core/ao_panic.c +++ b/src/core/ao_panic.c @@ -33,7 +33,7 @@ ao_panic_delay(uint8_t n) while (n--) while (--j) while (--i) - _asm nop _endasm; + ao_arch_nop(); } void diff --git a/src/core/ao_pins.h b/src/core/ao_pins.h deleted file mode 100644 index e1f5459f..00000000 --- a/src/core/ao_pins.h +++ /dev/null @@ -1,408 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_PINS_H_ -#define _AO_PINS_H_ - -#if defined(TELEMETRUM_V_1_0) - #define HAS_FLIGHT 1 - #define HAS_USB 1 - #define HAS_BEEP 1 - #define HAS_GPS 1 - #define HAS_SERIAL_1 1 - #define HAS_ADC 1 - #define USE_SERIAL_STDIN 0 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 0 - #define HAS_DBG 1 - #define DBG_ON_P1 1 - #define DBG_ON_P0 0 - #define IGNITE_ON_P2 1 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - - #define HAS_COMPANION 1 - #define COMPANION_CS_ON_P1 1 - #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ - #define COMPANION_CS P1_2 - - #define AO_LED_RED 1 - #define LEDS_AVAILABLE (AO_LED_RED) - #define HAS_EXTERNAL_TEMP 0 - #define HAS_ACCEL_REF 0 - #define HAS_ACCEL 1 - #define HAS_IGNITE 1 - #define HAS_MONITOR 0 -#endif - -#if defined(TELEMETRUM_V_1_1) - #define HAS_FLIGHT 1 - #define HAS_USB 1 - #define HAS_BEEP 1 - #define HAS_GPS 1 - #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 1 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 0 - #define HAS_DBG 1 - #define DBG_ON_P1 1 - #define DBG_ON_P0 0 - #define IGNITE_ON_P2 1 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - - #define HAS_COMPANION 1 - #define COMPANION_CS_ON_P1 1 - #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ - #define COMPANION_CS P1_2 - - #define AO_LED_RED 1 - #define LEDS_AVAILABLE (AO_LED_RED) - #define HAS_EXTERNAL_TEMP 0 - #define HAS_ACCEL_REF 1 - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ - #define M25_MAX_CHIPS 1 - #define HAS_ACCEL 1 - #define HAS_IGNITE 1 - #define HAS_MONITOR 0 -#endif - -#if defined(TELEDONGLE_V_0_2) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 0 - #define HAS_DBG 1 - #define HAS_EEPROM 0 - #define DBG_ON_P1 1 - #define DBG_ON_P0 0 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 1 - #define AO_LED_GREEN 2 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define HAS_IGNITE 0 - #define HAS_MONITOR 1 -#endif - -#if defined(TELEMINI_V_1_0) - #define HAS_FLIGHT 1 - #define HAS_USB 0 - #define HAS_BEEP 0 - #define HAS_GPS 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 1 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 1 - #define HAS_DBG 0 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 1 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - #define USE_FAST_ASCENT_LOG 1 - - #define AO_LED_GREEN 1 - #define AO_LED_RED 2 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define HAS_EXTERNAL_TEMP 0 - #define HAS_ACCEL 0 - #define HAS_IGNITE 1 - #define HAS_MONITOR 0 -#endif - -#if defined(TELENANO_V_0_1) - #define HAS_FLIGHT 1 - #define HAS_USB 0 - #define HAS_BEEP 0 - #define HAS_GPS 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 1 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 1 - #define HAS_DBG 0 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 1 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - - #define AO_LED_GREEN 1 - #define AO_LED_RED 2 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define HAS_EXTERNAL_TEMP 0 - #define HAS_ACCEL 0 - #define HAS_IGNITE 0 - #define HAS_MONITOR 0 -#endif - -#if defined(TELEMETRUM_V_0_1) - #define HAS_FLIGHT 1 - #define HAS_USB 1 - #define HAS_BEEP 1 - #define HAS_GPS 1 - #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 1 - #define HAS_DBG 0 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 0 - #define DBG_ON_P1 0 - #define DBG_ON_P0 1 - #define IGNITE_ON_P2 1 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 - #define AO_LED_RED 2 - #define AO_LED_GREEN 1 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define HAS_EXTERNAL_TEMP 1 - #define HAS_ACCEL_REF 0 - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define HAS_ACCEL 1 - #define HAS_IGNITE 1 - #define HAS_MONITOR 0 -#endif - -#if defined(TELEDONGLE_V_0_1) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 0 - #define HAS_DBG 0 - #define HAS_EEPROM 0 - #define DBG_ON_P1 0 - #define DBG_ON_P0 1 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 2 - #define AO_LED_GREEN 1 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define SPI_CS_ON_P1 0 - #define SPI_CS_ON_P0 1 - #define HAS_IGNITE 0 - #define HAS_MONITOR 1 -#endif - -#if defined(TIDONGLE) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 0 - #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 - #define HAS_ADC 0 - #define HAS_DBG 1 - #define HAS_EEPROM 0 - #define DBG_ON_P1 0 - #define DBG_ON_P0 1 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 2 - #define LEDS_AVAILABLE (AO_LED_RED) - #define SPI_CS_ON_P1 0 - #define SPI_CS_ON_P0 1 - #define HAS_IGNITE 0 - #define HAS_MONITOR 1 -#endif - -#if defined(TELEBT_V_0_0) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 0 - #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 1 - #define HAS_ADC 0 - #define HAS_DBG 1 - #define HAS_EEPROM 0 - #define HAS_BTM 1 - #define DBG_ON_P1 0 - #define DBG_ON_P0 1 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 2 - #define AO_LED_GREEN 1 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define HAS_IGNITE 0 - #define BT_LINK_ON_P2 1 - #define BT_LINK_ON_P1 0 - #define BT_LINK_PIN_INDEX 7 - #define BT_LINK_PIN P2_1 - #define HAS_MONITOR 1 -#endif - -#if defined(TELEBT_V_0_1) - #define HAS_FLIGHT 0 - #define HAS_USB 1 - #define HAS_BEEP 1 - #define HAS_SERIAL_1 1 - #define HAS_SERIAL_1_ALT_1 1 - #define HAS_SERIAL_1_ALT_2 0 - #define HAS_SERIAL_1_HW_FLOW 1 - #define USE_SERIAL_STDIN 1 - #define HAS_ADC 0 - #define HAS_DBG 1 - #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 0 - #define HAS_BTM 1 - #define DBG_ON_P1 1 - #define DBG_ON_P0 0 - #define IGNITE_ON_P2 0 - #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 - #define AO_LED_RED 1 - #define AO_LED_GREEN 2 - #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) - #define SPI_CS_ON_P1 1 - #define SPI_CS_ON_P0 0 - #define M25_CS_MASK 0x04 /* CS0 is P1_2 */ - #define M25_MAX_CHIPS 1 - #define HAS_ACCEL 0 - #define HAS_IGNITE 0 - #define BT_LINK_ON_P2 0 - #define BT_LINK_ON_P1 1 - #define BT_LINK_PIN_INDEX 7 - #define BT_LINK_PIN P1_7 - #define HAS_MONITOR 1 -#endif - -#if DBG_ON_P1 - - #define DBG_CLOCK (1 << 4) /* mi0 */ - #define DBG_DATA (1 << 5) /* mo0 */ - #define DBG_RESET_N (1 << 3) /* c0 */ - - #define DBG_CLOCK_PIN (P1_4) - #define DBG_DATA_PIN (P1_5) - #define DBG_RESET_N_PIN (P1_3) - - #define DBG_PORT_NUM 1 - #define DBG_PORT P1 - #define DBG_PORT_SEL P1SEL - #define DBG_PORT_INP P1INP - #define DBG_PORT_DIR P1DIR - -#endif /* DBG_ON_P1 */ - -#if DBG_ON_P0 - - #define DBG_CLOCK (1 << 3) - #define DBG_DATA (1 << 4) - #define DBG_RESET_N (1 << 5) - - #define DBG_CLOCK_PIN (P0_3) - #define DBG_DATA_PIN (P0_4) - #define DBG_RESET_N_PIN (P0_5) - - #define DBG_PORT_NUM 0 - #define DBG_PORT P0 - #define DBG_PORT_SEL P0SEL - #define DBG_PORT_INP P0INP - #define DBG_PORT_DIR P0DIR - -#endif /* DBG_ON_P0 */ - -#if COMPANION_CS_ON_P1 - #define COMPANION_CS_PORT P1 - #define COMPANION_CS_SEL P1SEL - #define COMPANION_CS_DIR P1DIR -#endif - -#if SPI_CS_ON_P1 - #define SPI_CS_PORT P1 - #define SPI_CS_SEL P1SEL - #define SPI_CS_DIR P1DIR -#endif - -#if SPI_CS_ON_P0 - #define SPI_CS_PORT P0 - #define SPI_CS_SEL P0SEL - #define SPI_CS_DIR P0DIR -#endif - -#ifndef IGNITE_ON_P2 -#error Please define IGNITE_ON_P2 -#endif - -#ifndef IGNITE_ON_P0 -#error Please define IGNITE_ON_P0 -#endif - -#ifndef HAS_SERIAL_1 -#error Please define HAS_SERIAL_1 -#endif - -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - -#ifndef HAS_ADC -#error Please define HAS_ADC -#endif - -#ifndef HAS_EEPROM -#error Please define HAS_EEPROM -#endif - -#if HAS_EEPROM -#ifndef USE_INTERNAL_FLASH -#error Please define USE_INTERNAL_FLASH -#endif -#endif - -#ifndef HAS_DBG -#error Please define HAS_DBG -#endif - -#ifndef HAS_IGNITE -#error Please define HAS_IGNITE -#endif - -#ifndef PACKET_HAS_MASTER -#error Please define PACKET_HAS_MASTER -#endif - -#ifndef PACKET_HAS_SLAVE -#error Please define PACKET_HAS_SLAVE -#endif - -#ifndef HAS_MONITOR -#error Please define HAS_MONITOR -#endif -#endif /* _AO_PINS_H_ */ diff --git a/src/core/ao_task.c b/src/core/ao_task.c index f5850fa4..41520476 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -27,7 +27,6 @@ __xdata struct ao_task *__data ao_cur_task; void ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant { - uint8_t __xdata *stack; uint8_t task_id; uint8_t t; if (ao_num_tasks == AO_NUM_TASKS) @@ -42,70 +41,19 @@ ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *nam ao_tasks[ao_num_tasks++] = task; task->task_id = task_id; task->name = name; + task->wchan = NULL; /* * Construct a stack frame so that it will 'return' * to the start of the task */ - stack = task->stack; - - *stack++ = ((uint16_t) start); /* 0 */ - *stack++ = ((uint16_t) start) >> 8; /* 1 */ - - /* and the stuff saved by ao_switch */ - *stack++ = 0; /* 2 acc */ - *stack++ = 0x80; /* 3 IE */ - - /* 4 DPL - * 5 DPH - * 6 B - * 7 R2 - * 8 R3 - * 9 R4 - * 10 R5 - * 11 R6 - * 12 R7 - * 13 R0 - * 14 R1 - * 15 PSW - * 16 BP - */ - for (t = 0; t < 13; t++) - *stack++ = 0; - - task->stack_count = 17; - task->wchan = NULL; + ao_arch_init_stack(task, start); } /* Task switching function. This must not use any stack variables */ void -ao_yield(void) __naked +ao_yield(void) ao_arch_naked_define { - - /* Save current context */ - _asm - /* Push ACC first, as when restoring the context it must be restored - * last (it is used to set the IE register). */ - push ACC - /* Store the IE register then enable interrupts. */ - push _IEN0 - setb _EA - push DPL - push DPH - push b - push ar2 - push ar3 - push ar4 - push ar5 - push ar6 - push ar7 - push ar0 - push ar1 - push PSW - _endasm; - PSW = 0; - _asm - push _bp - _endasm; + ao_arch_save_context(); if (ao_cur_task_index == AO_NO_TASK_INDEX) ao_cur_task_index = ao_num_tasks-1; diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index 99730b9f..d9ef1ea7 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -79,7 +79,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle index f32c037f..cfd9b806 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -78,7 +78,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index fd958aea..2759ac52 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -93,7 +93,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini index 3bd14226..7f251897 100644 --- a/src/product/Makefile.telemini +++ b/src/product/Makefile.telemini @@ -82,7 +82,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index 72043044..c47e95ff 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -81,7 +81,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile index fc8df1f4..247f4fe0 100644 --- a/src/tidongle/Makefile +++ b/src/tidongle/Makefile @@ -73,7 +73,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../core/ao.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ -- cgit v1.2.3 From 8125acc030574afed6f23aa8aa302d9c768bb04e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 25 Aug 2011 22:55:33 -0700 Subject: altos: get avr-demo to build. Pull in AVR drivers and LCD driver This completes the basic task of making an AVR version of altos by getting the Teensy 'avr-demo' program to build. Signed-off-by: Keith Packard --- src/avr-demo/Makefile | 7 +- src/avr-demo/ao_demo.c | 52 ++++ src/avr/ao_arch.h | 80 ++++-- src/avr/ao_avr_stdio.c | 2 +- src/avr/ao_debug_avr.c | 78 ++++++ src/avr/ao_led.c | 67 +++++ src/avr/ao_pins.h | 28 +- src/avr/ao_romconfig.c | 20 ++ src/avr/ao_serial_avr.c | 166 ++++++++++++ src/avr/ao_timer.c | 147 +++++++++++ src/avr/ao_usb.h | 100 +++++++ src/avr/ao_usb_avr.c | 688 ++++++++++++++++++++++++++++++++++++++++++++++++ src/cc1111/ao_arch.h | 118 +++++++-- src/core/ao.h | 11 +- src/core/ao_panic.c | 2 +- src/core/ao_task.c | 99 ++----- 16 files changed, 1542 insertions(+), 123 deletions(-) create mode 100644 src/avr-demo/ao_demo.c create mode 100644 src/avr/ao_debug_avr.c create mode 100644 src/avr/ao_led.c create mode 100644 src/avr/ao_romconfig.c create mode 100644 src/avr/ao_serial_avr.c create mode 100644 src/avr/ao_timer.c create mode 100644 src/avr/ao_usb.h create mode 100644 src/avr/ao_usb_avr.c (limited to 'src') diff --git a/src/avr-demo/Makefile b/src/avr-demo/Makefile index ea356654..93295166 100644 --- a/src/avr-demo/Makefile +++ b/src/avr-demo/Makefile @@ -2,7 +2,7 @@ # AltOS build # # -vpath % ..:../core:../product:../driver +vpath % ..:../core:../product:../drivers:../avr vpath make-altitude .. vpath make-kalman .. vpath kalman.5c ../kalman @@ -38,12 +38,15 @@ ALTOS_SRC = \ ao_mutex.c \ ao_panic.c \ ao_product.c \ + ao_romconfig.c \ ao_serial_avr.c \ ao_avr_stdio.c \ ao_stdio.c \ ao_task.c \ ao_timer.c \ - ao_led.c + ao_led.c \ + ao_usb_avr.c \ + ao_lcd.c PRODUCT=AvrDemo-v0.0 MCU=atmega32u4 diff --git a/src/avr-demo/ao_demo.c b/src/avr-demo/ao_demo.c new file mode 100644 index 00000000..756dd0d4 --- /dev/null +++ b/src/avr-demo/ao_demo.c @@ -0,0 +1,52 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +struct ao_task demo_task; + +void +ao_demo(void) +{ + for (;;) { + ao_led_toggle(AO_LED_RED); + printf ("hello %d\n", ao_time()); + ao_delay(AO_MS_TO_TICKS(200)); + } +} + +int +main(void) +{ + ao_clock_init(); + + ao_serial_init(); + + ao_led_init(LEDS_AVAILABLE); + ao_avr_stdio_init(); + printf ("stdio initialized\n"); +// ao_debug_init(); + ao_timer_init(); + ao_cmd_init(); + ao_usb_init(); + ao_lcd_init(); + +// ao_add_task(&demo_task, ao_demo, "demo"); + /* Turn on the LED until the system is stable */ + ao_start_scheduler(); + return 0; +} diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index 51a65880..0ed97361 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -18,8 +18,10 @@ #ifndef _AO_ARCH_H_ #define _AO_ARCH_H_ +#include #include #include +#include #ifdef AVR_DEMO #define TEENSY 1 @@ -48,6 +50,7 @@ #define __reentrant #define __critical #define __interrupt(n) +#define __at(n) #define ao_arch_reboot() /* XXX */ @@ -62,8 +65,18 @@ extern void putchar(char c); extern char getchar(void); +extern void ao_avr_stdio_init(void); -extern int ao_serial_number; +extern const uint16_t ao_serial_number; + +#define AVR_PUSH8(stack, val) (*((stack)--) = (val)) + +extern uint8_t ao_cpu_sleep_disable; + +#define ao_arch_task_globals uint8_t ao_cpu_sleep_disable; + +#define ao_arch_task_members\ + uint8_t *sp; /* saved stack pointer */ #define ao_arch_init_stack(task, start) do { \ uint8_t *sp = task->stack + AO_STACK_SIZE - 1; \ @@ -71,29 +84,66 @@ extern int ao_serial_number; int i; \ \ /* Return address */ \ - PUSH8(sp, a); \ - PUSH8(sp, (a >> 8)); \ + AVR_PUSH8(sp, a); \ + AVR_PUSH8(sp, (a >> 8)); \ \ /* Clear register values */ \ i = 32; \ while (i--) \ - PUSH8(sp, 0); \ + AVR_PUSH8(sp, 0); \ \ /* SREG with interrupts enabled */ \ - PUSH8(sp, 0x80); \ + AVR_PUSH8(sp, 0x80); \ task->sp = sp; \ } while (0); -#define ao_arch_save_context() do { \ - asm("push r31" "\n\t" "push r30"); \ - asm("push r29" "\n\t" "push r28" "\n\t" "push r27" "\n\t" "push r26" "\n\t" "push r25"); \ - asm("push r24" "\n\t" "push r23" "\n\t" "push r22" "\n\t" "push r21" "\n\t" "push r20"); \ - asm("push r19" "\n\t" "push r18" "\n\t" "push r17" "\n\t" "push r16" "\n\t" "push r15"); \ - asm("push r14" "\n\t" "push r13" "\n\t" "push r12" "\n\t" "push r11" "\n\t" "push r10"); \ - asm("push r9" "\n\t" "push r8" "\n\t" "push r7" "\n\t" "push r6" "\n\t" "push r5"); \ - asm("push r4" "\n\t" "push r3" "\n\t" "push r2" "\n\t" "push r1" "\n\t" "push r0"); \ - asm("in r0, __SREG__" "\n\t" "push r0"); \ - sei(); \ +#define ao_arch_save_regs() do { \ + asm("push r31" "\n\t" "push r30"); \ + asm("push r29" "\n\t" "push r28" "\n\t" "push r27" "\n\t" "push r26" "\n\t" "push r25"); \ + asm("push r24" "\n\t" "push r23" "\n\t" "push r22" "\n\t" "push r21" "\n\t" "push r20"); \ + asm("push r19" "\n\t" "push r18" "\n\t" "push r17" "\n\t" "push r16" "\n\t" "push r15"); \ + asm("push r14" "\n\t" "push r13" "\n\t" "push r12" "\n\t" "push r11" "\n\t" "push r10"); \ + asm("push r9" "\n\t" "push r8" "\n\t" "push r7" "\n\t" "push r6" "\n\t" "push r5"); \ + asm("push r4" "\n\t" "push r3" "\n\t" "push r2" "\n\t" "push r1" "\n\t" "push r0"); \ + cli(); \ + asm("in r0, __SREG__" "\n\t" "push r0"); \ + sei(); \ + } while (0) + +#define ao_arch_save_stack() do { \ + uint8_t sp_l, sp_h; \ + asm("in %0,__SP_L__" : "=&r" (sp_l) ); \ + asm("in %0,__SP_H__" : "=&r" (sp_h) ); \ + ao_cur_task->sp = (uint8_t *) ((uint16_t) sp_l | ((uint16_t) sp_h << 8)); \ } while (0) +#define ao_arch_isr_stack() /* nothing */ + +#define ao_arch_cpu_idle() do { \ + if (!ao_cpu_sleep_disable) \ + sleep_cpu(); \ + } while (0) + +#define ao_arch_restore_stack() do { \ + uint8_t sp_l, sp_h; \ + sp_l = (uint16_t) ao_cur_task->sp; \ + sp_h = ((uint16_t) ao_cur_task->sp) >> 8; \ + cli(); \ + asm("out __SP_H__,%0" : : "r" (sp_h) ); \ + asm("out __SP_L__,%0" : : "r" (sp_l) ); \ + asm("pop r0" "\n\t" \ + "out __SREG__, r0"); \ + asm("pop r0" "\n\t" "pop r1" "\n\t" "pop r2" "\n\t" "pop r3" "\n\t" "pop r4"); \ + asm("pop r5" "\n\t" "pop r6" "\n\t" "pop r7" "\n\t" "pop r8" "\n\t" "pop r9"); \ + asm("pop r10" "\n\t" "pop r11" "\n\t" "pop r12" "\n\t" "pop r13" "\n\t" "pop r14"); \ + asm("pop r15" "\n\t" "pop r16" "\n\t" "pop r17" "\n\t" "pop r18" "\n\t" "pop r19"); \ + asm("pop r20" "\n\t" "pop r21" "\n\t" "pop r22" "\n\t" "pop r23" "\n\t" "pop r24"); \ + asm("pop r25" "\n\t" "pop r26" "\n\t" "pop r27" "\n\t" "pop r28" "\n\t" "pop r29"); \ + asm("pop r30" "\n\t" "pop r31"); \ + asm("ret"); \ + } while(0) + +#define ao_arch_critical(b) do { cli(); b; sei(); } while (0) + #endif /* _AO_ARCH_H_ */ + diff --git a/src/avr/ao_avr_stdio.c b/src/avr/ao_avr_stdio.c index 2f358eb5..ba562dbf 100644 --- a/src/avr/ao_avr_stdio.c +++ b/src/avr/ao_avr_stdio.c @@ -44,7 +44,7 @@ static FILE mystdout = FDEV_SETUP_STREAM(stdio_put, NULL, _FDEV_SETUP_WRITE); static FILE mystdin = FDEV_SETUP_STREAM(NULL, stdio_get, _FDEV_SETUP_READ); void -ao_stdio_init(void) +ao_avr_stdio_init(void) { stdout = &mystdout; stdin = &mystdin; diff --git a/src/avr/ao_debug_avr.c b/src/avr/ao_debug_avr.c new file mode 100644 index 00000000..2e41e15a --- /dev/null +++ b/src/avr/ao_debug_avr.c @@ -0,0 +1,78 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +void +uart_send(char c) +{ + loop_until_bit_is_set(UCSR1A, UDRE1); + UDR1 = c; +} + +int +uart_put(char c, FILE *stream) +{ + if (c == '\n') + uart_send('\r'); + uart_send(c); + return 0; +} + +int +uart_get(FILE *stream) +{ + loop_until_bit_is_set(UCSR1A, RXC1); + return (int) UDR1 & 0xff; +} + +void +uart_init(uint16_t baud) +{ + PRR1 &= ~(1 << PRUSART1); + UBRR1L = baud; + UBRR1H = baud >> 8; + UCSR1A = 0; + UCSR1B = ((1 << RXEN1) | /* Enable receiver */ + (1 << TXEN1)); /* Enable transmitter */ + UCSR1C = ((0 << UMSEL10) | /* Asynchronous mode */ + (0 << UPM10) | /* No parity */ + (0 << USBS1) | /* 1 stop bit */ + (3 << UCSZ10) | /* 8 bit characters */ + (0 << UCPOL1)); /* MBZ for async mode */ +} + +static FILE mystdout = FDEV_SETUP_STREAM(uart_put, NULL, _FDEV_SETUP_WRITE); + +static FILE mystdin = FDEV_SETUP_STREAM(NULL, uart_get, _FDEV_SETUP_READ); + +void ao_debug_init(void) +{ + uart_init(F_CPU / (16UL * 9600UL) - 1); + + stdout = &mystdout; + stdin = &mystdin; + + if (DDRB & AO_LED_RED) { + printf ("oops, starting all over\n"); + for (;;) + ; + } + DDRB |= (1 << 7); + PORTB |= (1 << 7); + printf ("debug initialized\n"); +} diff --git a/src/avr/ao_led.c b/src/avr/ao_led.c new file mode 100644 index 00000000..91dfb85e --- /dev/null +++ b/src/avr/ao_led.c @@ -0,0 +1,67 @@ +/* + * 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" + +__pdata uint8_t ao_led_enable; + +#define LED_PORT PORTB +#define LED_DDR DDRB + +void +ao_led_on(uint8_t colors) +{ + LED_PORT |= (colors & ao_led_enable); +} + +void +ao_led_off(uint8_t colors) +{ + LED_PORT &= ~(colors & ao_led_enable); +} + +void +ao_led_set(uint8_t colors) +{ + LED_PORT = (LED_PORT & ~(ao_led_enable)) | (colors & ao_led_enable); +} + +void +ao_led_toggle(uint8_t colors) +{ + LED_PORT ^= (colors & ao_led_enable); +} + +void +ao_led_for(uint8_t colors, uint16_t ticks) __reentrant +{ + ao_led_on(colors); + ao_delay(ticks); + ao_led_off(colors); +} + +void +ao_led_init(uint8_t enable) +{ + ao_led_enable = enable; + if ((LED_DDR & enable)) { + printf ("oops! restarted\n"); + ao_panic(AO_PANIC_REBOOT); + } + LED_PORT &= ~enable; + LED_DDR |= enable; +} diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index ef41b59c..56435f18 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -22,10 +22,36 @@ #define AO_LED_RED (1<<7) #define LEDS_AVAILABLE (AO_LED_RED) #define USE_SERIAL_STDIN 1 - #define HAS_USB 0 + #define HAS_USB 1 #define PACKET_HAS_SLAVE 0 #define HAS_SERIAL_1 1 + #define TEENSY 1 + #define AVR_VCC_5V 1 + #define AVR_VCC_3V3 0 + #define AVR_CLOCK 16000000UL #define HAS_BEEP 0 #endif +#ifdef TELESCIENCE + #define LEDS_AVAILABLE 0 + #define HAS_USB 1 + #define HAS_LOG 1 + #define TEENSY 0 + #define USE_SERIAL_STDIN 1 + #define HAS_SERIAL_1 1 + #define HAS_USB 1 + #define HAS_ADC 1 + #define PACKET_HAS_SLAVE 0 + #define HAS_BEEP 0 + + #define AVR_VCC_5V 0 + #define AVR_VCC_3V3 1 + #define AVR_CLOCK 8000000UL + + #define SPI_CS_PORT PORTE + #define SPI_CS_DIR DDRE + #define M25_CS_MASK (1 << PORTE6) + #define M25_MAX_CHIPS 1 +#endif + #endif /* _AO_PINS_H_ */ diff --git a/src/avr/ao_romconfig.c b/src/avr/ao_romconfig.c new file mode 100644 index 00000000..bbb677e2 --- /dev/null +++ b/src/avr/ao_romconfig.c @@ -0,0 +1,20 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +const uint16_t ao_serial_number = 0; diff --git a/src/avr/ao_serial_avr.c b/src/avr/ao_serial_avr.c new file mode 100644 index 00000000..2fe39755 --- /dev/null +++ b/src/avr/ao_serial_avr.c @@ -0,0 +1,166 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +__xdata struct ao_fifo ao_usart1_rx_fifo; +__xdata struct ao_fifo ao_usart1_tx_fifo; + +void +ao_debug_out(char c) +{ + if (c == '\n') + ao_debug_out('\r'); + loop_until_bit_is_set(UCSR1A, UDRE1); + UDR1 = c; +} + +ISR(USART1_RX_vect) +{ + if (!ao_fifo_full(ao_usart1_rx_fifo)) + ao_fifo_insert(ao_usart1_rx_fifo, UDR1); + ao_wakeup(&ao_usart1_rx_fifo); +#if USE_SERIAL_STDIN + ao_wakeup(&ao_stdin_ready); +#endif +} + +static __xdata uint8_t ao_serial_tx1_started; + +static void +ao_serial_tx1_start(void) +{ + if (!ao_fifo_empty(ao_usart1_tx_fifo) && + !ao_serial_tx1_started) + { + ao_serial_tx1_started = 1; + ao_fifo_remove(ao_usart1_tx_fifo, UDR1); + } +} + +ISR(USART1_UDRE_vect) +{ + ao_serial_tx1_started = 0; + ao_serial_tx1_start(); + ao_wakeup(&ao_usart1_tx_fifo); +} + +char +ao_serial_getchar(void) __critical +{ + char c; + cli(); + while (ao_fifo_empty(ao_usart1_rx_fifo)) + ao_sleep(&ao_usart1_rx_fifo); + ao_fifo_remove(ao_usart1_rx_fifo, c); + sei(); + return c; +} + +#if USE_SERIAL_STDIN +char +ao_serial_pollchar(void) __critical +{ + char c; + cli(); + if (ao_fifo_empty(ao_usart1_rx_fifo)) { + sei(); + return AO_READ_AGAIN; + } + ao_fifo_remove(ao_usart1_rx_fifo,c); + sei(); + return c; +} +#endif + +void +ao_serial_putchar(char c) __critical +{ + cli(); + while (ao_fifo_full(ao_usart1_tx_fifo)) + ao_sleep(&ao_usart1_tx_fifo); + ao_fifo_insert(ao_usart1_tx_fifo, c); + ao_serial_tx1_start(); + sei(); +} + +void +ao_serial_drain(void) __critical +{ + cli(); + while (!ao_fifo_empty(ao_usart1_tx_fifo)) + ao_sleep(&ao_usart1_tx_fifo); + sei(); +} + +static const struct { + uint16_t ubrr; +} ao_serial_speeds[] = { + /* [AO_SERIAL_SPEED_4800] = */ { + F_CPU / (16UL * 4800UL) - 1 + }, + /* [AO_SERIAL_SPEED_9600] = */ { + F_CPU / (16UL * 9600UL) - 1 + }, + /* [AO_SERIAL_SPEED_19200] = */ { + F_CPU / (16UL * 19200UL) - 1 + }, + /* [AO_SERIAL_SPEED_57600] = */ { + F_CPU / (16UL * 57600UL) - 1 + }, +}; + +void +ao_serial_set_speed(uint8_t speed) +{ + ao_serial_drain(); + if (speed > AO_SERIAL_SPEED_57600) + return; + UBRR1L = ao_serial_speeds[speed].ubrr; + UBRR1H = ao_serial_speeds[speed].ubrr >> 8; +} + +void +ao_serial_init(void) +{ + /* Ensure the uart is powered up */ + + PRR1 &= ~(1 << PRUSART1); + + /* Pick a 9600 baud rate */ + ao_serial_set_speed(AO_SERIAL_SPEED_9600); + + UCSR1A = 0; + UCSR1C = ((0 << UMSEL10) | /* Asynchronous mode */ + (0 << UPM10) | /* No parity */ + (0 << USBS1) | /* 1 stop bit */ + (3 << UCSZ10) | /* 8 bit characters */ + (0 << UCPOL1)); /* MBZ for async mode */ + UCSR1B = ((1 << RXEN1) | /* Enable receiver */ + (1 << TXEN1) | /* Enable transmitter */ + (1 << RXCIE1) | /* Enable receive interrupts */ + (1 << UDRIE1)); /* Enable transmit empty interrupts */ +#if 0 +#if USE_SERIAL_STDIN + int8_t i; + i = ao_add_stdio(ao_serial_pollchar, + ao_serial_putchar, + NULL); + printf("Register serial stdio as %d\n", i); +#endif +#endif +} diff --git a/src/avr/ao_timer.c b/src/avr/ao_timer.c new file mode 100644 index 00000000..1e374c75 --- /dev/null +++ b/src/avr/ao_timer.c @@ -0,0 +1,147 @@ +/* + * 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" + +static volatile __data uint16_t ao_tick_count; + +uint16_t ao_time(void) +{ + uint16_t v; + ao_arch_critical( + v = ao_tick_count; + ); + return v; +} + +static __xdata uint8_t ao_forever; + +void +ao_delay(uint16_t ticks) +{ + ao_alarm(ticks); + ao_sleep(&ao_forever); +} + +#define T1_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ +#define T1_SAMPLE_TIME 30000 /* 3e6/30000 = 100 */ + +#if HAS_ADC +volatile __data uint8_t ao_adc_interval = 1; +volatile __data uint8_t ao_adc_count; +#endif + +void +ao_debug_out(char c); + +ISR(TIMER1_COMPA_vect) +{ + ++ao_tick_count; +#if HAS_ADC + if (++ao_adc_count == ao_adc_interval) { + ao_adc_count = 0; + ao_adc_poll(); + } +#endif +} + +#if HAS_ADC +void +ao_timer_set_adc_interval(uint8_t interval) __critical +{ + ao_adc_interval = interval; + ao_adc_count = 0; +} +#endif + +void +ao_timer_init(void) +{ + TCCR1A = ((0 << WGM11) | /* CTC mode, OCR1A */ + (0 << WGM10)); /* CTC mode, OCR1A */ + TCCR1B = ((0 << ICNC1) | /* no input capture noise canceler */ + (0 << ICES1) | /* input capture on falling edge (don't care) */ + (0 << WGM13) | /* CTC mode, OCR1A */ + (1 << WGM12) | /* CTC mode, OCR1A */ + (3 << CS10)); /* clk/64 from prescaler */ + +#if TEENSY + OCR1A = 2500; /* 16MHz clock */ +#else + OCR1A = 1250; /* 8MHz clock */ +#endif + + TIMSK1 = (1 << OCIE1A); /* Interrupt on compare match */ +} + +/* + * AltOS always cranks the clock to the max frequency + */ +void +ao_clock_init(void) +{ + /* disable RC clock */ + CLKSEL0 &= ~(1 << RCE); + + /* Disable PLL */ + PLLCSR &= ~(1 << PLLE); + + /* Enable external clock */ + CLKSEL0 |= (1 << EXTE); + + /* wait for external clock to be ready */ + while ((CLKSTA & (1 << EXTON)) == 0) + ; + + /* select external clock */ + CLKSEL0 |= (1 << CLKS); + + /* Disable the clock prescaler */ + cli(); + CLKPR = (1 << CLKPCE); + + /* Always run the system clock at 8MHz */ +#if AVR_CLOCK > 12000000UL + CLKPR = 1; +#else + CLKPR = 0; +#endif + sei(); + + /* Set up the PLL to use the crystal */ + + /* Use primary system clock as PLL source */ + PLLFRQ = ((0 << PINMUX) | /* Use primary clock */ + (0 << PLLUSB) | /* No divide by 2 for USB */ + (0 << PLLTM0) | /* Disable high speed timer */ + (0x4 << PDIV0)); /* 48MHz PLL clock */ + + /* Set the frequency of the crystal */ +#if AVR_CLOCK > 12000000UL + PLLCSR |= (1 << PINDIV); /* For 16MHz crystal on Teensy board */ +#else + PLLCSR &= ~(1 << PINDIV); /* For 8MHz crystal on TeleScience board */ +#endif + + /* Enable the PLL */ + PLLCSR |= (1 << PLLE); + while (!(PLLCSR & (1 << PLOCK))) + ; + + set_sleep_mode(SLEEP_MODE_IDLE); + sleep_enable(); +} diff --git a/src/avr/ao_usb.h b/src/avr/ao_usb.h new file mode 100644 index 00000000..6633dafc --- /dev/null +++ b/src/avr/ao_usb.h @@ -0,0 +1,100 @@ +/* + * 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. + */ + +#ifndef _AO_USB_H_ +#define _AO_USB_H_ + +#define AO_USB_SETUP_DIR_MASK (0x01 << 7) +#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) +#define AO_USB_SETUP_RECIP_MASK (0x1f) + +#define AO_USB_DIR_OUT 0 +#define AO_USB_DIR_IN (1 << 7) + +#define AO_USB_TYPE_STANDARD 0 +#define AO_USB_TYPE_CLASS (1 << 5) +#define AO_USB_TYPE_VENDOR (2 << 5) +#define AO_USB_TYPE_RESERVED (3 << 5) + +#define AO_USB_RECIP_DEVICE 0 +#define AO_USB_RECIP_INTERFACE 1 +#define AO_USB_RECIP_ENDPOINT 2 +#define AO_USB_RECIP_OTHER 3 + +/* standard requests */ +#define AO_USB_REQ_GET_STATUS 0x00 +#define AO_USB_REQ_CLEAR_FEATURE 0x01 +#define AO_USB_REQ_SET_FEATURE 0x03 +#define AO_USB_REQ_SET_ADDRESS 0x05 +#define AO_USB_REQ_GET_DESCRIPTOR 0x06 +#define AO_USB_REQ_SET_DESCRIPTOR 0x07 +#define AO_USB_REQ_GET_CONFIGURATION 0x08 +#define AO_USB_REQ_SET_CONFIGURATION 0x09 +#define AO_USB_REQ_GET_INTERFACE 0x0A +#define AO_USB_REQ_SET_INTERFACE 0x0B +#define AO_USB_REQ_SYNCH_FRAME 0x0C + +#define AO_USB_DESC_DEVICE 1 +#define AO_USB_DESC_CONFIGURATION 2 +#define AO_USB_DESC_STRING 3 +#define AO_USB_DESC_INTERFACE 4 +#define AO_USB_DESC_ENDPOINT 5 +#define AO_USB_DESC_DEVICE_QUALIFIER 6 +#define AO_USB_DESC_OTHER_SPEED 7 +#define AO_USB_DESC_INTERFACE_POWER 8 + +#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) +#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) + +#define AO_USB_CONTROL_EP 0 +#define AO_USB_INT_EP 1 +#define AO_USB_OUT_EP 4 +#define AO_USB_IN_EP 5 +#define AO_USB_CONTROL_SIZE 32 +/* + * Double buffer IN and OUT EPs, so each + * gets half of the available space + * + * Ah, but USB bulk packets can only come in 8, 16, 32 and 64 + * byte sizes, so we'll use 64 for everything + */ +#define AO_USB_IN_SIZE 64 +#define AO_USB_OUT_SIZE 64 + +#define AO_USB_EP0_IDLE 0 +#define AO_USB_EP0_DATA_IN 1 +#define AO_USB_EP0_DATA_OUT 2 + +#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) + +/* CDC definitions */ +#define CS_INTERFACE 0x24 +#define CS_ENDPOINT 0x25 + +#define SET_LINE_CODING 0x20 +#define GET_LINE_CODING 0x21 +#define SET_CONTROL_LINE_STATE 0x22 + +/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ +struct ao_usb_line_coding { + uint32_t rate; + uint8_t char_format; + uint8_t parity; + uint8_t data_bits; +} ; + +#endif /* _AO_USB_H_ */ diff --git a/src/avr/ao_usb_avr.c b/src/avr/ao_usb_avr.c new file mode 100644 index 00000000..74bdea23 --- /dev/null +++ b/src/avr/ao_usb_avr.c @@ -0,0 +1,688 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_usb.h" + +#define USB_DEBUG 0 + +#if USB_DEBUG +#define debug(format, args...) printf(format, ## args) +#else +#define debug(format, args...) +#endif + +struct ao_task __xdata ao_usb_task; + +struct ao_usb_setup { + uint8_t dir_type_recip; + uint8_t request; + uint16_t value; + uint16_t index; + uint16_t length; +} __xdata ao_usb_setup; + +static __xdata uint8_t ao_usb_ep0_state; +static const uint8_t * __xdata ao_usb_ep0_in_data; +static __xdata uint8_t ao_usb_ep0_in_len; +static __xdata uint8_t ao_usb_ep0_in_pending; +static __xdata uint8_t ao_usb_addr_pending; +static __xdata uint8_t ao_usb_ep0_in_buf[2]; +static __xdata uint8_t ao_usb_ep0_out_len; +static __xdata uint8_t *__xdata ao_usb_ep0_out_data; + +static __xdata uint8_t ao_usb_in_flushed; +static __xdata uint8_t ao_usb_running; +static __xdata uint8_t ao_usb_configuration; +static __xdata uint8_t ueienx_0; + +void +ao_usb_set_address(uint8_t address) +{ + UDADDR = (0 << ADDEN) | address; + ao_usb_addr_pending = 1; +} + +#define EP_SIZE(s) ((s) == 64 ? 0x30 : \ + ((s) == 32 ? 0x20 : \ + ((s) == 16 ? 0x10 : \ + 0x00))) + +static void +ao_usb_dump_ep(uint8_t ep) +{ + UENUM = ep; + debug ("EP %d: UECONX %02x UECFG0X %02x UECFG1X %02x UEIENX %02x UESTA0X %02x UESTA1X %02X\n", + ep, UECONX, UECFG0X, UECFG1X, UEIENX, UESTA0X, UESTA1X); +} + +static void +ao_usb_set_ep0(void) +{ + debug ("set_ep0\n"); + /* Set the CONTROL max packet size, single buffered */ + UENUM = 0; + UECONX = (1 << EPEN); /* Enable */ + + UECFG0X = ((0 << EPTYPE0) | /* Control */ + (0 << EPDIR)); /* Out (ish) */ + + UECFG1X = (EP_SIZE(AO_USB_CONTROL_SIZE) | /* Size */ + (0 << EPBK0) | /* Single bank */ + (1 << ALLOC)); + + ueienx_0 = ((1 << RXSTPE) | /* Enable SETUP interrupt */ + (1 << RXOUTE)); /* Enable OUT interrupt */ + +// ao_usb_dump_ep(0); + ao_usb_addr_pending = 0; +} + +static void +ao_usb_set_configuration(void) +{ + /* Set the IN max packet size, double buffered */ + UENUM = AO_USB_IN_EP; + UECONX = (1 << EPEN); /* Enable */ + + UECFG0X = ((2 << EPTYPE0) | /* Bulk */ + (1 << EPDIR)); /* In */ + + UECFG1X = (EP_SIZE(AO_USB_IN_SIZE) | /* Size */ + (1 << EPBK0) | /* Double bank */ + (1 << ALLOC)); /* Allocate */ + +#if 0 + UEIENX = ((1 << TXINE)); /* Enable IN complete interrupt */ +#endif + + ao_usb_dump_ep(AO_USB_IN_EP); + + /* Set the OUT max packet size, double buffered */ + UENUM = AO_USB_OUT_EP; + UECONX |= (1 << EPEN); /* Enable */ + + UECFG0X = ((2 << EPTYPE0) | /* Bulk */ + (0 << EPDIR)); /* Out */ + + UECFG1X = (EP_SIZE(AO_USB_OUT_SIZE) | /* Size */ + (1 << EPBK0) | /* Double bank */ + (1 << ALLOC)); /* Allocate */ + + UEIENX = ((1 << RXOUTE)); /* Enable OUT complete interrupt */ + + ao_usb_dump_ep(AO_USB_OUT_EP); + ao_usb_running = 1; +} + +ISR(USB_GEN_vect) +{ + ao_wakeup(&ao_usb_task); +} + + +__xdata static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; + +/* Walk through the list of descriptors and find a match + */ +static void +ao_usb_get_descriptor(uint16_t value) +{ + const uint8_t *__xdata descriptor; + __xdata uint8_t type = value >> 8; + __xdata uint8_t index = value; + + descriptor = ao_usb_descriptors; + while (descriptor[0] != 0) { + if (descriptor[1] == type && index-- == 0) { + if (type == AO_USB_DESC_CONFIGURATION) + ao_usb_ep0_in_len = descriptor[2]; + else + ao_usb_ep0_in_len = descriptor[0]; + ao_usb_ep0_in_data = descriptor; + break; + } + descriptor += descriptor[0]; + } +} + +static void +ao_usb_ep0_set_in_pending(uint8_t in_pending) +{ + ao_usb_ep0_in_pending = in_pending; + + if (in_pending) + ueienx_0 = ((1 << RXSTPE) | (1 << RXOUTE) | (1 << TXINE)); /* Enable IN interrupt */ +} + +/* Send an IN data packet */ +static void +ao_usb_ep0_flush(void) +{ + __xdata uint8_t this_len; + + cli(); + UENUM = 0; + if (!(UEINTX & (1 << TXINI))) { + debug("EP0 not accepting IN data\n"); + ao_usb_ep0_set_in_pending(1); + } else { + this_len = ao_usb_ep0_in_len; + if (this_len > AO_USB_CONTROL_SIZE) + this_len = AO_USB_CONTROL_SIZE; + + ao_usb_ep0_in_len -= this_len; + + /* Set IN interrupt enable */ + if (ao_usb_ep0_in_len == 0 && this_len != AO_USB_CONTROL_SIZE) + ao_usb_ep0_set_in_pending(0); + else + ao_usb_ep0_set_in_pending(1); + + debug ("Flush EP0 len %d:", this_len); + while (this_len--) { + uint8_t c = *ao_usb_ep0_in_data++; + debug(" %02x", c); + UEDATX = c; + } + debug ("\n"); + + /* Clear the TXINI bit to send the packet */ + UEINTX &= ~(1 << TXINI); + } + sei(); +} + +/* Read data from the ep0 OUT fifo */ +static void +ao_usb_ep0_fill(uint8_t len, uint8_t ack) +{ + if (len > ao_usb_ep0_out_len) + len = ao_usb_ep0_out_len; + ao_usb_ep0_out_len -= len; + +// debug ("EP0 UEINTX %02x UEBCLX %d UEBCHX %d\n", +// UEINTX, UEBCLX, UEBCHX); + /* Pull all of the data out of the packet */ + debug ("Fill EP0 len %d:", len); + UENUM = 0; + while (len--) { + uint8_t c = UEDATX; + *ao_usb_ep0_out_data++ = c; + debug (" %02x", c); + } + debug ("\n"); + + /* ACK the packet */ + UEINTX &= ~ack; +} + +void +ao_usb_ep0_queue_byte(uint8_t a) +{ + ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a; +} + +static void +ao_usb_ep0_setup(void) +{ + /* Pull the setup packet out of the fifo */ + ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_setup; + ao_usb_ep0_out_len = 8; + ao_usb_ep0_fill(8, (1 << RXSTPI) | (1 << RXOUTI) | (1 << TXINI)); + if (ao_usb_ep0_out_len != 0) { + debug ("invalid setup packet length\n"); + return; + } + + /* Figure out how to ACK the setup packet */ + if (ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) { + if (ao_usb_setup.length) + ao_usb_ep0_state = AO_USB_EP0_DATA_IN; + else + ao_usb_ep0_state = AO_USB_EP0_IDLE; + } else { + if (ao_usb_setup.length) + ao_usb_ep0_state = AO_USB_EP0_DATA_OUT; + else + ao_usb_ep0_state = AO_USB_EP0_IDLE; + } +/* + UENUM = 0; + if (ao_usb_ep0_state == AO_USB_EP0_IDLE) + USBCS0 = USBCS0_CLR_OUTPKT_RDY | USBCS0_DATA_END; + else + USBCS0 = USBCS0_CLR_OUTPKT_RDY; +*/ + + ao_usb_ep0_in_data = ao_usb_ep0_in_buf; + ao_usb_ep0_in_len = 0; + switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_TYPE_MASK) { + case AO_USB_TYPE_STANDARD: + debug ("Standard setup packet\n"); + switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_RECIP_MASK) { + case AO_USB_RECIP_DEVICE: + debug ("Device setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + debug ("get status\n"); + ao_usb_ep0_queue_byte(0); + ao_usb_ep0_queue_byte(0); + break; + case AO_USB_REQ_SET_ADDRESS: + debug ("set address %d\n", ao_usb_setup.value); + ao_usb_set_address(ao_usb_setup.value); + break; + case AO_USB_REQ_GET_DESCRIPTOR: + debug ("get descriptor %d\n", ao_usb_setup.value); + ao_usb_get_descriptor(ao_usb_setup.value); + break; + case AO_USB_REQ_GET_CONFIGURATION: + debug ("get configuration %d\n", ao_usb_configuration); + ao_usb_ep0_queue_byte(ao_usb_configuration); + break; + case AO_USB_REQ_SET_CONFIGURATION: + ao_usb_configuration = ao_usb_setup.value; + debug ("set configuration %d\n", ao_usb_configuration); + ao_usb_set_configuration(); + break; + } + break; + case AO_USB_RECIP_INTERFACE: +#ifndef AVR + #pragma disable_warning 110 +#endif + debug ("Interface setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + ao_usb_ep0_queue_byte(0); + ao_usb_ep0_queue_byte(0); + break; + case AO_USB_REQ_GET_INTERFACE: + ao_usb_ep0_queue_byte(0); + break; + case AO_USB_REQ_SET_INTERFACE: + break; + } + break; + case AO_USB_RECIP_ENDPOINT: + debug ("Endpoint setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + ao_usb_ep0_queue_byte(0); + ao_usb_ep0_queue_byte(0); + break; + } + break; + } + break; + case AO_USB_TYPE_CLASS: + debug ("Class setup packet\n"); + switch (ao_usb_setup.request) { + case SET_LINE_CODING: + debug ("set line coding\n"); + ao_usb_ep0_out_len = 7; + ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_line_coding; + break; + case GET_LINE_CODING: + debug ("get line coding\n"); + ao_usb_ep0_in_len = 7; + ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding; + break; + case SET_CONTROL_LINE_STATE: + break; + } + break; + } + if (ao_usb_ep0_state != AO_USB_EP0_DATA_OUT) { + if (ao_usb_setup.length < ao_usb_ep0_in_len) + ao_usb_ep0_in_len = ao_usb_setup.length; + debug ("Start ep0 in delivery %d\n", ao_usb_ep0_in_len); + ao_usb_ep0_set_in_pending(1); + } +} + +/* End point 0 receives all of the control messages. */ +static void +ao_usb_ep0(void) +{ + uint8_t intx, udint; + + debug ("usb task started\n"); + ao_usb_ep0_state = AO_USB_EP0_IDLE; + for (;;) { + cli(); + for (;;) { + udint = UDINT; + UDINT = 0; +// debug ("UDINT %02x\n", udint); + if (udint & (1 << EORSTI)) { + ao_usb_configuration = 0; + ao_usb_set_ep0(); + } + UENUM = 0; + intx = UEINTX; +// debug ("UEINTX %02x\n", intx); + if (intx & ((1 << RXSTPI) | (1 << RXOUTI))) + break; + if ((intx & (1 << TXINI))) { + if (ao_usb_ep0_in_pending) + break; + else + { + if (ao_usb_addr_pending) { + UDADDR |= (1 << ADDEN); + ao_usb_addr_pending = 0; + } + ueienx_0 = ((1 << RXSTPE) | (1 << RXOUTE)); /* Disable IN interrupt */ + } + } +// debug ("usb task sleeping...\n"); + UENUM = 0; + UEIENX = ueienx_0; + ao_sleep(&ao_usb_task); + } + sei(); +// debug ("UEINTX for ep0 is %02x\n", intx); + if (intx & (1 << RXSTPI)) { + ao_usb_ep0_setup(); + } + if (intx & (1 << RXOUTI)) { + ao_usb_ep0_fill(UEBCLX, (1 << RXOUTI)); + ao_usb_ep0_set_in_pending(1); + } + if (intx & (1 << TXINI) && ao_usb_ep0_in_pending) { + debug ("continue sending ep0 IN data\n"); + ao_usb_ep0_flush(); + } + } +} + +/* Wait for a free IN buffer */ +static void +ao_usb_in_wait(void) +{ + for (;;) { + /* Check if the current buffer is writable */ + UENUM = AO_USB_IN_EP; + if (UEINTX & (1 << RWAL)) + break; + + cli(); + /* Wait for an IN buffer to be ready */ + for (;;) { + UENUM = AO_USB_IN_EP; + if ((UEINTX & (1 << TXINI))) + break; + UEIENX = (1 << TXINE); + ao_sleep(&ao_usb_in_flushed); + } + /* Ack the interrupt */ + UEINTX &= ~(1 << TXINI); + sei(); + } +} + +/* Queue the current IN buffer for transmission */ +static void +ao_usb_in_send(void) +{ + UENUM = AO_USB_IN_EP; + UEINTX &= ~(1 << FIFOCON); +} + +void +ao_usb_flush(void) __critical +{ + if (!ao_usb_running) + return; + + /* Anytime we've sent a character since + * the last time we flushed, we'll need + * to send a packet -- the only other time + * we would send a packet is when that + * packet was full, in which case we now + * want to send an empty packet + */ + if (!ao_usb_in_flushed) { + ao_usb_in_flushed = 1; + ao_usb_in_wait(); + ao_usb_in_send(); + } +} + +void +ao_usb_putchar(char c) __critical __reentrant +{ + if (!ao_usb_running) + return; + + ao_usb_in_wait(); + + /* Queue a byte */ + UENUM = AO_USB_IN_EP; + UEDATX = c; + + /* Send the packet when full */ + if ((UEINTX & (1 << RWAL)) == 0) + ao_usb_in_send(); + ao_usb_in_flushed = 0; +} + +static char +_ao_usb_pollchar(void) +{ + char c; + uint8_t intx; + + if (!ao_usb_running) + return AO_READ_AGAIN; + + for (;;) { + UENUM = AO_USB_OUT_EP; + intx = UEINTX; + debug("usb_pollchar UEINTX %02d\n", intx); + if (intx & (1 << RWAL)) + break; + + if (intx & (1 << FIFOCON)) { + /* Ack the last packet */ + UEINTX = (uint8_t) ~(1 << FIFOCON); + } + + /* Check to see if a packet has arrived */ + if ((intx & (1 << RXOUTI)) == 0) { + UENUM = AO_USB_OUT_EP; + UEIENX = (1 << RXOUTE); + return AO_READ_AGAIN; + } + + /* Ack the interrupt */ + UEINTX = ~(1 << RXOUTI); + } + + /* Pull a character out of the fifo */ + c = UEDATX; + return c; +} + +char +ao_usb_pollchar(void) +{ + char c; + cli(); + c = _ao_usb_pollchar(); + sei(); + return c; +} + +char +ao_usb_getchar(void) __critical +{ + char c; + + cli(); + while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) + ao_sleep(&ao_stdin_ready); + sei(); + return c; +} + +uint16_t control_count; +uint16_t in_count; +uint16_t out_count; + +/* Endpoint interrupt */ +ISR(USB_COM_vect) +{ + uint8_t old_num = UENUM; + uint8_t i = UEINT; + +#ifdef AO_LED_RED + ao_led_toggle(AO_LED_RED); +#endif + UEINT = 0; + if (i & (1 << 0)) { + UENUM = 0; + UEIENX = 0; + ao_wakeup(&ao_usb_task); + ++control_count; + } + if (i & (1 << AO_USB_IN_EP)) { + UENUM = AO_USB_IN_EP; + UEIENX = 0; + ao_wakeup(&ao_usb_in_flushed); + in_count++; + } + if (i & (1 << AO_USB_OUT_EP)) { + UENUM = AO_USB_OUT_EP; + UEIENX = 0; + ao_wakeup(&ao_stdin_ready); + ++out_count; + } + UENUM = old_num; +} + +#if AVR_VCC_5V +#define AO_PAD_REGULATOR_INIT (1 << UVREGE) /* Turn on pad regulator */ +#endif +#if AVR_VCC_3V3 +/* TeleScience V0.1 has a hardware bug -- UVcc is hooked up, but UCap is not + * Make this work by running power through UVcc to the USB system + */ +#define AO_PAD_REGULATOR_INIT (1 << UVREGE) /* Turn off pad regulator */ +#endif + +#if AVR_CLOCK == 16000000UL +#define AO_USB_PLL_INPUT_PRESCALER (1 << PINDIV) /* Divide 16MHz clock by 2 */ +#endif +#if AVR_CLOCK == 8000000UL +#define AO_USB_PLL_INPUT_PRESCALER 0 /* Don't divide clock */ +#endif + +void +ao_usb_disable(void) +{ + /* Unplug from the bus */ + UDCON = (1 << DETACH); + + /* Disable the interface */ + USBCON = 0; + + /* Disable the PLL */ + PLLCSR = 0; + + /* Turn off the pad regulator */ + UHWCON = 0; +} + +#define AO_USB_CON ((1 << USBE) | /* USB enable */ \ + (0 << RSTCPU) | /* do not reset CPU */ \ + (0 << LSM) | /* Full speed mode */ \ + (0 << RMWKUP)) /* no remote wake-up */ \ + +void +ao_usb_enable(void) +{ + /* Configure pad regulator */ + UHWCON = AO_PAD_REGULATOR_INIT; + + /* Enable USB device, but freeze the clocks until initialized */ + USBCON = AO_USB_CON | (1 <stack_count = stack_len; \ + stack_ptr = (uint8_t __data *) AO_STACK_START; \ + save_ptr = (uint8_t __xdata *) ao_cur_task->stack; \ + do \ + *save_ptr++ = *stack_ptr++; \ + while (--stack_len); \ + } +#define ao_arch_isr_stack() \ + /* Empty the stack; might as well let interrupts have the whole thing */ \ + (SP = AO_STACK_START - 1) + +#define ao_arch_cpu_idle() (PCON = PCON_IDLE) + +#define ao_arch_restore_stack() { \ + uint8_t stack_len; \ + __data uint8_t *stack_ptr; \ + __xdata uint8_t *save_ptr; \ + \ + /* Restore the old stack */ \ + stack_len = ao_cur_task->stack_count; \ + SP = AO_STACK_START - 1 + stack_len; \ + \ + stack_ptr = (uint8_t __data *) AO_STACK_START; \ + save_ptr = (uint8_t __xdata *) ao_cur_task->stack; \ + do \ + *stack_ptr++ = *save_ptr++; \ + while (--stack_len); \ + \ + _asm \ + pop _bp \ + pop PSW \ + pop ar1 \ + pop ar0 \ + pop ar7 \ + pop ar6 \ + pop ar5 \ + pop ar4 \ + pop ar3 \ + pop ar2 \ + pop b \ + pop DPH \ + pop DPL \ + /* The next byte of the stack is the IE register. Only the global \ + enable bit forms part of the task context. Pop off the IE then set \ + the global enable bit to match that of the stored IE register. */ \ + pop ACC \ + JB ACC.7,0098$ \ + CLR _EA \ + LJMP 0099$ \ + 0098$: \ + SETB _EA \ + 0099$: \ + /* Finally pop off the ACC, which was the first register saved. */ \ + pop ACC \ + ret \ + _endasm; \ +} + +#define ao_arch_critical(b) __critical { b } #endif /* _AO_ARCH_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index 9b0bb545..98a01a4a 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -37,9 +37,9 @@ struct ao_task { __xdata void *wchan; /* current wait channel (NULL if running) */ uint16_t alarm; /* abort ao_sleep time */ - uint8_t stack_count; /* amount of saved stack */ uint8_t task_id; /* unique id */ __code char *name; /* task name */ + ao_arch_task_members /* any architecture-specific fields */ uint8_t stack[AO_STACK_SIZE]; /* saved stack */ }; @@ -321,6 +321,10 @@ ao_usb_disable(void); void ao_usb_init(void); +#if HAS_USB +extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; +#endif + /* * ao_cmd.c */ @@ -1571,4 +1575,9 @@ extern __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; void ao_companion_init(void); +/* ao_lcd.c */ + +void +ao_lcd_init(void); + #endif /* _AO_H_ */ diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c index cbfdf399..0668dad2 100644 --- a/src/core/ao_panic.c +++ b/src/core/ao_panic.c @@ -53,7 +53,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); diff --git a/src/core/ao_task.c b/src/core/ao_task.c index 41520476..32826114 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -24,6 +24,10 @@ __data uint8_t ao_num_tasks; __data uint8_t ao_cur_task_index; __xdata struct ao_task *__data ao_cur_task; +#ifdef ao_arch_task_globals +ao_arch_task_globals +#endif + void ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant { @@ -53,27 +57,16 @@ ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *nam void ao_yield(void) ao_arch_naked_define { - ao_arch_save_context(); + ao_arch_save_regs(); if (ao_cur_task_index == AO_NO_TASK_INDEX) ao_cur_task_index = ao_num_tasks-1; else { - uint8_t stack_len; - __data uint8_t *stack_ptr; - __xdata uint8_t *save_ptr; - /* Save the current stack */ - stack_len = SP - (AO_STACK_START - 1); - ao_cur_task->stack_count = stack_len; - stack_ptr = (uint8_t __data *) AO_STACK_START; - save_ptr = (uint8_t __xdata *) ao_cur_task->stack; - do - *save_ptr++ = *stack_ptr++; - while (--stack_len); + ao_arch_save_stack(); } - /* Empty the stack; might as well let interrupts have the whole thing */ - SP = AO_STACK_START - 1; + ao_arch_isr_stack(); /* Find a task to run. If there isn't any runnable task, * this loop will run forever, which is just fine @@ -99,63 +92,20 @@ ao_yield(void) ao_arch_naked_define } /* Enter lower power mode when there isn't anything to do */ - if (ao_next_task_index == ao_cur_task_index) - PCON = PCON_IDLE; + if (ao_next_task_index == ao_cur_task_index) { + ao_arch_cpu_idle(); + } } } - - { - uint8_t stack_len; - __data uint8_t *stack_ptr; - __xdata uint8_t *save_ptr; - - /* Restore the old stack */ - stack_len = ao_cur_task->stack_count; - SP = AO_STACK_START - 1 + stack_len; - - stack_ptr = (uint8_t __data *) AO_STACK_START; - save_ptr = (uint8_t __xdata *) ao_cur_task->stack; - do - *stack_ptr++ = *save_ptr++; - while (--stack_len); - } - - _asm - pop _bp - pop PSW - pop ar1 - pop ar0 - pop ar7 - pop ar6 - pop ar5 - pop ar4 - pop ar3 - pop ar2 - pop b - pop DPH - pop DPL - /* The next byte of the stack is the IE register. Only the global - enable bit forms part of the task context. Pop off the IE then set - the global enable bit to match that of the stored IE register. */ - pop ACC - JB ACC.7,0098$ - CLR _EA - LJMP 0099$ - 0098$: - SETB _EA - 0099$: - /* Finally pop off the ACC, which was the first register saved. */ - pop ACC - ret - _endasm; + ao_arch_restore_stack(); } uint8_t ao_sleep(__xdata void *wchan) { - __critical { + ao_arch_critical( ao_cur_task->wchan = wchan; - } + ); ao_yield(); ao_cur_task->alarm = 0; if (ao_cur_task->wchan) { @@ -186,14 +136,16 @@ ao_alarm(uint16_t delay) } void -ao_exit(void) __critical +ao_exit(void) { - uint8_t i; - ao_num_tasks--; - for (i = ao_cur_task_index; i < ao_num_tasks; i++) - ao_tasks[i] = ao_tasks[i+1]; - ao_cur_task_index = AO_NO_TASK_INDEX; - ao_yield(); + ao_arch_critical( + uint8_t i; + ao_num_tasks--; + for (i = ao_cur_task_index; i < ao_num_tasks; i++) + ao_tasks[i] = ao_tasks[i+1]; + ao_cur_task_index = AO_NO_TASK_INDEX; + ao_yield(); + ); /* we'll never get back here */ } @@ -201,16 +153,13 @@ void ao_task_info(void) { uint8_t i; - uint8_t pc_loc; __xdata struct ao_task *task; for (i = 0; i < ao_num_tasks; i++) { task = ao_tasks[i]; - pc_loc = task->stack_count - 17; - printf("%12s: wchan %04x pc %04x\n", + printf("%12s: wchan %04x\n", task->name, - (int16_t) task->wchan, - (task->stack[pc_loc]) | (task->stack[pc_loc+1] << 8)); + (int16_t) task->wchan); } } -- cgit v1.2.3 From c32893ce79835a8f861d6ef414644c2ff9769ff6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 26 Aug 2011 15:02:43 -0700 Subject: altos: Integrate telescience support Adds a few drivers including an LCD driver Signed-off-by: Keith Packard --- src/Makefile | 2 +- src/avr/ao_adc_avr.c | 129 +++++++++++++++++++ src/avr/ao_arch.h | 9 ++ src/avr/ao_spi_slave.c | 142 +++++++++++++++++++++ src/avr/ao_spi_usart.c | 112 +++++++++++++++++ src/cc1111/ao_arch.h | 12 ++ src/core/ao.h | 40 ++++-- src/core/ao_log_telescience.c | 274 ++++++++++++++++++++++++++++++++++++++++ src/core/ao_panic.c | 4 + src/drivers/ao_companion.c | 2 +- src/drivers/ao_lcd.c | 281 ++++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_m25.c | 2 + src/product/ao_telescience.c | 39 ++++++ src/telescience-v0.1/Makefile | 109 ++++++++++++++++ src/util/check-avr-mem | 9 ++ 15 files changed, 1153 insertions(+), 13 deletions(-) create mode 100644 src/avr/ao_adc_avr.c create mode 100644 src/avr/ao_spi_slave.c create mode 100644 src/avr/ao_spi_usart.c create mode 100644 src/core/ao_log_telescience.c create mode 100644 src/drivers/ao_lcd.c create mode 100644 src/product/ao_telescience.c create mode 100644 src/telescience-v0.1/Makefile create mode 100644 src/util/check-avr-mem (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 4e40c2bf..caa91e83 100644 --- a/src/Makefile +++ b/src/Makefile @@ -18,7 +18,7 @@ SUBDIRS=\ telemini-v1.0 telenano-v0.1 \ telebt-v0.0 telebt-v0.1 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ - tidongle test + tidongle test telescience-v0.1 all: all-local all-recursive diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c new file mode 100644 index 00000000..5afced74 --- /dev/null +++ b/src/avr/ao_adc_avr.c @@ -0,0 +1,129 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; +volatile __data uint8_t ao_adc_head; + +const uint8_t adc_channels[AO_LOG_TELESCIENCE_NUM_ADC] = { + 0x00, + 0x01, + 0x04, + 0x05, + 0x06, + 0x07, + 0x20, + 0x21, + 0x22, + 0x23, + 0x24, + 0x25, +}; + +static uint8_t ao_adc_channel; + +#define ADC_CHANNEL_LOW(c) (((c) & 0x1f) << MUX0) +#define ADC_CHANNEL_HIGH(c) ((((c) & 0x20) >> 5) << MUX5) + +#define ADCSRA_INIT ((1 << ADEN) | /* Enable ADC */ \ + (0 << ADATE) | /* No auto ADC trigger */ \ + (1 << ADIF) | /* Clear interrupt */ \ + (0 << ADIE) | /* Enable interrupt */ \ + (6 << ADPS0)) /* Prescale clock by 64 */ + +#define ADCSRB_INIT ((0 << ADHSM) | /* No high-speed mode */ \ + (0 << ACME) | /* Some comparitor thing */ \ + (2 << ADTS0)) /* Free running mode (don't care) */ + +static void +ao_adc_start(void) +{ + uint8_t channel = adc_channels[ao_adc_channel]; + ADMUX = ((0 << REFS1) | /* AVcc reference */ + (1 << REFS0) | /* AVcc reference */ + (1 << ADLAR) | /* Left-shift results */ + (ADC_CHANNEL_LOW(channel))); /* Select channel */ + + ADCSRB = (ADCSRB_INIT | + ADC_CHANNEL_HIGH(channel)); /* High channel bit */ + + ADCSRA = (ADCSRA_INIT | + (1 << ADSC) | + (1 << ADIE)); /* Start conversion */ +} + +ISR(ADC_vect) +{ + uint16_t value; + + /* Must read ADCL first or the value there will be lost */ + value = ADCL; + value |= (ADCH << 8); + ao_adc_ring[ao_adc_head].adc[ao_adc_channel] = value; + if (++ao_adc_channel < AO_TELESCIENCE_NUM_ADC) + ao_adc_start(); + else { + ADCSRA = ADCSRA_INIT; + ao_adc_ring[ao_adc_head].tick = ao_time(); + ao_adc_head = ao_adc_ring_next(ao_adc_head); + ao_wakeup((void *) &ao_adc_head); + ao_cpu_sleep_disable = 0; + } +} + +void +ao_adc_poll(void) +{ + ao_cpu_sleep_disable = 1; + ao_adc_channel = 0; + ao_adc_start(); +} + +void +ao_adc_get(__xdata struct ao_adc *packet) +{ + uint8_t i = ao_adc_ring_prev(ao_adc_head); + memcpy(packet, (void *) &ao_adc_ring[i], sizeof (struct ao_adc)); +} + +static void +ao_adc_dump(void) __reentrant +{ + static __xdata struct ao_adc packet; + uint8_t i; + ao_adc_get(&packet); + printf("tick: %5u", packet.tick); + for (i = 0; i < AO_TELESCIENCE_NUM_ADC; i++) + printf (" %2d: %5u", i, packet.adc[i]); + printf ("\n"); +} + +__code struct ao_cmds ao_adc_cmds[] = { + { ao_adc_dump, "a\0Display current ADC values" }, + { 0, NULL }, +}; + +void +ao_adc_init(void) +{ + DIDR0 = 0xf3; + DIDR2 = 0x3f; + ADCSRB = ADCSRB_INIT; + ADCSRA = ADCSRA_INIT; + ao_cmd_register(&ao_adc_cmds[0]); +} diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index 0ed97361..c695a725 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -145,5 +145,14 @@ extern uint8_t ao_cpu_sleep_disable; #define ao_arch_critical(b) do { cli(); b; sei(); } while (0) +#define AO_TELESCIENCE_NUM_ADC 12 + +struct ao_adc { + uint16_t tick; /* tick when the sample was read */ + uint16_t adc[AO_TELESCIENCE_NUM_ADC]; /* samples */ +}; + +#define AO_ADC_RING 16 + #endif /* _AO_ARCH_H_ */ diff --git a/src/avr/ao_spi_slave.c b/src/avr/ao_spi_slave.c new file mode 100644 index 00000000..4dde09f3 --- /dev/null +++ b/src/avr/ao_spi_slave.c @@ -0,0 +1,142 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_product.h" + +struct ao_companion_command ao_companion_command; + +static const struct ao_companion_setup ao_telescience_setup = { + .board_id = AO_idProduct_NUMBER, + .board_id_inverse = ~AO_idProduct_NUMBER, + .update_period = 50, + .channels = AO_LOG_TELESCIENCE_NUM_ADC, +}; + +static uint8_t +ao_spi_read(uint8_t *buf, uint8_t len) +{ + while (len--) { + while (!(SPSR & (1 << SPIF))) + if ((PINB & (1 << PINB0))) + return 0; + *buf++ = SPDR; + } + return 1; +} + +static void +ao_spi_write(uint8_t *buf, uint8_t len) +{ + while (len--) { + SPDR = *buf++; + while (!(SPSR & (1 << SPIF))) + if ((PINB & (1 << PINB0))) + return; + } + /* Clear pending SPIF bit by reading */ + (void) SPDR; +} + +static uint8_t ao_spi_slave_recv(void) +{ + if (!ao_spi_read((uint8_t *) &ao_companion_command, + sizeof (ao_companion_command))) + return 0; + + /* Figure out the outbound data */ + switch (ao_companion_command.command) { + case AO_COMPANION_SETUP: + ao_spi_write((uint8_t *) &ao_telescience_setup, + sizeof (ao_telescience_setup)); + break; + case AO_COMPANION_FETCH: + ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, + AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); + break; + case AO_COMPANION_NOTIFY: + break; + default: + return 0; + } + + ao_log_store.tm_tick = ao_companion_command.tick; + if (ao_log_store.tm_state != ao_companion_command.flight_state) { + ao_log_store.tm_state = ao_companion_command.flight_state; + return 1; + } + return 0; +} + +static uint8_t ao_spi_slave_running; + +ISR(PCINT0_vect) +{ + if ((PINB & (1 << PINB0)) == 0) { + if (!ao_spi_slave_running) { + uint8_t changed; + ao_spi_slave_running = 1; + cli(); + changed = ao_spi_slave_recv(); + sei(); + if (changed && ao_flight_boost <= ao_log_store.tm_state) { + if (ao_log_store.tm_state < ao_flight_landed) + ao_log_start(); + else + ao_log_stop(); + } + } + } else { + ao_spi_slave_running = 0; + } +} + +void ao_spi_slave_debug(void) { + printf ("slave running %d\n", ao_spi_slave_running); +} + +void +ao_spi_slave_init(void) +{ + PCMSK0 |= (1 << PCINT0); /* Enable PCINT0 pin change */ + PCICR |= (1 << PCIE0); /* Enable pin change interrupt */ + + DDRB = ((DDRB & 0xf0) | + (1 << 3) | /* MISO, output */ + (0 << 2) | /* MOSI, input */ + (0 << 1) | /* SCK, input */ + (0 << 0)); /* SS, input */ + + /* We'd like to have a pull-up on SS so that disconnecting the + * TM would cause any SPI transaction to abort. However, when + * I tried that, SPI transactions would spontaneously abort, + * making me assume that we needed a less aggressive pull-up + * than is offered inside the AVR + */ + PORTB = ((PORTB & 0xf0) | + (1 << 3) | /* MISO, output */ + (0 << 2) | /* MOSI, no pull-up */ + (0 << 1) | /* SCK, no pull-up */ + (0 << 0)); /* SS, no pull-up */ + + SPCR = (0 << SPIE) | /* Disable SPI interrupts */ + (1 << SPE) | /* Enable SPI */ + (0 << DORD) | /* MSB first */ + (0 << MSTR) | /* Slave mode */ + (0 << CPOL) | /* Clock low when idle */ + (0 << CPHA); /* Sample at leading clock edge */ +} diff --git a/src/avr/ao_spi_usart.c b/src/avr/ao_spi_usart.c new file mode 100644 index 00000000..6ed708ff --- /dev/null +++ b/src/avr/ao_spi_usart.c @@ -0,0 +1,112 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +/* + * Atmega32u4 USART in MSPIM (master SPI mode) + */ + +__xdata uint8_t ao_spi_mutex; + +/* Send bytes over SPI. + * + * This just polls; the SPI is set to go as fast as possible, + * so using interrupts would take way too long + */ +void +ao_spi_send(void __xdata *block, uint16_t len) __reentrant +{ + uint8_t *d = block; + + ao_mutex_get(&ao_spi_mutex); + while (len--) { + while (!(UCSR1A & (1 << UDRE1))); + UDR1 = *d++; + while (!(UCSR1A & (1 << RXC1))); + (void) UDR1; + } + ao_mutex_put(&ao_spi_mutex); +} + +/* Receive bytes over SPI. + * + * This sets up tow DMA engines, one reading the data and another + * writing constant values to the SPI transmitter as that is what + * clocks the data coming in. + */ +void +ao_spi_recv(void __xdata *block, uint16_t len) __reentrant +{ + uint8_t *d = block; + + ao_mutex_get(&ao_spi_mutex); + while (len--) { + while (!(UCSR1A & (1 << UDRE1))); + UDR1 = 0; + while (!(UCSR1A & (1 << RXC1))); + *d++ = UDR1; + } + ao_mutex_put(&ao_spi_mutex); +} + +/* + * Initialize USART0 for SPI using config alt 2 + * + * MO P1_5 + * MI P1_4 + * CLK P1_3 + * + * Chip select is the responsibility of the caller + */ + +#define XCK1_DDR DDRD +#define XCK1_PORT PORTD +#define XCK1 PORTD5 +#define XMS1_DDR DDRE +#define XMS1_PORT PORTE +#define XMS1 PORTE6 + +void +ao_spi_init(void) +{ + /* Ensure the USART is powered */ + PRR1 &= ~(1 << PRUSART1); + + /* + * Set pin directions + */ + XCK1_DDR |= (1 << XCK1); + + /* Clear chip select (which is negated) */ + XMS1_PORT |= (1 < XMS1); + XMS1_DDR |= (1 << XMS1); + + /* Set baud register to zero (required before turning transmitter on) */ + UBRR1 = 0; + + UCSR1C = ((0x3 << UMSEL10) | /* Master SPI mode */ + (0 << UCSZ10) | /* SPI mode 0 */ + (0 << UCPOL1)); /* SPI mode 0 */ + + /* Enable transmitter and receiver */ + UCSR1B = ((1 << RXEN1) | + (1 << TXEN1)); + + /* It says that 0 is a legal value; we'll see... */ + UBRR1 = 0; +} diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index c4972819..8a41791f 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -192,4 +192,16 @@ extern __code __at (0x00a6) uint32_t ao_radio_cal; #define ao_arch_critical(b) __critical { b } +struct ao_adc { + uint16_t tick; /* tick when the sample was read */ + int16_t accel; /* accelerometer */ + int16_t pres; /* pressure sensor */ + int16_t temp; /* temperature sensor */ + int16_t v_batt; /* battery voltage */ + int16_t sense_d; /* drogue continuity sense */ + int16_t sense_m; /* main continuity sense */ +}; + +#define AO_ADC_RING 32 + #endif /* _AO_ARCH_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index 98a01a4a..05f056fd 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -144,15 +144,6 @@ ao_clock_init(void); /* * One set of samples read from the A/D converter or telemetry */ -struct ao_adc { - uint16_t tick; /* tick when the sample was read */ - int16_t accel; /* accelerometer */ - int16_t pres; /* pressure sensor */ - int16_t temp; /* temperature sensor */ - int16_t v_batt; /* battery voltage */ - int16_t sense_d; /* drogue continuity sense */ - int16_t sense_m; /* main continuity sense */ -}; #if HAS_ADC @@ -160,7 +151,6 @@ struct ao_adc { * ao_adc.c */ -#define AO_ADC_RING 32 #define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) #define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) @@ -505,6 +495,23 @@ extern __pdata uint32_t ao_log_start_pos; extern __xdata uint8_t ao_log_running; extern __pdata enum flight_state ao_log_state; +#define AO_LOG_TELESCIENCE_START ((uint8_t) 's') +#define AO_LOG_TELESCIENCE_DATA ((uint8_t) 'd') + +#define AO_LOG_TELESCIENCE_NUM_ADC 12 + +struct ao_log_telescience { + uint8_t type; + uint8_t csum; + uint16_t tick; + uint16_t tm_tick; + uint8_t tm_state; + uint8_t unused; + uint16_t adc[AO_LOG_TELESCIENCE_NUM_ADC]; +}; + +extern struct ao_log_telescience ao_log_store; + /* required functions from the underlying log system */ #define AO_LOG_FORMAT_UNKNOWN 0 /* unknown; altosui will have to guess */ @@ -970,6 +977,16 @@ ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; void ao_spi_init(void); +/* + * ao_spi_slave.c + */ + +void +ao_spi_slave_debug(void); + +void +ao_spi_slave_init(void); + /* * ao_telemetry.c */ @@ -1568,8 +1585,9 @@ struct ao_companion_setup { }; extern __pdata uint8_t ao_companion_running; -extern __xdata struct ao_companion_setup ao_companion_setup; extern __xdata uint8_t ao_companion_mutex; +extern __xdata struct ao_companion_command ao_companion_command; +extern __xdata struct ao_companion_setup ao_companion_setup; extern __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; void diff --git a/src/core/ao_log_telescience.c b/src/core/ao_log_telescience.c new file mode 100644 index 00000000..aac780fa --- /dev/null +++ b/src/core/ao_log_telescience.c @@ -0,0 +1,274 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_product.h" + +static struct ao_task ao_log_task; +//static struct ao_task ao_spi_task; + +uint8_t ao_log_running; +uint8_t ao_log_mutex; +uint32_t ao_log_start_pos; +uint32_t ao_log_end_pos; +uint32_t ao_log_current_pos; + +#define AO_LOG_TELESCIENCE_START ((uint8_t) 's') +#define AO_LOG_TELESCIENCE_DATA ((uint8_t) 'd') + +struct ao_log_telescience ao_log_store; +struct ao_log_telescience ao_log_fetch; + +static uint8_t ao_log_adc_pos; + +__code uint8_t ao_log_format = AO_LOG_FORMAT_TELESCIENCE; + +static uint8_t +ao_log_csum(__xdata uint8_t *b) __reentrant +{ + uint8_t sum = 0x5a; + uint8_t i; + + for (i = 0; i < sizeof (struct ao_log_telescience); i++) + sum += *b++; + return -sum; +} + +static uint8_t +ao_log_telescience_write(void) +{ + uint8_t wrote = 0; + + ao_log_store.csum = 0; + ao_log_store.csum = ao_log_csum((__xdata uint8_t *) &ao_log_store); + ao_mutex_get(&ao_log_mutex); { + if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_stop(); + if (ao_log_running) { + wrote = 1; + ao_storage_write(ao_log_current_pos, + (__xdata uint8_t *) &ao_log_store, + sizeof (struct ao_log_telescience)); + ao_log_current_pos += sizeof (struct ao_log_telescience); + } + } ao_mutex_put(&ao_log_mutex); + return wrote; +} + +static uint8_t +ao_log_valid(struct ao_log_telescience *log) +{ + uint8_t *d; + uint8_t i; + d = (uint8_t *) log; + for (i = 0; i < sizeof (struct ao_log_telescience); i++) + if (d[i] != 0xff) + return 1; + return 0; +} + +static uint8_t +ao_log_telescience_read(uint32_t pos) +{ + if (!ao_storage_read(pos, &ao_log_fetch, sizeof (struct ao_log_telescience))) + return 0; + return ao_log_valid(&ao_log_fetch); +} + +void +ao_log_start(void) +{ + if (!ao_log_running) { + ao_log_running = 1; + ao_wakeup(&ao_log_running); + } +} + +void +ao_log_stop(void) +{ + if (ao_log_running) { + ao_log_running = 0; + } +} + +void +ao_log_restart(void) +{ + /* Find end of data */ + ao_log_end_pos = ao_storage_config; + for (ao_log_current_pos = 0; + ao_log_current_pos < ao_storage_config; + ao_log_current_pos += ao_storage_block) + { + if (!ao_log_telescience_read(ao_log_current_pos)) + break; + } + if (ao_log_current_pos > 0) { + ao_log_current_pos -= ao_storage_block; + for (; ao_log_current_pos < ao_storage_config; + ao_log_current_pos += sizeof (struct ao_log_telescience)) + { + if (!ao_log_telescience_read(ao_log_current_pos)) + break; + } + } +} + +void +ao_log_telescience(void) +{ + ao_storage_setup(); + + /* This can take a while, so let the rest + * of the system finish booting before we start + */ + ao_delay(AO_SEC_TO_TICKS(10)); + + ao_log_restart(); + for (;;) { + while (!ao_log_running) + ao_sleep(&ao_log_running); + + ao_log_start_pos = ao_log_current_pos; + ao_log_store.type = AO_LOG_TELESCIENCE_START; + ao_log_store.tick = ao_time(); + ao_log_store.adc[0] = ao_companion_command.serial; + ao_log_store.adc[1] = ao_companion_command.flight; + ao_log_telescience_write(); + /* Write the whole contents of the ring to the log + * when starting up. + */ + ao_log_adc_pos = ao_adc_ring_next(ao_adc_head); + ao_log_store.type = AO_LOG_TELESCIENCE_DATA; + while (ao_log_running) { + /* Write samples to EEPROM */ + while (ao_log_adc_pos != ao_adc_head) { + ao_log_store.tick = ao_adc_ring[ao_log_adc_pos].tick; + memcpy(&ao_log_store.adc, (void *) ao_adc_ring[ao_log_adc_pos].adc, + AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); + ao_log_telescience_write(); + ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); + } + /* Wait for more ADC data to arrive */ + ao_sleep((void *) &ao_adc_head); + } + memset(&ao_log_store.adc, '\0', sizeof (ao_log_store.adc)); + } +} + +void +ao_log_set(void) +{ + printf("Logging currently %s\n", ao_log_running ? "on" : "off"); + ao_cmd_hex(); + if (ao_cmd_status == ao_cmd_success) { + if (ao_cmd_lex_i) { + printf("Logging from %ld to %ld\n", ao_log_current_pos, ao_log_end_pos); + ao_log_start(); + } else { + printf ("Log stopped at %ld\n", ao_log_current_pos); + ao_log_stop(); + } + } + ao_cmd_status = ao_cmd_success; +} + +void +ao_log_list(void) +{ + uint32_t pos; + uint32_t start = 0; + uint8_t flight = 0; + + for (pos = 0; ; pos += sizeof (struct ao_log_telescience)) { + if (pos >= ao_storage_config || + !ao_log_telescience_read(pos) || + ao_log_fetch.type == AO_LOG_TELESCIENCE_START) + { + if (pos != start) { + printf("flight %d start %x end %x\n", + flight, + (uint16_t) (start >> 8), + (uint16_t) ((pos + 0xff) >> 8)); flush(); + } + if (ao_log_fetch.type != AO_LOG_TELESCIENCE_START) + break; + start = pos; + flight++; + } + } + printf ("done\n"); +} + +void +ao_log_delete(void) +{ + uint32_t pos; + + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + if (ao_cmd_lex_i != 1) { + ao_cmd_status = ao_cmd_syntax_error; + printf("No such flight: %d\n", ao_cmd_lex_i); + return; + } + ao_log_stop(); + for (pos = 0; pos < ao_storage_config; pos += ao_storage_block) { + if (!ao_log_telescience_read(pos)) + break; + ao_storage_erase(pos); + } + ao_log_current_pos = ao_log_start_pos = 0; + if (pos == 0) + printf("No such flight: %d\n", ao_cmd_lex_i); + else + printf ("Erased\n"); +} + +static void +ao_log_query(void) +{ + printf("Logging enabled: %d\n", ao_log_running); + printf("Log start: %ld\n", ao_log_start_pos); + printf("Log cur: %ld\n", ao_log_current_pos); + printf("Log end: %ld\n", ao_log_end_pos); + printf("log data tick: %04x\n", ao_log_store.tick); + printf("TM data tick: %04x\n", ao_log_store.tm_tick); + printf("TM state: %d\n", ao_log_store.tm_state); + printf("TM serial: %d\n", ao_companion_command.serial); + printf("TM flight: %d\n", ao_companion_command.flight); +} + +const struct ao_cmds ao_log_cmds[] = { + { ao_log_set, "L <0 off, 1 on>\0Set logging mode" }, + { ao_log_list, "l\0List stored flight logs" }, + { ao_log_delete, "d 1\0Delete all stored flights" }, + { ao_log_query, "q\0Query log status" }, + { 0, NULL }, +}; + +void +ao_log_init(void) +{ + ao_log_running = 0; + + ao_cmd_register(&ao_log_cmds[0]); + + ao_add_task(&ao_log_task, ao_log_telescience, "log"); +} diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c index 0668dad2..b6ff65cc 100644 --- a/src/core/ao_panic.c +++ b/src/core/ao_panic.c @@ -24,6 +24,10 @@ #if !HAS_BEEP #define ao_beep(x) #endif +#if !LEDS_AVAILABLE +#define ao_led_on(x) +#define ao_led_off(x) +#endif static void ao_panic_delay(uint8_t n) diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index 4c8f4269..2e587f8e 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -30,7 +30,7 @@ #define COMPANION_SELECT() do { ao_spi_get_bit(COMPANION_CS); ao_spi_slow(); } while (0) #define COMPANION_DESELECT() do { ao_spi_fast(); ao_spi_put_bit(COMPANION_CS); } while (0) -static __xdata struct ao_companion_command ao_companion_command; +__xdata struct ao_companion_command ao_companion_command; __xdata struct ao_companion_setup ao_companion_setup; __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; diff --git a/src/drivers/ao_lcd.c b/src/drivers/ao_lcd.c new file mode 100644 index 00000000..5bc89bbd --- /dev/null +++ b/src/drivers/ao_lcd.c @@ -0,0 +1,281 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +#define LCD_PORT PORTB +#define LCD_DDR DDRB + +#define PIN_RS 4 +#define PIN_E 5 +#define PIN_RW 6 + +void +ao_lcd_set_bits(uint8_t bits) +{ +#if 0 + printf("\tLCD data %x RS %d R/W %d E %d\n", + bits & 0xf, + (bits & (1 << PIN_RS)) ? 1 : 0, + (bits & (1 << PIN_RW)) ? 1 : 0, + (bits & (1 << PIN_E)) ? 1 : 0); +#endif + LCD_PORT = bits; +#if 0 + ao_delay(1); + if (bits & (1 << PIN_RW)) + printf("\tLCD input %x\n", PINB); +#endif +} + +uint8_t +ao_lcd_get_nibble(uint8_t rs) +{ + uint8_t data = (rs ? (1 << PIN_RS) : 0) | (1 << PIN_RW); + uint8_t n; + + DDRB = (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); + ao_lcd_set_bits(data); + ao_lcd_set_bits(data | (1 << PIN_E)); + n = PINB & 0xf; + ao_lcd_set_bits(data); + return n; +} + +uint8_t +ao_lcd_get_status(void) +{ + uint8_t high, low; + uint8_t data; + + high = ao_lcd_get_nibble(0); + low = ao_lcd_get_nibble(0); + data = (high << 4) | low; + printf ("\tLCD status %02x\n", data); + return data; +} + +uint8_t +ao_lcd_get_data(void) +{ + uint8_t high, low; + uint8_t data; + + high = ao_lcd_get_nibble(1); + low = ao_lcd_get_nibble(1); + data = (high << 4) | low; + printf ("\tLCD data %02x\n", data); + return data; +} + +void +ao_lcd_wait_idle(void) +{ + uint8_t status; + uint8_t count = 0; + + do { + status = ao_lcd_get_status(); + count++; + if (count > 100) { + printf("idle timeout\n"); + break; + } + } while (0); /* status & 0x80); */ +} + +void +ao_lcd_send_nibble(uint8_t rs, uint8_t data) +{ + data = (data & 0xf) | (rs ? (1 << PIN_RS) : 0); + DDRB = (0xf) | (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); + ao_lcd_set_bits(data); + ao_lcd_set_bits(data | (1 << PIN_E)); + ao_lcd_set_bits(data); +} + +static uint16_t ao_lcd_time = 3; + +void +ao_lcd_delay(void) +{ + volatile uint16_t count; + + for (count = 0; count < ao_lcd_time; count++) + ; +} + +void +ao_lcd_send_ins(uint8_t data) +{ +// printf("send ins %02x\n", data); +// ao_lcd_wait_idle(); +// ao_delay(1); + ao_lcd_delay(); + ao_lcd_send_nibble(0, data >> 4); + ao_lcd_send_nibble(0, data & 0xf); +} + +void +ao_lcd_send_data(uint8_t data) +{ +// printf ("send data %02x\n", data); +// ao_lcd_wait_idle(); + ao_lcd_delay(); + ao_lcd_send_nibble(1, data >> 4); + ao_lcd_send_nibble(1, data & 0x0f); +} + +void +ao_lcd_send_string(char *string) +{ + uint8_t c; + + while ((c = (uint8_t) *string++)) + ao_lcd_send_data(c); +} + +#define AO_LCD_POWER_CONTROL 0x54 + +void +ao_lcd_contrast_set(uint8_t contrast) +{ + ao_lcd_send_ins(AO_LCD_POWER_CONTROL | ((contrast >> 4) & 0x3)); + ao_lcd_send_ins(0x70 | (contrast & 0xf)); +} + +void +ao_lcd_clear(void) +{ + ao_lcd_send_ins(0x01); + ao_delay(1); + /* Entry mode */ + ao_lcd_send_ins(0x04 | 0x02); +} + +void +ao_lcd_start(void) +{ + /* get to 4bit mode */ + ao_lcd_send_nibble(0, 0x3); + ao_lcd_send_nibble(0, 0x3); + ao_lcd_send_nibble(0, 0x3); + ao_lcd_send_nibble(0, 0x2); + + /* function set */ + ao_lcd_send_ins(0x28); + /* function set, instruction table 1 */ + ao_lcd_send_ins(0x29); + + /* freq set */ + ao_lcd_send_ins(0x14); + + /* Power/icon/contrast control*/ + ao_lcd_send_ins(AO_LCD_POWER_CONTROL); + + /* Follower control */ + ao_lcd_send_ins(0x6d); + ao_delay(AO_MS_TO_TICKS(200)); + + /* contrast set */ + ao_lcd_contrast_set(0x18); + + /* Display on */ + ao_lcd_send_ins(0x08 | 0x04); + + /* Clear */ + ao_lcd_clear(); + +} + +void +ao_lcd_contrast(void) +{ + ao_cmd_hex(); + if (ao_cmd_status == ao_cmd_success) { + printf("setting contrast to %02x\n", ao_cmd_lex_i); + ao_lcd_contrast_set(ao_cmd_lex_i & 0x3f); + } +} + +static uint8_t +ao_cmd_hex_nibble(void) +{ + if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') + return ao_cmd_lex_c - '0'; + if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f') + return ao_cmd_lex_c - ('a' - 10); + if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F') + return ao_cmd_lex_c - ('A' - 10); + ao_cmd_status = ao_cmd_syntax_error; + return 0; +} + +void +ao_lcd_string(void) +{ + uint8_t col = 0; + uint8_t c; + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_lcd_send_ins(0x80 | (ao_cmd_lex_i ? 0x40 : 0x00)); + ao_cmd_white(); + while (ao_cmd_lex_c != '\n') { + c = ao_cmd_lex_c; + if (c == '\\') { + ao_cmd_lex(); + c = ao_cmd_hex_nibble() << 4; + ao_cmd_lex(); + c |= ao_cmd_hex_nibble(); + } + ao_lcd_send_data(c); + ao_cmd_lex(); + col++; + } + while (col < 16) { + ao_lcd_send_data(' '); + col++; + } +} + +void +ao_lcd_delay_set(void) +{ + ao_cmd_decimal(); + if (ao_cmd_status == ao_cmd_success) { + printf("setting LCD delay to %d\n", ao_cmd_lex_i); + ao_lcd_time = ao_cmd_lex_i; + } +} + +__code struct ao_cmds ao_lcd_cmds[] = { + { ao_lcd_start, "S\0Start LCD" }, + { ao_lcd_contrast, "C \0Set LCD contrast" }, + { ao_lcd_string, "s \0Send string to LCD" }, + { ao_lcd_delay_set, "t \0Set LCD delay" }, + { 0, NULL }, +}; + +void +ao_lcd_init(void) +{ + DDRB = (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); + PORTB = 0; + ao_cmd_register(&ao_lcd_cmds[0]); +} diff --git a/src/drivers/ao_m25.c b/src/drivers/ao_m25.c index d7208273..28cb1dd7 100644 --- a/src/drivers/ao_m25.c +++ b/src/drivers/ao_m25.c @@ -376,5 +376,7 @@ ao_storage_device_init(void) /* Set up chip select wires */ SPI_CS_PORT |= M25_CS_MASK; /* raise all CS pins */ SPI_CS_DIR |= M25_CS_MASK; /* set CS pins as outputs */ +#ifdef SPI_CS_SEL SPI_CS_SEL &= ~M25_CS_MASK; /* set CS pins as GPIO */ +#endif } diff --git a/src/product/ao_telescience.c b/src/product/ao_telescience.c new file mode 100644 index 00000000..4dec3a18 --- /dev/null +++ b/src/product/ao_telescience.c @@ -0,0 +1,39 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +int +main(void) +{ + ao_clock_init(); + + PORTE |= (1 << 6); + DDRE |= (1 << 6); + + ao_avr_stdio_init(); + ao_timer_init(); + ao_cmd_init(); + ao_spi_init(); + ao_spi_slave_init(); + ao_storage_init(); + ao_usb_init(); + ao_adc_init(); + ao_log_init(); + ao_start_scheduler(); + return 0; +} diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile new file mode 100644 index 00000000..3ccbb787 --- /dev/null +++ b/src/telescience-v0.1/Makefile @@ -0,0 +1,109 @@ +# +# AltOS build +# +# +vpath % ..:../core:../product:../drivers:../avr +vpath ao-make-product.5c ../util + +MCU=atmega32u4 +DUDECPUTYPE=m32u4 +#PROGRAMMER=stk500v2 -P usb +PROGRAMMER=usbtiny +LOADCMD=avrdude +LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: +CC=avr-gcc +OBJCOPY=avr-objcopy + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_usb.h \ + ao_pins.h \ + altitude.h + +# +# Common AltOS sources +# +TELESCIENCE_STORAGE= \ + ao_m25.c \ + ao_spi_usart.c \ + ao_storage.c \ + +ALTOS_SRC = \ + ao_cmd.c \ + ao_mutex.c \ + ao_panic.c \ + ao_product.c \ + ao_stdio.c \ + ao_task.c \ + ao_timer.c \ + ao_led.c \ + ao_avr_stdio.c \ + ao_romconfig.c \ + ao_usb_avr.c \ + ao_adc_avr.c \ + ao_spi_slave.c \ + ao_log_telescience.c \ + $(TELESCIENCE_STORAGE) + +PRODUCT=TeleScience-v0.1 +MCU=atmega32u4 +PRODUCT_DEF=-DTELESCIENCE +IDPRODUCT=0x0011 +CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../core -I.. +CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O3 -mcall-prologues -DAVR + +NICKLE=nickle + +PROG=telescience-v0.1 + +SRC=$(ALTOS_SRC) ao_telescience.c +OBJ=$(SRC:.c=.o) + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: $(PROG) + +CHECK=sh ../util/check-avr-mem + +$(PROG): Makefile $(OBJ) + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) + $(call quiet,CHECK) $(PROG) || ($(RM) -f $(PROG); exit 1) + +$(PROG).hex: $(PROG) + avr-size $(PROG) + $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@ + + +load: $(PROG).hex + $(LOADCMD) $(LOADARG)$(PROG).hex + +../altitude.h: make-altitude + nickle $< > $@ + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +ao_product.rel: ao_product.c ao_product.h + $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< + +distclean: clean + +clean: + rm -f $(OBJ) + rm -f ao_product.h + +install: + +uninstall: + +$(OBJ): ao.h ao_product.h ao_usb.h diff --git a/src/util/check-avr-mem b/src/util/check-avr-mem new file mode 100644 index 00000000..c73edbd1 --- /dev/null +++ b/src/util/check-avr-mem @@ -0,0 +1,9 @@ +#!/bin/sh +nm "$@" | +grep ' N _end' | +awk '{ iram = strtonum("0x" $1) % 0x10000; +if ( iram > 0xaff) { + printf ("%d bytes of ram more than %d available\n", iram, 0xaff); + exit(1); +} else + exit(0); }' -- cgit v1.2.3 From 1c46c419704f661064d200432eb7efeeb11b3859 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 26 Aug 2011 20:46:47 -0700 Subject: altos: re-order ao_task to match single-arch code This is just for testing to make the new build match the old build exactly. Signed-off-by: Keith Packard --- src/core/ao.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 05f056fd..c926c001 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -37,9 +37,9 @@ struct ao_task { __xdata void *wchan; /* current wait channel (NULL if running) */ uint16_t alarm; /* abort ao_sleep time */ + ao_arch_task_members /* any architecture-specific fields */ uint8_t task_id; /* unique id */ __code char *name; /* task name */ - ao_arch_task_members /* any architecture-specific fields */ uint8_t stack[AO_STACK_SIZE]; /* saved stack */ }; -- cgit v1.2.3 From b10fbbf0830053a39e4640a53598b1c027615c63 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 1 Aug 2011 22:44:13 -0700 Subject: altos: Add 'send all baro' compile-time option This option creates a new packet type that delivers full sensor-rate barometer telemetry data to allow for off-line analysis of flight algorithms using all of the data, rather than the slower rate provided either over telemetry or stored in the eeprom file. Define AO_SEND_ALL_BARO and this will get built in. Perhaps this could be a run-time option... Signed-off-by: Keith Packard --- src/core/ao.h | 31 +++++++++++++++++++++++++++++++ src/core/ao_telemetry.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index c926c001..0cff0436 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1118,6 +1118,30 @@ struct ao_telemetry_companion { /* 32 */ }; +/* #define AO_SEND_ALL_BARO */ + +#define AO_TELEMETRY_BARO 0x80 + +/* + * This packet allows the full sampling rate baro + * data to be captured over the RF link so that the + * flight software can be tested using 'real' data. + * + * Along with this telemetry packet, the flight + * code is modified to send full-rate telemetry all the time + * and never send an RDF tone; this ensure that the full radio + * link is available. + */ +struct ao_telemetry_baro { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t samples; /* 5 number samples */ + + int16_t baro[12]; /* 6 samples */ + /* 32 */ +}; + union ao_telemetry_all { struct ao_telemetry_generic generic; struct ao_telemetry_sensor sensor; @@ -1125,6 +1149,7 @@ union ao_telemetry_all { struct ao_telemetry_location location; struct ao_telemetry_satellite satellite; struct ao_telemetry_companion companion; + struct ao_telemetry_baro baro; }; /* @@ -1258,9 +1283,15 @@ struct ao_telemetry_raw_recv { /* Set delay between telemetry reports (0 to disable) */ +#ifdef AO_SEND_ALL_BARO +#define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(100) +#define AO_TELEMETRY_INTERVAL_FLIGHT AO_MS_TO_TICKS(100) +#define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(100) +#else #define AO_TELEMETRY_INTERVAL_PAD AO_MS_TO_TICKS(1000) #define AO_TELEMETRY_INTERVAL_FLIGHT AO_MS_TO_TICKS(100) #define AO_TELEMETRY_INTERVAL_RECOVER AO_MS_TO_TICKS(1000) +#endif void ao_telemetry_set_interval(uint16_t interval); diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index c7338a58..de669ce1 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -94,6 +94,30 @@ ao_send_sensor(void) ao_radio_send(&telemetry, sizeof (telemetry)); } +static uint8_t ao_baro_sample; + +#ifdef AO_SEND_ALL_BARO +static void +ao_send_baro(void) +{ + uint8_t sample = ao_sample_adc; + uint8_t samples = (sample - ao_baro_sample) & (AO_ADC_RING - 1); + + if (samples > 12) { + ao_baro_sample = (ao_baro_sample + (samples - 12)) & (AO_ADC_RING - 1); + samples = 12; + } + telemetry.generic.tick = ao_adc_ring[sample].tick; + telemetry.generic.type = AO_TELEMETRY_BARO; + telemetry.baro.samples = samples; + for (sample = 0; sample < samples; sample++) { + telemetry.baro.baro[sample] = ao_adc_ring[ao_baro_sample].pres; + ao_baro_sample = ao_adc_ring_next(ao_baro_sample); + } + ao_radio_send(&telemetry, sizeof (telemetry)); +} +#endif + static void ao_send_configuration(void) { @@ -193,6 +217,9 @@ ao_telemetry(void) while (ao_telemetry_interval) { +#ifdef AO_SEND_ALL_BARO + ao_send_baro(); +#endif ao_send_sensor(); #if HAS_COMPANION if (ao_companion_running) @@ -203,12 +230,14 @@ ao_telemetry(void) ao_send_location(); ao_send_satellite(); #endif +#ifndef AO_SEND_ALL_BARO if (ao_rdf && (int16_t) (ao_time() - ao_rdf_time) >= 0) { ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; ao_radio_rdf(AO_RDF_LENGTH_MS); } +#endif time += ao_telemetry_interval; delay = time - ao_time(); if (delay > 0) -- cgit v1.2.3 From f145be3fc4ee94fdb5c1e2406b6c11d38bdbbd9b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 13 Jul 2011 20:01:47 -0700 Subject: altos: Start telelaunch product Looks a lot like TM, but without the flight code. Signed-off-by: Keith Packard --- src/Makefile | 3 ++- src/cc1111/ao_adc.c | 4 ++++ src/cc1111/ao_pins.h | 29 +++++++++++++++++++++++++++++ src/core/ao_config.c | 8 +++++--- src/telelaunch-v0.1/.gitignore | 2 ++ src/telelaunch-v0.1/.sdcdbrc | 1 + src/telelaunch-v0.1/Makefile | 1 + src/telelaunch-v0.1/Makefile.defs | 11 +++++++++++ 8 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 src/telelaunch-v0.1/.gitignore create mode 100644 src/telelaunch-v0.1/.sdcdbrc create mode 100644 src/telelaunch-v0.1/Makefile create mode 100644 src/telelaunch-v0.1/Makefile.defs (limited to 'src') diff --git a/src/Makefile b/src/Makefile index caa91e83..9ef5ae0a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -18,6 +18,7 @@ SUBDIRS=\ telemini-v1.0 telenano-v0.1 \ telebt-v0.0 telebt-v0.1 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ + telelaunch-v0.1 \ tidongle test telescience-v0.1 all: all-local all-recursive @@ -50,4 +51,4 @@ ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c sh $< kalman > $@ clean-local: - rm -f altitude.h ao_kalman.h \ No newline at end of file + rm -f altitude.h ao_kalman.h diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index 786dfd11..6aa6e018 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -41,7 +41,11 @@ ao_adc_poll(void) void ao_adc_get(__xdata struct ao_adc *packet) { +#if HAS_FLIGHT uint8_t i = ao_adc_ring_prev(ao_sample_adc); +#else + uint8_t i = ao_adc_ring_prev(ao_adc_head); +#endif memcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); } diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 4ac6a84b..19ea0cfd 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -302,6 +302,35 @@ #define HAS_MONITOR 1 #endif +#if defined(TELELAUNCH_V_0_1) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 0 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_DBG 0 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 0 + #define DBG_ON_P1 0 + #define DBG_ON_P0 1 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + #define AO_LED_RED 2 + #define AO_LED_GREEN 1 + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define HAS_EXTERNAL_TEMP 1 + #define HAS_ACCEL_REF 0 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_ACCEL 0 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + #if DBG_ON_P1 #define DBG_CLOCK (1 << 4) /* mi0 */ diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 0c10e608..ec2b61f6 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -47,7 +47,9 @@ _ao_config_put(void) ao_storage_setup(); ao_storage_erase(ao_storage_config); ao_storage_write(ao_storage_config, &ao_config, sizeof (ao_config)); +#if HAS_FLIGHT ao_log_write_erase(0); +#endif ao_storage_flush(); } @@ -301,7 +303,7 @@ ao_config_radio_cal_set(void) __reentrant _ao_config_edit_finish(); } -#if HAS_EEPROM +#if HAS_EEPROM && HAS_FLIGHT void ao_config_log_show(void) __reentrant { @@ -329,7 +331,7 @@ ao_config_log_set(void) __reentrant _ao_config_edit_finish(); } } -#endif /* HAS_EEPROM */ +#endif /* HAS_EEPROM && HAS_FLIGHT */ #if HAS_IGNITE void @@ -448,7 +450,7 @@ __code struct ao_config_var ao_config_vars[] = { #endif /* HAS_ACCEL */ { "f \0Radio calib (cal = rf/(xtal/2^16))", ao_config_radio_cal_set, ao_config_radio_cal_show }, -#if HAS_EEPROM +#if HAS_EEPROM && HAS_FLIGHT { "l \0Flight log size in kB", ao_config_log_set, ao_config_log_show }, #endif diff --git a/src/telelaunch-v0.1/.gitignore b/src/telelaunch-v0.1/.gitignore new file mode 100644 index 00000000..d25d7ad9 --- /dev/null +++ b/src/telelaunch-v0.1/.gitignore @@ -0,0 +1,2 @@ +telemetrum-v0.1-sky* +ao_product.h diff --git a/src/telelaunch-v0.1/.sdcdbrc b/src/telelaunch-v0.1/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telelaunch-v0.1/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telelaunch-v0.1/Makefile b/src/telelaunch-v0.1/Makefile new file mode 100644 index 00000000..d8867b19 --- /dev/null +++ b/src/telelaunch-v0.1/Makefile @@ -0,0 +1 @@ +include ../Makefile.proto diff --git a/src/telelaunch-v0.1/Makefile.defs b/src/telelaunch-v0.1/Makefile.defs new file mode 100644 index 00000000..0c7efb52 --- /dev/null +++ b/src/telelaunch-v0.1/Makefile.defs @@ -0,0 +1,11 @@ +PROG = telelaunch-v0.1-$(VERSION).ihx + +SRC = \ + $(TLAUNCH_BASE_SRC) \ + $(SPI_DRIVER_SRC) \ + $(EE_DRIVER_SRC) \ + $(DBG_SRC) + +PRODUCT=TeleLaunch-v0.1 +PRODUCT_DEF=-DTELELAUNCH_V_0_1 +IDPRODUCT=0x000f -- cgit v1.2.3 From a731d240f802d37524ce84c3c6acf22bcda4d522 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jul 2011 18:51:33 -0700 Subject: altos: Start work on AES and raw radio interfaces. We probably don't want this raw radio interface, but it's a start. Signed-off-by: Keith Packard --- src/ao_aes.c | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/ao_radio_cmac.c | 100 +++++++++++++++++++++++++++++++++++++++++ src/cc1111/ao_pins.h | 4 ++ src/cc1111/cc1111.h | 24 +++++++++- src/core/ao.h | 26 +++++++++++ 5 files changed, 275 insertions(+), 1 deletion(-) create mode 100644 src/ao_aes.c create mode 100644 src/ao_radio_cmac.c (limited to 'src') diff --git a/src/ao_aes.c b/src/ao_aes.c new file mode 100644 index 00000000..649eda06 --- /dev/null +++ b/src/ao_aes.c @@ -0,0 +1,122 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +__xdata uint8_t ao_aes_mutex; +__xdata uint8_t ao_aes_done; +__xdata uint8_t ao_aes_dma_in, ao_aes_dma_out; +__xdata uint8_t ao_aes_dma_in_done, ao_aes_dma_out_done; +__pdata enum ao_aes_mode ao_aes_current_mode; + +void +ao_aes_isr(void) __interrupt 4 +{ + S0CON = 0; + if (ENCCCS & ENCCCS_RDY) { + ao_aes_done = 1; + ao_wakeup(&ao_aes_done); + } +} + +void +ao_aes_set_mode(enum ao_aes_mode mode) +{ + ao_aes_current_mode = mode; +} + +void +ao_aes_set_key(__xdata uint8_t *in) +{ + ao_dma_set_transfer(ao_aes_dma_in, + in, + &ENCDIXADDR, + 7, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_ENC_DW, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_LOW); + ao_aes_done = 0; + ENCCCS = ENCCCS_MODE_CBC_MAC | + ENCCCS_CMD_LOAD_KEY | + ENCCCS_START; + while (!ao_aes_done) + ao_sleep(&ao_aes_done); +} + +void +ao_aes_run(__xdata uint8_t *in, + __xdata uint8_t *out) +{ + uint8_t b; + if (in) { + ao_dma_set_transfer(ao_aes_dma_in, + in, + &ENCDIXADDR, + 7, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_ENC_DW, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_LOW); + } + if (out) { + ao_dma_set_transfer(ao_aes_dma_out, + &ENCDOXADDR, + out, + 7, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_ENC_UP, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_1 | + DMA_CFG1_PRIORITY_LOW); + } + switch (ao_aes_current_mode) { + case ao_aes_mode_cbc_mac: + if (out) + b = (ENCCCS_MODE_CBC | + ENCCCS_CMD_ENCRYPT | + ENCCCS_START); + else + b = (ENCCCS_MODE_CBC_MAC | + ENCCCS_CMD_ENCRYPT | + ENCCCS_START); + break; + default: + return; + } + ao_aes_done = 0; + ENCCCS = b; + if (out) + while (!ao_aes_dma_out_done) + ao_sleep(&ao_aes_dma_out_done); + else + while (!ao_aes_done) + ao_sleep(&ao_aes_done); +} + +void +ao_aes_init(void) +{ + ao_aes_dma_in = ao_dma_alloc(&ao_aes_dma_in_done); + ao_aes_dma_out = ao_dma_alloc(&ao_aes_dma_out_done); + ENCIE = 1; +} diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c new file mode 100644 index 00000000..4b118d02 --- /dev/null +++ b/src/ao_radio_cmac.c @@ -0,0 +1,100 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +#define AO_CMAC_KEY_LEN 16 +#define AO_CMAC_MAX_LEN (128 - AO_CMAC_KEY_LEN) + +static __xdata uint8_t cmac_key[AO_CMAC_KEY_LEN]; +static __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN]; + +static uint8_t +getnibble(void) +{ + __pdata char 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 +ao_radio_cmac_key(void) __reentrant +{ + uint8_t i; + + for (i = 0; i < AO_CMAC_KEY_LEN; i++) { + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + cmac_key[i] = ao_cmd_lex_i; + } +} + +static void +ao_radio_cmac_send(void) __reentrant +{ + uint8_t i, b; + + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + if (ao_cmd_lex_i > AO_CMAC_MAX_LEN || ao_cmd_lex_i % AO_CMAC_KEY_LEN != 0) { + ao_cmd_status = ao_cmd_syntax_error; + return; + } + for (i = 0; i < ao_cmd_lex_i; i++) { + b = getnibble() << 4; + b |= getnibble(); + if (ao_cmd_status != ao_cmd_success) + return; + cmac_data[i] = b; + } + ao_mutex_get(&ao_aes_mutex); + ao_aes_set_mode(ao_aes_mode_cbc_mac); + ao_aes_set_key(cmac_key); + for (i = 0; i < ao_cmd_lex_i; i += AO_CMAC_KEY_LEN) { + if (i + AO_CMAC_KEY_LEN < ao_cmd_lex_i) + ao_aes_run(&cmac_data[i], NULL); + else + ao_aes_run(&cmac_data[i], &cmac_data[ao_cmd_lex_i]); + } + ao_mutex_put(&ao_aes_mutex); + ao_set_monitor(0); + ao_radio_send(cmac_data, ao_cmd_lex_i + AO_CMAC_KEY_LEN); +} + +__code struct ao_cmds ao_radio_cmac_cmds[] = { + { ao_radio_cmac_key, "k ...\0Set AES-CMAC key." }, + { ao_radio_cmac_send, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, + { ao_radio_cmac_recv, "S \0Receive AES-CMAC packet. Timeout in ms" }, + { 0, NULL }, +}; + +void +ao_radio_cmac_init(void) +{ + ao_cmd_register(&ao_radio_cmac_cmds[0]); + +} diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 19ea0cfd..9e9b3bf6 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -108,6 +108,7 @@ #define SPI_CS_ON_P0 0 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define HAS_AES 1 #endif #if defined(TELEMINI_V_1_0) @@ -212,6 +213,7 @@ #define SPI_CS_ON_P0 1 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define HAS_AES 1 #endif #if defined(TIDONGLE) @@ -235,6 +237,7 @@ #define SPI_CS_ON_P0 1 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define HAS_AES 1 #endif #if defined(TELEBT_V_0_0) @@ -300,6 +303,7 @@ #define BT_LINK_PIN_INDEX 7 #define BT_LINK_PIN P1_7 #define HAS_MONITOR 1 + #define HAS_AES 1 #endif #if defined(TELELAUNCH_V_0_1) diff --git a/src/cc1111/cc1111.h b/src/cc1111/cc1111.h index e52aa79f..11ea8bbb 100644 --- a/src/cc1111/cc1111.h +++ b/src/cc1111/cc1111.h @@ -768,7 +768,7 @@ struct cc_dma_channel { # define DMA_CFG0_TRIGGER_ADC_CH7 28 # define DMA_CFG0_TRIGGER_I2STX 28 # define DMA_CFG0_TRIGGER_ENC_DW 29 -# define DMA_CFG0_TRIGGER_DNC_UP 30 +# define DMA_CFG0_TRIGGER_ENC_UP 30 # define DMA_CFG1_SRCINC_MASK (3 << 6) # define DMA_CFG1_SRCINC_0 (0 << 6) @@ -1303,4 +1303,26 @@ __xdata __at (0xdf3c) uint8_t RF_PKTSTATUS; __xdata __at (0xdf3d) uint8_t RF_VCO_VC_DAC; #define RF_VCO_VC_DAC_OFF 0x3d +/* AES engine */ + +__sfr at 0xB1 ENCDI; +__sfr at 0xB2 ENCDO; +__xdata at (0xDFB1) volatile uint8_t ENCDIXADDR; +__xdata at (0xDFB2) volatile uint8_t ENCDOXADDR; + +__sfr at 0xB3 ENCCCS; + +#define ENCCCS_MODE_CBC (0 << 4) +#define ENCCCS_MODE_CFB (1 << 4) +#define ENCCCS_MODE_OFB (2 << 4) +#define ENCCCS_MODE_CTR (3 << 4) +#define ENCCCS_MODE_ECB (4 << 4) +#define ENCCCS_MODE_CBC_MAC (5 << 4) +#define ENCCCS_RDY (1 << 3) +#define ENCCCS_CMD_ENCRYPT (0 << 1) +#define ENCCCS_CMD_DECRYPT (1 << 1) +#define ENCCCS_CMD_LOAD_KEY (2 << 1) +#define ENCCCS_CMD_LOAD_IV (3 << 1) +#define ENCCCS_START (1 << 0) + #endif diff --git a/src/core/ao.h b/src/core/ao.h index 0cff0436..0275cad1 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1629,4 +1629,30 @@ ao_companion_init(void); void ao_lcd_init(void); +/* ao_aes.c */ + +__xdata uint8_t ao_aes_mutex; + +enum ao_aes_mode { + ao_aes_mode_cbc_mac +}; + +#if HAS_AES +void +ao_aes_isr(void) __interrupt 4; +#endif + +void +ao_aes_set_mode(enum ao_aes_mode mode); + +void +ao_aes_set_key(__xdata uint8_t *in); + +void +ao_aes_run(__xdata uint8_t *in, + __xdata uint8_t *out); + +void +ao_aes_init(void); + #endif /* _AO_H_ */ -- cgit v1.2.3 From bd0bf00081bb24af5cd67a9351b0b0c1a041d0d3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 16 Jul 2011 14:25:01 -0700 Subject: altos: More work on AES bits Signed-off-by: Keith Packard --- src/ao_radio_cmac.c | 9 +++++++++ src/core/ao.h | 4 ++++ src/telelaunch-v0.1/Makefile.defs | 1 + 3 files changed, 14 insertions(+) (limited to 'src') diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c index 4b118d02..9b406a21 100644 --- a/src/ao_radio_cmac.c +++ b/src/ao_radio_cmac.c @@ -22,6 +22,7 @@ static __xdata uint8_t cmac_key[AO_CMAC_KEY_LEN]; static __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN]; +static __pdata uint8_t ao_radio_cmac_len; static uint8_t getnibble(void) @@ -85,6 +86,14 @@ ao_radio_cmac_send(void) __reentrant ao_radio_send(cmac_data, ao_cmd_lex_i + AO_CMAC_KEY_LEN); } +static void +ao_radio_cmac_recv(void) __reentrant +{ + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; +} + __code struct ao_cmds ao_radio_cmac_cmds[] = { { ao_radio_cmac_key, "k ...\0Set AES-CMAC key." }, { ao_radio_cmac_send, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, diff --git a/src/core/ao.h b/src/core/ao.h index 0275cad1..2394d401 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1655,4 +1655,8 @@ ao_aes_run(__xdata uint8_t *in, void ao_aes_init(void); +/* ao_launch.c */ +void +ao_launch_init(void); + #endif /* _AO_H_ */ diff --git a/src/telelaunch-v0.1/Makefile.defs b/src/telelaunch-v0.1/Makefile.defs index 0c7efb52..e4934ffa 100644 --- a/src/telelaunch-v0.1/Makefile.defs +++ b/src/telelaunch-v0.1/Makefile.defs @@ -4,6 +4,7 @@ SRC = \ $(TLAUNCH_BASE_SRC) \ $(SPI_DRIVER_SRC) \ $(EE_DRIVER_SRC) \ + ao_launch.c \ $(DBG_SRC) PRODUCT=TeleLaunch-v0.1 -- cgit v1.2.3 From 776df9ce2e7b4fa5cedda326988e66c614299af4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 20 Jul 2011 23:46:04 -0700 Subject: altos: Get AES CBC-MAC packet transfers running This just has simple command-line based packet transfers for testing. This also adds special ao_telelaunch bits where the launch control code will live. Signed-off-by: Keith Packard --- src/ao_aes.c | 48 +++++++++++++++------ src/ao_launch.c | 59 +++++++++++++++++++++++++ src/ao_radio_cmac.c | 90 +++++++++++++++++++++++++++++++-------- src/ao_telelaunch.c | 47 ++++++++++++++++++++ src/cc1111/ao_pins.h | 4 +- src/core/ao.h | 12 ++++++ src/product/ao_telebt.c | 4 ++ src/product/ao_teledongle.c | 2 + src/teledongle-v0.1/.sdcdbrc | 1 + src/telelaunch-v0.1/Makefile.defs | 2 + 10 files changed, 237 insertions(+), 32 deletions(-) create mode 100644 src/ao_launch.c create mode 100644 src/ao_telelaunch.c create mode 100644 src/teledongle-v0.1/.sdcdbrc (limited to 'src') diff --git a/src/ao_aes.c b/src/ao_aes.c index 649eda06..d50fecfb 100644 --- a/src/ao_aes.c +++ b/src/ao_aes.c @@ -17,6 +17,10 @@ #include "ao.h" +#if !HAS_AES +#error Must define HAS_AES 1 +#endif + __xdata uint8_t ao_aes_mutex; __xdata uint8_t ao_aes_done; __xdata uint8_t ao_aes_dma_in, ao_aes_dma_out; @@ -45,21 +49,32 @@ ao_aes_set_key(__xdata uint8_t *in) ao_dma_set_transfer(ao_aes_dma_in, in, &ENCDIXADDR, - 7, + AO_AES_LEN, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | DMA_CFG0_TRIGGER_ENC_DW, DMA_CFG1_SRCINC_1 | DMA_CFG1_DESTINC_0 | DMA_CFG1_PRIORITY_LOW); + ao_dma_start(ao_aes_dma_in); ao_aes_done = 0; ENCCCS = ENCCCS_MODE_CBC_MAC | - ENCCCS_CMD_LOAD_KEY | - ENCCCS_START; - while (!ao_aes_done) + ENCCCS_CMD_LOAD_KEY; + ENCCCS |= ENCCCS_START; + __critical while (!ao_aes_done) ao_sleep(&ao_aes_done); } +void +ao_aes_zero_iv(void) +{ + uint8_t b; + + ENCCCS = ENCCCS_MODE_CBC_MAC | ENCCCS_CMD_LOAD_IV | ENCCCS_START; + for (b = 0; b < AO_AES_LEN; b++) + ENCDI = 0; +} + void ao_aes_run(__xdata uint8_t *in, __xdata uint8_t *out) @@ -69,7 +84,7 @@ ao_aes_run(__xdata uint8_t *in, ao_dma_set_transfer(ao_aes_dma_in, in, &ENCDIXADDR, - 7, + AO_AES_LEN, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | DMA_CFG0_TRIGGER_ENC_DW, @@ -81,7 +96,7 @@ ao_aes_run(__xdata uint8_t *in, ao_dma_set_transfer(ao_aes_dma_out, &ENCDOXADDR, out, - 7, + AO_AES_LEN, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | DMA_CFG0_TRIGGER_ENC_UP, @@ -93,24 +108,28 @@ ao_aes_run(__xdata uint8_t *in, case ao_aes_mode_cbc_mac: if (out) b = (ENCCCS_MODE_CBC | - ENCCCS_CMD_ENCRYPT | - ENCCCS_START); + ENCCCS_CMD_ENCRYPT); else b = (ENCCCS_MODE_CBC_MAC | - ENCCCS_CMD_ENCRYPT | - ENCCCS_START); + ENCCCS_CMD_ENCRYPT); break; default: return; } ao_aes_done = 0; - ENCCCS = b; + if (in) + ao_dma_start(ao_aes_dma_in); if (out) - while (!ao_aes_dma_out_done) + ao_dma_start(ao_aes_dma_out); + ENCCCS = b; + ENCCCS |= ENCCCS_START; + if (out) { + __critical while (!ao_aes_dma_out_done) ao_sleep(&ao_aes_dma_out_done); - else - while (!ao_aes_done) + } else { + __critical while (!ao_aes_done) ao_sleep(&ao_aes_done); + } } void @@ -118,5 +137,6 @@ ao_aes_init(void) { ao_aes_dma_in = ao_dma_alloc(&ao_aes_dma_in_done); ao_aes_dma_out = ao_dma_alloc(&ao_aes_dma_out_done); + S0CON = 0; ENCIE = 1; } diff --git a/src/ao_launch.c b/src/ao_launch.c new file mode 100644 index 00000000..4870869e --- /dev/null +++ b/src/ao_launch.c @@ -0,0 +1,59 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static void +ao_launch(void) +{ + enum ao_igniter_status arm_status, ignite_status; + + ao_led_off(AO_LED_RED); + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + for (;;) { + arm_status = ao_igniter_status(ao_igniter_drogue); + + switch (arm_status) { + case ao_igniter_unknown: + break; + case ao_igniter_active: + case ao_igniter_open: + break; + case ao_igniter_ready: + ignite_status = ao_igniter_status(ao_igniter_main); + switch (ignite_status) { + case ao_igniter_unknown: + /* some kind of failure signal here */ + break; + case ao_igniter_active: + break; + case ao_igniter_open: + break; + } + break; + } + ao_delay(AO_SEC_TO_TICKS(1)); + } +} + +static __xdata struct ao_task ao_launch_task; + +void +ao_launch_init(void) +{ + ao_add_task(&ao_launch_task, ao_launch, "launch status"); +} diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c index 9b406a21..7648a2f5 100644 --- a/src/ao_radio_cmac.c +++ b/src/ao_radio_cmac.c @@ -40,62 +40,119 @@ getnibble(void) return 0; } +static uint8_t +getbyte(void) +{ + uint8_t b; + b = getnibble() << 4; + b |= getnibble(); + return b; +} + static void ao_radio_cmac_key(void) __reentrant { uint8_t i; for (i = 0; i < AO_CMAC_KEY_LEN; i++) { - ao_cmd_hex(); + cmac_key[i] = getbyte(); if (ao_cmd_status != ao_cmd_success) return; - cmac_key[i] = ao_cmd_lex_i; } } static void ao_radio_cmac_send(void) __reentrant { - uint8_t i, b; + uint8_t i; + uint8_t len; - ao_cmd_hex(); + ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - if (ao_cmd_lex_i > AO_CMAC_MAX_LEN || ao_cmd_lex_i % AO_CMAC_KEY_LEN != 0) { + if (ao_cmd_lex_i < AO_CMAC_KEY_LEN || + ao_cmd_lex_i > AO_CMAC_MAX_LEN || + ao_cmd_lex_i % AO_CMAC_KEY_LEN != 0) + { ao_cmd_status = ao_cmd_syntax_error; return; } - for (i = 0; i < ao_cmd_lex_i; i++) { - b = getnibble() << 4; - b |= getnibble(); + flush(); + len = ao_cmd_lex_i; + for (i = 0; i < len; i++) { + cmac_data[i] = getbyte(); if (ao_cmd_status != ao_cmd_success) return; - cmac_data[i] = b; } ao_mutex_get(&ao_aes_mutex); ao_aes_set_mode(ao_aes_mode_cbc_mac); ao_aes_set_key(cmac_key); - for (i = 0; i < ao_cmd_lex_i; i += AO_CMAC_KEY_LEN) { - if (i + AO_CMAC_KEY_LEN < ao_cmd_lex_i) + ao_aes_zero_iv(); + for (i = 0; i < len; i += AO_CMAC_KEY_LEN) { + if (i + AO_CMAC_KEY_LEN < len) ao_aes_run(&cmac_data[i], NULL); else - ao_aes_run(&cmac_data[i], &cmac_data[ao_cmd_lex_i]); + ao_aes_run(&cmac_data[i], &cmac_data[len]); } ao_mutex_put(&ao_aes_mutex); +#if HAS_MONITOR ao_set_monitor(0); - ao_radio_send(cmac_data, ao_cmd_lex_i + AO_CMAC_KEY_LEN); +#endif + printf("send:"); + for (i = 0; i < len + AO_CMAC_KEY_LEN; i++) + printf(" %02x", cmac_data[i]); + printf("\n"); flush(); + ao_radio_send(cmac_data, len + AO_CMAC_KEY_LEN); } static void ao_radio_cmac_recv(void) __reentrant { - ao_cmd_hex(); + uint8_t len, i; + uint16_t timeout; + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + if (ao_cmd_lex_i < AO_CMAC_KEY_LEN || + ao_cmd_lex_i > AO_CMAC_MAX_LEN || + ao_cmd_lex_i % AO_CMAC_KEY_LEN != 0) + { + ao_cmd_status = ao_cmd_syntax_error; + return; + } + len = ao_cmd_lex_i; + ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; + timeout = ao_cmd_lex_i; +#if HAS_MONITOR + ao_set_monitor(0); +#endif + if (timeout) + ao_alarm(timeout); + if (!ao_radio_recv(cmac_data, len + AO_CMAC_KEY_LEN + 2)) { + printf("timeout\n"); + return; + } + ao_mutex_get(&ao_aes_mutex); + ao_aes_set_mode(ao_aes_mode_cbc_mac); + ao_aes_set_key(cmac_key); + ao_aes_zero_iv(); + for (i = 0; i < len; i += AO_CMAC_KEY_LEN) { + if (i + AO_CMAC_KEY_LEN < len) + ao_aes_run(&cmac_data[i], NULL); + else + ao_aes_run(&cmac_data[i], &cmac_data[len + AO_CMAC_KEY_LEN + 2]); + } + printf ("PACKET "); + for (i = 0; i < len + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN; i++) + printf("%02x", cmac_data[i]); + printf ("\n"); } -__code struct ao_cmds ao_radio_cmac_cmds[] = { - { ao_radio_cmac_key, "k ...\0Set AES-CMAC key." }, +static __code struct ao_cmds ao_radio_cmac_cmds[] = { + { ao_radio_cmac_key, "k\0Set AES-CMAC key. 16 key bytes follow on next line" }, { ao_radio_cmac_send, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, { ao_radio_cmac_recv, "S \0Receive AES-CMAC packet. Timeout in ms" }, { 0, NULL }, @@ -105,5 +162,4 @@ void ao_radio_cmac_init(void) { ao_cmd_register(&ao_radio_cmac_cmds[0]); - } diff --git a/src/ao_telelaunch.c b/src/ao_telelaunch.c new file mode 100644 index 00000000..b5404710 --- /dev/null +++ b/src/ao_telelaunch.c @@ -0,0 +1,47 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +void +main(void) +{ + ao_clock_init(); + + /* Turn on the red LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + + ao_timer_init(); + ao_adc_init(); + ao_beep_init(); + ao_cmd_init(); + ao_spi_init(); + ao_storage_init(); + ao_usb_init(); + ao_radio_init(); + ao_igniter_init(); +#if HAS_DBG + ao_dbg_init(); +#endif + ao_aes_init(); + ao_radio_cmac_init(); + ao_launch_init(); + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 9e9b3bf6..819dc7df 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -267,6 +267,7 @@ #define BT_LINK_PIN_INDEX 7 #define BT_LINK_PIN P2_1 #define HAS_MONITOR 1 + #define HAS_AES 1 #endif #if defined(TELEBT_V_0_1) @@ -322,7 +323,7 @@ #define IGNITE_ON_P2 1 #define IGNITE_ON_P0 0 #define PACKET_HAS_MASTER 0 - #define PACKET_HAS_SLAVE 1 + #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 2 #define AO_LED_GREEN 1 #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) @@ -333,6 +334,7 @@ #define HAS_ACCEL 0 #define HAS_IGNITE 1 #define HAS_MONITOR 0 + #define HAS_AES 1 #endif #if DBG_ON_P1 diff --git a/src/core/ao.h b/src/core/ao.h index 2394d401..2898852b 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1633,6 +1633,10 @@ ao_lcd_init(void); __xdata uint8_t ao_aes_mutex; +/* AES keys and blocks are 128 bits */ + +#define AO_AES_LEN 16 + enum ao_aes_mode { ao_aes_mode_cbc_mac }; @@ -1648,6 +1652,9 @@ ao_aes_set_mode(enum ao_aes_mode mode); void ao_aes_set_key(__xdata uint8_t *in); +void +ao_aes_zero_iv(void); + void ao_aes_run(__xdata uint8_t *in, __xdata uint8_t *out); @@ -1655,6 +1662,11 @@ ao_aes_run(__xdata uint8_t *in, void ao_aes_init(void); +/* ao_radio_cmac.c */ + +void +ao_radio_cmac_init(void); + /* ao_launch.c */ void ao_launch_init(void); diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index 85565172..5bbbf71b 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -44,6 +44,10 @@ main(void) ao_btm_init(); #if HAS_DBG ao_dbg_init(); +#endif +#if HAS_AES + ao_aes_init(); + ao_radio_cmac_init(); #endif ao_config_init(); ao_start_scheduler(); diff --git a/src/product/ao_teledongle.c b/src/product/ao_teledongle.c index 008b200a..b8be9f45 100644 --- a/src/product/ao_teledongle.c +++ b/src/product/ao_teledongle.c @@ -35,6 +35,8 @@ main(void) #if HAS_DBG ao_dbg_init(); #endif + ao_aes_init(); + ao_radio_cmac_init(); ao_config_init(); ao_start_scheduler(); } diff --git a/src/teledongle-v0.1/.sdcdbrc b/src/teledongle-v0.1/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/teledongle-v0.1/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telelaunch-v0.1/Makefile.defs b/src/telelaunch-v0.1/Makefile.defs index e4934ffa..56f5730b 100644 --- a/src/telelaunch-v0.1/Makefile.defs +++ b/src/telelaunch-v0.1/Makefile.defs @@ -5,6 +5,8 @@ SRC = \ $(SPI_DRIVER_SRC) \ $(EE_DRIVER_SRC) \ ao_launch.c \ + ao_aes.c \ + ao_radio_cmac.c \ $(DBG_SRC) PRODUCT=TeleLaunch-v0.1 -- cgit v1.2.3 From 4299b5a36a2f6f9f7bbbc3a1b935dd2357c1fb0f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Jul 2011 20:04:05 -0700 Subject: altos: Implement remote launch protocol Uses the radio_cmac module to provide secure communication. Keeps igniter closed for 500ms. Provides remote status for arming and ignition. Signed-off-by: Keith Packard --- src/ao_launch.c | 170 +++++++++++++++++++++++--- src/ao_radio_cmac.c | 278 ++++++++++++++++++++++++++++++------------ src/ao_telelaunch.c | 1 - src/cc1111/ao_ignite.c | 6 - src/cc1111/ao_packet_master.c | 6 +- src/cc1111/ao_timer.c | 1 + src/core/ao.h | 59 ++++++++- src/core/ao_cmd.c | 44 +++++-- src/core/ao_config.c | 36 ++++++ src/core/ao_task.c | 7 +- 10 files changed, 497 insertions(+), 111 deletions(-) (limited to 'src') diff --git a/src/ao_launch.c b/src/ao_launch.c index 4870869e..6c154719 100644 --- a/src/ao_launch.c +++ b/src/ao_launch.c @@ -17,43 +17,183 @@ #include "ao.h" +__xdata uint16_t ao_launch_ignite; + +static void +ao_launch_run(void) +{ + for (;;) { + while (!ao_launch_ignite) + ao_sleep(&ao_launch_ignite); + while (ao_launch_ignite) { + ao_launch_ignite = 0; + + ao_ignition[ao_igniter_drogue].firing = 1; + ao_ignition[ao_igniter_main].firing = 1; + AO_IGNITER_DROGUE = 1; + ao_delay(AO_MS_TO_TICKS(500)); + AO_IGNITER_DROGUE = 0; + ao_ignition[ao_igniter_drogue].firing = 0; + ao_ignition[ao_igniter_main].firing = 0; + } + } +} + +static void +ao_launch_status(void) +{ + uint8_t i; + for (;;) { + ao_delay(AO_SEC_TO_TICKS(1)); + if (ao_igniter_status(ao_igniter_drogue) == ao_igniter_ready) { + if (ao_igniter_status(ao_igniter_main) == ao_igniter_ready) { + for (i = 0; i < 5; i++) { + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(50)); + ao_delay(AO_MS_TO_TICKS(100)); + } + } else { + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + } + } + } +} + +static __pdata uint8_t ao_launch_armed; +static __pdata uint16_t ao_launch_arm_time; + static void ao_launch(void) { - enum ao_igniter_status arm_status, ignite_status; + static __xdata struct ao_launch_command command; + static __xdata struct ao_launch_query query; + int16_t time_difference; ao_led_off(AO_LED_RED); ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); for (;;) { - arm_status = ao_igniter_status(ao_igniter_drogue); + if (ao_radio_cmac_recv(&command, sizeof (command), 0) != AO_RADIO_CMAC_OK) + continue; + + printf ("tick %d serial %d cmd %d channel %d\n", + command.tick, command.serial, command.cmd, command.channel); + + if (command.serial != ao_serial_number) { + printf ("serial number mismatch\n"); + continue; + } - switch (arm_status) { - case ao_igniter_unknown: + switch (command.cmd) { + case AO_LAUNCH_QUERY: + if (command.channel == 0) { + query.valid = 1; + query.arm_status = ao_igniter_status(ao_igniter_drogue); + query.igniter_status = ao_igniter_status(ao_igniter_main); + } else { + query.valid = 0; + } + query.tick = ao_time(); + query.serial = ao_serial_number; + query.channel = command.channel; + printf ("query tick %d serial %d channel %d valid %d arm %d igniter %d\n", + query.tick, query.serial, query.channel, query.valid, query.arm_status, + query.igniter_status); + ao_radio_cmac_send(&query, sizeof (query)); break; - case ao_igniter_active: - case ao_igniter_open: + case AO_LAUNCH_ARM: + if (command.channel != 0) + break; + time_difference = command.tick - ao_time(); + printf ("arm tick %d local tick %d\n", command.tick, ao_time()); + if (time_difference < 0) + time_difference = -time_difference; + if (time_difference > 10) { + printf ("time difference too large %d\n", time_difference); + break; + } + printf ("armed\n"); + ao_launch_armed = 1; + ao_launch_arm_time = ao_time(); break; - case ao_igniter_ready: - ignite_status = ao_igniter_status(ao_igniter_main); - switch (ignite_status) { - case ao_igniter_unknown: - /* some kind of failure signal here */ + case AO_LAUNCH_FIRE: + if (command.channel != 0) break; - case ao_igniter_active: + if (!ao_launch_armed) { + printf ("not armed\n"); break; - case ao_igniter_open: + } + if ((uint16_t) (ao_launch_arm_time - ao_time()) > AO_SEC_TO_TICKS(20)) { + printf ("late launch arm_time %d time %d\n", + ao_launch_arm_time, ao_time()); + break; + } + time_difference = command.tick - ao_time(); + if (time_difference < 0) + time_difference = -time_difference; + if (time_difference > 10) { + printf ("time different too large %d\n", time_difference); break; } + printf ("ignite\n"); + ao_launch_ignite = 1; + ao_wakeup(&ao_launch_ignite); break; } - ao_delay(AO_SEC_TO_TICKS(1)); } } +void +ao_launch_test(void) +{ + switch (ao_igniter_status(ao_igniter_drogue)) { + case ao_igniter_ready: + case ao_igniter_active: + printf ("Armed: "); + switch (ao_igniter_status(ao_igniter_main)) { + default: + printf("unknown status\n"); + break; + case ao_igniter_ready: + printf("igniter good\n"); + break; + case ao_igniter_open: + printf("igniter bad\n"); + break; + } + break; + default: + printf("Disarmed\n"); + } +} + +void +ao_launch_manual(void) +{ + ao_cmd_white(); + if (!ao_match_word("DoIt")) + return; + ao_cmd_white(); + ao_launch_ignite = 1; + ao_wakeup(&ao_launch_ignite); +} + static __xdata struct ao_task ao_launch_task; +static __xdata struct ao_task ao_launch_ignite_task; +static __xdata struct ao_task ao_launch_status_task; + +__code struct ao_cmds ao_launch_cmds[] = { + { ao_launch_test, "t\0Test launch continuity" }, + { ao_launch_manual, "i \0Fire igniter. is doit with D&I" }, + { 0, NULL } +}; void ao_launch_init(void) { - ao_add_task(&ao_launch_task, ao_launch, "launch status"); + AO_IGNITER_DROGUE = 0; + AO_IGNITER_MAIN = 0; + AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; + ao_cmd_register(&ao_launch_cmds[0]); + ao_add_task(&ao_launch_task, ao_launch, "launch listener"); + ao_add_task(&ao_launch_ignite_task, ao_launch_run, "launch igniter"); + ao_add_task(&ao_launch_status_task, ao_launch_status, "launch status"); } diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c index 7648a2f5..9694b5b3 100644 --- a/src/ao_radio_cmac.c +++ b/src/ao_radio_cmac.c @@ -17,27 +17,24 @@ #include "ao.h" -#define AO_CMAC_KEY_LEN 16 +#define AO_CMAC_KEY_LEN AO_AES_LEN #define AO_CMAC_MAX_LEN (128 - AO_CMAC_KEY_LEN) -static __xdata uint8_t cmac_key[AO_CMAC_KEY_LEN]; +static __xdata uint8_t ao_radio_cmac_mutex; static __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN]; static __pdata uint8_t ao_radio_cmac_len; static uint8_t getnibble(void) { - __pdata char 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; + int8_t b; + + b = ao_cmd_hexchar(getchar()); + if (b < 0) { + ao_cmd_status = ao_cmd_lex_error; + return 0; + } + return (uint8_t) b; } static uint8_t @@ -49,20 +46,137 @@ getbyte(void) return b; } +static uint8_t +round_len(uint8_t len) +{ + uint8_t rem; + + /* Make sure we transfer at least one packet, and + * then make sure every packet is full. Note that + * there is no length encoded, and that the receiver + * must deal with any extra bytes in the packet + */ + if (len < AO_CMAC_KEY_LEN) + len = AO_CMAC_KEY_LEN; + rem = len % AO_CMAC_KEY_LEN; + if (rem != 0) + len += (AO_CMAC_KEY_LEN - rem); + return len; +} + +/* + * Sign and deliver the data sitting in the cmac buffer + */ static void -ao_radio_cmac_key(void) __reentrant +radio_cmac_send(uint8_t len) __reentrant { uint8_t i; - for (i = 0; i < AO_CMAC_KEY_LEN; i++) { - cmac_key[i] = getbyte(); - if (ao_cmd_status != ao_cmd_success) - return; + len = round_len(len); + /* Make sure the AES key is loaded */ + ao_config_get(); + +#if HAS_MONITOR + ao_set_monitor(0); +#endif + + ao_mutex_get(&ao_aes_mutex); + ao_aes_set_mode(ao_aes_mode_cbc_mac); + ao_aes_set_key(ao_config.aes_key); + ao_aes_zero_iv(); + for (i = 0; i < len; i += AO_CMAC_KEY_LEN) { + if (i + AO_CMAC_KEY_LEN < len) + ao_aes_run(&cmac_data[i], NULL); + else + ao_aes_run(&cmac_data[i], &cmac_data[len]); } + ao_mutex_put(&ao_aes_mutex); + + ao_radio_send(cmac_data, len + AO_CMAC_KEY_LEN); +} + +/* + * Receive and validate an incoming packet + */ + +static int8_t +radio_cmac_recv(uint8_t len, uint16_t timeout) __reentrant +{ + uint8_t i; + + len = round_len(len); +#if HAS_MONITOR + ao_set_monitor(0); +#endif + if (timeout) + ao_alarm(timeout); + + i = ao_radio_recv(cmac_data, len + AO_CMAC_KEY_LEN + 2); + ao_clear_alarm(); + + if (!i) + return AO_RADIO_CMAC_TIMEOUT; + + if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & PKT_APPEND_STATUS_1_CRC_OK)) + return AO_RADIO_CMAC_CRC_ERROR; + + ao_config_get(); + + /* Compute the packet signature + */ + ao_mutex_get(&ao_aes_mutex); + ao_aes_set_mode(ao_aes_mode_cbc_mac); + ao_aes_set_key(ao_config.aes_key); + ao_aes_zero_iv(); + for (i = 0; i < len; i += AO_CMAC_KEY_LEN) { + if (i + AO_CMAC_KEY_LEN < len) + ao_aes_run(&cmac_data[i], NULL); + else + ao_aes_run(&cmac_data[i], &cmac_data[len + AO_CMAC_KEY_LEN + 2]); + } + ao_mutex_put(&ao_aes_mutex); + + /* Check the packet signature against the signature provided + * over the link + */ + + if (memcmp(&cmac_data[len], + &cmac_data[len + AO_CMAC_KEY_LEN + 2], + AO_CMAC_KEY_LEN) != 0) { + return AO_RADIO_CMAC_MAC_ERROR; + } + + return AO_RADIO_CMAC_OK; +} + +int8_t +ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant +{ + if (len > AO_CMAC_MAX_LEN) + return AO_RADIO_CMAC_LEN_ERROR; + ao_mutex_get(&ao_radio_cmac_mutex); + memcpy(cmac_data, packet, len); + radio_cmac_send(len); + ao_mutex_put(&ao_radio_cmac_mutex); + return AO_RADIO_CMAC_OK; +} + +int8_t +ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant +{ + uint8_t i; + if (len > AO_CMAC_MAX_LEN) + return AO_RADIO_CMAC_LEN_ERROR; + ao_mutex_get(&ao_radio_cmac_mutex); + i = radio_cmac_recv(len, timeout); + if (i == AO_RADIO_CMAC_OK) + memcpy(packet, cmac_data, len); + ao_mutex_put(&ao_radio_cmac_mutex); + return i; } static void -ao_radio_cmac_send(void) __reentrant +radio_cmac_send_cmd(void) __reentrant { uint8_t i; uint8_t len; @@ -70,43 +184,25 @@ ao_radio_cmac_send(void) __reentrant ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - if (ao_cmd_lex_i < AO_CMAC_KEY_LEN || - ao_cmd_lex_i > AO_CMAC_MAX_LEN || - ao_cmd_lex_i % AO_CMAC_KEY_LEN != 0) - { + len = ao_cmd_lex_i; + if (len > AO_CMAC_MAX_LEN) { ao_cmd_status = ao_cmd_syntax_error; return; } flush(); + ao_mutex_get(&ao_radio_cmac_mutex); len = ao_cmd_lex_i; for (i = 0; i < len; i++) { cmac_data[i] = getbyte(); if (ao_cmd_status != ao_cmd_success) return; } - ao_mutex_get(&ao_aes_mutex); - ao_aes_set_mode(ao_aes_mode_cbc_mac); - ao_aes_set_key(cmac_key); - ao_aes_zero_iv(); - for (i = 0; i < len; i += AO_CMAC_KEY_LEN) { - if (i + AO_CMAC_KEY_LEN < len) - ao_aes_run(&cmac_data[i], NULL); - else - ao_aes_run(&cmac_data[i], &cmac_data[len]); - } - ao_mutex_put(&ao_aes_mutex); -#if HAS_MONITOR - ao_set_monitor(0); -#endif - printf("send:"); - for (i = 0; i < len + AO_CMAC_KEY_LEN; i++) - printf(" %02x", cmac_data[i]); - printf("\n"); flush(); - ao_radio_send(cmac_data, len + AO_CMAC_KEY_LEN); + radio_cmac_send(len); + ao_mutex_put(&ao_radio_cmac_mutex); } static void -ao_radio_cmac_recv(void) __reentrant +radio_cmac_recv_cmd(void) __reentrant { uint8_t len, i; uint16_t timeout; @@ -114,47 +210,79 @@ ao_radio_cmac_recv(void) __reentrant ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - if (ao_cmd_lex_i < AO_CMAC_KEY_LEN || - ao_cmd_lex_i > AO_CMAC_MAX_LEN || - ao_cmd_lex_i % AO_CMAC_KEY_LEN != 0) - { - ao_cmd_status = ao_cmd_syntax_error; - return; - } len = ao_cmd_lex_i; ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) return; - timeout = ao_cmd_lex_i; -#if HAS_MONITOR - ao_set_monitor(0); -#endif - if (timeout) - ao_alarm(timeout); - if (!ao_radio_recv(cmac_data, len + AO_CMAC_KEY_LEN + 2)) { - printf("timeout\n"); + timeout = AO_MS_TO_TICKS(ao_cmd_lex_i); + ao_mutex_get(&ao_radio_cmac_mutex); + i = radio_cmac_recv(len, timeout); + if (i == AO_RADIO_CMAC_OK) { + printf ("PACKET "); + for (i = 0; i < len; i++) + printf("%02x", cmac_data[i]); + printf ("\n"); + } else + printf ("ERROR %d\n", i); + ao_mutex_put(&ao_radio_cmac_mutex); +} + +static void +launch_report_cmd(void) __reentrant +{ + static __xdata struct ao_launch_command command; + static __xdata struct ao_launch_query query; + uint8_t channel; + uint16_t serial; + uint8_t i; + + ao_cmd_decimal(); + serial = ao_cmd_lex_i; + ao_cmd_decimal(); + channel = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) return; + flush(); + for (i = 0; i < 10; i++) { + printf ("."); flush(); + command.tick = 0; + command.serial = serial; + command.cmd = AO_LAUNCH_QUERY; + command.channel = channel; + ao_radio_cmac_send(&command, sizeof (command)); + switch (ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500))) { + case AO_RADIO_CMAC_OK: + printf("\n"); + switch (query.arm_status) { + case ao_igniter_ready: + case ao_igniter_active: + printf ("Armed: "); + switch (query.igniter_status) { + default: + printf("unknown status\n"); + break; + case ao_igniter_ready: + printf("igniter good\n"); + break; + case ao_igniter_open: + printf("igniter bad\n"); + break; + } + default: + printf("Disarmed\n"); + } + return; + default: + continue; + } } - ao_mutex_get(&ao_aes_mutex); - ao_aes_set_mode(ao_aes_mode_cbc_mac); - ao_aes_set_key(cmac_key); - ao_aes_zero_iv(); - for (i = 0; i < len; i += AO_CMAC_KEY_LEN) { - if (i + AO_CMAC_KEY_LEN < len) - ao_aes_run(&cmac_data[i], NULL); - else - ao_aes_run(&cmac_data[i], &cmac_data[len + AO_CMAC_KEY_LEN + 2]); - } - printf ("PACKET "); - for (i = 0; i < len + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN; i++) - printf("%02x", cmac_data[i]); - printf ("\n"); + printf ("Timeout\n"); } static __code struct ao_cmds ao_radio_cmac_cmds[] = { - { ao_radio_cmac_key, "k\0Set AES-CMAC key. 16 key bytes follow on next line" }, - { ao_radio_cmac_send, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, - { ao_radio_cmac_recv, "S \0Receive AES-CMAC packet. Timeout in ms" }, + { radio_cmac_send_cmd, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, + { radio_cmac_recv_cmd, "S \0Receive AES-CMAC packet. Timeout in ms" }, + { launch_report_cmd, "l \0Get remote launch status" }, { 0, NULL }, }; diff --git a/src/ao_telelaunch.c b/src/ao_telelaunch.c index b5404710..506431de 100644 --- a/src/ao_telelaunch.c +++ b/src/ao_telelaunch.c @@ -35,7 +35,6 @@ main(void) ao_storage_init(); ao_usb_init(); ao_radio_init(); - ao_igniter_init(); #if HAS_DBG ao_dbg_init(); #endif diff --git a/src/cc1111/ao_ignite.c b/src/cc1111/ao_ignite.c index 5238beb4..0fd2b4bf 100644 --- a/src/cc1111/ao_ignite.c +++ b/src/cc1111/ao_ignite.c @@ -39,12 +39,6 @@ #define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) #define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) -struct ao_ignition { - uint8_t request; - uint8_t fired; - uint8_t firing; -}; - __xdata struct ao_ignition ao_ignition[2]; void diff --git a/src/cc1111/ao_packet_master.c b/src/cc1111/ao_packet_master.c index b0fdf5a8..0d0be30e 100644 --- a/src/cc1111/ao_packet_master.c +++ b/src/cc1111/ao_packet_master.c @@ -80,13 +80,16 @@ ao_packet_master(void) ao_packet_master_time = ao_time(); ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; while (ao_packet_enable) { + uint8_t r; memcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN); ao_packet_send(); if (ao_tx_packet.len) ao_packet_master_busy(); ao_packet_master_check_busy(); ao_alarm(ao_packet_master_delay); - if (ao_packet_recv()) { + r = ao_packet_recv(); + ao_clear_alarm(); + if (r) { /* if we can transmit data, do so */ if (ao_packet_tx_used && ao_tx_packet.len == 0) continue; @@ -95,6 +98,7 @@ ao_packet_master(void) ao_packet_master_sleeping = 1; ao_alarm(ao_packet_master_delay); ao_sleep(&ao_packet_master_sleeping); + ao_clear_alarm(); ao_packet_master_sleeping = 0; } } diff --git a/src/cc1111/ao_timer.c b/src/cc1111/ao_timer.c index c977fbc8..aadee71e 100644 --- a/src/cc1111/ao_timer.c +++ b/src/cc1111/ao_timer.c @@ -31,6 +31,7 @@ ao_delay(uint16_t ticks) { ao_alarm(ticks); ao_sleep(&ao_forever); + ao_clear_alarm(); } #define T1_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ diff --git a/src/core/ao.h b/src/core/ao.h index 2898852b..a5bbb6f1 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -68,6 +68,10 @@ ao_wakeup(__xdata void *wchan); void ao_alarm(uint16_t delay); +/* Clear any pending alarm */ +void +ao_clear_alarm(void); + /* Yield the processor to another task */ void ao_yield(void) ao_arch_naked_declare; @@ -342,6 +346,12 @@ ao_cmd_put16(uint16_t v); void ao_cmd_white(void); +int8_t +ao_cmd_hexchar(char c); + +void +ao_cmd_hexbyte(void); + void ao_cmd_hex(void); @@ -1417,6 +1427,14 @@ enum ao_igniter_status { ao_igniter_open, /* open circuit detected */ }; +struct ao_ignition { + uint8_t request; + uint8_t fired; + uint8_t firing; +}; + +extern __xdata struct ao_ignition ao_ignition[2]; + enum ao_igniter_status ao_igniter_status(enum ao_igniter igniter); @@ -1431,7 +1449,8 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 8 +#define AO_CONFIG_MINOR 9 +#define AO_AES_LEN 16 struct ao_config { uint8_t major; @@ -1448,6 +1467,7 @@ struct ao_config { uint8_t pad_orientation; /* minor version 6 */ uint32_t radio_setting; /* minor version 7 */ uint8_t radio_enable; /* minor version 8 */ + uint8_t aes_key[AO_AES_LEN]; /* minor version 9 */ }; #define AO_IGNITE_MODE_DUAL 0 @@ -1635,8 +1655,6 @@ __xdata uint8_t ao_aes_mutex; /* AES keys and blocks are 128 bits */ -#define AO_AES_LEN 16 - enum ao_aes_mode { ao_aes_mode_cbc_mac }; @@ -1664,10 +1682,45 @@ ao_aes_init(void); /* ao_radio_cmac.c */ +int8_t +ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant; + +#define AO_RADIO_CMAC_OK 0 +#define AO_RADIO_CMAC_LEN_ERROR -1 +#define AO_RADIO_CMAC_CRC_ERROR -2 +#define AO_RADIO_CMAC_MAC_ERROR -3 +#define AO_RADIO_CMAC_TIMEOUT -4 + +int8_t +ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant; + void ao_radio_cmac_init(void); /* ao_launch.c */ + +struct ao_launch_command { + uint16_t tick; + uint16_t serial; + uint8_t cmd; + uint8_t channel; + uint16_t unused; +}; + +#define AO_LAUNCH_QUERY 1 + +struct ao_launch_query { + uint16_t tick; + uint16_t serial; + uint8_t channel; + uint8_t valid; + uint8_t arm_status; + uint8_t igniter_status; +}; + +#define AO_LAUNCH_ARM 2 +#define AO_LAUNCH_FIRE 3 + void ao_launch_init(void); diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 7663d875..9e14c221 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -22,7 +22,7 @@ __pdata uint32_t ao_cmd_lex_u32; __pdata char ao_cmd_lex_c; __pdata enum ao_cmd_status ao_cmd_status; -#define CMD_LEN 32 +#define CMD_LEN 48 static __xdata char cmd_line[CMD_LEN]; static __pdata uint8_t cmd_len; @@ -128,22 +128,48 @@ ao_cmd_white(void) ao_cmd_lex(); } +int8_t +ao_cmd_hexchar(char c) +{ + 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); + return -1; +} + +void +ao_cmd_hexbyte(void) +{ + uint8_t i; + int8_t n; + + ao_cmd_lex_i = 0; + ao_cmd_white(); + for (i = 0; i < 2; i++) { + n = ao_cmd_hexchar(ao_cmd_lex_c); + if (n < 0) { + ao_cmd_status = ao_cmd_syntax_error; + break; + } + ao_cmd_lex_i = (ao_cmd_lex_i << 4) | n; + ao_cmd_lex(); + } +} + void ao_cmd_hex(void) { __pdata uint8_t r = ao_cmd_lex_error; - uint8_t n; + int8_t n; ao_cmd_lex_i = 0; ao_cmd_white(); for(;;) { - if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') - n = (ao_cmd_lex_c - '0'); - else if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f') - n = (ao_cmd_lex_c - 'a' + 10); - else if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F') - n = (ao_cmd_lex_c - 'A' + 10); - else + n = ao_cmd_hexchar(ao_cmd_lex_c); + if (n < 0) break; ao_cmd_lex_i = (ao_cmd_lex_i << 4) | n; r = ao_cmd_success; diff --git a/src/core/ao_config.c b/src/core/ao_config.c index ec2b61f6..7f999feb 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -74,11 +74,14 @@ _ao_config_get(void) if (ao_config.major != AO_CONFIG_MAJOR) { ao_config.major = AO_CONFIG_MAJOR; ao_config.minor = 0; + + /* Version 0 stuff */ ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); + ao_config_dirty = 1; } if (ao_config.minor < AO_CONFIG_MINOR) { /* Fixups for minor version 1 */ @@ -104,6 +107,8 @@ _ao_config_get(void) ao_config.radio_setting = ao_config.radio_cal; if (ao_config.minor < 8) ao_config.radio_enable = TRUE; + if (ao_config.minor < 9) + memset(&ao_config.aes_key, '\0', AO_AES_LEN); ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -414,6 +419,33 @@ ao_config_radio_enable_set(void) __reentrant _ao_config_edit_finish(); } +#if HAS_AES +void +ao_config_key_show(void) __reentrant +{ + uint8_t i; + printf("AES key: "); + for (i = 0; i < AO_AES_LEN; i++) + printf ("%02x", ao_config.aes_key[i]); + printf("\n"); +} + +void +ao_config_key_set(void) __reentrant +{ + uint8_t i; + + _ao_config_edit_start(); + for (i = 0; i < AO_AES_LEN; i++) { + ao_cmd_hexbyte(); + if (ao_cmd_status != ao_cmd_success) + break; + ao_config.aes_key[i] = ao_cmd_lex_i; + } + _ao_config_edit_finish(); +} +#endif + struct ao_config_var { __code char *str; void (*set)(void) __reentrant; @@ -461,6 +493,10 @@ __code struct ao_config_var ao_config_vars[] = { #if HAS_ACCEL { "o <0 antenna up, 1 antenna down>\0Set pad orientation", ao_config_pad_orientation_set,ao_config_pad_orientation_show }, +#endif +#if HAS_AES + { "k <32 hex digits>\0Set AES encryption key", + ao_config_key_set, ao_config_key_show }, #endif { "s\0Show", ao_config_show, 0 }, diff --git a/src/core/ao_task.c b/src/core/ao_task.c index 32826114..a19a6a6f 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -107,7 +107,6 @@ ao_sleep(__xdata void *wchan) ao_cur_task->wchan = wchan; ); ao_yield(); - ao_cur_task->alarm = 0; if (ao_cur_task->wchan) { ao_cur_task->wchan = NULL; return 1; @@ -135,6 +134,12 @@ ao_alarm(uint16_t delay) ao_cur_task->alarm = 1; } +void +ao_clear_alarm(void) +{ + ao_cur_task->alarm = 0; +} + void ao_exit(void) { -- cgit v1.2.3 From bc1b94df4d6b92e794ec93d9c1682ae5f61efa61 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Jul 2011 22:25:45 -0700 Subject: altos: Finish up primitive telelaunch protocol This adds two commands to teledongle, one to query and one to actually fire the igniter. These will (eventually) want to be replaced with something nicer. Signed-off-by: Keith Packard --- src/ao_launch.c | 44 +++++++++++++--------- src/ao_radio_cmac.c | 101 ++++++++++++++++++++++++++++++++++++++++++--------- src/core/ao_config.c | 2 +- 3 files changed, 111 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/ao_launch.c b/src/ao_launch.c index 6c154719..35afbda8 100644 --- a/src/ao_launch.c +++ b/src/ao_launch.c @@ -19,6 +19,12 @@ __xdata uint16_t ao_launch_ignite; +#if 0 +#define PRINTD(...) printf(__VA_ARGS__) +#else +#define PRINTD(...) +#endif + static void ao_launch_run(void) { @@ -71,19 +77,20 @@ ao_launch(void) ao_led_off(AO_LED_RED); ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); for (;;) { + flush(); if (ao_radio_cmac_recv(&command, sizeof (command), 0) != AO_RADIO_CMAC_OK) continue; - printf ("tick %d serial %d cmd %d channel %d\n", + PRINTD ("tick %d serial %d cmd %d channel %d\n", command.tick, command.serial, command.cmd, command.channel); - if (command.serial != ao_serial_number) { - printf ("serial number mismatch\n"); - continue; - } - switch (command.cmd) { case AO_LAUNCH_QUERY: + if (command.serial != ao_serial_number) { + PRINTD ("serial number mismatch\n"); + break; + } + if (command.channel == 0) { query.valid = 1; query.arm_status = ao_igniter_status(ao_igniter_drogue); @@ -94,35 +101,38 @@ ao_launch(void) query.tick = ao_time(); query.serial = ao_serial_number; query.channel = command.channel; - printf ("query tick %d serial %d channel %d valid %d arm %d igniter %d\n", + PRINTD ("query tick %d serial %d channel %d valid %d arm %d igniter %d\n", query.tick, query.serial, query.channel, query.valid, query.arm_status, query.igniter_status); ao_radio_cmac_send(&query, sizeof (query)); break; case AO_LAUNCH_ARM: + if (command.serial != ao_serial_number) { + PRINTD ("serial number mismatch\n"); + break; + } + if (command.channel != 0) break; time_difference = command.tick - ao_time(); - printf ("arm tick %d local tick %d\n", command.tick, ao_time()); + PRINTD ("arm tick %d local tick %d\n", command.tick, ao_time()); if (time_difference < 0) time_difference = -time_difference; if (time_difference > 10) { - printf ("time difference too large %d\n", time_difference); + PRINTD ("time difference too large %d\n", time_difference); break; } - printf ("armed\n"); + PRINTD ("armed\n"); ao_launch_armed = 1; ao_launch_arm_time = ao_time(); break; case AO_LAUNCH_FIRE: - if (command.channel != 0) - break; if (!ao_launch_armed) { - printf ("not armed\n"); + PRINTD ("not armed\n"); break; } - if ((uint16_t) (ao_launch_arm_time - ao_time()) > AO_SEC_TO_TICKS(20)) { - printf ("late launch arm_time %d time %d\n", + if ((uint16_t) (ao_time() - ao_launch_arm_time) > AO_SEC_TO_TICKS(20)) { + PRINTD ("late launch arm_time %d time %d\n", ao_launch_arm_time, ao_time()); break; } @@ -130,10 +140,10 @@ ao_launch(void) if (time_difference < 0) time_difference = -time_difference; if (time_difference > 10) { - printf ("time different too large %d\n", time_difference); + PRINTD ("time different too large %d\n", time_difference); break; } - printf ("ignite\n"); + PRINTD ("ignite\n"); ao_launch_ignite = 1; ao_wakeup(&ao_launch_ignite); break; diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c index 9694b5b3..c2757b16 100644 --- a/src/ao_radio_cmac.c +++ b/src/ao_radio_cmac.c @@ -227,14 +227,37 @@ radio_cmac_recv_cmd(void) __reentrant ao_mutex_put(&ao_radio_cmac_mutex); } +static __xdata struct ao_launch_command command; +static __xdata struct ao_launch_query query; + + +static int8_t +launch_query(uint16_t serial, uint8_t channel) +{ + uint8_t i; + int8_t r = AO_RADIO_CMAC_OK; + + for (i = 0; i < 10; i++) { + printf ("."); flush(); + command.tick = ao_time(); + command.serial = serial; + command.cmd = AO_LAUNCH_QUERY; + command.channel = channel; + ao_radio_cmac_send(&command, sizeof (command)); + r = ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500)); + if (r == AO_RADIO_CMAC_OK) + break; + } + printf("\n"); flush(); + return r; +} + static void launch_report_cmd(void) __reentrant { - static __xdata struct ao_launch_command command; - static __xdata struct ao_launch_query query; uint8_t channel; uint16_t serial; - uint8_t i; + int8_t r; ao_cmd_decimal(); serial = ao_cmd_lex_i; @@ -242,17 +265,10 @@ launch_report_cmd(void) __reentrant channel = ao_cmd_lex_i; if (ao_cmd_status != ao_cmd_success) return; - flush(); - for (i = 0; i < 10; i++) { - printf ("."); flush(); - command.tick = 0; - command.serial = serial; - command.cmd = AO_LAUNCH_QUERY; - command.channel = channel; - ao_radio_cmac_send(&command, sizeof (command)); - switch (ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500))) { - case AO_RADIO_CMAC_OK: - printf("\n"); + r = launch_query(serial, channel); + switch (r) { + case AO_RADIO_CMAC_OK: + if (query.valid) { switch (query.arm_status) { case ao_igniter_ready: case ao_igniter_active: @@ -268,21 +284,70 @@ launch_report_cmd(void) __reentrant printf("igniter bad\n"); break; } + break; default: printf("Disarmed\n"); } - return; - default: - continue; + } else { + printf("Invalid channel %d\n", channel); } + break; + default: + printf("Error %d\n", r); + break; + } +} + +static void +launch_fire_cmd(void) __reentrant +{ + static __xdata struct ao_launch_command command; + uint8_t channel; + uint16_t serial; + uint8_t secs; + uint8_t i; + int8_t r; + uint16_t tick_offset; + + ao_cmd_decimal(); + serial = ao_cmd_lex_i; + ao_cmd_decimal(); + channel = ao_cmd_lex_i; + ao_cmd_decimal(); + secs = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) + return; + tick_offset = ao_time(); + r = launch_query(serial, channel); + tick_offset -= query.tick; + + for (i = 0; i < 4; i++) { + printf("arm %d\n", i); flush(); + command.tick = ao_time() - tick_offset; + command.serial = serial; + command.cmd = AO_LAUNCH_ARM; + command.channel = channel; + ao_radio_cmac_send(&command, sizeof (command)); + } + secs = secs * 10 - 5; + if (secs > 100) + secs = 100; + for (i = 0; i < secs; i++) { + printf("fire %d\n", i); flush(); + command.tick = ao_time() - tick_offset; + command.serial = serial; + command.cmd = AO_LAUNCH_FIRE; + command.channel = 0; + ao_radio_cmac_send(&command, sizeof (command)); + ao_delay(AO_MS_TO_TICKS(100)); } - printf ("Timeout\n"); } static __code struct ao_cmds ao_radio_cmac_cmds[] = { { radio_cmac_send_cmd, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, { radio_cmac_recv_cmd, "S \0Receive AES-CMAC packet. Timeout in ms" }, { launch_report_cmd, "l \0Get remote launch status" }, + { launch_fire_cmd, "f \0Fire remote igniter" }, { 0, NULL }, }; diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 7f999feb..28854ab5 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -108,7 +108,7 @@ _ao_config_get(void) if (ao_config.minor < 8) ao_config.radio_enable = TRUE; if (ao_config.minor < 9) - memset(&ao_config.aes_key, '\0', AO_AES_LEN); + memset(&ao_config.aes_key, 0, AO_AES_LEN); ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } -- cgit v1.2.3 From be117376179126824439d98379079025ca0b245a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 1 Aug 2011 17:06:49 -0700 Subject: altos: Keep relay closed while firing launcher Instead of opening the relay while checking the desired state, keep it closed until the state goes off. Signed-off-by: Keith Packard --- src/ao_launch.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/ao_launch.c b/src/ao_launch.c index 35afbda8..a593d0b2 100644 --- a/src/ao_launch.c +++ b/src/ao_launch.c @@ -31,17 +31,17 @@ ao_launch_run(void) for (;;) { while (!ao_launch_ignite) ao_sleep(&ao_launch_ignite); + ao_ignition[ao_igniter_drogue].firing = 1; + ao_ignition[ao_igniter_main].firing = 1; + AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; + AO_IGNITER_DROGUE = 1; while (ao_launch_ignite) { ao_launch_ignite = 0; - - ao_ignition[ao_igniter_drogue].firing = 1; - ao_ignition[ao_igniter_main].firing = 1; - AO_IGNITER_DROGUE = 1; ao_delay(AO_MS_TO_TICKS(500)); - AO_IGNITER_DROGUE = 0; - ao_ignition[ao_igniter_drogue].firing = 0; - ao_ignition[ao_igniter_main].firing = 0; } + AO_IGNITER_DROGUE = 0; + ao_ignition[ao_igniter_drogue].firing = 0; + ao_ignition[ao_igniter_main].firing = 0; } } -- cgit v1.2.3 From 4568bc796a6c362ebf7f72ee9a5fa4a9a3c4ba6a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 1 Aug 2011 17:08:24 -0700 Subject: altosui: Add primitive UI for TeleLaunch Display status along with arm and fire buttons. Signed-off-by: Keith Packard --- altosui/AltosLaunch.java | 201 ++++++++++++++++ altosui/AltosLaunchUI.java | 518 ++++++++++++++++++++++++++++++++++++++++++ altosui/AltosPreferences.java | 39 ++++ altosui/Makefile.am | 2 + src/ao_radio_cmac.c | 140 ++++++++---- 5 files changed, 854 insertions(+), 46 deletions(-) create mode 100644 altosui/AltosLaunch.java create mode 100644 altosui/AltosLaunchUI.java (limited to 'src') diff --git a/altosui/AltosLaunch.java b/altosui/AltosLaunch.java new file mode 100644 index 00000000..77f681b8 --- /dev/null +++ b/altosui/AltosLaunch.java @@ -0,0 +1,201 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package altosui; + +import java.io.*; +import java.util.concurrent.*; +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.table.*; +import javax.swing.event.*; + +public class AltosLaunch { + AltosDevice device; + AltosSerial serial; + boolean serial_started; + int launcher_serial; + int launcher_channel; + int rssi; + + final static int Unknown = -1; + final static int Good = 0; + final static int Bad = 1; + + int armed; + int igniter; + + private void start_serial() throws InterruptedException { + serial_started = true; + } + + private void stop_serial() throws InterruptedException { + if (!serial_started) + return; + serial_started = false; + if (serial == null) + return; + } + + class string_ref { + String value; + + public String get() { + return value; + } + public void set(String i) { + value = i; + } + public string_ref() { + value = null; + } + } + + private boolean get_string(String line, String label, string_ref s) { + if (line.startsWith(label)) { + String quoted = line.substring(label.length()).trim(); + + if (quoted.startsWith("\"")) + quoted = quoted.substring(1); + if (quoted.endsWith("\"")) + quoted = quoted.substring(0,quoted.length()-1); + s.set(quoted); + return true; + } else { + return false; + } + } + + public boolean status() throws InterruptedException, TimeoutException { + boolean ok = false; + if (serial == null) + return false; + string_ref status_name = new string_ref(); + start_serial(); + serial.printf("l %d %d\n", launcher_serial, launcher_channel); + for (;;) { + String line = serial.get_reply(20000); + if (line == null) + throw new TimeoutException(); + if (get_string(line, "Rssi: ", status_name)) { + try { + rssi = Altos.fromdec(status_name.get()); + } catch (NumberFormatException ne) { + } + break; + } else if (get_string(line, "Armed: ", status_name)) { + armed = Good; + String status = status_name.get(); + if (status.startsWith("igniter good")) + igniter = Good; + else if (status.startsWith("igniter bad")) + igniter = Bad; + else + igniter = Unknown; + ok = true; + } else if (get_string(line, "Disarmed: ", status_name)) { + armed = Bad; + if (status_name.get().startsWith("igniter good")) + igniter = Good; + else if (status_name.get().startsWith("igniter bad")) + igniter = Bad; + else + igniter = Unknown; + ok = true; + } else if (get_string(line, "Error ", status_name)) { + armed = Unknown; + igniter = Unknown; + ok = false; + break; + } + } + stop_serial(); + if (!ok) { + armed = Unknown; + igniter = Unknown; + } + return ok; + } + + public static String status_string(int status) { + switch (status) { + case Good: + return "good"; + case Bad: + return "open"; + } + return "unknown"; + } + + public void arm() { + if (serial == null) + return; + try { + start_serial(); + serial.printf("a %d %d\n", launcher_serial, launcher_channel); + serial.flush_output(); + } catch (InterruptedException ie) { + } finally { + try { + stop_serial(); + } catch (InterruptedException ie) { + } + } + } + + public void fire() { + if (serial == null) + return; + try { + start_serial(); + serial.printf("i %d %d\n", launcher_serial, launcher_channel); + serial.flush_output(); + } catch (InterruptedException ie) { + } finally { + try { + stop_serial(); + } catch (InterruptedException ie) { + } + } + } + + public void close() { + try { + stop_serial(); + } catch (InterruptedException ie) { + } + serial.close(); + serial = null; + } + + public void set_frame(Frame frame) { + serial.set_frame(frame); + } + + public void set_remote(int in_serial, int in_channel) { + launcher_serial = in_serial; + launcher_channel = in_channel; + } + + public AltosLaunch(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { + + device = in_device; + serial = new AltosSerial(device); + } +} \ No newline at end of file diff --git a/altosui/AltosLaunchUI.java b/altosui/AltosLaunchUI.java new file mode 100644 index 00000000..4e630afb --- /dev/null +++ b/altosui/AltosLaunchUI.java @@ -0,0 +1,518 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +package altosui; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.filechooser.FileNameExtensionFilter; +import javax.swing.table.*; +import javax.swing.event.*; +import java.io.*; +import java.util.*; +import java.text.*; +import java.util.prefs.*; +import java.util.concurrent.*; + +class FireButton extends JButton { + protected void processMouseEvent(MouseEvent e) { + super.processMouseEvent(e); + switch (e.getID()) { + case MouseEvent.MOUSE_PRESSED: + if (actionListener != null) + actionListener.actionPerformed(new ActionEvent(this, e.getID(), "fire_down")); + break; + case MouseEvent.MOUSE_RELEASED: + if (actionListener != null) + actionListener.actionPerformed(new ActionEvent(this, e.getID(), "fire_up")); + break; + } + } + + public FireButton(String s) { + super(s); + } +} + +public class AltosLaunchUI + extends JDialog + implements ActionListener +{ + AltosDevice device; + JFrame owner; + JLabel label; + + int radio_channel; + JLabel radio_channel_label; + JTextField radio_channel_text; + + int launcher_serial; + JLabel launcher_serial_label; + JTextField launcher_serial_text; + + int launcher_channel; + JLabel launcher_channel_label; + JTextField launcher_channel_text; + + JLabel armed_label; + JLabel armed_status_label; + JLabel igniter; + JLabel igniter_status_label; + JToggleButton arm; + FireButton fire; + javax.swing.Timer arm_timer; + javax.swing.Timer fire_timer; + + boolean firing; + boolean armed; + int armed_status; + int igniter_status; + int rssi; + + final static int arm_timeout = 1 * 1000; + final static int fire_timeout = 250; + + int armed_count; + + LinkedBlockingQueue command_queue; + + class LaunchHandler implements Runnable { + AltosLaunch launch; + JFrame owner; + + void send_exception(Exception e) { + final Exception f_e = e; + Runnable r = new Runnable() { + public void run() { + launch_exception(f_e); + } + }; + SwingUtilities.invokeLater(r); + } + + public void run () { + try { + launch = new AltosLaunch(device); + } catch (Exception e) { + send_exception(e); + return; + } + launch.set_frame(owner); + launch.set_remote(launcher_serial, launcher_channel); + + for (;;) { + Runnable r; + + try { + String command = command_queue.take(); + String reply = null; + + if (command.equals("get_status")) { + launch.status(); + reply = "status"; + armed_status = launch.armed; + igniter_status = launch.igniter; + rssi = launch.rssi; + } else if (command.equals("set_remote")) { + launch.set_remote(launcher_serial, launcher_channel); + reply = "remote set"; + } else if (command.equals("arm")) { + launch.arm(); + reply = "armed"; + } else if (command.equals("fire")) { + launch.fire(); + reply = "fired"; + } else if (command.equals("quit")) { + launch.close(); + break; + } else { + throw new ParseException(String.format("invalid command %s", command), 0); + } + final String f_reply = reply; + r = new Runnable() { + public void run() { + launch_reply(f_reply); + } + }; + SwingUtilities.invokeLater(r); + } catch (Exception e) { + send_exception(e); + } + } + } + + public LaunchHandler(JFrame in_owner) { + owner = in_owner; + } + } + + void launch_exception(Exception e) { + if (e instanceof FileNotFoundException) { + JOptionPane.showMessageDialog(owner, + String.format("Cannot open device \"%s\"", + device.toShortString()), + "Cannot open target device", + JOptionPane.ERROR_MESSAGE); + } else if (e instanceof AltosSerialInUseException) { + JOptionPane.showMessageDialog(owner, + String.format("Device \"%s\" already in use", + device.toShortString()), + "Device in use", + JOptionPane.ERROR_MESSAGE); + } else if (e instanceof IOException) { + IOException ee = (IOException) e; + JOptionPane.showMessageDialog(owner, + device.toShortString(), + ee.getLocalizedMessage(), + JOptionPane.ERROR_MESSAGE); + } else { + JOptionPane.showMessageDialog(owner, + String.format("Connection to \"%s\" failed", + device.toShortString()), + "Connection Failed", + JOptionPane.ERROR_MESSAGE); + } + close(); + } + + void launch_reply(String reply) { + if (reply == null) + return; + if (reply.equals("remote set")) + poll_launch_status(); + if (reply.equals("status")) { + set_launch_status(); + } + } + + void set_arm_text() { + if (arm.isSelected()) + arm.setText(String.format("%d", armed_count)); + else + arm.setText("Arm"); + } + + void start_arm_timer() { + armed_count = 30; + set_arm_text(); + } + + void stop_arm_timer() { + armed_count = 0; + armed = false; + arm.setSelected(false); + fire.setEnabled(false); + set_arm_text(); + } + + void cancel () { + fire.setEnabled(false); + firing = false; + stop_arm_timer(); + } + + void send_command(String command) { + try { + command_queue.put(command); + } catch (Exception ex) { + launch_exception(ex); + } + } + + boolean getting_status = false; + + void set_launch_status() { + getting_status = false; + armed_status_label.setText(String.format("\"%s\"", AltosLaunch.status_string(armed_status))); + igniter_status_label.setText(String.format("\"%s\"", AltosLaunch.status_string(igniter_status))); + } + + void poll_launch_status() { + if (!getting_status && !firing && !armed) { + getting_status = true; + send_command("get_status"); + } + } + + void fired() { + firing = false; + cancel(); + } + + void close() { + send_command("quit"); + arm_timer.stop(); + setVisible(false); + dispose(); + } + + void tick_arm_timer() { + if (armed_count > 0) { + --armed_count; + if (armed_count <= 0) { + armed_count = 0; + cancel(); + } else { + if (!firing) { + send_command("arm"); + set_arm_text(); + } + } + } + poll_launch_status(); + } + + void arm() { + if (arm.isSelected()) { + fire.setEnabled(true); + start_arm_timer(); + if (!firing) + send_command("arm"); + armed = true; + } else + cancel(); + } + + void fire_more() { + if (firing) + send_command("fire"); + } + + void fire_down() { + if (arm.isEnabled() && arm.isSelected() && armed_count > 0) { + firing = true; + fire_more(); + fire_timer.restart(); + } + } + + void fire_up() { + firing = false; + fire_timer.stop(); + } + + void set_radio() { + try { + radio_channel = Integer.parseInt(radio_channel_text.getText()); + } catch (NumberFormatException ne) { + radio_channel_text.setText(String.format("%d", radio_channel)); + } + } + + void set_serial() { + try { + launcher_serial = Integer.parseInt(launcher_serial_text.getText()); + AltosPreferences.set_launcher_serial(launcher_serial); + send_command("set_remote"); + } catch (NumberFormatException ne) { + launcher_serial_text.setText(String.format("%d", launcher_serial)); + } + } + + void set_channel() { + try { + launcher_channel = Integer.parseInt(launcher_channel_text.getText()); + AltosPreferences.set_launcher_serial(launcher_channel); + send_command("set_remote"); + } catch (NumberFormatException ne) { + launcher_channel_text.setText(String.format("%d", launcher_channel)); + } + } + + public void actionPerformed(ActionEvent e) { + String cmd = e.getActionCommand(); + System.out.printf("cmd %s\n", cmd); + if (cmd.equals("armed") || cmd.equals("igniter")) { + stop_arm_timer(); + } + + if (cmd.equals("arm")) + arm(); + if (cmd.equals("tick_arm")) + tick_arm_timer(); + if (cmd.equals("close")) + close(); + if (cmd.equals("fire_down")) + fire_down(); + if (cmd.equals("fire_up")) + fire_up(); + if (cmd.equals("tick_fire")) + fire_more(); + if (cmd.equals("new_serial")) + set_serial(); + if (cmd.equals("new_channel")) + set_channel(); + } + + /* A window listener to catch closing events and tell the config code */ + class ConfigListener extends WindowAdapter { + AltosLaunchUI ui; + + public ConfigListener(AltosLaunchUI this_ui) { + ui = this_ui; + } + + public void windowClosing(WindowEvent e) { + ui.actionPerformed(new ActionEvent(e.getSource(), + ActionEvent.ACTION_PERFORMED, + "close")); + } + } + + private boolean open() { + command_queue = new LinkedBlockingQueue(); + + device = AltosDeviceDialog.show(owner, Altos.product_any); + if (device != null) { + LaunchHandler handler = new LaunchHandler(owner); + Thread t = new Thread(handler); + t.start(); + return true; + } + return false; + } + + public AltosLaunchUI(JFrame in_owner) { + + launcher_channel = AltosPreferences.launcher_channel(); + launcher_serial = AltosPreferences.launcher_serial(); + owner = in_owner; + armed_status = AltosLaunch.Unknown; + igniter_status = AltosLaunch.Unknown; + + if (!open()) + return; + + Container pane = getContentPane(); + GridBagConstraints c = new GridBagConstraints(); + Insets i = new Insets(4,4,4,4); + + arm_timer = new javax.swing.Timer(arm_timeout, this); + arm_timer.setActionCommand("tick_arm"); + arm_timer.restart(); + + fire_timer = new javax.swing.Timer(fire_timeout, this); + fire_timer.setActionCommand("tick_fire"); + + owner = in_owner; + + pane.setLayout(new GridBagLayout()); + + c.fill = GridBagConstraints.NONE; + c.anchor = GridBagConstraints.CENTER; + c.insets = i; + c.weightx = 1; + c.weighty = 1; + + c.gridx = 0; + c.gridy = 0; + c.gridwidth = 2; + c.anchor = GridBagConstraints.CENTER; + label = new JLabel ("Launch Controller"); + pane.add(label, c); + + c.gridx = 0; + c.gridy = 1; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + launcher_serial_label = new JLabel("Launcher Serial"); + pane.add(launcher_serial_label, c); + + c.gridx = 1; + c.gridy = 1; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + launcher_serial_text = new JTextField(7); + launcher_serial_text.setText(String.format("%d", launcher_serial)); + launcher_serial_text.setActionCommand("new_serial"); + launcher_serial_text.addActionListener(this); + pane.add(launcher_serial_text, c); + + c.gridx = 0; + c.gridy = 2; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + launcher_channel_label = new JLabel("Launcher Channel"); + pane.add(launcher_channel_label, c); + + c.gridx = 1; + c.gridy = 2; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + launcher_channel_text = new JTextField(7); + launcher_channel_text.setText(String.format("%d", launcher_channel)); + launcher_channel_text.setActionCommand("new_channel"); + launcher_channel_text.addActionListener(this); + pane.add(launcher_channel_text, c); + + c.gridx = 0; + c.gridy = 3; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + armed_label = new JLabel ("Armed"); + pane.add(armed_label, c); + + c.gridx = 1; + c.gridy = 3; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + armed_status_label = new JLabel(); + pane.add(armed_status_label, c); + + c.gridx = 0; + c.gridy = 4; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + igniter = new JLabel ("Igniter"); + pane.add(igniter, c); + + c.gridx = 1; + c.gridy = 4; + c.gridwidth = 1; + c.anchor = GridBagConstraints.WEST; + igniter_status_label = new JLabel(); + pane.add(igniter_status_label, c); + + c.gridx = 0; + c.gridy = 5; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + arm = new JToggleButton ("Arm"); + pane.add(arm, c); + arm.addActionListener(this); + arm.setActionCommand("arm"); + arm.setEnabled(true); + + c.gridx = 1; + c.gridy = 5; + c.gridwidth = 1; + c.anchor = GridBagConstraints.CENTER; + fire = new FireButton ("Fire"); + fire.setEnabled(false); + pane.add(fire, c); + fire.addActionListener(this); + fire.setActionCommand("fire"); + + pack(); + setLocationRelativeTo(owner); + + addWindowListener(new ConfigListener(this)); + + setVisible(true); + } +} \ No newline at end of file diff --git a/altosui/AltosPreferences.java b/altosui/AltosPreferences.java index 716559ab..48aed441 100644 --- a/altosui/AltosPreferences.java +++ b/altosui/AltosPreferences.java @@ -58,6 +58,12 @@ class AltosPreferences { /* font size preferences name */ final static String fontSizePreference = "FONT-SIZE"; + /* Launcher serial preference name */ + final static String launcherSerialPreference = "LAUNCHER-SERIAL"; + + /* Launcher channel prefernce name */ + final static String launcherChannelPreference = "LAUNCHER-CHANNEL"; + /* Default logdir is ~/TeleMetrum */ final static String logdirName = "TeleMetrum"; @@ -143,6 +149,9 @@ class AltosPreferences { node.put(String.format(description_format, i), frequencies[i].description); } } + static int launcher_serial; + + static int launcher_channel; public static void init() { preferences = Preferences.userRoot().node("/org/altusmetrum/altosui"); @@ -176,6 +185,10 @@ class AltosPreferences { font_size = preferences.getInt(fontSizePreference, Altos.font_size_medium); Altos.set_fonts(font_size); + launcher_serial = preferences.getInt(launcherSerialPreference, 0); + + launcher_channel = preferences.getInt(launcherChannelPreference, 0); + String firmwaredir_string = preferences.get(firmwaredirPreference, null); if (firmwaredir_string != null) firmwaredir = new File(firmwaredir_string); @@ -390,6 +403,32 @@ class AltosPreferences { return serial_debug; } + public static void set_launcher_serial(int new_launcher_serial) { + launcher_serial = new_launcher_serial; + System.out.printf("set launcher serial to %d\n", new_launcher_serial); + synchronized (preferences) { + preferences.putInt(launcherSerialPreference, launcher_serial); + flush_preferences(); + } + } + + public static int launcher_serial() { + return launcher_serial; + } + + public static void set_launcher_channel(int new_launcher_channel) { + launcher_channel = new_launcher_channel; + System.out.printf("set launcher channel to %d\n", new_launcher_channel); + synchronized (preferences) { + preferences.putInt(launcherChannelPreference, launcher_channel); + flush_preferences(); + } + } + + public static int launcher_channel() { + return launcher_channel; + } + public static Preferences bt_devices() { return preferences.node("bt_devices"); } diff --git a/altosui/Makefile.am b/altosui/Makefile.am index ba1c830c..e2e42d84 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -68,6 +68,8 @@ altosui_JAVA = \ AltosIdleMonitorUI.java \ AltosIgnite.java \ AltosIgniteUI.java \ + AltosLaunch.java \ + AltosLaunchUI.java \ AltosInfoTable.java \ AltosKML.java \ AltosLanded.java \ diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c index c2757b16..41fbbe1f 100644 --- a/src/ao_radio_cmac.c +++ b/src/ao_radio_cmac.c @@ -21,6 +21,7 @@ #define AO_CMAC_MAX_LEN (128 - AO_CMAC_KEY_LEN) static __xdata uint8_t ao_radio_cmac_mutex; +__pdata int16_t ao_radio_cmac_rssi; static __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN]; static __pdata uint8_t ao_radio_cmac_len; @@ -114,9 +115,12 @@ radio_cmac_recv(uint8_t len, uint16_t timeout) __reentrant i = ao_radio_recv(cmac_data, len + AO_CMAC_KEY_LEN + 2); ao_clear_alarm(); - if (!i) + if (!i) { + ao_radio_cmac_rssi = 0; return AO_RADIO_CMAC_TIMEOUT; + } + ao_radio_cmac_rssi = (int16_t) (((int8_t) cmac_data[len + AO_CMAC_KEY_LEN]) >> 1) - 74; if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & PKT_APPEND_STATUS_1_CRC_OK)) return AO_RADIO_CMAC_CRC_ERROR; @@ -221,33 +225,46 @@ radio_cmac_recv_cmd(void) __reentrant printf ("PACKET "); for (i = 0; i < len; i++) printf("%02x", cmac_data[i]); - printf ("\n"); + printf (" %d\n", ao_radio_cmac_rssi); } else - printf ("ERROR %d\n", i); + printf ("ERROR %d %d\n", i, ao_radio_cmac_rssi); ao_mutex_put(&ao_radio_cmac_mutex); } static __xdata struct ao_launch_command command; static __xdata struct ao_launch_query query; +static pdata uint16_t launch_serial; +static pdata uint8_t launch_channel; +static pdata uint16_t tick_offset; +static void +launch_args(void) __reentrant +{ + ao_cmd_decimal(); + launch_serial = ao_cmd_lex_i; + ao_cmd_decimal(); + launch_channel = ao_cmd_lex_i; +} static int8_t -launch_query(uint16_t serial, uint8_t channel) +launch_query(void) { uint8_t i; int8_t r = AO_RADIO_CMAC_OK; + tick_offset = ao_time(); for (i = 0; i < 10; i++) { printf ("."); flush(); command.tick = ao_time(); - command.serial = serial; + command.serial = launch_serial; command.cmd = AO_LAUNCH_QUERY; - command.channel = channel; + command.channel = launch_channel; ao_radio_cmac_send(&command, sizeof (command)); r = ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500)); if (r == AO_RADIO_CMAC_OK) break; } + tick_offset -= query.tick; printf("\n"); flush(); return r; } @@ -255,17 +272,12 @@ launch_query(uint16_t serial, uint8_t channel) static void launch_report_cmd(void) __reentrant { - uint8_t channel; - uint16_t serial; int8_t r; - ao_cmd_decimal(); - serial = ao_cmd_lex_i; - ao_cmd_decimal(); - channel = ao_cmd_lex_i; + launch_args(); if (ao_cmd_status != ao_cmd_success) return; - r = launch_query(serial, channel); + r = launch_query(); switch (r) { case AO_RADIO_CMAC_OK: if (query.valid) { @@ -273,24 +285,25 @@ launch_report_cmd(void) __reentrant case ao_igniter_ready: case ao_igniter_active: printf ("Armed: "); - switch (query.igniter_status) { - default: - printf("unknown status\n"); - break; - case ao_igniter_ready: - printf("igniter good\n"); - break; - case ao_igniter_open: - printf("igniter bad\n"); - break; - } break; default: - printf("Disarmed\n"); + printf("Disarmed: "); + } + switch (query.igniter_status) { + default: + printf("unknown\n"); + break; + case ao_igniter_ready: + printf("igniter good\n"); + break; + case ao_igniter_open: + printf("igniter bad\n"); + break; } } else { - printf("Invalid channel %d\n", channel); + printf("Invalid channel %d\n", launch_channel); } + printf("Rssi: %d\n", ao_radio_cmac_rssi); break; default: printf("Error %d\n", r); @@ -298,56 +311,91 @@ launch_report_cmd(void) __reentrant } } +static void +launch_arm(void) __reentrant +{ + command.tick = ao_time() - tick_offset; + command.serial = launch_serial; + command.cmd = AO_LAUNCH_ARM; + command.channel = launch_channel; + ao_radio_cmac_send(&command, sizeof (command)); +} + +static void +launch_ignite(void) __reentrant +{ + command.tick = ao_time() - tick_offset; + command.serial = launch_serial; + command.cmd = AO_LAUNCH_FIRE; + command.channel = 0; + ao_radio_cmac_send(&command, sizeof (command)); +} + static void launch_fire_cmd(void) __reentrant { static __xdata struct ao_launch_command command; - uint8_t channel; - uint16_t serial; uint8_t secs; uint8_t i; int8_t r; - uint16_t tick_offset; - ao_cmd_decimal(); - serial = ao_cmd_lex_i; - ao_cmd_decimal(); - channel = ao_cmd_lex_i; + launch_args(); ao_cmd_decimal(); secs = ao_cmd_lex_i; if (ao_cmd_status != ao_cmd_success) return; - tick_offset = ao_time(); - r = launch_query(serial, channel); - tick_offset -= query.tick; + r = launch_query(); + if (r != AO_RADIO_CMAC_OK) { + printf("query failed %d\n", r); + return; + } for (i = 0; i < 4; i++) { printf("arm %d\n", i); flush(); - command.tick = ao_time() - tick_offset; - command.serial = serial; - command.cmd = AO_LAUNCH_ARM; - command.channel = channel; - ao_radio_cmac_send(&command, sizeof (command)); + launch_arm(); } + secs = secs * 10 - 5; if (secs > 100) secs = 100; for (i = 0; i < secs; i++) { printf("fire %d\n", i); flush(); - command.tick = ao_time() - tick_offset; - command.serial = serial; - command.cmd = AO_LAUNCH_FIRE; - command.channel = 0; - ao_radio_cmac_send(&command, sizeof (command)); + launch_ignite(); ao_delay(AO_MS_TO_TICKS(100)); } } +static void +launch_arm_cmd(void) __reentrant +{ + uint8_t i; + int8_t r; + launch_args(); + r = launch_query(); + if (r != AO_RADIO_CMAC_OK) { + printf("query failed %d\n", r); + return; + } + for (i = 0; i < 4; i++) + launch_arm(); +} + +static void +launch_ignite_cmd(void) __reentrant +{ + uint8_t i; + launch_args(); + for (i = 0; i < 4; i++) + launch_ignite(); +} + static __code struct ao_cmds ao_radio_cmac_cmds[] = { { radio_cmac_send_cmd, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, { radio_cmac_recv_cmd, "S \0Receive AES-CMAC packet. Timeout in ms" }, { launch_report_cmd, "l \0Get remote launch status" }, { launch_fire_cmd, "f \0Fire remote igniter" }, + { launch_arm_cmd, "a \0Arm remote igniter" }, + { launch_ignite_cmd, "i \0Pulse remote igniter" }, { 0, NULL }, }; -- cgit v1.2.3 From 6b2db651a1dbc7ea97fce802b5f10b88be1ab42b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Aug 2011 12:42:10 -0700 Subject: altos: Add makefile for telelaunch Signed-off-by: Keith Packard --- src/product/Makefile.telelaunch | 97 +++++++++++++++++++++++++++++++++++++++++ src/telelaunch-v0.1/Makefile | 5 ++- 2 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 src/product/Makefile.telelaunch (limited to 'src') diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch new file mode 100644 index 00000000..71781bb1 --- /dev/null +++ b/src/product/Makefile.telelaunch @@ -0,0 +1,97 @@ +# +# TeleLaunch build file +# +# define TELELAUNCH_VER, TELELAUNCH_DEF +# this file + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + ao_product.h + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_convert.c \ + ao_mutex.c \ + ao_panic.c \ + ao_stdio.c \ + ao_storage.c \ + ao_task.c \ + ao_sample.c + +CC1111_SRC = \ + ao_adc.c \ + ao_beep.c \ + ao_dbg.c \ + ao_dma.c \ + ao_ignite.c \ + ao_led.c \ + ao_packet.c \ + ao_packet_slave.c \ + ao_radio.c \ + ao_romconfig.c \ + ao_serial.c \ + ao_spi.c \ + ao_timer.c \ + ao_usb.c \ + _bp.c + +DRIVER_SRC = + +PRODUCT_SRC = \ + ao_telelaunch.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROG = telelaunch-v$(TELELAUNCH_VER)-$(VERSION).ihx +PRODUCT=TeleLaunch-v$(TELELAUNCH_VER) +PRODUCT_DEF=-DTELELAUNCH_V_$(TELELAUNCH_DEF) +IDPRODUCT=0x000f + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: diff --git a/src/telelaunch-v0.1/Makefile b/src/telelaunch-v0.1/Makefile index d8867b19..b0d9d165 100644 --- a/src/telelaunch-v0.1/Makefile +++ b/src/telelaunch-v0.1/Makefile @@ -1 +1,4 @@ -include ../Makefile.proto +TELELAUNCH_VER=0.1 +TELELAUNCH_DEF=0_1 + +include ../product/Makefile.telelaunch -- cgit v1.2.3 From b3c95582774355c991d0a9f27d0a86881e643e62 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Aug 2011 13:24:41 -0700 Subject: altos: move igniter defines back to ao_pins.h so that ao_launch gets them too Signed-off-by: Keith Packard --- src/cc1111/ao_ignite.c | 22 ------ src/cc1111/ao_launch.c | 209 +++++++++++++++++++++++++++++++++++++++++++++++++ src/cc1111/ao_pins.h | 39 ++++++++- 3 files changed, 247 insertions(+), 23 deletions(-) create mode 100644 src/cc1111/ao_launch.c (limited to 'src') diff --git a/src/cc1111/ao_ignite.c b/src/cc1111/ao_ignite.c index 0fd2b4bf..289263ab 100644 --- a/src/cc1111/ao_ignite.c +++ b/src/cc1111/ao_ignite.c @@ -17,28 +17,6 @@ #include "ao.h" -#if IGNITE_ON_P2 -#define AO_IGNITER_DROGUE P2_3 -#define AO_IGNITER_MAIN P2_4 -#define AO_IGNITER_DIR P2DIR -#define AO_IGNITER_DROGUE_BIT (1 << 3) -#define AO_IGNITER_MAIN_BIT (1 << 4) -#endif - -#if IGNITE_ON_P0 -#define AO_IGNITER_DROGUE P0_5 -#define AO_IGNITER_MAIN P0_4 -#define AO_IGNITER_DIR P0DIR -#define AO_IGNITER_DROGUE_BIT (1 << 5) -#define AO_IGNITER_MAIN_BIT (1 << 4) -#endif - -/* test these values with real igniters */ -#define AO_IGNITER_OPEN 1000 -#define AO_IGNITER_CLOSED 7000 -#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) -#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) - __xdata struct ao_ignition ao_ignition[2]; void diff --git a/src/cc1111/ao_launch.c b/src/cc1111/ao_launch.c new file mode 100644 index 00000000..a593d0b2 --- /dev/null +++ b/src/cc1111/ao_launch.c @@ -0,0 +1,209 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +__xdata uint16_t ao_launch_ignite; + +#if 0 +#define PRINTD(...) printf(__VA_ARGS__) +#else +#define PRINTD(...) +#endif + +static void +ao_launch_run(void) +{ + for (;;) { + while (!ao_launch_ignite) + ao_sleep(&ao_launch_ignite); + ao_ignition[ao_igniter_drogue].firing = 1; + ao_ignition[ao_igniter_main].firing = 1; + AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; + AO_IGNITER_DROGUE = 1; + while (ao_launch_ignite) { + ao_launch_ignite = 0; + ao_delay(AO_MS_TO_TICKS(500)); + } + AO_IGNITER_DROGUE = 0; + ao_ignition[ao_igniter_drogue].firing = 0; + ao_ignition[ao_igniter_main].firing = 0; + } +} + +static void +ao_launch_status(void) +{ + uint8_t i; + for (;;) { + ao_delay(AO_SEC_TO_TICKS(1)); + if (ao_igniter_status(ao_igniter_drogue) == ao_igniter_ready) { + if (ao_igniter_status(ao_igniter_main) == ao_igniter_ready) { + for (i = 0; i < 5; i++) { + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(50)); + ao_delay(AO_MS_TO_TICKS(100)); + } + } else { + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + } + } + } +} + +static __pdata uint8_t ao_launch_armed; +static __pdata uint16_t ao_launch_arm_time; + +static void +ao_launch(void) +{ + static __xdata struct ao_launch_command command; + static __xdata struct ao_launch_query query; + int16_t time_difference; + + ao_led_off(AO_LED_RED); + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + for (;;) { + flush(); + if (ao_radio_cmac_recv(&command, sizeof (command), 0) != AO_RADIO_CMAC_OK) + continue; + + PRINTD ("tick %d serial %d cmd %d channel %d\n", + command.tick, command.serial, command.cmd, command.channel); + + switch (command.cmd) { + case AO_LAUNCH_QUERY: + if (command.serial != ao_serial_number) { + PRINTD ("serial number mismatch\n"); + break; + } + + if (command.channel == 0) { + query.valid = 1; + query.arm_status = ao_igniter_status(ao_igniter_drogue); + query.igniter_status = ao_igniter_status(ao_igniter_main); + } else { + query.valid = 0; + } + query.tick = ao_time(); + query.serial = ao_serial_number; + query.channel = command.channel; + PRINTD ("query tick %d serial %d channel %d valid %d arm %d igniter %d\n", + query.tick, query.serial, query.channel, query.valid, query.arm_status, + query.igniter_status); + ao_radio_cmac_send(&query, sizeof (query)); + break; + case AO_LAUNCH_ARM: + if (command.serial != ao_serial_number) { + PRINTD ("serial number mismatch\n"); + break; + } + + if (command.channel != 0) + break; + time_difference = command.tick - ao_time(); + PRINTD ("arm tick %d local tick %d\n", command.tick, ao_time()); + if (time_difference < 0) + time_difference = -time_difference; + if (time_difference > 10) { + PRINTD ("time difference too large %d\n", time_difference); + break; + } + PRINTD ("armed\n"); + ao_launch_armed = 1; + ao_launch_arm_time = ao_time(); + break; + case AO_LAUNCH_FIRE: + if (!ao_launch_armed) { + PRINTD ("not armed\n"); + break; + } + if ((uint16_t) (ao_time() - ao_launch_arm_time) > AO_SEC_TO_TICKS(20)) { + PRINTD ("late launch arm_time %d time %d\n", + ao_launch_arm_time, ao_time()); + break; + } + time_difference = command.tick - ao_time(); + if (time_difference < 0) + time_difference = -time_difference; + if (time_difference > 10) { + PRINTD ("time different too large %d\n", time_difference); + break; + } + PRINTD ("ignite\n"); + ao_launch_ignite = 1; + ao_wakeup(&ao_launch_ignite); + break; + } + } +} + +void +ao_launch_test(void) +{ + switch (ao_igniter_status(ao_igniter_drogue)) { + case ao_igniter_ready: + case ao_igniter_active: + printf ("Armed: "); + switch (ao_igniter_status(ao_igniter_main)) { + default: + printf("unknown status\n"); + break; + case ao_igniter_ready: + printf("igniter good\n"); + break; + case ao_igniter_open: + printf("igniter bad\n"); + break; + } + break; + default: + printf("Disarmed\n"); + } +} + +void +ao_launch_manual(void) +{ + ao_cmd_white(); + if (!ao_match_word("DoIt")) + return; + ao_cmd_white(); + ao_launch_ignite = 1; + ao_wakeup(&ao_launch_ignite); +} + +static __xdata struct ao_task ao_launch_task; +static __xdata struct ao_task ao_launch_ignite_task; +static __xdata struct ao_task ao_launch_status_task; + +__code struct ao_cmds ao_launch_cmds[] = { + { ao_launch_test, "t\0Test launch continuity" }, + { ao_launch_manual, "i \0Fire igniter. is doit with D&I" }, + { 0, NULL } +}; + +void +ao_launch_init(void) +{ + AO_IGNITER_DROGUE = 0; + AO_IGNITER_MAIN = 0; + AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; + ao_cmd_register(&ao_launch_cmds[0]); + ao_add_task(&ao_launch_task, ao_launch, "launch listener"); + ao_add_task(&ao_launch_ignite_task, ao_launch_run, "launch igniter"); + ao_add_task(&ao_launch_status_task, ao_launch_status, "launch status"); +} diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 819dc7df..91719b54 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -27,6 +27,7 @@ #define HAS_ADC 1 #define USE_SERIAL_STDIN 0 #define HAS_EEPROM 1 + #define HAS_LOG 1 #define USE_INTERNAL_FLASH 0 #define HAS_DBG 1 #define DBG_ON_P1 1 @@ -59,6 +60,7 @@ #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 + #define HAS_LOG 1 #define USE_INTERNAL_FLASH 0 #define HAS_DBG 1 #define DBG_ON_P1 1 @@ -95,6 +97,7 @@ #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 + #define HAS_LOG 0 #define DBG_ON_P1 1 #define DBG_ON_P0 0 #define IGNITE_ON_P2 0 @@ -120,6 +123,7 @@ #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 + #define HAS_LOG 1 #define USE_INTERNAL_FLASH 1 #define HAS_DBG 0 #define IGNITE_ON_P2 0 @@ -146,6 +150,7 @@ #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 + #define HAS_LOG 1 #define USE_INTERNAL_FLASH 1 #define HAS_DBG 0 #define IGNITE_ON_P2 0 @@ -172,6 +177,7 @@ #define HAS_ADC 1 #define HAS_DBG 0 #define HAS_EEPROM 1 + #define HAS_LOG 1 #define USE_INTERNAL_FLASH 0 #define DBG_ON_P1 0 #define DBG_ON_P0 1 @@ -200,6 +206,7 @@ #define HAS_ADC 0 #define HAS_DBG 0 #define HAS_EEPROM 0 + #define HAS_LOG 0 #define DBG_ON_P1 0 #define DBG_ON_P0 1 #define IGNITE_ON_P2 0 @@ -225,6 +232,7 @@ #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 + #define HAS_LOG 0 #define DBG_ON_P1 0 #define DBG_ON_P0 1 #define IGNITE_ON_P2 0 @@ -249,6 +257,7 @@ #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 + #define HAS_LOG 0 #define HAS_BTM 1 #define DBG_ON_P1 0 #define DBG_ON_P0 1 @@ -282,6 +291,7 @@ #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 1 + #define HAS_LOG 1 #define USE_INTERNAL_FLASH 0 #define HAS_BTM 1 #define DBG_ON_P1 1 @@ -317,7 +327,8 @@ #define HAS_ADC 1 #define HAS_DBG 0 #define HAS_EEPROM 1 - #define USE_INTERNAL_FLASH 0 + #define HAS_LOG 0 + #define USE_INTERNAL_FLASH 1 #define DBG_ON_P1 0 #define DBG_ON_P0 1 #define IGNITE_ON_P2 1 @@ -415,6 +426,10 @@ #error Please define HAS_EEPROM #endif +#ifndef HAS_LOG +#error Please define HAS_LOG +#endif + #if HAS_EEPROM #ifndef USE_INTERNAL_FLASH #error Please define USE_INTERNAL_FLASH @@ -457,4 +472,26 @@ #endif /* HAS_ADC */ +#if IGNITE_ON_P2 +#define AO_IGNITER_DROGUE P2_3 +#define AO_IGNITER_MAIN P2_4 +#define AO_IGNITER_DIR P2DIR +#define AO_IGNITER_DROGUE_BIT (1 << 3) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +#if IGNITE_ON_P0 +#define AO_IGNITER_DROGUE P0_5 +#define AO_IGNITER_MAIN P0_4 +#define AO_IGNITER_DIR P0DIR +#define AO_IGNITER_DROGUE_BIT (1 << 5) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +/* test these values with real igniters */ +#define AO_IGNITER_OPEN 1000 +#define AO_IGNITER_CLOSED 7000 +#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) +#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) + #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 9adf2c9c40ea1da2637ed809dc0d004e47844440 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Aug 2011 13:25:23 -0700 Subject: altos: add ao_aes/radio_cmac to tidongle, teledongle and telebt All of these can do the telelco stuff at this point. Signed-off-by: Keith Packard --- src/product/Makefile.telebt | 2 ++ src/product/Makefile.teledongle | 2 ++ src/product/ao_tidongle.c | 2 ++ src/tidongle/Makefile | 2 ++ 4 files changed, 8 insertions(+) (limited to 'src') diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index d9ef1ea7..ff0e1502 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -32,12 +32,14 @@ CORE_SRC = \ ao_task.c CC1111_SRC = \ + ao_aes.c \ ao_dbg.c \ ao_dma.c \ ao_led.c \ ao_packet.c \ ao_packet_master.c \ ao_radio.c \ + ao_radio_cmac.c \ ao_romconfig.c \ ao_serial.c \ ao_timer.c \ diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle index cfd9b806..56182b84 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -34,12 +34,14 @@ CORE_SRC = \ ao_task.c CC1111_SRC = \ + ao_aes.c \ ao_dbg.c \ ao_dma.c \ ao_led.c \ ao_packet.c \ ao_packet_master.c \ ao_radio.c \ + ao_radio_cmac.c \ ao_romconfig.c \ ao_timer.c \ ao_usb.c \ diff --git a/src/product/ao_tidongle.c b/src/product/ao_tidongle.c index 3b7c2733..5adbb05c 100644 --- a/src/product/ao_tidongle.c +++ b/src/product/ao_tidongle.c @@ -34,6 +34,8 @@ main(void) ao_rssi_init(AO_LED_RED); ao_radio_init(); ao_dbg_init(); + ao_aes_init(); + ao_radio_cmac_init(); ao_config_init(); /* Bring up the USB link */ P1DIR |= 1; diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile index 247f4fe0..057e420b 100644 --- a/src/tidongle/Makefile +++ b/src/tidongle/Makefile @@ -29,12 +29,14 @@ CORE_SRC = \ ao_task.c CC1111_SRC = \ + ao_aes.c \ ao_dbg.c \ ao_dma.c \ ao_led.c \ ao_packet.c \ ao_packet_master.c \ ao_radio.c \ + ao_radio_cmac.c \ ao_romconfig.c \ ao_timer.c \ ao_usb.c \ -- cgit v1.2.3 From 6afbc1876cd63f64e8975e300692f95a43866f5f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Aug 2011 13:27:00 -0700 Subject: altos: ao_launch belongs in cc1111 Signed-off-by: Keith Packard --- src/ao_launch.c | 209 -------------------------------------------------------- 1 file changed, 209 deletions(-) delete mode 100644 src/ao_launch.c (limited to 'src') diff --git a/src/ao_launch.c b/src/ao_launch.c deleted file mode 100644 index a593d0b2..00000000 --- a/src/ao_launch.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -__xdata uint16_t ao_launch_ignite; - -#if 0 -#define PRINTD(...) printf(__VA_ARGS__) -#else -#define PRINTD(...) -#endif - -static void -ao_launch_run(void) -{ - for (;;) { - while (!ao_launch_ignite) - ao_sleep(&ao_launch_ignite); - ao_ignition[ao_igniter_drogue].firing = 1; - ao_ignition[ao_igniter_main].firing = 1; - AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; - AO_IGNITER_DROGUE = 1; - while (ao_launch_ignite) { - ao_launch_ignite = 0; - ao_delay(AO_MS_TO_TICKS(500)); - } - AO_IGNITER_DROGUE = 0; - ao_ignition[ao_igniter_drogue].firing = 0; - ao_ignition[ao_igniter_main].firing = 0; - } -} - -static void -ao_launch_status(void) -{ - uint8_t i; - for (;;) { - ao_delay(AO_SEC_TO_TICKS(1)); - if (ao_igniter_status(ao_igniter_drogue) == ao_igniter_ready) { - if (ao_igniter_status(ao_igniter_main) == ao_igniter_ready) { - for (i = 0; i < 5; i++) { - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(50)); - ao_delay(AO_MS_TO_TICKS(100)); - } - } else { - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); - } - } - } -} - -static __pdata uint8_t ao_launch_armed; -static __pdata uint16_t ao_launch_arm_time; - -static void -ao_launch(void) -{ - static __xdata struct ao_launch_command command; - static __xdata struct ao_launch_query query; - int16_t time_difference; - - ao_led_off(AO_LED_RED); - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); - for (;;) { - flush(); - if (ao_radio_cmac_recv(&command, sizeof (command), 0) != AO_RADIO_CMAC_OK) - continue; - - PRINTD ("tick %d serial %d cmd %d channel %d\n", - command.tick, command.serial, command.cmd, command.channel); - - switch (command.cmd) { - case AO_LAUNCH_QUERY: - if (command.serial != ao_serial_number) { - PRINTD ("serial number mismatch\n"); - break; - } - - if (command.channel == 0) { - query.valid = 1; - query.arm_status = ao_igniter_status(ao_igniter_drogue); - query.igniter_status = ao_igniter_status(ao_igniter_main); - } else { - query.valid = 0; - } - query.tick = ao_time(); - query.serial = ao_serial_number; - query.channel = command.channel; - PRINTD ("query tick %d serial %d channel %d valid %d arm %d igniter %d\n", - query.tick, query.serial, query.channel, query.valid, query.arm_status, - query.igniter_status); - ao_radio_cmac_send(&query, sizeof (query)); - break; - case AO_LAUNCH_ARM: - if (command.serial != ao_serial_number) { - PRINTD ("serial number mismatch\n"); - break; - } - - if (command.channel != 0) - break; - time_difference = command.tick - ao_time(); - PRINTD ("arm tick %d local tick %d\n", command.tick, ao_time()); - if (time_difference < 0) - time_difference = -time_difference; - if (time_difference > 10) { - PRINTD ("time difference too large %d\n", time_difference); - break; - } - PRINTD ("armed\n"); - ao_launch_armed = 1; - ao_launch_arm_time = ao_time(); - break; - case AO_LAUNCH_FIRE: - if (!ao_launch_armed) { - PRINTD ("not armed\n"); - break; - } - if ((uint16_t) (ao_time() - ao_launch_arm_time) > AO_SEC_TO_TICKS(20)) { - PRINTD ("late launch arm_time %d time %d\n", - ao_launch_arm_time, ao_time()); - break; - } - time_difference = command.tick - ao_time(); - if (time_difference < 0) - time_difference = -time_difference; - if (time_difference > 10) { - PRINTD ("time different too large %d\n", time_difference); - break; - } - PRINTD ("ignite\n"); - ao_launch_ignite = 1; - ao_wakeup(&ao_launch_ignite); - break; - } - } -} - -void -ao_launch_test(void) -{ - switch (ao_igniter_status(ao_igniter_drogue)) { - case ao_igniter_ready: - case ao_igniter_active: - printf ("Armed: "); - switch (ao_igniter_status(ao_igniter_main)) { - default: - printf("unknown status\n"); - break; - case ao_igniter_ready: - printf("igniter good\n"); - break; - case ao_igniter_open: - printf("igniter bad\n"); - break; - } - break; - default: - printf("Disarmed\n"); - } -} - -void -ao_launch_manual(void) -{ - ao_cmd_white(); - if (!ao_match_word("DoIt")) - return; - ao_cmd_white(); - ao_launch_ignite = 1; - ao_wakeup(&ao_launch_ignite); -} - -static __xdata struct ao_task ao_launch_task; -static __xdata struct ao_task ao_launch_ignite_task; -static __xdata struct ao_task ao_launch_status_task; - -__code struct ao_cmds ao_launch_cmds[] = { - { ao_launch_test, "t\0Test launch continuity" }, - { ao_launch_manual, "i \0Fire igniter. is doit with D&I" }, - { 0, NULL } -}; - -void -ao_launch_init(void) -{ - AO_IGNITER_DROGUE = 0; - AO_IGNITER_MAIN = 0; - AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; - ao_cmd_register(&ao_launch_cmds[0]); - ao_add_task(&ao_launch_task, ao_launch, "launch listener"); - ao_add_task(&ao_launch_ignite_task, ao_launch_run, "launch igniter"); - ao_add_task(&ao_launch_status_task, ao_launch_status, "launch status"); -} -- cgit v1.2.3 From 8a1cbef0e316e38c80b71d3bac15641fe56e0a99 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Aug 2011 13:27:28 -0700 Subject: altos: Add HAS_LOG for products that log to eeprom Some products have eeprom for config, but none for logging (like telelaunch) Signed-off-by: Keith Packard --- src/core/ao_cmd.c | 2 +- src/core/ao_config.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 9e14c221..d0a46633 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -237,7 +237,7 @@ version(void) printf("manufacturer %s\n", ao_manufacturer); printf("product %s\n", ao_product); printf("serial-number %u\n", ao_serial_number); -#if HAS_EEPROM +#if HAS_LOG printf("log-format %u\n", ao_log_format); #endif printf("software-version %s\n", ao_version); diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 28854ab5..a653bed2 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -308,7 +308,7 @@ ao_config_radio_cal_set(void) __reentrant _ao_config_edit_finish(); } -#if HAS_EEPROM && HAS_FLIGHT +#if HAS_LOG void ao_config_log_show(void) __reentrant { @@ -336,7 +336,7 @@ ao_config_log_set(void) __reentrant _ao_config_edit_finish(); } } -#endif /* HAS_EEPROM && HAS_FLIGHT */ +#endif /* HAS_LOG */ #if HAS_IGNITE void @@ -482,7 +482,7 @@ __code struct ao_config_var ao_config_vars[] = { #endif /* HAS_ACCEL */ { "f \0Radio calib (cal = rf/(xtal/2^16))", ao_config_radio_cal_set, ao_config_radio_cal_show }, -#if HAS_EEPROM && HAS_FLIGHT +#if HAS_LOG { "l \0Flight log size in kB", ao_config_log_set, ao_config_log_show }, #endif -- cgit v1.2.3 From bc827699be4ed9ac60a7e862e6532791968bf685 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Aug 2011 13:28:01 -0700 Subject: altos: Fix up telelaunch Makefile Adding all of the mising sources Signed-off-by: Keith Packard --- src/product/Makefile.telelaunch | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch index 71781bb1..5da42e46 100644 --- a/src/product/Makefile.telelaunch +++ b/src/product/Makefile.telelaunch @@ -22,23 +22,26 @@ CORE_SRC = \ ao_cmd.c \ ao_config.c \ ao_convert.c \ + ao_launch.c \ ao_mutex.c \ ao_panic.c \ ao_stdio.c \ ao_storage.c \ - ao_task.c \ - ao_sample.c + ao_task.c CC1111_SRC = \ ao_adc.c \ + ao_aes.c \ ao_beep.c \ ao_dbg.c \ ao_dma.c \ ao_ignite.c \ + ao_intflash.c \ ao_led.c \ ao_packet.c \ ao_packet_slave.c \ ao_radio.c \ + ao_radio_cmac.c \ ao_romconfig.c \ ao_serial.c \ ao_spi.c \ @@ -61,6 +64,7 @@ PROG = telelaunch-v$(TELELAUNCH_VER)-$(VERSION).ihx PRODUCT=TeleLaunch-v$(TELELAUNCH_VER) PRODUCT_DEF=-DTELELAUNCH_V_$(TELELAUNCH_DEF) IDPRODUCT=0x000f +CODESIZE=0x6700 include ../cc1111/Makefile.cc1111 -- cgit v1.2.3 From b33a92e372327158ab21c1bb2d091c58761efe10 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 27 Aug 2011 15:19:43 -0700 Subject: altos: Share log code between telescience and telebt. Add telebt log Telescience and telebt both log data in 32-byte chunks, so share some code which manages that between the two products. Add simple telemetry logging to telebt. Signed-off-by: Keith Packard --- src/avr/ao_spi_slave.c | 14 +-- src/core/ao.h | 97 +++++++++++++++---- src/core/ao_log_telem.c | 48 +++++++++- src/core/ao_log_telescience.c | 211 ++++++------------------------------------ src/core/ao_monitor.c | 10 +- src/product/ao_telebt.c | 3 + src/product/ao_telescience.c | 2 +- src/telebt-v0.1/Makefile | 1 + src/telescience-v0.1/Makefile | 1 + 9 files changed, 164 insertions(+), 223 deletions(-) (limited to 'src') diff --git a/src/avr/ao_spi_slave.c b/src/avr/ao_spi_slave.c index 4dde09f3..e4d866a8 100644 --- a/src/avr/ao_spi_slave.c +++ b/src/avr/ao_spi_slave.c @@ -74,9 +74,9 @@ static uint8_t ao_spi_slave_recv(void) return 0; } - ao_log_store.tm_tick = ao_companion_command.tick; - if (ao_log_store.tm_state != ao_companion_command.flight_state) { - ao_log_store.tm_state = ao_companion_command.flight_state; + ao_log_single_write_data.telescience.tm_tick = ao_companion_command.tick; + if (ao_log_single_write_data.telescience.tm_state != ao_companion_command.flight_state) { + ao_log_single_write_data.telescience.tm_state = ao_companion_command.flight_state; return 1; } return 0; @@ -93,11 +93,11 @@ ISR(PCINT0_vect) cli(); changed = ao_spi_slave_recv(); sei(); - if (changed && ao_flight_boost <= ao_log_store.tm_state) { - if (ao_log_store.tm_state < ao_flight_landed) - ao_log_start(); + if (changed && ao_flight_boost <= ao_log_single_write_data.telescience.tm_state) { + if (ao_log_single_write_data.telescience.tm_state < ao_flight_landed) + ao_log_single_start(); else - ao_log_stop(); + ao_log_single_stop(); } } } else { diff --git a/src/core/ao.h b/src/core/ao.h index a5bbb6f1..8b978272 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -505,23 +505,6 @@ extern __pdata uint32_t ao_log_start_pos; extern __xdata uint8_t ao_log_running; extern __pdata enum flight_state ao_log_state; -#define AO_LOG_TELESCIENCE_START ((uint8_t) 's') -#define AO_LOG_TELESCIENCE_DATA ((uint8_t) 'd') - -#define AO_LOG_TELESCIENCE_NUM_ADC 12 - -struct ao_log_telescience { - uint8_t type; - uint8_t csum; - uint16_t tick; - uint16_t tm_tick; - uint8_t tm_state; - uint8_t unused; - uint16_t adc[AO_LOG_TELESCIENCE_NUM_ADC]; -}; - -extern struct ao_log_telescience ao_log_store; - /* required functions from the underlying log system */ #define AO_LOG_FORMAT_UNKNOWN 0 /* unknown; altosui will have to guess */ @@ -1365,6 +1348,20 @@ ao_radio_init(void); extern const char const * const ao_state_names[]; +#define AO_MONITOR_RING 8 + +union ao_monitor { + struct ao_telemetry_raw_recv raw; + struct ao_telemetry_orig_recv orig; + struct ao_telemetry_tiny_recv tiny; +}; + +extern __xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING]; + +#define ao_monitor_ring_next(n) (((n) + 1) & (AO_MONITOR_RING - 1)) + +extern __data uint8_t ao_monitor_head; + void ao_monitor(void); @@ -1724,4 +1721,70 @@ struct ao_launch_query { void ao_launch_init(void); +/* + * ao_log_single.c + */ + +#define AO_LOG_TELESCIENCE_START ((uint8_t) 's') +#define AO_LOG_TELESCIENCE_DATA ((uint8_t) 'd') + +#define AO_LOG_TELESCIENCE_NUM_ADC 12 + +struct ao_log_telescience { + uint8_t type; + uint8_t csum; + uint16_t tick; + uint16_t tm_tick; + uint8_t tm_state; + uint8_t unused; + uint16_t adc[AO_LOG_TELESCIENCE_NUM_ADC]; +}; + +#define AO_LOG_SINGLE_SIZE 32 + +union ao_log_single { + struct ao_log_telescience telescience; + union ao_telemetry_all telemetry; + uint8_t bytes[AO_LOG_SINGLE_SIZE]; +}; + +extern __xdata union ao_log_single ao_log_single_write_data; +extern __xdata union ao_log_single ao_log_single_read_data; + +void +ao_log_single_extra_query(void); + +void +ao_log_single_list(void); + +void +ao_log_single_main(void); + +uint8_t +ao_log_single_write(void); + +uint8_t +ao_log_single_read(uint32_t pos); + +void +ao_log_single_start(void); + +void +ao_log_single_stop(void); + +void +ao_log_single_restart(void); + +void +ao_log_single_set(void); + +void +ao_log_single_delete(void); + +void +ao_log_single_init(void); + +void +ao_log_single(void); + #endif /* _AO_H_ */ diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index 1b472efe..34abe879 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -17,14 +17,52 @@ #include "ao.h" +__code uint8_t ao_log_format = AO_LOG_FORMAT_TELEMETRY; + +static __data uint8_t ao_log_monitor_pos; + +void +ao_log_single(void) +{ + ao_storage_setup(); + + /* This can take a while, so let the rest + * of the system finish booting before we start + */ + ao_delay(AO_SEC_TO_TICKS(2)); + + ao_log_single_restart(); + for (;;) { + while (!ao_log_running) + ao_sleep(&ao_log_running); + + ao_log_monitor_pos = ao_monitor_head; + while (ao_log_running) { + /* Write samples to EEPROM */ + while (ao_log_monitor_pos != ao_monitor_head) { + memcpy(&ao_log_single_write_data.telemetry, + &ao_monitor_ring[ao_log_monitor_pos], + AO_LOG_SINGLE_SIZE); + ao_log_single_write(); + ao_log_monitor_pos = ao_monitor_ring_next(ao_log_monitor_pos); + } + /* Wait for more ADC data to arrive */ + ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); + } + } +} + void -ao_log_write_erase(uint8_t pos) +ao_log_single_list(void) { - (void) pos; + if (ao_log_current_pos != 0) + printf("flight 1 start %x end %x\n", + 0, + (uint16_t) ((ao_log_current_pos + 0xff) >> 8)); + printf ("done\n"); } -uint8_t -ao_log_present(void) +void +ao_log_single_extra_query(void) { - return 0; } diff --git a/src/core/ao_log_telescience.c b/src/core/ao_log_telescience.c index aac780fa..31eda381 100644 --- a/src/core/ao_log_telescience.c +++ b/src/core/ao_log_telescience.c @@ -18,119 +18,25 @@ #include "ao.h" #include "ao_product.h" -static struct ao_task ao_log_task; -//static struct ao_task ao_spi_task; - -uint8_t ao_log_running; -uint8_t ao_log_mutex; -uint32_t ao_log_start_pos; -uint32_t ao_log_end_pos; -uint32_t ao_log_current_pos; - -#define AO_LOG_TELESCIENCE_START ((uint8_t) 's') -#define AO_LOG_TELESCIENCE_DATA ((uint8_t) 'd') - -struct ao_log_telescience ao_log_store; -struct ao_log_telescience ao_log_fetch; - static uint8_t ao_log_adc_pos; __code uint8_t ao_log_format = AO_LOG_FORMAT_TELESCIENCE; -static uint8_t -ao_log_csum(__xdata uint8_t *b) __reentrant +static void +ao_log_telescience_csum(void) __reentrant { + __xdata uint8_t *b = ao_log_single_write_data.bytes; uint8_t sum = 0x5a; uint8_t i; + ao_log_single_write_data.telescience.csum = 0; for (i = 0; i < sizeof (struct ao_log_telescience); i++) sum += *b++; - return -sum; -} - -static uint8_t -ao_log_telescience_write(void) -{ - uint8_t wrote = 0; - - ao_log_store.csum = 0; - ao_log_store.csum = ao_log_csum((__xdata uint8_t *) &ao_log_store); - ao_mutex_get(&ao_log_mutex); { - if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) - ao_log_stop(); - if (ao_log_running) { - wrote = 1; - ao_storage_write(ao_log_current_pos, - (__xdata uint8_t *) &ao_log_store, - sizeof (struct ao_log_telescience)); - ao_log_current_pos += sizeof (struct ao_log_telescience); - } - } ao_mutex_put(&ao_log_mutex); - return wrote; -} - -static uint8_t -ao_log_valid(struct ao_log_telescience *log) -{ - uint8_t *d; - uint8_t i; - d = (uint8_t *) log; - for (i = 0; i < sizeof (struct ao_log_telescience); i++) - if (d[i] != 0xff) - return 1; - return 0; -} - -static uint8_t -ao_log_telescience_read(uint32_t pos) -{ - if (!ao_storage_read(pos, &ao_log_fetch, sizeof (struct ao_log_telescience))) - return 0; - return ao_log_valid(&ao_log_fetch); -} - -void -ao_log_start(void) -{ - if (!ao_log_running) { - ao_log_running = 1; - ao_wakeup(&ao_log_running); - } -} - -void -ao_log_stop(void) -{ - if (ao_log_running) { - ao_log_running = 0; - } -} - -void -ao_log_restart(void) -{ - /* Find end of data */ - ao_log_end_pos = ao_storage_config; - for (ao_log_current_pos = 0; - ao_log_current_pos < ao_storage_config; - ao_log_current_pos += ao_storage_block) - { - if (!ao_log_telescience_read(ao_log_current_pos)) - break; - } - if (ao_log_current_pos > 0) { - ao_log_current_pos -= ao_storage_block; - for (; ao_log_current_pos < ao_storage_config; - ao_log_current_pos += sizeof (struct ao_log_telescience)) - { - if (!ao_log_telescience_read(ao_log_current_pos)) - break; - } - } + ao_log_single_write_data.telescience.csum = -sum; } void -ao_log_telescience(void) +ao_log_single(void) { ao_storage_setup(); @@ -139,57 +45,42 @@ ao_log_telescience(void) */ ao_delay(AO_SEC_TO_TICKS(10)); - ao_log_restart(); + ao_log_single_restart(); for (;;) { while (!ao_log_running) ao_sleep(&ao_log_running); ao_log_start_pos = ao_log_current_pos; - ao_log_store.type = AO_LOG_TELESCIENCE_START; - ao_log_store.tick = ao_time(); - ao_log_store.adc[0] = ao_companion_command.serial; - ao_log_store.adc[1] = ao_companion_command.flight; - ao_log_telescience_write(); + ao_log_single_write_data.telescience.type = AO_LOG_TELESCIENCE_START; + ao_log_single_write_data.telescience.tick = ao_time(); + ao_log_single_write_data.telescience.adc[0] = ao_companion_command.serial; + ao_log_single_write_data.telescience.adc[1] = ao_companion_command.flight; + ao_log_telescience_csum(); + ao_log_single_write(); /* Write the whole contents of the ring to the log * when starting up. */ ao_log_adc_pos = ao_adc_ring_next(ao_adc_head); - ao_log_store.type = AO_LOG_TELESCIENCE_DATA; + ao_log_single_write_data.telescience.type = AO_LOG_TELESCIENCE_DATA; while (ao_log_running) { /* Write samples to EEPROM */ while (ao_log_adc_pos != ao_adc_head) { - ao_log_store.tick = ao_adc_ring[ao_log_adc_pos].tick; - memcpy(&ao_log_store.adc, (void *) ao_adc_ring[ao_log_adc_pos].adc, + ao_log_single_write_data.telescience.tick = ao_adc_ring[ao_log_adc_pos].tick; + memcpy(&ao_log_single_write_data.telescience.adc, (void *) ao_adc_ring[ao_log_adc_pos].adc, AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); - ao_log_telescience_write(); + ao_log_telescience_csum(); + ao_log_single_write(); ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); } /* Wait for more ADC data to arrive */ ao_sleep((void *) &ao_adc_head); } - memset(&ao_log_store.adc, '\0', sizeof (ao_log_store.adc)); + memset(&ao_log_single_write_data.telescience.adc, '\0', sizeof (ao_log_single_write_data.telescience.adc)); } } void -ao_log_set(void) -{ - printf("Logging currently %s\n", ao_log_running ? "on" : "off"); - ao_cmd_hex(); - if (ao_cmd_status == ao_cmd_success) { - if (ao_cmd_lex_i) { - printf("Logging from %ld to %ld\n", ao_log_current_pos, ao_log_end_pos); - ao_log_start(); - } else { - printf ("Log stopped at %ld\n", ao_log_current_pos); - ao_log_stop(); - } - } - ao_cmd_status = ao_cmd_success; -} - -void -ao_log_list(void) +ao_log_single_list(void) { uint32_t pos; uint32_t start = 0; @@ -197,8 +88,8 @@ ao_log_list(void) for (pos = 0; ; pos += sizeof (struct ao_log_telescience)) { if (pos >= ao_storage_config || - !ao_log_telescience_read(pos) || - ao_log_fetch.type == AO_LOG_TELESCIENCE_START) + !ao_log_single_read(pos) || + ao_log_single_read_data.telescience.type == AO_LOG_TELESCIENCE_START) { if (pos != start) { printf("flight %d start %x end %x\n", @@ -206,7 +97,7 @@ ao_log_list(void) (uint16_t) (start >> 8), (uint16_t) ((pos + 0xff) >> 8)); flush(); } - if (ao_log_fetch.type != AO_LOG_TELESCIENCE_START) + if (ao_log_single_read_data.telescience.type != AO_LOG_TELESCIENCE_START) break; start = pos; flight++; @@ -216,59 +107,11 @@ ao_log_list(void) } void -ao_log_delete(void) +ao_log_single_extra_query(void) { - uint32_t pos; - - ao_cmd_hex(); - if (ao_cmd_status != ao_cmd_success) - return; - if (ao_cmd_lex_i != 1) { - ao_cmd_status = ao_cmd_syntax_error; - printf("No such flight: %d\n", ao_cmd_lex_i); - return; - } - ao_log_stop(); - for (pos = 0; pos < ao_storage_config; pos += ao_storage_block) { - if (!ao_log_telescience_read(pos)) - break; - ao_storage_erase(pos); - } - ao_log_current_pos = ao_log_start_pos = 0; - if (pos == 0) - printf("No such flight: %d\n", ao_cmd_lex_i); - else - printf ("Erased\n"); -} - -static void -ao_log_query(void) -{ - printf("Logging enabled: %d\n", ao_log_running); - printf("Log start: %ld\n", ao_log_start_pos); - printf("Log cur: %ld\n", ao_log_current_pos); - printf("Log end: %ld\n", ao_log_end_pos); - printf("log data tick: %04x\n", ao_log_store.tick); - printf("TM data tick: %04x\n", ao_log_store.tm_tick); - printf("TM state: %d\n", ao_log_store.tm_state); + printf("log data tick: %04x\n", ao_log_single_write_data.telescience.tick); + printf("TM data tick: %04x\n", ao_log_single_write_data.telescience.tm_tick); + printf("TM state: %d\n", ao_log_single_write_data.telescience.tm_state); printf("TM serial: %d\n", ao_companion_command.serial); printf("TM flight: %d\n", ao_companion_command.flight); } - -const struct ao_cmds ao_log_cmds[] = { - { ao_log_set, "L <0 off, 1 on>\0Set logging mode" }, - { ao_log_list, "l\0List stored flight logs" }, - { ao_log_delete, "d 1\0Delete all stored flights" }, - { ao_log_query, "q\0Query log status" }, - { 0, NULL }, -}; - -void -ao_log_init(void) -{ - ao_log_running = 0; - - ao_cmd_register(&ao_log_cmds[0]); - - ao_add_task(&ao_log_task, ao_log_telescience, "log"); -} diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 69eb58e8..6f2d9dbb 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -25,15 +25,7 @@ __xdata uint8_t ao_monitoring; __pdata uint8_t ao_monitor_led; -#define AO_MONITOR_RING 8 - -__xdata union ao_monitor { - struct ao_telemetry_raw_recv raw; - struct ao_telemetry_orig_recv orig; - struct ao_telemetry_tiny_recv tiny; -} ao_monitor_ring[AO_MONITOR_RING]; - -#define ao_monitor_ring_next(n) (((n) + 1) & (AO_MONITOR_RING - 1)) +__xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING]; __data uint8_t ao_monitor_head; diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index 5bbbf71b..cb23f391 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -42,6 +42,9 @@ main(void) ao_radio_init(); ao_packet_master_init(); ao_btm_init(); +#if HAS_LOG + ao_log_single_init(); +#endif #if HAS_DBG ao_dbg_init(); #endif diff --git a/src/product/ao_telescience.c b/src/product/ao_telescience.c index 4dec3a18..45b6d40e 100644 --- a/src/product/ao_telescience.c +++ b/src/product/ao_telescience.c @@ -33,7 +33,7 @@ main(void) ao_storage_init(); ao_usb_init(); ao_adc_init(); - ao_log_init(); + ao_log_single_init(); ao_start_scheduler(); return 0; } diff --git a/src/telebt-v0.1/Makefile b/src/telebt-v0.1/Makefile index a34e8912..01fbaf52 100644 --- a/src/telebt-v0.1/Makefile +++ b/src/telebt-v0.1/Makefile @@ -10,6 +10,7 @@ TELEBT_INC = \ TELEBT_SRC = \ ao_beep.c \ + ao_log_single.c \ ao_log_telem.c \ ao_spi.c \ ao_storage.c \ diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index 3ccbb787..282829e7 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -46,6 +46,7 @@ ALTOS_SRC = \ ao_usb_avr.c \ ao_adc_avr.c \ ao_spi_slave.c \ + ao_log_single.c \ ao_log_telescience.c \ $(TELESCIENCE_STORAGE) -- cgit v1.2.3 From e53557373e539d591a03d02db146b27d08c7eba3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 15:18:29 -0700 Subject: altos: Start logging telemetry data right at boot time Anything logging telemetry data should just start logging packets as soon as they boot. Signed-off-by: Keith Packard --- src/core/ao_log_telem.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index 34abe879..af0e8e6b 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -31,6 +31,7 @@ ao_log_single(void) */ ao_delay(AO_SEC_TO_TICKS(2)); + ao_log_running = 1; ao_log_single_restart(); for (;;) { while (!ao_log_running) @@ -46,7 +47,7 @@ ao_log_single(void) ao_log_single_write(); ao_log_monitor_pos = ao_monitor_ring_next(ao_log_monitor_pos); } - /* Wait for more ADC data to arrive */ + /* Wait for more telemetry data to arrive */ ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); } } -- cgit v1.2.3 From 27835686648e14b030f6f7ec1fc0c0fd1c387ea4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 15:38:12 -0700 Subject: altos: Add RSSI blinking to new-style telemetry code Pull the RSSI data out locally and set the RSSI led blinking when using the variable-length TELEM output mechanism. Signed-off-by: Keith Packard --- src/core/ao_monitor.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 6f2d9dbb..c167b861 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -228,6 +228,10 @@ ao_monitor_put(void) printf("%02x", byte); } printf("%02x\n", sum); + if (recv_raw.packet[ao_monitoring + 1] & PKT_APPEND_STATUS_1_CRC_OK) { + rssi = ((int16_t) recv_raw.packet[ao_monitoring] >> 1) - 74; + ao_rssi_set(rssi); + } break; } ao_usb_flush(); -- cgit v1.2.3 From cff737c290347b61ba16584880c2f4c436b95042 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 15:40:40 -0700 Subject: altos: Remove RSSI reporting from telebt Telebt uses one LED for bluetooth connection and the other for telem packet reception leaving none for RSSI. Signed-off-by: Keith Packard --- src/cc1111/ao_pins.h | 11 +++++++++++ src/core/ao_monitor.c | 6 ++++++ src/product/Makefile.telebt | 1 - src/product/ao_telebt.c | 3 +-- 4 files changed, 18 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 91719b54..57de67b2 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -111,6 +111,7 @@ #define SPI_CS_ON_P0 0 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define HAS_RSSI 1 #define HAS_AES 1 #endif @@ -220,6 +221,7 @@ #define SPI_CS_ON_P0 1 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define HAS_RSSI 1 #define HAS_AES 1 #endif @@ -245,6 +247,7 @@ #define SPI_CS_ON_P0 1 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define HAS_RSSI 1 #define HAS_AES 1 #endif @@ -276,6 +279,7 @@ #define BT_LINK_PIN_INDEX 7 #define BT_LINK_PIN P2_1 #define HAS_MONITOR 1 + #define HAS_RSSI 0 #define HAS_AES 1 #endif @@ -314,6 +318,7 @@ #define BT_LINK_PIN_INDEX 7 #define BT_LINK_PIN P1_7 #define HAS_MONITOR 1 + #define HAS_RSSI 0 #define HAS_AES 1 #endif @@ -456,6 +461,12 @@ #error Please define HAS_MONITOR #endif +#if HAS_MONITOR +#ifndef HAS_RSSI +#error Please define HAS_RSSI +#endif +#endif + #ifndef HAS_ADC #error Please define HAS_ADC #endif diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index c167b861..aaa6bb8b 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -151,7 +151,9 @@ ao_monitor_put(void) ao_gps_print(&recv_orig.telemetry_orig.gps); ao_gps_tracking_print(&recv_orig.telemetry_orig.gps_tracking); putchar('\n'); +#if HAS_RSSI ao_rssi_set(rssi); +#endif } else { printf("CRC INVALID RSSI %3d\n", rssi); } @@ -214,7 +216,9 @@ ao_monitor_put(void) recv_tiny.telemetry_tiny.flight_vel, recv_tiny.telemetry_tiny.flight_pres); #endif +#if HAS_RSSI ao_rssi_set(rssi); +#endif } else { printf("CRC INVALID RSSI %3d\n", rssi); } @@ -228,10 +232,12 @@ ao_monitor_put(void) printf("%02x", byte); } printf("%02x\n", sum); +#if HAS_RSSI if (recv_raw.packet[ao_monitoring + 1] & PKT_APPEND_STATUS_1_CRC_OK) { rssi = ((int16_t) recv_raw.packet[ao_monitoring] >> 1) - 74; ao_rssi_set(rssi); } +#endif break; } ao_usb_flush(); diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index ff0e1502..46c87db0 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -26,7 +26,6 @@ CORE_SRC = \ ao_monitor.c \ ao_mutex.c \ ao_panic.c \ - ao_rssi.c \ ao_state.c \ ao_stdio.c \ ao_task.c diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index cb23f391..9154f4be 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -37,8 +37,7 @@ main(void) ao_storage_init(); #endif ao_usb_init(); - ao_monitor_init(AO_LED_GREEN, TRUE); - ao_rssi_init(AO_LED_RED); + ao_monitor_init(AO_LED_RED, TRUE); ao_radio_init(); ao_packet_master_init(); ao_btm_init(); -- cgit v1.2.3 From 7c6a3195dec6ac68f5d7b3f883ccc2c316384e76 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 15:42:25 -0700 Subject: altos: Blink on telem packet receive instead of toggle Toggling the LED was too confusing; just blink for 100ms each time a packet comes in. Signed-off-by: Keith Packard --- src/core/ao_monitor.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index aaa6bb8b..382af8a2 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -55,7 +55,15 @@ ao_monitor_get(void) continue; ao_monitor_head = ao_monitor_ring_next(ao_monitor_head); ao_wakeup(DATA_TO_XDATA(&ao_monitor_head)); - ao_led_toggle(ao_monitor_led); + } +} + +void +ao_monitor_blink(void) +{ + for (;;) { + ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); + ao_led_for(ao_monitor_led, AO_MS_TO_TICKS(100)); } } @@ -246,6 +254,7 @@ ao_monitor_put(void) __xdata struct ao_task ao_monitor_get_task; __xdata struct ao_task ao_monitor_put_task; +__xdata struct ao_task ao_monitor_blink_task; void ao_set_monitor(uint8_t monitoring) @@ -276,4 +285,6 @@ ao_monitor_init(uint8_t monitor_led, uint8_t monitoring) __reentrant ao_cmd_register(&ao_monitor_cmds[0]); ao_add_task(&ao_monitor_get_task, ao_monitor_get, "monitor_get"); ao_add_task(&ao_monitor_put_task, ao_monitor_put, "monitor_put"); + if (ao_monitor_led) + ao_add_task(&ao_monitor_blink_task, ao_monitor_blink, "monitor_blink"); } -- cgit v1.2.3 From 8eaa1c4697a3cfc2406e1adadc3094f7f712341a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 15:43:32 -0700 Subject: altos: Add pragma to eliminate unreachable code warning on SDCC This pragma was removed as GCC doesn't support it; make it conditional on SDCC so that we eliminate a warning message. Signed-off-by: Keith Packard --- src/core/ao_panic.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c index b6ff65cc..244917a8 100644 --- a/src/core/ao_panic.c +++ b/src/core/ao_panic.c @@ -58,6 +58,9 @@ ao_panic(uint8_t reason) ao_beep(AO_BEEP_OFF); ao_panic_delay(2); +#ifdef SDCC +#pragma disable_warning 126 +#endif for (n = 0; n < reason; n++) { ao_led_on(AO_LED_RED); ao_beep(AO_BEEP_MID); -- cgit v1.2.3 From 3d478a39f2ede7b805bbe568cc1c8ecc176d7a04 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 15:45:05 -0700 Subject: altos: Add the BT serial debug code back in, disabled This code is useful whenever the BT stuff is acting up, so just leave the source in place, turned off by default. Signed-off-by: Keith Packard --- src/drivers/ao_btm.c | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) (limited to 'src') diff --git a/src/drivers/ao_btm.c b/src/drivers/ao_btm.c index 44155ec1..e70e3048 100644 --- a/src/drivers/ao_btm.c +++ b/src/drivers/ao_btm.c @@ -20,6 +20,87 @@ int8_t ao_btm_stdio; __xdata uint8_t ao_btm_connected; +#define BT_DEBUG 0 + +#if BT_DEBUG +__xdata char ao_btm_buffer[256]; +int ao_btm_ptr; +char ao_btm_dir; + +static void +ao_btm_add_char(char c) +{ + if (ao_btm_ptr < sizeof (ao_btm_buffer)) + ao_btm_buffer[ao_btm_ptr++] = c; +} + +static void +ao_btm_log_char(char c, char dir) +{ + if (dir != ao_btm_dir) { + ao_btm_add_char(dir); + ao_btm_dir = dir; + } + ao_btm_add_char(c); +} + +static void +ao_btm_log_out_char(char c) +{ + ao_btm_log_char(c, '>'); +} + +static void +ao_btm_log_in_char(char c) +{ + ao_btm_log_char(c, '<'); +} + +/* + * Dump everything received from the bluetooth device during startup + */ +static void +ao_btm_dump(void) +{ + int i; + char c; + + for (i = 0; i < ao_btm_ptr; i++) { + c = ao_btm_buffer[i]; + if (c < ' ' && c != '\n') + printf("\\%03o", ((int) c) & 0xff); + else + putchar(ao_btm_buffer[i]); + } + putchar('\n'); +} + +static void +ao_btm_speed(void) +{ + ao_cmd_decimal(); + if (ao_cmd_lex_u32 == 57600) + ao_serial_set_speed(AO_SERIAL_SPEED_57600); + else if (ao_cmd_lex_u32 == 19200) + ao_serial_set_speed(AO_SERIAL_SPEED_19200); + else + ao_cmd_status = ao_cmd_syntax_error; +} + +__code struct ao_cmds ao_btm_cmds[] = { + { ao_btm_dump, "d\0Dump btm buffer." }, + { ao_btm_speed, "s <19200,57600>\0Set btm serial speed." }, + { 0, NULL }, +}; + +#define ao_btm_log_init() ao_cmd_register(&ao_btm_cmds[0]) + +#else +#define ao_btm_log_in_char(c) +#define ao_btm_log_out_char(c) +#define ao_btm_log_init() +#endif + #define AO_BTM_MAX_REPLY 16 __xdata char ao_btm_reply[AO_BTM_MAX_REPLY]; @@ -39,6 +120,7 @@ ao_btm_get_line(void) for (;;) { while ((c = ao_serial_pollchar()) != AO_READ_AGAIN) { + ao_btm_log_in_char(c); if (ao_btm_reply_len < sizeof (ao_btm_reply)) ao_btm_reply[ao_btm_reply_len++] = c; if (c == '\r' || c == '\n') @@ -85,6 +167,7 @@ ao_btm_echo(uint8_t echo) void ao_btm_putchar(char c) { + ao_btm_log_out_char(c); ao_serial_putchar(c); ao_delay(1); } @@ -299,4 +382,5 @@ ao_btm_init (void) #endif ao_add_task(&ao_btm_task, ao_btm, "bt"); + ao_btm_log_init(); } -- cgit v1.2.3 From 9b9568a637ffdbc67225271005f2b996ee08a0df Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 16:39:41 -0700 Subject: altos: add 'report' to telebt This beeps out flight state changes and max altitude at landing, just like the altimeter. Signed-off-by: Keith Packard --- src/core/ao.h | 1 + src/core/ao_log_telem.c | 25 ++++++++++++++++++++++++- src/core/ao_monitor.c | 6 +++--- src/drivers/ao_btm.c | 4 ---- src/product/Makefile.telebt | 1 + src/product/ao_telebt.c | 3 ++- 6 files changed, 31 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 8b978272..f2e40fc6 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1360,6 +1360,7 @@ extern __xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING]; #define ao_monitor_ring_next(n) (((n) + 1) & (AO_MONITOR_RING - 1)) +extern __data uint8_t ao_monitoring; extern __data uint8_t ao_monitor_head; void diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index af0e8e6b..9afa13b2 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -19,8 +19,29 @@ __code uint8_t ao_log_format = AO_LOG_FORMAT_TELEMETRY; -static __data uint8_t ao_log_monitor_pos; +static __data uint8_t ao_log_monitor_pos; +__pdata enum ao_flight_state ao_flight_state; +__pdata int16_t ao_max_height; /* max of ao_height */ +static void +ao_log_telem_track() { + if (ao_monitoring == sizeof (union ao_telemetry_all)) { + switch (ao_log_single_write_data.telemetry.generic.type) { + case AO_TELEMETRY_SENSOR_TELEMETRUM: + case AO_TELEMETRY_SENSOR_TELEMINI: + case AO_TELEMETRY_SENSOR_TELENANO: + if (ao_log_single_write_data.telemetry.sensor.height > ao_max_height) { + ao_max_height = ao_log_single_write_data.telemetry.sensor.height; + } + if (ao_log_single_write_data.telemetry.sensor.state != ao_flight_state) { + ao_flight_state = ao_log_single_write_data.telemetry.sensor.state; + if (ao_flight_state == ao_flight_pad) + ao_max_height = 0; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + } + } +} void ao_log_single(void) { @@ -33,6 +54,7 @@ ao_log_single(void) ao_log_running = 1; ao_log_single_restart(); + ao_flight_state = ao_flight_startup; for (;;) { while (!ao_log_running) ao_sleep(&ao_log_running); @@ -46,6 +68,7 @@ ao_log_single(void) AO_LOG_SINGLE_SIZE); ao_log_single_write(); ao_log_monitor_pos = ao_monitor_ring_next(ao_log_monitor_pos); + ao_log_telem_track(); } /* Wait for more telemetry data to arrive */ ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 382af8a2..56d7604d 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -22,7 +22,7 @@ #error Must define HAS_MONITOR to 1 #endif -__xdata uint8_t ao_monitoring; +__data uint8_t ao_monitoring; __pdata uint8_t ao_monitor_led; __xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING]; @@ -37,7 +37,7 @@ ao_monitor_get(void) for (;;) { switch (ao_monitoring) { case 0: - ao_sleep(&ao_monitoring); + ao_sleep(DATA_TO_XDATA(&ao_monitoring)); continue; case AO_MONITORING_ORIG: size = sizeof (struct ao_telemetry_orig_recv); @@ -262,7 +262,7 @@ ao_set_monitor(uint8_t monitoring) if (ao_monitoring) ao_radio_recv_abort(); ao_monitoring = monitoring; - ao_wakeup(&ao_monitoring); + ao_wakeup(DATA_TO_XDATA(&ao_monitoring)); } static void diff --git a/src/drivers/ao_btm.c b/src/drivers/ao_btm.c index e70e3048..5eb78815 100644 --- a/src/drivers/ao_btm.c +++ b/src/drivers/ao_btm.c @@ -249,10 +249,6 @@ ao_btm(void) */ ao_delay(AO_SEC_TO_TICKS(3)); -#if HAS_BEEP - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); -#endif - /* * The first time we connect, the BTM-180 comes up at 19200 baud. * After that, it will remember and come up at 57600 baud. So, see diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index 46c87db0..04dd044e 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -26,6 +26,7 @@ CORE_SRC = \ ao_monitor.c \ ao_mutex.c \ ao_panic.c \ + ao_report.c \ ao_state.c \ ao_stdio.c \ ao_task.c diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index 9154f4be..6fe18a4d 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -37,7 +37,8 @@ main(void) ao_storage_init(); #endif ao_usb_init(); - ao_monitor_init(AO_LED_RED, TRUE); + ao_monitor_init(AO_LED_RED, sizeof (union ao_telemetry_all)); + ao_report_init(); ao_radio_init(); ao_packet_master_init(); ao_btm_init(); -- cgit v1.2.3 From 122c4101164d598e655fa9ad8473053d30ff4212 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 16:55:55 -0700 Subject: altos: Report continuity in telebt Report continuity values from remote altimeter Signed-off-by: Keith Packard --- src/cc1111/ao_pins.h | 6 ++++++ src/core/ao_log_telem.c | 29 +++++++++++++++++++++++++++++ src/core/ao_report.c | 6 ++++-- src/product/Makefile.telebt | 1 - src/product/ao_telebt.c | 2 ++ src/telebt-v0.1/Makefile | 1 + 6 files changed, 42 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 57de67b2..723f1500 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -274,6 +274,7 @@ #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 #define HAS_IGNITE 0 + #define HAS_IGNITE_REPORT 1 #define BT_LINK_ON_P2 1 #define BT_LINK_ON_P1 0 #define BT_LINK_PIN_INDEX 7 @@ -313,6 +314,7 @@ #define M25_MAX_CHIPS 1 #define HAS_ACCEL 0 #define HAS_IGNITE 0 + #define HAS_IGNITE_REPORT 1 #define BT_LINK_ON_P2 0 #define BT_LINK_ON_P1 1 #define BT_LINK_PIN_INDEX 7 @@ -449,6 +451,10 @@ #error Please define HAS_IGNITE #endif +#if HAS_IGNITE +#define HAS_IGNITE_REPORT 1 +#endif + #ifndef PACKET_HAS_MASTER #error Please define PACKET_HAS_MASTER #endif diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index 9afa13b2..193c11f3 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -22,6 +22,7 @@ __code uint8_t ao_log_format = AO_LOG_FORMAT_TELEMETRY; static __data uint8_t ao_log_monitor_pos; __pdata enum ao_flight_state ao_flight_state; __pdata int16_t ao_max_height; /* max of ao_height */ +__pdata int16_t sense_d, sense_m; static void ao_log_telem_track() { @@ -29,6 +30,9 @@ ao_log_telem_track() { switch (ao_log_single_write_data.telemetry.generic.type) { case AO_TELEMETRY_SENSOR_TELEMETRUM: case AO_TELEMETRY_SENSOR_TELEMINI: + sense_d = ao_log_single_write_data.telemetry.sensor.sense_d; + sense_m = ao_log_single_write_data.telemetry.sensor.sense_m; + /* fall through ... */ case AO_TELEMETRY_SENSOR_TELENANO: if (ao_log_single_write_data.telemetry.sensor.height > ao_max_height) { ao_max_height = ao_log_single_write_data.telemetry.sensor.height; @@ -42,6 +46,31 @@ ao_log_telem_track() { } } } + +enum ao_igniter_status +ao_igniter_status(enum ao_igniter igniter) +{ + int16_t value; + + switch (igniter) { + case ao_igniter_drogue: + value = sense_d; + break; + case ao_igniter_main: + value = sense_m; + break; + default: + value = 0; + break; + } + if (value < AO_IGNITER_OPEN) + return ao_igniter_open; + else if (value > AO_IGNITER_CLOSED) + return ao_igniter_ready; + else + return ao_igniter_unknown; +} + void ao_log_single(void) { diff --git a/src/core/ao_report.c b/src/core/ao_report.c index 3cf558e1..e0355d96 100644 --- a/src/core/ao_report.c +++ b/src/core/ao_report.c @@ -109,7 +109,7 @@ ao_report_altitude(void) } } -#if HAS_IGNITE +#if HAS_IGNITE_REPORT static uint8_t ao_report_igniter_ready(enum ao_igniter igniter) { @@ -133,6 +133,7 @@ ao_report_continuity(void) __reentrant low(AO_MS_TO_TICKS(20)); } } +#if HAS_LOG if (ao_log_full()) { pause(AO_MS_TO_TICKS(100)); c = 2; @@ -143,6 +144,7 @@ ao_report_continuity(void) __reentrant mid(AO_MS_TO_TICKS(100)); } } +#endif c = 50; while (c-- && ao_flight_state == ao_flight_pad) pause(AO_MS_TO_TICKS(100)); @@ -157,7 +159,7 @@ ao_report(void) if (ao_flight_state == ao_flight_landed) ao_report_altitude(); ao_report_beep(); -#if HAS_IGNITE +#if HAS_IGNITE_REPORT if (ao_flight_state == ao_flight_idle) ao_report_continuity(); while (ao_flight_state == ao_flight_pad) diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index 04dd044e..46c87db0 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -26,7 +26,6 @@ CORE_SRC = \ ao_monitor.c \ ao_mutex.c \ ao_panic.c \ - ao_report.c \ ao_state.c \ ao_stdio.c \ ao_task.c diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index 6fe18a4d..9e409db7 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -38,7 +38,9 @@ main(void) #endif ao_usb_init(); ao_monitor_init(AO_LED_RED, sizeof (union ao_telemetry_all)); +#if HAS_LOG ao_report_init(); +#endif ao_radio_init(); ao_packet_master_init(); ao_btm_init(); diff --git a/src/telebt-v0.1/Makefile b/src/telebt-v0.1/Makefile index 01fbaf52..90cd3cac 100644 --- a/src/telebt-v0.1/Makefile +++ b/src/telebt-v0.1/Makefile @@ -12,6 +12,7 @@ TELEBT_SRC = \ ao_beep.c \ ao_log_single.c \ ao_log_telem.c \ + ao_report.c \ ao_spi.c \ ao_storage.c \ ao_m25.c -- cgit v1.2.3 From e66fd72664aae7c000dce9c528803e28e7918fdf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 28 Aug 2011 17:03:26 -0700 Subject: altos: don't beep igniter continuity for telenano Without any igniters, it's not nice to annoy people. Signed-off-by: Keith Packard --- src/core/ao.h | 2 ++ src/core/ao_log_telem.c | 10 ++++++++-- src/core/ao_report.c | 18 +++++++++++++----- 3 files changed, 23 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index f2e40fc6..a541d8ac 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1436,6 +1436,8 @@ extern __xdata struct ao_ignition ao_ignition[2]; enum ao_igniter_status ao_igniter_status(enum ao_igniter igniter); +extern __pdata uint8_t ao_igniter_present; + void ao_ignite_set_pins(void); diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index 193c11f3..096ad919 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -23,6 +23,7 @@ static __data uint8_t ao_log_monitor_pos; __pdata enum ao_flight_state ao_flight_state; __pdata int16_t ao_max_height; /* max of ao_height */ __pdata int16_t sense_d, sense_m; +__pdata uint8_t ao_igniter_present; static void ao_log_telem_track() { @@ -30,10 +31,15 @@ ao_log_telem_track() { switch (ao_log_single_write_data.telemetry.generic.type) { case AO_TELEMETRY_SENSOR_TELEMETRUM: case AO_TELEMETRY_SENSOR_TELEMINI: - sense_d = ao_log_single_write_data.telemetry.sensor.sense_d; - sense_m = ao_log_single_write_data.telemetry.sensor.sense_m; /* fall through ... */ case AO_TELEMETRY_SENSOR_TELENANO: + if (ao_log_single_write_data.telemetry.generic.type == AO_TELEMETRY_SENSOR_TELENANO) { + ao_igniter_present = 0; + } else { + sense_d = ao_log_single_write_data.telemetry.sensor.sense_d; + sense_m = ao_log_single_write_data.telemetry.sensor.sense_m; + ao_igniter_present = 1; + } if (ao_log_single_write_data.telemetry.sensor.height > ao_max_height) { ao_max_height = ao_log_single_write_data.telemetry.sensor.height; } diff --git a/src/core/ao_report.c b/src/core/ao_report.c index e0355d96..70f0b49d 100644 --- a/src/core/ao_report.c +++ b/src/core/ao_report.c @@ -119,7 +119,13 @@ ao_report_igniter_ready(enum ao_igniter igniter) static void ao_report_continuity(void) __reentrant { - uint8_t c = (ao_report_igniter_ready(ao_igniter_drogue) | + uint8_t c; + +#if !HAS_IGNITE + if (!ao_igniter_present) + return; +#endif + c = (ao_report_igniter_ready(ao_igniter_drogue) | (ao_report_igniter_ready(ao_igniter_main) << 1)); if (c) { while (c--) { @@ -145,9 +151,6 @@ ao_report_continuity(void) __reentrant } } #endif - c = 50; - while (c-- && ao_flight_state == ao_flight_pad) - pause(AO_MS_TO_TICKS(100)); } #endif @@ -162,8 +165,13 @@ ao_report(void) #if HAS_IGNITE_REPORT if (ao_flight_state == ao_flight_idle) ao_report_continuity(); - while (ao_flight_state == ao_flight_pad) + while (ao_flight_state == ao_flight_pad) { + uint8_t c; ao_report_continuity(); + c = 50; + while (c-- && ao_flight_state == ao_flight_pad) + pause(AO_MS_TO_TICKS(100)); + } #endif __critical { while (ao_report_state == ao_flight_state) -- cgit v1.2.3 From b2d4e49bfe88aa61ca36fb1af8f3088c5754304c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 29 Aug 2011 14:22:19 -0700 Subject: altos: Split avr clock initialization to ao_clock.c This will be shared with the attiny code for TeleTerra v0.1 Signed-off-by: Keith Packard --- src/avr/ao_clock.c | 77 +++++++++++++++++++++++++++++++++++++++++++ src/avr/ao_timer.c | 58 -------------------------------- src/telescience-v0.1/Makefile | 1 + 3 files changed, 78 insertions(+), 58 deletions(-) create mode 100644 src/avr/ao_clock.c (limited to 'src') diff --git a/src/avr/ao_clock.c b/src/avr/ao_clock.c new file mode 100644 index 00000000..0d42b6d5 --- /dev/null +++ b/src/avr/ao_clock.c @@ -0,0 +1,77 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +/* + * AltOS always cranks the clock to the max frequency + */ + +void +ao_clock_init(void) +{ + /* disable RC clock */ + CLKSEL0 &= ~(1 << RCE); + + /* Disable PLL */ + PLLCSR &= ~(1 << PLLE); + + /* Enable external clock */ + CLKSEL0 |= (1 << EXTE); + + /* wait for external clock to be ready */ + while ((CLKSTA & (1 << EXTON)) == 0) + ; + + /* select external clock */ + CLKSEL0 |= (1 << CLKS); + + /* Disable the clock prescaler */ + cli(); + CLKPR = (1 << CLKPCE); + + /* Always run the system clock at 8MHz */ +#if AVR_CLOCK > 12000000UL + CLKPR = 1; +#else + CLKPR = 0; +#endif + sei(); + + /* Set up the PLL to use the crystal */ + + /* Use primary system clock as PLL source */ + PLLFRQ = ((0 << PINMUX) | /* Use primary clock */ + (0 << PLLUSB) | /* No divide by 2 for USB */ + (0 << PLLTM0) | /* Disable high speed timer */ + (0x4 << PDIV0)); /* 48MHz PLL clock */ + + /* Set the frequency of the crystal */ +#if AVR_CLOCK > 12000000UL + PLLCSR |= (1 << PINDIV); /* For 16MHz crystal on Teensy board */ +#else + PLLCSR &= ~(1 << PINDIV); /* For 8MHz crystal on TeleScience board */ +#endif + + /* Enable the PLL */ + PLLCSR |= (1 << PLLE); + while (!(PLLCSR & (1 << PLOCK))) + ; + + set_sleep_mode(SLEEP_MODE_IDLE); + sleep_enable(); +} diff --git a/src/avr/ao_timer.c b/src/avr/ao_timer.c index 1e374c75..eef14345 100644 --- a/src/avr/ao_timer.c +++ b/src/avr/ao_timer.c @@ -87,61 +87,3 @@ ao_timer_init(void) TIMSK1 = (1 << OCIE1A); /* Interrupt on compare match */ } - -/* - * AltOS always cranks the clock to the max frequency - */ -void -ao_clock_init(void) -{ - /* disable RC clock */ - CLKSEL0 &= ~(1 << RCE); - - /* Disable PLL */ - PLLCSR &= ~(1 << PLLE); - - /* Enable external clock */ - CLKSEL0 |= (1 << EXTE); - - /* wait for external clock to be ready */ - while ((CLKSTA & (1 << EXTON)) == 0) - ; - - /* select external clock */ - CLKSEL0 |= (1 << CLKS); - - /* Disable the clock prescaler */ - cli(); - CLKPR = (1 << CLKPCE); - - /* Always run the system clock at 8MHz */ -#if AVR_CLOCK > 12000000UL - CLKPR = 1; -#else - CLKPR = 0; -#endif - sei(); - - /* Set up the PLL to use the crystal */ - - /* Use primary system clock as PLL source */ - PLLFRQ = ((0 << PINMUX) | /* Use primary clock */ - (0 << PLLUSB) | /* No divide by 2 for USB */ - (0 << PLLTM0) | /* Disable high speed timer */ - (0x4 << PDIV0)); /* 48MHz PLL clock */ - - /* Set the frequency of the crystal */ -#if AVR_CLOCK > 12000000UL - PLLCSR |= (1 << PINDIV); /* For 16MHz crystal on Teensy board */ -#else - PLLCSR &= ~(1 << PINDIV); /* For 8MHz crystal on TeleScience board */ -#endif - - /* Enable the PLL */ - PLLCSR |= (1 << PLLE); - while (!(PLLCSR & (1 << PLOCK))) - ; - - set_sleep_mode(SLEEP_MODE_IDLE); - sleep_enable(); -} diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index 282829e7..28620242 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -33,6 +33,7 @@ TELESCIENCE_STORAGE= \ ao_storage.c \ ALTOS_SRC = \ + ao_clock.c \ ao_cmd.c \ ao_mutex.c \ ao_panic.c \ -- cgit v1.2.3 From d1e81db87ce0f89fd0b7651ca00979498cd00b78 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 4 Sep 2011 08:48:05 -0700 Subject: altos: Delay restart of RDF at apogee Instead of immediately trying to send RDF at apogee, start it after the usual RDF interval to avoid doing RDF while firing the apogee igniter. Signed-off-by: Keith Packard --- src/ao_telemetry.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ao_telemetry.c b/src/ao_telemetry.c index c7338a58..d006aa59 100644 --- a/src/ao_telemetry.c +++ b/src/ao_telemetry.c @@ -258,7 +258,7 @@ ao_rdf_set(uint8_t rdf) if (rdf == 0) ao_radio_rdf_abort(); else - ao_rdf_time = ao_time(); + ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; } __xdata struct ao_task ao_telemetry_task; -- cgit v1.2.3 From eaa7d7c7dd445ade7d8e3228306785f9a545b89a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 4 Sep 2011 08:49:16 -0700 Subject: altos: Silence radio while firing igniters Hold the radio mutex while firing igniters to reduce potential interactions between the two. Signed-off-by: Keith Packard --- src/ao_ignite.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/ao_ignite.c b/src/ao_ignite.c index 5238beb4..ac1d28e7 100644 --- a/src/ao_ignite.c +++ b/src/ao_ignite.c @@ -90,6 +90,7 @@ ao_igniter_status(enum ao_igniter igniter) void ao_igniter_fire(enum ao_igniter igniter) __critical { + ao_mutex_get(&ao_radio_mutex); ao_ignition[igniter].firing = 1; switch(ao_config.ignite_mode) { case AO_IGNITE_MODE_DUAL: @@ -134,6 +135,7 @@ ao_igniter_fire(enum ao_igniter igniter) __critical break; } ao_ignition[igniter].firing = 0; + ao_mutex_put(&ao_radio_mutex); } void -- cgit v1.2.3 From abf17522c206b465375b73a004a6d67bfa714ba3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Sep 2011 11:36:11 -0700 Subject: altos: SPI slave code is now per-product We can't write general purpose SPI slave code as we must eliminate any latency because the SPI ports have no buffering. Signed-off-by: Keith Packard --- src/avr/ao_pins.h | 7 +++ src/avr/ao_spi_slave.c | 99 +++++++++++++++--------------------------- src/core/ao.h | 13 +++++- src/drivers/ao_science_slave.c | 62 ++++++++++++++++++++++++++ src/telescience-v0.1/Makefile | 1 + 5 files changed, 118 insertions(+), 64 deletions(-) create mode 100644 src/drivers/ao_science_slave.c (limited to 'src') diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index 56435f18..88f03829 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -52,6 +52,13 @@ #define SPI_CS_DIR DDRE #define M25_CS_MASK (1 << PORTE6) #define M25_MAX_CHIPS 1 + + #define SPI_SLAVE_CS_PORT PORTB + #define SPI_SLAVE_CS_PIN PINB + #define SPI_SLAVE_CS_PIN_NO PINB0 + + #define SPI_SLAVE_PIN_0_3 1 + #define SPI_SLAVE_PIN_2_5 0 #endif #endif /* _AO_PINS_H_ */ diff --git a/src/avr/ao_spi_slave.c b/src/avr/ao_spi_slave.c index e4d866a8..76f574c6 100644 --- a/src/avr/ao_spi_slave.c +++ b/src/avr/ao_spi_slave.c @@ -16,18 +16,8 @@ */ #include "ao.h" -#include "ao_product.h" -struct ao_companion_command ao_companion_command; - -static const struct ao_companion_setup ao_telescience_setup = { - .board_id = AO_idProduct_NUMBER, - .board_id_inverse = ~AO_idProduct_NUMBER, - .update_period = 50, - .channels = AO_LOG_TELESCIENCE_NUM_ADC, -}; - -static uint8_t +uint8_t ao_spi_read(uint8_t *buf, uint8_t len) { while (len--) { @@ -39,7 +29,7 @@ ao_spi_read(uint8_t *buf, uint8_t len) return 1; } -static void +void ao_spi_write(uint8_t *buf, uint8_t len) { while (len--) { @@ -52,66 +42,38 @@ ao_spi_write(uint8_t *buf, uint8_t len) (void) SPDR; } -static uint8_t ao_spi_slave_recv(void) -{ - if (!ao_spi_read((uint8_t *) &ao_companion_command, - sizeof (ao_companion_command))) - return 0; - - /* Figure out the outbound data */ - switch (ao_companion_command.command) { - case AO_COMPANION_SETUP: - ao_spi_write((uint8_t *) &ao_telescience_setup, - sizeof (ao_telescience_setup)); - break; - case AO_COMPANION_FETCH: - ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, - AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); - break; - case AO_COMPANION_NOTIFY: - break; - default: - return 0; - } - - ao_log_single_write_data.telescience.tm_tick = ao_companion_command.tick; - if (ao_log_single_write_data.telescience.tm_state != ao_companion_command.flight_state) { - ao_log_single_write_data.telescience.tm_state = ao_companion_command.flight_state; - return 1; - } - return 0; -} - static uint8_t ao_spi_slave_running; ISR(PCINT0_vect) { - if ((PINB & (1 << PINB0)) == 0) { + cli(); +#if SPI_SLAVE_PIN_0_3 + if ((PINB & (1 << PORTB0)) == 0) +#endif +#if SPI_SLAVE_PIN_2_5 + if ((PINB & (1 << PORTB2)) == 0) +#endif + { if (!ao_spi_slave_running) { - uint8_t changed; ao_spi_slave_running = 1; - cli(); - changed = ao_spi_slave_recv(); - sei(); - if (changed && ao_flight_boost <= ao_log_single_write_data.telescience.tm_state) { - if (ao_log_single_write_data.telescience.tm_state < ao_flight_landed) - ao_log_single_start(); - else - ao_log_single_stop(); - } + ao_spi_slave(); } } else { ao_spi_slave_running = 0; } -} - -void ao_spi_slave_debug(void) { - printf ("slave running %d\n", ao_spi_slave_running); + sei(); } void ao_spi_slave_init(void) { + /* We'd like to have a pull-up on SS so that disconnecting the + * TM would cause any SPI transaction to abort. However, when + * I tried that, SPI transactions would spontaneously abort, + * making me assume that we needed a less aggressive pull-up + * than is offered inside the AVR + */ +#if SPI_SLAVE_PIN_0_3 PCMSK0 |= (1 << PCINT0); /* Enable PCINT0 pin change */ PCICR |= (1 << PCIE0); /* Enable pin change interrupt */ @@ -121,17 +83,28 @@ ao_spi_slave_init(void) (0 << 1) | /* SCK, input */ (0 << 0)); /* SS, input */ - /* We'd like to have a pull-up on SS so that disconnecting the - * TM would cause any SPI transaction to abort. However, when - * I tried that, SPI transactions would spontaneously abort, - * making me assume that we needed a less aggressive pull-up - * than is offered inside the AVR - */ PORTB = ((PORTB & 0xf0) | (1 << 3) | /* MISO, output */ (0 << 2) | /* MOSI, no pull-up */ (0 << 1) | /* SCK, no pull-up */ (0 << 0)); /* SS, no pull-up */ +#endif +#if SPI_SLAVE_PIN_2_5 + PCMSK0 |= (1 << PCINT2); /* Enable PCINT2 pin change */ + PCICR |= (1 << PCIE0); /* Enable pin change interrupt */ + + DDRB = ((DDRB & 0xf0) | + (0 << 5) | /* SCK, input */ + (1 << 4) | /* MISO, output */ + (0 << 3) | /* MOSI, input */ + (0 << 2)); /* SS, input */ + + PORTB = ((PORTB & 0xf0) | + (0 << 5) | /* SCK, no pull-up */ + (1 << 4) | /* MISO, output */ + (0 << 3) | /* MOSI, no pull-up */ + (0 << 2)); /* SS, no pull-up */ +#endif SPCR = (0 << SPIE) | /* Disable SPI interrupts */ (1 << SPE) | /* Enable SPI */ diff --git a/src/core/ao.h b/src/core/ao.h index a541d8ac..1d5769cb 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -974,12 +974,23 @@ ao_spi_init(void); * ao_spi_slave.c */ +uint8_t +ao_spi_read(uint8_t *buf, uint8_t len); + void -ao_spi_slave_debug(void); +ao_spi_write(uint8_t *buf, uint8_t len); void ao_spi_slave_init(void); +/* This must be defined by the product; it will get called when chip + * select goes low, at which point it should use ao_spi_read and + * ao_spi_write to deal with the request + */ + +void +ao_spi_slave(void); + /* * ao_telemetry.c */ diff --git a/src/drivers/ao_science_slave.c b/src/drivers/ao_science_slave.c new file mode 100644 index 00000000..e902318f --- /dev/null +++ b/src/drivers/ao_science_slave.c @@ -0,0 +1,62 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_product.h" + +struct ao_companion_command ao_companion_command; + +static const struct ao_companion_setup ao_telescience_setup = { + .board_id = AO_idProduct_NUMBER, + .board_id_inverse = ~AO_idProduct_NUMBER, + .update_period = 50, + .channels = AO_LOG_TELESCIENCE_NUM_ADC, +}; + +void ao_spi_slave(void) +{ + if (!ao_spi_read((uint8_t *) &ao_companion_command, + sizeof (ao_companion_command))) + return; + + /* Figure out the outbound data */ + switch (ao_companion_command.command) { + case AO_COMPANION_SETUP: + ao_spi_write((uint8_t *) &ao_telescience_setup, + sizeof (ao_telescience_setup)); + break; + case AO_COMPANION_FETCH: + ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, + AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); + break; + case AO_COMPANION_NOTIFY: + break; + default: + return; + } + + ao_log_single_write_data.telescience.tm_tick = ao_companion_command.tick; + if (ao_log_single_write_data.telescience.tm_state != ao_companion_command.flight_state) { + ao_log_single_write_data.telescience.tm_state = ao_companion_command.flight_state; + if (ao_flight_boost <= ao_log_single_write_data.telescience.tm_state) { + if (ao_log_single_write_data.telescience.tm_state < ao_flight_landed) + ao_log_single_start(); + else + ao_log_single_stop(); + } + } +} diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index 28620242..a6797cbe 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -46,6 +46,7 @@ ALTOS_SRC = \ ao_romconfig.c \ ao_usb_avr.c \ ao_adc_avr.c \ + ao_science_slave.c \ ao_spi_slave.c \ ao_log_single.c \ ao_log_telescience.c \ -- cgit v1.2.3 From c8a00bb9ccdf0d4257f037c2bf996ce5e6b0b0c0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Sep 2011 11:39:24 -0700 Subject: altos: Pre-compute RDF packet len at compile time Instead of computing the RDF packet len at run time, which takes a pile of code space. Signed-off-by: Keith Packard --- src/cc1111/ao_radio.c | 14 +------------- src/core/ao.h | 12 +++++++++++- src/core/ao_telemetry.c | 2 +- 3 files changed, 13 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index 00816b33..75f241d4 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -367,21 +367,9 @@ ao_radio_recv_abort(void) __xdata ao_radio_rdf_value = 0x55; void -ao_radio_rdf(int ms) +ao_radio_rdf(uint8_t pkt_len) { uint8_t i; - uint8_t pkt_len; - - /* - * Compute the packet length as follows: - * - * 2000 bps (for a 1kHz tone) - * so, for 'ms' milliseconds, we need - * 2 * ms bits, or ms / 4 bytes - */ - if (ms > (255 * 4)) - ms = 255 * 4; - pkt_len = ms >> 2; ao_radio_abort = 0; ao_radio_get(pkt_len); diff --git a/src/core/ao.h b/src/core/ao.h index 1d5769cb..c28c4549 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1341,8 +1341,18 @@ ao_radio_recv(__xdata void *data, uint8_t size) __reentrant; void ao_radio_recv_abort(void); +/* + * Compute the packet length as follows: + * + * 2000 bps (for a 1kHz tone) + * so, for 'ms' milliseconds, we need + * 2 * ms bits, or ms / 4 bytes + */ + +#define AO_MS_TO_RDF_LEN(ms) ((ms) > 255 * 4 ? 255 : ((ms) >> 2)) + void -ao_radio_rdf(int ms); +ao_radio_rdf(uint8_t pkt_len); void ao_radio_rdf_abort(void); diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index de669ce1..c2707e7d 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -235,7 +235,7 @@ ao_telemetry(void) (int16_t) (ao_time() - ao_rdf_time) >= 0) { ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; - ao_radio_rdf(AO_RDF_LENGTH_MS); + ao_radio_rdf(AO_MS_TO_RDF_LEN(AO_RDF_LENGTH_MS)); } #endif time += ao_telemetry_interval; -- cgit v1.2.3 From 0820f5c6dfe067590f36e8201a4049719dcf3d7c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Sep 2011 11:40:56 -0700 Subject: altos: Support staging by going back to boost as needed Detect additional motor burns by looking for high positive acceleration in coast or fast modes. Signed-off-by: Keith Packard --- src/core/ao_flight.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index 85c1825b..a5cf7468 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -34,7 +34,7 @@ /* Main flight thread. */ __pdata enum ao_flight_state ao_flight_state; /* current flight state */ -__pdata uint16_t ao_launch_tick; /* time of launch detect */ +__pdata uint16_t ao_boost_tick; /* time of launch detect */ /* * track min/max data over a long interval to detect @@ -151,7 +151,7 @@ ao_flight(void) ) { ao_flight_state = ao_flight_boost; - ao_launch_tick = ao_sample_tick; + ao_boost_tick = ao_sample_tick; /* start logging data */ ao_log_start(); @@ -184,7 +184,7 @@ ao_flight(void) * (15 seconds) has past. */ if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || - (int16_t) (ao_sample_tick - ao_launch_tick) > BOOST_TICKS_MAX) + (int16_t) (ao_sample_tick - ao_boost_tick) > BOOST_TICKS_MAX) { #if HAS_ACCEL ao_flight_state = ao_flight_fast; @@ -205,7 +205,8 @@ ao_flight(void) { ao_flight_state = ao_flight_coast; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } + } else + goto check_re_boost; break; #endif case ao_flight_coast: @@ -237,6 +238,16 @@ ao_flight(void) ao_flight_state = ao_flight_drogue; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } +#if HAS_ACCEL + else { + check_re_boost: + if (ao_accel > AO_MSS_TO_ACCEL(20)) { + ao_boost_tick = ao_sample_tick; + ao_flight_state = ao_flight_boost; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + } +#endif break; case ao_flight_drogue: -- cgit v1.2.3 From 7a02d4bace05cc829522933b9df6b82a9e17336f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Sep 2011 11:30:43 -0700 Subject: altos: Add TelePyro v0.1 support Signed-off-by: Keith Packard --- src/Makefile | 2 +- src/avr/ao_adc_avr.c | 21 ++++++++- src/avr/ao_pins.h | 24 +++++++++++ src/core/ao.h | 6 +++ src/drivers/ao_pyro_slave.c | 51 ++++++++++++++++++++++ src/product/ao_telepyro.c | 36 ++++++++++++++++ src/telepyro-v0.1/Makefile | 101 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 238 insertions(+), 3 deletions(-) create mode 100644 src/drivers/ao_pyro_slave.c create mode 100644 src/product/ao_telepyro.c create mode 100644 src/telepyro-v0.1/Makefile (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 9ef5ae0a..91d3f035 100644 --- a/src/Makefile +++ b/src/Makefile @@ -19,7 +19,7 @@ SUBDIRS=\ telebt-v0.0 telebt-v0.1 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ telelaunch-v0.1 \ - tidongle test telescience-v0.1 + tidongle test telescience-v0.1 telepyro-v0.1 all: all-local all-recursive diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c index 5afced74..9f45acaf 100644 --- a/src/avr/ao_adc_avr.c +++ b/src/avr/ao_adc_avr.c @@ -20,6 +20,7 @@ volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; volatile __data uint8_t ao_adc_head; +#ifdef TELESCIENCE const uint8_t adc_channels[AO_LOG_TELESCIENCE_NUM_ADC] = { 0x00, 0x01, @@ -34,6 +35,22 @@ const uint8_t adc_channels[AO_LOG_TELESCIENCE_NUM_ADC] = { 0x24, 0x25, }; +#endif + +#ifdef TELEPYRO +const uint8_t adc_channels[AO_TELEPYRO_NUM_ADC] = { + 0x00, /* ADC0 v_batt */ + 0x04, /* ADC4 sense_a */ + 0x05, /* ADC5 sense_b */ + 0x06, /* ADC6 sense_c */ + 0x07, /* ADC7 sense_d */ + 0x23, /* ADC11 sense_e */ + 0x22, /* ADC10 sense_f */ + 0x21, /* ADC9 sense_g */ +}; +#endif + +#define NUM_ADC (sizeof (adc_channels) / sizeof (adc_channels[0])) static uint8_t ao_adc_channel; @@ -75,7 +92,7 @@ ISR(ADC_vect) value = ADCL; value |= (ADCH << 8); ao_adc_ring[ao_adc_head].adc[ao_adc_channel] = value; - if (++ao_adc_channel < AO_TELESCIENCE_NUM_ADC) + if (++ao_adc_channel < NUM_ADC) ao_adc_start(); else { ADCSRA = ADCSRA_INIT; @@ -108,7 +125,7 @@ ao_adc_dump(void) __reentrant uint8_t i; ao_adc_get(&packet); printf("tick: %5u", packet.tick); - for (i = 0; i < AO_TELESCIENCE_NUM_ADC; i++) + for (i = 0; i < NUM_ADC; i++) printf (" %2d: %5u", i, packet.adc[i]); printf ("\n"); } diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index 88f03829..6b72530b 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -61,4 +61,28 @@ #define SPI_SLAVE_PIN_2_5 0 #endif +#ifdef TELEPYRO + #define LEDS_AVAILABLE 0 + #define HAS_USB 1 + #define HAS_LOG 0 + #define TEENSY 0 + #define USE_SERIAL_STDIN 1 + #define HAS_SERIAL_1 1 + #define HAS_USB 1 + #define HAS_ADC 1 + #define PACKET_HAS_SLAVE 0 + #define HAS_BEEP 0 + + #define AVR_VCC_5V 0 + #define AVR_VCC_3V3 1 + #define AVR_CLOCK 8000000UL + + #define SPI_SLAVE_CS_PORT PORTB + #define SPI_SLAVE_CS_PIN PINB + #define SPI_SLAVE_CS_PIN_NO PINB0 + + #define SPI_SLAVE_PIN_0_3 1 + #define SPI_SLAVE_PIN_2_5 0 +#endif + #endif /* _AO_PINS_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index c28c4549..04610fea 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1811,4 +1811,10 @@ ao_log_single_init(void); void ao_log_single(void); +/* + * ao_pyro_slave.c + */ + +#define AO_TELEPYRO_NUM_ADC 9 + #endif /* _AO_H_ */ diff --git a/src/drivers/ao_pyro_slave.c b/src/drivers/ao_pyro_slave.c new file mode 100644 index 00000000..e6c73a3c --- /dev/null +++ b/src/drivers/ao_pyro_slave.c @@ -0,0 +1,51 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_product.h" + +struct ao_companion_command ao_companion_command; + +static const struct ao_companion_setup ao_telepyro_setup = { + .board_id = AO_idProduct_NUMBER, + .board_id_inverse = ~AO_idProduct_NUMBER, + .update_period = 50, + .channels = AO_TELEPYRO_NUM_ADC, +}; + +void ao_spi_slave(void) +{ + if (!ao_spi_read((uint8_t *) &ao_companion_command, + sizeof (ao_companion_command))) + return; + + /* Figure out the outbound data */ + switch (ao_companion_command.command) { + case AO_COMPANION_SETUP: + ao_spi_write((uint8_t *) &ao_telepyro_setup, + sizeof (ao_telepyro_setup)); + break; + case AO_COMPANION_FETCH: + ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, + AO_TELEPYRO_NUM_ADC * sizeof (uint16_t)); + break; + case AO_COMPANION_NOTIFY: + break; + default: + return; + } +} diff --git a/src/product/ao_telepyro.c b/src/product/ao_telepyro.c new file mode 100644 index 00000000..a2b8f83c --- /dev/null +++ b/src/product/ao_telepyro.c @@ -0,0 +1,36 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +int +main(void) +{ + ao_clock_init(); + + PORTE |= (1 << 6); + DDRE |= (1 << 6); + + ao_avr_stdio_init(); + ao_timer_init(); + ao_cmd_init(); + ao_spi_slave_init(); + ao_usb_init(); + ao_adc_init(); + ao_start_scheduler(); + return 0; +} diff --git a/src/telepyro-v0.1/Makefile b/src/telepyro-v0.1/Makefile new file mode 100644 index 00000000..2f664fcb --- /dev/null +++ b/src/telepyro-v0.1/Makefile @@ -0,0 +1,101 @@ +# +# AltOS build +# +# +vpath % ..:../core:../product:../drivers:../avr +vpath ao-make-product.5c ../util + +MCU=atmega32u4 +DUDECPUTYPE=m32u4 +#PROGRAMMER=stk500v2 -P usb +PROGRAMMER=usbtiny +LOADCMD=avrdude +LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: +CC=avr-gcc +OBJCOPY=avr-objcopy + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_usb.h \ + ao_pins.h \ + altitude.h + +ALTOS_SRC = \ + ao_clock.c \ + ao_cmd.c \ + ao_mutex.c \ + ao_panic.c \ + ao_product.c \ + ao_stdio.c \ + ao_task.c \ + ao_timer.c \ + ao_led.c \ + ao_avr_stdio.c \ + ao_romconfig.c \ + ao_usb_avr.c \ + ao_adc_avr.c \ + ao_pyro_slave.c \ + ao_spi_slave.c + +PRODUCT=TelePyro-v0.1 +MCU=atmega32u4 +PRODUCT_DEF=-DTELEPYRO +IDPRODUCT=0x0011 +CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../core -I.. +CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O3 -mcall-prologues -DAVR + +NICKLE=nickle + +PROG=telepyro-v0.1 + +SRC=$(ALTOS_SRC) ao_telepyro.c +OBJ=$(SRC:.c=.o) + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: $(PROG) + +CHECK=sh ../util/check-avr-mem + +$(PROG): Makefile $(OBJ) + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) + $(call quiet,CHECK) $(PROG) || ($(RM) -f $(PROG); exit 1) + +$(PROG).hex: $(PROG) + avr-size $(PROG) + $(OBJCOPY) -R .eeprom -O ihex $(PROG) $@ + + +load: $(PROG).hex + $(LOADCMD) $(LOADARG)$(PROG).hex + +../altitude.h: make-altitude + nickle $< > $@ + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +ao_product.rel: ao_product.c ao_product.h + $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< + +distclean: clean + +clean: + rm -f $(OBJ) + rm -f ao_product.h + +install: + +uninstall: + +$(OBJ): ao.h ao_product.h ao_usb.h -- cgit v1.2.3 From 16aa67fc77b82a9d051f205037b27a5384e3e3b7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Sep 2011 14:24:30 -0700 Subject: altos: missing ao_log_single.c Neglected to add this file. Signed-off-by: Keith Packard --- src/core/ao_log_single.c | 198 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 src/core/ao_log_single.c (limited to 'src') diff --git a/src/core/ao_log_single.c b/src/core/ao_log_single.c new file mode 100644 index 00000000..9e90bd82 --- /dev/null +++ b/src/core/ao_log_single.c @@ -0,0 +1,198 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +/* + * ao_log_single.c + * + * Stores a sequence of fixed-size (32 byte) chunks + * without splitting memory up into separate flights + */ + +#include "ao.h" +#include "ao_product.h" + +static __xdata struct ao_task ao_log_single_task; + +__xdata uint8_t ao_log_running; +__xdata uint8_t ao_log_mutex; +__pdata uint32_t ao_log_start_pos; +__pdata uint32_t ao_log_end_pos; +__pdata uint32_t ao_log_current_pos; + +__xdata union ao_log_single ao_log_single_write_data; +__xdata union ao_log_single ao_log_single_read_data; + +uint8_t +ao_log_single_write(void) +{ + uint8_t wrote = 0; + + ao_mutex_get(&ao_log_mutex); { + if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_single_stop(); + if (ao_log_running) { + wrote = 1; + ao_storage_write(ao_log_current_pos, + &ao_log_single_write_data, + AO_LOG_SINGLE_SIZE); + ao_log_current_pos += AO_LOG_SINGLE_SIZE; + } + } ao_mutex_put(&ao_log_mutex); + return wrote; +} + +static uint8_t +ao_log_single_valid(void) +{ + __xdata uint8_t *d = ao_log_single_read_data.bytes; + uint8_t i; + for (i = 0; i < AO_LOG_SINGLE_SIZE; i++) + if (*d++ != 0xff) + return 1; + return 0; +} + +uint8_t +ao_log_single_read(uint32_t pos) +{ + if (!ao_storage_read(pos, &ao_log_single_read_data, AO_LOG_SINGLE_SIZE)) + return 0; + return ao_log_single_valid(); +} + +void +ao_log_single_start(void) +{ + if (!ao_log_running) { + ao_log_running = 1; + ao_wakeup(&ao_log_running); + } +} + +void +ao_log_single_stop(void) +{ + if (ao_log_running) { + ao_log_running = 0; + } +} + +void +ao_log_single_restart(void) +{ + /* Find end of data */ + ao_log_end_pos = ao_storage_config; + for (ao_log_current_pos = 0; + ao_log_current_pos < ao_storage_config; + ao_log_current_pos += ao_storage_block) + { + if (!ao_log_single_read(ao_log_current_pos)) + break; + } + if (ao_log_current_pos > 0) { + ao_log_current_pos -= ao_storage_block; + for (; ao_log_current_pos < ao_storage_config; + ao_log_current_pos += sizeof (struct ao_log_telescience)) + { + if (!ao_log_single_read(ao_log_current_pos)) + break; + } + } +} + +void +ao_log_single_set(void) +{ + printf("Logging currently %s\n", ao_log_running ? "on" : "off"); + ao_cmd_hex(); + if (ao_cmd_status == ao_cmd_success) { + if (ao_cmd_lex_i) { + printf("Logging from %ld to %ld\n", ao_log_current_pos, ao_log_end_pos); + ao_log_single_start(); + } else { + printf ("Log stopped at %ld\n", ao_log_current_pos); + ao_log_single_stop(); + } + } + ao_cmd_status = ao_cmd_success; +} + +void +ao_log_single_delete(void) +{ + uint32_t pos; + + ao_cmd_hex(); + if (ao_cmd_status != ao_cmd_success) + return; + if (ao_cmd_lex_i != 1) { + ao_cmd_status = ao_cmd_syntax_error; + printf("No such flight: %d\n", ao_cmd_lex_i); + return; + } + ao_log_single_stop(); + for (pos = 0; pos < ao_storage_config; pos += ao_storage_block) { + if (!ao_log_single_read(pos)) + break; + ao_storage_erase(pos); + } + ao_log_current_pos = ao_log_start_pos = 0; + if (pos == 0) + printf("No such flight: %d\n", ao_cmd_lex_i); + else + printf ("Erased\n"); +} + +uint8_t +ao_log_full(void) +{ + return ao_log_current_pos >= ao_log_end_pos; +} + +uint8_t +ao_log_present(void) +{ + return ao_log_single_read(0); +} + +static void +ao_log_single_query(void) +{ + printf("Logging enabled: %d\n", ao_log_running); + printf("Log start: %ld\n", ao_log_start_pos); + printf("Log cur: %ld\n", ao_log_current_pos); + printf("Log end: %ld\n", ao_log_end_pos); + ao_log_single_extra_query(); +} + +const struct ao_cmds ao_log_single_cmds[] = { + { ao_log_single_set, "L <0 off, 1 on>\0Set logging mode" }, + { ao_log_single_list, "l\0List stored flight logs" }, + { ao_log_single_delete, "d 1\0Delete all stored flights" }, + { ao_log_single_query, "q\0Query log status" }, + { 0, NULL }, +}; + +void +ao_log_single_init(void) +{ + ao_log_running = 0; + + ao_cmd_register(&ao_log_single_cmds[0]); + + ao_add_task(&ao_log_single_task, ao_log_single, "log"); +} -- cgit v1.2.3 From f68f22f527104cdffa1f5e398a51a466a13ff1fb Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 21 Sep 2011 16:42:22 -0600 Subject: add missing sense_h entry in TelePyro table --- src/avr/ao_adc_avr.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c index 9f45acaf..4c4bcbda 100644 --- a/src/avr/ao_adc_avr.c +++ b/src/avr/ao_adc_avr.c @@ -47,6 +47,7 @@ const uint8_t adc_channels[AO_TELEPYRO_NUM_ADC] = { 0x23, /* ADC11 sense_e */ 0x22, /* ADC10 sense_f */ 0x21, /* ADC9 sense_g */ + 0x20, /* ADC8 sense_h */ }; #endif -- cgit v1.2.3 From 74d5dea5d5ef91db823018b631613d15c6da085d Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Wed, 21 Sep 2011 16:42:52 -0600 Subject: fix bashism that prevents building with /bin/sh->/bin/dash --- src/Makefile | 2 +- src/util/make-kalman | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 91d3f035..5da7c855 100644 --- a/src/Makefile +++ b/src/Makefile @@ -48,7 +48,7 @@ altitude.h: make-altitude nickle $< > $@ ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c - sh $< kalman > $@ + bash $< kalman > $@ clean-local: rm -f altitude.h ao_kalman.h diff --git a/src/util/make-kalman b/src/util/make-kalman index f78f30a9..b4e5d919 100644 --- a/src/util/make-kalman +++ b/src/util/make-kalman @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash cd $1 >&/dev/null -- cgit v1.2.3 From 7bc007ed45af8fe9ef5daeb7844f183cd9a49035 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Sep 2011 18:13:55 -0700 Subject: altos: Fix make-kalman to run under dash Dash can't deal with >&, so use the old-school > file 2>&1 Signed-off-by: Keith Packard --- src/util/make-kalman | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/util/make-kalman b/src/util/make-kalman index b4e5d919..397d6020 100644 --- a/src/util/make-kalman +++ b/src/util/make-kalman @@ -1,6 +1,6 @@ #!/bin/bash -cd $1 >&/dev/null +cd $1 2> /dev/null 1>&2 SIGMA_BOTH="-M 2 -H 6 -A 2" SIGMA_BARO="-M 2 -H 6 -A 2" -- cgit v1.2.3 From 9b498a6b1327f543c73145e02ff16e76d09f2fe4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Sep 2011 22:54:56 -0700 Subject: Dump ADC registers --- src/avr/ao_adc_avr.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c index 4c4bcbda..06284d68 100644 --- a/src/avr/ao_adc_avr.c +++ b/src/avr/ao_adc_avr.c @@ -125,6 +125,14 @@ ao_adc_dump(void) __reentrant static __xdata struct ao_adc packet; uint8_t i; ao_adc_get(&packet); + printf("ADMUX: %02x\n", ADMUX); + printf("ADCSRA: %02x\n", ADCSRA); + printf("ADCSRB: %02x\n", ADCSRB); + printf("DIDR0: %02x\n", DIDR0); + printf("DIDR2: %02x\n", DIDR2); + printf("PORTF: %02x\n", PORTF); + printf("DDRF: %02x\n", DDRF); + printf("PINF: %02x\n", PINF); printf("tick: %5u", packet.tick); for (i = 0; i < NUM_ADC; i++) printf (" %2d: %5u", i, packet.adc[i]); -- cgit v1.2.3 From f1328d22aab4378c4fb6f0c24dbee95948ca836c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Sep 2011 23:21:04 -0700 Subject: Dump test conversion of ADC0 --- src/avr/ao_adc_avr.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c index 06284d68..a47703e5 100644 --- a/src/avr/ao_adc_avr.c +++ b/src/avr/ao_adc_avr.c @@ -66,7 +66,7 @@ static uint8_t ao_adc_channel; #define ADCSRB_INIT ((0 << ADHSM) | /* No high-speed mode */ \ (0 << ACME) | /* Some comparitor thing */ \ - (2 << ADTS0)) /* Free running mode (don't care) */ + (0 << ADTS0)) /* Free running mode (don't care) */ static void ao_adc_start(void) @@ -136,6 +136,15 @@ ao_adc_dump(void) __reentrant printf("tick: %5u", packet.tick); for (i = 0; i < NUM_ADC; i++) printf (" %2d: %5u", i, packet.adc[i]); + + + ADMUX = 0x60; + ADCSRB = 0x00; + ADCSRA = 0xc6; + while (ADCSRA & 0x40) + ; + printf ("ADCL: %02x\n", ADCL); + printf ("ADCH: %02x\n", ADCH); printf ("\n"); } -- cgit v1.2.3 From 4ed53ef838afd4e922deb1c721a311974527525a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Sep 2011 10:24:33 -0700 Subject: altos: Debug code for telepyro doesn't fit in telescience Just too many strings. Signed-off-by: Keith Packard --- src/avr/ao_adc_avr.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c index a47703e5..8c0cade0 100644 --- a/src/avr/ao_adc_avr.c +++ b/src/avr/ao_adc_avr.c @@ -125,6 +125,7 @@ ao_adc_dump(void) __reentrant static __xdata struct ao_adc packet; uint8_t i; ao_adc_get(&packet); +#ifdef TELEPYRO printf("ADMUX: %02x\n", ADMUX); printf("ADCSRA: %02x\n", ADCSRA); printf("ADCSRB: %02x\n", ADCSRB); @@ -133,11 +134,13 @@ ao_adc_dump(void) __reentrant printf("PORTF: %02x\n", PORTF); printf("DDRF: %02x\n", DDRF); printf("PINF: %02x\n", PINF); +#endif printf("tick: %5u", packet.tick); for (i = 0; i < NUM_ADC; i++) printf (" %2d: %5u", i, packet.adc[i]); +#ifdef TELEPYRO ADMUX = 0x60; ADCSRB = 0x00; ADCSRA = 0xc6; @@ -146,6 +149,7 @@ ao_adc_dump(void) __reentrant printf ("ADCL: %02x\n", ADCL); printf ("ADCH: %02x\n", ADCH); printf ("\n"); +#endif } __code struct ao_cmds ao_adc_cmds[] = { -- cgit v1.2.3 From fba1d605a627d03f9587ec060c45fb5d3e96aaeb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Sep 2011 11:50:28 -0700 Subject: altos: Delay reboot by a second to avoid re-entering idle mode TM and Tm go into idle mode if they receive a packet after boot time. When tebooting the device over the packet link, the packet master would be (rapidly) polling the device for additional data and so the device would invariably receive a packet during bootup and go into idle mode again. Delay the reboot by a second to give the controller time to disable the master end of the packet link. Signed-off-by: Keith Packard --- src/ao_cmd.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/ao_cmd.c b/src/ao_cmd.c index 1442ebea..8037195a 100644 --- a/src/ao_cmd.c +++ b/src/ao_cmd.c @@ -208,6 +208,13 @@ ao_reboot(void) ao_cmd_white(); if (!ao_match_word("eboot")) return; + + /* Delay waiting for the packet master to be turned off + * so that we don't end up back in idle mode because we + * received a packet after boot. + */ + flush(); + ao_delay(AO_SEC_TO_TICKS(1)); WDCTL = WDCTL_EN | WDCTL_MODE_WATCHDOG | WDCTL_INT_64; ao_delay(AO_SEC_TO_TICKS(2)); ao_panic(AO_PANIC_REBOOT); -- cgit v1.2.3 From 0d10e25766b96f5660e213115cf27b71ff164405 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Sep 2011 21:06:54 -0700 Subject: altos: TM: Don't turn on packet slave mode until idle/invalid state Leave the packet link disabled until we've checked the accelerometer. That way, we cannot accidentally get to idle mode when the rocket is on the rail. Signed-off-by: Keith Packard --- src/ao_flight.c | 11 ++++++++++- src/ao_packet_slave.c | 6 ++++-- src/ao_telemetrum.c | 2 +- 3 files changed, 15 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ao_flight.c b/src/ao_flight.c index 85c1825b..0a9cc046 100644 --- a/src/ao_flight.c +++ b/src/ao_flight.c @@ -91,6 +91,8 @@ ao_flight(void) */ ao_flight_state = ao_flight_invalid; + /* Turn on packet system in invalid mode on TeleMetrum */ + ao_packet_slave_start(); } else #endif if (!ao_flight_force_idle @@ -108,8 +110,10 @@ ao_flight(void) ao_usb_disable(); #endif - /* Disable packet mode in pad state */ +#if !HAS_ACCEL + /* Disable packet mode in pad state on TeleMini */ ao_packet_slave_stop(); +#endif /* Turn on telemetry system */ ao_rdf_set(1); @@ -121,6 +125,11 @@ ao_flight(void) /* Set idle mode */ ao_flight_state = ao_flight_idle; +#if HAS_ACCEL + /* Turn on packet system in idle mode on TeleMetrum */ + ao_packet_slave_start(); +#endif + /* signal successful initialization by turning off the LED */ ao_led_off(AO_LED_RED); } diff --git a/src/ao_packet_slave.c b/src/ao_packet_slave.c index 9f14052a..d7cafa68 100644 --- a/src/ao_packet_slave.c +++ b/src/ao_packet_slave.c @@ -37,8 +37,10 @@ ao_packet_slave(void) void ao_packet_slave_start(void) { - ao_packet_enable = 1; - ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); + if (!ao_packet_enable) { + ao_packet_enable = 1; + ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); + } } void diff --git a/src/ao_telemetrum.c b/src/ao_telemetrum.c index f560740a..ea77f5af 100644 --- a/src/ao_telemetrum.c +++ b/src/ao_telemetrum.c @@ -57,7 +57,7 @@ main(void) ao_gps_report_init(); ao_telemetry_init(); ao_radio_init(); - ao_packet_slave_init(TRUE); + ao_packet_slave_init(FALSE); ao_igniter_init(); #if HAS_DBG ao_dbg_init(); -- cgit v1.2.3 From 258b75498916183ed250d3abb3282fe3d843e7a1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 7 Oct 2011 09:53:09 -0600 Subject: altos: Write xdata versions of memory functions These are significantly smaller than the general pointer versions from libc on the cc1111. Signed-off-by: Keith Packard Conflicts: src/Makefile.proto src/cc1111/ao_adc.c src/cc1111/ao_packet_master.c src/core/ao.h Fix up the new makefiles --- src/cc1111/ao_adc.c | 2 +- src/cc1111/ao_arch.h | 17 +++++++++++++++++ src/cc1111/ao_intflash.c | 2 +- src/cc1111/ao_packet.c | 4 ++-- src/cc1111/ao_packet_master.c | 2 +- src/cc1111/ao_packet_slave.c | 2 +- src/core/ao.h | 6 ++++++ src/core/ao_cmd.c | 4 ++-- src/core/ao_config.c | 11 ++++++----- src/core/ao_ee_fake.c | 2 +- src/core/ao_gps_report.c | 4 ++-- src/core/ao_host.h | 4 ++++ src/core/ao_monitor.c | 4 ++-- src/core/ao_telemetry.c | 10 +++++----- src/drivers/ao_25lc1024.c | 6 +++--- src/drivers/ao_at45db161d.c | 6 +++--- src/drivers/ao_gps_skytraq.c | 4 ++-- src/product/Makefile.telebt | 1 + src/product/Makefile.teledongle | 1 + src/product/Makefile.telelaunch | 1 + src/product/Makefile.telemetrum | 1 + src/product/Makefile.telemini | 1 + src/product/Makefile.telenano | 1 + src/test/ao_flight_test.c | 8 ++++++-- src/tidongle/Makefile | 1 + 25 files changed, 72 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index 6aa6e018..1688eceb 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -46,7 +46,7 @@ ao_adc_get(__xdata struct ao_adc *packet) #else uint8_t i = ao_adc_ring_prev(ao_adc_head); #endif - memcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); + ao_xmemcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); } void diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 8a41791f..02e36189 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -204,4 +204,21 @@ struct ao_adc { #define AO_ADC_RING 32 +/* ao_string.c */ + +void +_ao_xmemcpy(__xdata uint8_t *dst, __xdata uint8_t *src, uint8_t count); + +#define ao_xmemcpy(d,s,c) _ao_xmemcpy((__xdata uint8_t *) (d), (__xdata uint8_t *) (s), (c)) + +void +_ao_xmemset(__xdata uint8_t *dst, uint8_t value, uint8_t count); + +#define ao_xmemset(d,v,c) _ao_xmemset((__xdata uint8_t *) (d), (v), (c)) + +int8_t +_ao_xmemcmp(__xdata uint8_t *a, __xdata uint8_t *b, uint8_t count); + +#define ao_xmemcmp(d,s,c) _ao_xmemcmp((__xdata uint8_t *) (d), (__xdata uint8_t *) (s), (c)) + #endif /* _AO_ARCH_H_ */ diff --git a/src/cc1111/ao_intflash.c b/src/cc1111/ao_intflash.c index d76d954e..632e2a85 100644 --- a/src/cc1111/ao_intflash.c +++ b/src/cc1111/ao_intflash.c @@ -180,7 +180,7 @@ ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant { if (pos >= ao_storage_total || pos + len > ao_storage_total) return 0; - memcpy(d, ao_intflash+pos, len); + ao_xmemcpy(d, ao_intflash+pos, len); return 1; } diff --git a/src/cc1111/ao_packet.c b/src/cc1111/ao_packet.c index f627e02b..37ba92e0 100644 --- a/src/cc1111/ao_packet.c +++ b/src/cc1111/ao_packet.c @@ -35,7 +35,7 @@ ao_packet_send(void) ao_led_on(AO_LED_RED); /* If any tx data is pending then copy it into the tx packet */ if (ao_packet_tx_used && ao_tx_packet.len == 0) { - memcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); + ao_xmemcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); ao_tx_packet.len = ao_packet_tx_used; ao_tx_packet.seq++; ao_packet_tx_used = 0; @@ -80,7 +80,7 @@ ao_packet_recv(void) /* Copy data to the receive data buffer and set up the * offsets */ - memcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); + ao_xmemcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); ao_packet_rx_used = 0; ao_packet_rx_len = ao_rx_packet.packet.len; diff --git a/src/cc1111/ao_packet_master.c b/src/cc1111/ao_packet_master.c index 0d0be30e..ab19f979 100644 --- a/src/cc1111/ao_packet_master.c +++ b/src/cc1111/ao_packet_master.c @@ -81,7 +81,7 @@ ao_packet_master(void) ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; while (ao_packet_enable) { uint8_t r; - memcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN); + ao_xmemcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN); ao_packet_send(); if (ao_tx_packet.len) ao_packet_master_busy(); diff --git a/src/cc1111/ao_packet_slave.c b/src/cc1111/ao_packet_slave.c index d7cafa68..fd5d443e 100644 --- a/src/cc1111/ao_packet_slave.c +++ b/src/cc1111/ao_packet_slave.c @@ -24,7 +24,7 @@ ao_packet_slave(void) ao_tx_packet.len = AO_PACKET_SYN; while (ao_packet_enable) { if (ao_packet_recv()) { - memcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN); + ao_xmemcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN); #if HAS_FLIGHT ao_flight_force_idle = TRUE; #endif diff --git a/src/core/ao.h b/src/core/ao.h index 04610fea..c0474729 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1817,4 +1817,10 @@ ao_log_single(void); #define AO_TELEPYRO_NUM_ADC 9 +#ifndef ao_xmemcpy +#define ao_xmemcpy(d,s,c) memcpy(d,s,c) +#define ao_xmemset(d,v,c) memset(d,v,c) +#define ao_xmemcmp(d,s,c) memcmp(d,s,c) +#endif + #endif /* _AO_H_ */ diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 2b64b8ca..0c902f6b 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -265,8 +265,8 @@ help(void) cs = ao_cmds[cmds]; for (cmd = 0; cs[cmd].func; cmd++) printf("%-45s %s\n", - cs[cmd].help, - cs[cmd].help+1+strlen(cs[cmd].help)); + cs[cmd].help, + cs[cmd].help+1+strlen(cs[cmd].help)); } } diff --git a/src/core/ao_config.c b/src/core/ao_config.c index a653bed2..08cc79b1 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -78,8 +78,8 @@ _ao_config_get(void) /* Version 0 stuff */ ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; - memset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); - memcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, + ao_xmemset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); + ao_xmemcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); ao_config_dirty = 1; } @@ -148,7 +148,7 @@ ao_config_callsign_set(void) __reentrant uint8_t c; static __xdata char callsign[AO_MAX_CALLSIGN + 1]; - memset(callsign, '\0', sizeof callsign); + ao_xmemset(callsign, '\0', sizeof callsign); ao_cmd_white(); c = 0; while (ao_cmd_lex_c != '\n') { @@ -161,7 +161,7 @@ ao_config_callsign_set(void) __reentrant if (ao_cmd_status != ao_cmd_success) return; _ao_config_edit_start(); - memcpy(&ao_config.callsign, &callsign, + ao_xmemcpy(&ao_config.callsign, &callsign, AO_MAX_CALLSIGN + 1); _ao_config_edit_finish(); } @@ -535,7 +535,8 @@ ao_config_help(void) __reentrant for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) printf("%-20s %s\n", ao_config_vars[cmd].str, - ao_config_vars[cmd].str+1+strlen(ao_config_vars[cmd].str)); + ao_config_vars[cmd].str+1+ + strlen(ao_config_vars[cmd].str)); } static void diff --git a/src/core/ao_ee_fake.c b/src/core/ao_ee_fake.c index b0c1d61e..7fcfcab0 100644 --- a/src/core/ao_ee_fake.c +++ b/src/core/ao_ee_fake.c @@ -32,6 +32,6 @@ ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant uint8_t ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant { - memset(buf, '\0', len); + ao_xmemset(buf, '\0', len); return 1; } diff --git a/src/core/ao_gps_report.c b/src/core/ao_gps_report.c index e57f8744..c52ef621 100644 --- a/src/core/ao_gps_report.c +++ b/src/core/ao_gps_report.c @@ -27,7 +27,7 @@ ao_gps_report(void) for (;;) { ao_sleep(&ao_gps_data); ao_mutex_get(&ao_gps_mutex); - memcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); + ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); ao_mutex_put(&ao_gps_mutex); if (!(gps_data.flags & AO_GPS_VALID)) @@ -72,7 +72,7 @@ ao_gps_tracking_report(void) ao_sleep(&ao_gps_tracking_data); ao_mutex_get(&ao_gps_mutex); gps_log.tick = ao_gps_tick; - memcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); + ao_xmemcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); ao_mutex_put(&ao_gps_mutex); if (!(n = gps_tracking_data.channels)) diff --git a/src/core/ao_host.h b/src/core/ao_host.h index 65c25fe5..f2b2f0c9 100644 --- a/src/core/ao_host.h +++ b/src/core/ao_host.h @@ -125,3 +125,7 @@ struct ao_config { #define ao_config_get() struct ao_config ao_config = { 250, 16000 }; + +#define ao_xmemcpy(d,s,c) memcpy(d,s,c) +#define ao_xmemset(d,v,c) memset(d,v,c) +#define ao_xmemcmp(d,s,c) memcmp(d,s,c) diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 56d7604d..1a8bb52a 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -94,7 +94,7 @@ ao_monitor_put(void) /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ rssi = (int16_t) (recv_orig.rssi >> 1) - 74; - memcpy(callsign, recv_orig.telemetry_orig.callsign, AO_MAX_CALLSIGN); + ao_xmemcpy(callsign, recv_orig.telemetry_orig.callsign, AO_MAX_CALLSIGN); if (state > ao_flight_invalid) state = ao_flight_invalid; if (recv_orig.status & PKT_APPEND_STATUS_1_CRC_OK) { @@ -171,7 +171,7 @@ ao_monitor_put(void) /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ rssi = (int16_t) (recv_tiny.rssi >> 1) - 74; - memcpy(callsign, recv_tiny.telemetry_tiny.callsign, AO_MAX_CALLSIGN); + ao_xmemcpy(callsign, recv_tiny.telemetry_tiny.callsign, AO_MAX_CALLSIGN); if (state > ao_flight_invalid) state = ao_flight_invalid; if (recv_tiny.status & PKT_APPEND_STATUS_1_CRC_OK) { diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 26e4e2a0..95e53917 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -131,10 +131,10 @@ ao_send_configuration(void) telemetry.configuration.apogee_delay = ao_config.apogee_delay; telemetry.configuration.main_deploy = ao_config.main_deploy; telemetry.configuration.flight_log_max = ao_config.flight_log_max >> 10; - memcpy (telemetry.configuration.callsign, + ao_xmemcpy (telemetry.configuration.callsign, ao_config.callsign, AO_MAX_CALLSIGN); - memcpy (telemetry.configuration.version, + ao_xmemcpy (telemetry.configuration.version, ao_version, AO_MAX_VERSION); ao_radio_send(&telemetry, sizeof (telemetry)); @@ -150,7 +150,7 @@ ao_send_location(void) { telemetry.generic.type = AO_TELEMETRY_LOCATION; ao_mutex_get(&ao_gps_mutex); - memcpy(&telemetry.location.flags, + ao_xmemcpy(&telemetry.location.flags, &ao_gps_data.flags, 26); ao_mutex_put(&ao_gps_mutex); @@ -167,7 +167,7 @@ ao_send_satellite(void) telemetry.generic.type = AO_TELEMETRY_SATELLITE; ao_mutex_get(&ao_gps_mutex); telemetry.satellite.channels = ao_gps_tracking_data.channels; - memcpy(&telemetry.satellite.sats, + ao_xmemcpy(&telemetry.satellite.sats, &ao_gps_tracking_data.sats, AO_MAX_GPS_TRACKING * sizeof (struct ao_telemetry_satellite_info)); ao_mutex_put(&ao_gps_mutex); @@ -187,7 +187,7 @@ ao_send_companion(void) telemetry.companion.update_period = ao_companion_setup.update_period; telemetry.companion.channels = ao_companion_setup.channels; ao_mutex_get(&ao_companion_mutex); - memcpy(&telemetry.companion.companion_data, + ao_xmemcpy(&telemetry.companion.companion_data, ao_companion_data, ao_companion_setup.channels * 2); ao_mutex_put(&ao_companion_mutex); diff --git a/src/drivers/ao_25lc1024.c b/src/drivers/ao_25lc1024.c index 738f8ce6..2d047a44 100644 --- a/src/drivers/ao_25lc1024.c +++ b/src/drivers/ao_25lc1024.c @@ -167,7 +167,7 @@ ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentra ao_ee_flush_internal(); ao_ee_block = block; } - memcpy(ao_ee_data + (uint16_t) (pos & 0xff), buf, len); + ao_xmemcpy(ao_ee_data + (uint16_t) (pos & 0xff), buf, len); ao_ee_block_dirty = 1; } ao_mutex_put(&ao_ee_mutex); return 1; @@ -181,7 +181,7 @@ ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentran /* Transfer the data */ ao_mutex_get(&ao_ee_mutex); { ao_ee_fill(block); - memcpy(buf, ao_ee_data + (uint16_t) (pos & 0xff), len); + ao_xmemcpy(buf, ao_ee_data + (uint16_t) (pos & 0xff), len); } ao_mutex_put(&ao_ee_mutex); return 1; } @@ -200,7 +200,7 @@ ao_storage_erase(uint32_t pos) __reentrant ao_mutex_get(&ao_ee_mutex); { ao_ee_flush_internal(); ao_ee_block = (uint16_t) (pos >> EE_BLOCK_SHIFT); - memset(ao_ee_data, 0xff, EE_BLOCK_SIZE); + ao_xmemset(ao_ee_data, 0xff, EE_BLOCK_SIZE); ao_ee_block_dirty = 1; } ao_mutex_put(&ao_ee_mutex); return 1; diff --git a/src/drivers/ao_at45db161d.c b/src/drivers/ao_at45db161d.c index aee9877a..6cd689e5 100644 --- a/src/drivers/ao_at45db161d.c +++ b/src/drivers/ao_at45db161d.c @@ -245,7 +245,7 @@ ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentra ao_flash_flush_internal(); ao_flash_block = block; } - memcpy(ao_flash_data + (uint16_t) (pos & ao_flash_block_mask), + ao_xmemcpy(ao_flash_data + (uint16_t) (pos & ao_flash_block_mask), buf, len); ao_flash_block_dirty = 1; @@ -261,7 +261,7 @@ ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentran /* Transfer the data */ ao_mutex_get(&ao_flash_mutex); { ao_flash_fill(block); - memcpy(buf, + ao_xmemcpy(buf, ao_flash_data + (uint16_t) (pos & ao_flash_block_mask), len); } ao_mutex_put(&ao_flash_mutex); @@ -282,7 +282,7 @@ ao_storage_erase(uint32_t pos) __reentrant ao_mutex_get(&ao_flash_mutex); { ao_flash_flush_internal(); ao_flash_block = (uint16_t) (pos >> ao_flash_block_shift); - memset(ao_flash_data, 0xff, ao_flash_block_size); + ao_xmemset(ao_flash_data, 0xff, ao_flash_block_size); ao_flash_block_dirty = 1; } ao_mutex_put(&ao_flash_mutex); return 1; diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index 7ac26946..6e65d651 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -265,7 +265,7 @@ ao_nmea_gga() if (!ao_gps_error) { ao_mutex_get(&ao_gps_mutex); ao_gps_tick = ao_gps_next_tick; - memcpy(&ao_gps_data, &ao_gps_next, sizeof (ao_gps_data)); + ao_xmemcpy(&ao_gps_data, &ao_gps_next, sizeof (ao_gps_data)); ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_data); } @@ -327,7 +327,7 @@ ao_nmea_gsv(void) ao_gps_tracking_next.channels = 0; else if (done) { ao_mutex_get(&ao_gps_mutex); - memcpy(&ao_gps_tracking_data, &ao_gps_tracking_next, + ao_xmemcpy(&ao_gps_tracking_data, &ao_gps_tracking_next, sizeof(ao_gps_tracking_data)); ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_tracking_data); diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index 46c87db0..8f7c7429 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -41,6 +41,7 @@ CC1111_SRC = \ ao_radio_cmac.c \ ao_romconfig.c \ ao_serial.c \ + ao_string.c \ ao_timer.c \ ao_usb.c \ _bp.c diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle index 56182b84..c1b422c0 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -43,6 +43,7 @@ CC1111_SRC = \ ao_radio.c \ ao_radio_cmac.c \ ao_romconfig.c \ + ao_string.c \ ao_timer.c \ ao_usb.c \ _bp.c diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch index 5da42e46..b40f61a2 100644 --- a/src/product/Makefile.telelaunch +++ b/src/product/Makefile.telelaunch @@ -45,6 +45,7 @@ CC1111_SRC = \ ao_romconfig.c \ ao_serial.c \ ao_spi.c \ + ao_string.c \ ao_timer.c \ ao_usb.c \ _bp.c diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index 2759ac52..4f4195a9 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -54,6 +54,7 @@ CC1111_SRC = \ ao_radio.c \ ao_romconfig.c \ ao_serial.c \ + ao_string.c \ ao_spi.c \ ao_timer.c \ ao_usb.c \ diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini index 7f251897..9f90b01f 100644 --- a/src/product/Makefile.telemini +++ b/src/product/Makefile.telemini @@ -45,6 +45,7 @@ CC1111_SRC = \ ao_packet_slave.c \ ao_radio.c \ ao_romconfig.c \ + ao_string.c \ ao_timer.c \ _bp.c diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index c47e95ff..eff3ea97 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -44,6 +44,7 @@ CC1111_SRC = \ ao_packet_slave.c \ ao_radio.c \ ao_romconfig.c \ + ao_string.c \ ao_timer.c \ _bp.c diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 56733c89..921d44e7 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -173,6 +173,10 @@ struct ao_cmds { const char *help; }; +#define ao_xmemcpy(d,s,c) memcpy(d,s,c) +#define ao_xmemset(d,v,c) memset(d,v,c) +#define ao_xmemcmp(d,s,c) memcmp(d,s,c) + #include "ao_convert.c" struct ao_config { @@ -542,7 +546,7 @@ ao_sleep(void *wchan) ao_flight_started = 1; } } else if (nword == 2 && strcmp(words[0], "TELEM") == 0) { - char *hex = words[1]; + __xdata char *hex = words[1]; char elt[3]; int i, len; uint8_t sum; @@ -574,7 +578,7 @@ ao_sleep(void *wchan) continue; } if (len == 36) { - memcpy(&telem, bytes + 1, 32); + ao_xmemcpy(&telem, bytes + 1, 32); tick = telem.generic.tick; switch (telem.generic.type) { case AO_TELEMETRY_SENSOR_TELEMETRUM: diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile index 057e420b..58b9d735 100644 --- a/src/tidongle/Makefile +++ b/src/tidongle/Makefile @@ -38,6 +38,7 @@ CC1111_SRC = \ ao_radio.c \ ao_radio_cmac.c \ ao_romconfig.c \ + ao_string.c \ ao_timer.c \ ao_usb.c \ _bp.c -- cgit v1.2.3 From 6a7363b3ba99310bd44c9b66f6f5159e46762be4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 8 Oct 2011 11:51:05 -0600 Subject: altos: Ignore ejection bumps when doing boost re-detect An ejection charge looks an awful lot like an extra (really small) motor burn. Ignore them by averaging the acceleration during fast/coast using a /64 exponential decay filter. Signed-off-by: Keith Packard --- src/core/ao_flight.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index 433efeae..5e194638 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -40,9 +40,11 @@ __pdata uint16_t ao_boost_tick; /* time of launch detect */ * track min/max data over a long interval to detect * resting */ -__pdata uint16_t ao_interval_end; -__pdata int16_t ao_interval_min_height; -__pdata int16_t ao_interval_max_height; +static __data uint16_t ao_interval_end; +static __data int16_t ao_interval_min_height; +static __data int16_t ao_interval_max_height; +static __data int16_t ao_coast_avg_accel; + __pdata uint8_t ao_flight_force_idle; /* We also have a clock, which can be used to sanity check things in @@ -197,6 +199,7 @@ ao_flight(void) { #if HAS_ACCEL ao_flight_state = ao_flight_fast; + ao_coast_avg_accel = ao_accel; #else ao_flight_state = ao_flight_coast; #endif @@ -250,7 +253,8 @@ ao_flight(void) #if HAS_ACCEL else { check_re_boost: - if (ao_accel > AO_MSS_TO_ACCEL(20)) { + ao_coast_avg_accel = ao_coast_avg_accel - (ao_coast_avg_accel >> 6) + (ao_accel >> 6); + if (ao_coast_avg_accel > AO_MSS_TO_ACCEL(20)) { ao_boost_tick = ao_sample_tick; ao_flight_state = ao_flight_boost; ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); -- cgit v1.2.3 From ca036c5616c3e745c0b878ed90618d4ff710c0e5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 8 Oct 2011 22:19:52 -0600 Subject: altos: Improve TM v1.0 apogee estimate v1.0 boards have noisy accelerometer data caused by interactions between RF transmission and the accelerometer measurements; this noise generates a negative bias in the accelerometer readings. The net effect is that the estimated speed is lower than the actual speed, causing early an apogee estimate. By increasing the sigma value for accelerometer data, the kalman filter 'trusts' the acceleration data less, putting more weight on the barometer data. This causes the estimated time of apogee to be closer to the correct value. This reduces the response to changes in acceleration. This new value is applied solely to TeleMetrum v1.0 boards. v1.1 boards correct for this error, and hence can use the correct sigma value for the accelerometer. Signed-off-by: Keith Packard --- src/cc1111/ao_pins.h | 1 + src/test/Makefile | 12 ++++++++++-- src/util/make-kalman | 22 ++++++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 723f1500..d2fbb209 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -36,6 +36,7 @@ #define IGNITE_ON_P0 0 #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 1 + #define NOISY_ACCEL 1 #define HAS_COMPANION 1 #define COMPANION_CS_ON_P1 1 diff --git a/src/test/Makefile b/src/test/Makefile index 333850e4..4e403da6 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,6 +1,8 @@ -vpath % ..:../core:../drivers +vpath % ..:../core:../drivers:../util -PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_gps_test ao_gps_test_skytraq ao_convert_test +PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_gps_test ao_gps_test_skytraq ao_convert_test + +KALMAN=make-kalman CFLAGS=-I.. -I. -I../core -I../drivers -O0 -g @@ -14,6 +16,9 @@ install: ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h cc $(CFLAGS) -o $@ $< +ao_flight_test_noisy_accel: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h + cc -DNOISY_ACCEL=1 $(CFLAGS) -o $@ $< + ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h cc $(CFLAGS) -o $@ -DHAS_ACCEL=0 ao_flight_test.c @@ -28,3 +33,6 @@ ao_gps_test_skytraq: ao_gps_test_skytraq.c ao_gps_skytraq.c ao_gps_print.c ao_ho ao_convert_test: ao_convert_test.c ao_convert.c altitude.h cc $(CFLAGS) -o $@ $< + +ao_kalman.h: $(KALMAN) + (cd .. && make ao_kalman.h) \ No newline at end of file diff --git a/src/util/make-kalman b/src/util/make-kalman index 397d6020..fd33bab0 100644 --- a/src/util/make-kalman +++ b/src/util/make-kalman @@ -5,11 +5,32 @@ cd $1 2> /dev/null 1>&2 SIGMA_BOTH="-M 2 -H 6 -A 2" SIGMA_BARO="-M 2 -H 6 -A 2" SIGMA_ACCEL="-M 2 -H 4 -A 4" +SIGMA_BOTH_NOISY_ACCEL="-M 2 -H 6 -A 3" + +echo '#if NOISY_ACCEL' +echo +echo '/* TeleMetrum v1.0 boards have noisy accelerometer values' +echo ' * increase the sigma value for accel data to compensate.' +echo ' * This improves the accuracy of apogee detection.' +echo ' */' +echo + +nickle kalman.5c -p AO_BOTH -c both -t 0.01 $SIGMA_BOTH_NOISY_ACCEL +nickle kalman.5c -p AO_BOTH -c both -t 0.1 $SIGMA_BOTH_NOISY_ACCEL +nickle kalman.5c -p AO_BOTH -c both -t 1 $SIGMA_BOTH_NOISY_ACCEL + +echo '#endif' +echo +echo '#ifndef AO_BOTH_K00_100' +echo nickle kalman.5c -p AO_BOTH -c both -t 0.01 $SIGMA_BOTH nickle kalman.5c -p AO_BOTH -c both -t 0.1 $SIGMA_BOTH nickle kalman.5c -p AO_BOTH -c both -t 1 $SIGMA_BOTH +echo '#endif' +echo + nickle kalman.5c -p AO_ACCEL -c accel -t 0.01 $SIGMA_ACCEL nickle kalman.5c -p AO_ACCEL -c accel -t 0.1 $SIGMA_ACCEL nickle kalman.5c -p AO_ACCEL -c accel -t 1 $SIGMA_ACCEL @@ -17,3 +38,4 @@ nickle kalman.5c -p AO_ACCEL -c accel -t 1 $SIGMA_ACCEL nickle kalman.5c -p AO_BARO -c baro -t 0.01 $SIGMA_BARO nickle kalman.5c -p AO_BARO -c baro -t 0.1 $SIGMA_BARO nickle kalman.5c -p AO_BARO -c baro -t 1 $SIGMA_BARO + -- cgit v1.2.3 From 636b7b368e67346b0796cd84fbfd71e10966d61f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Oct 2011 10:21:56 -0600 Subject: altos: Respond to telemetry rate changes immediately Instead of waiting for the previous telemetry interval to expire, immediately switch to the new telemetry rate. This will provide more telemetry data early in the boost. Signed-off-by: Keith Packard --- src/core/ao_telemetry.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 95e53917..d909bea5 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -240,8 +240,11 @@ ao_telemetry(void) #endif time += ao_telemetry_interval; delay = time - ao_time(); - if (delay > 0) - ao_delay(delay); + if (delay > 0) { + ao_alarm(delay); + ao_sleep(&telemetry); + ao_clear_alarm(); + } else time = ao_time(); } -- cgit v1.2.3 From 06b044629951b06c7ec9b0105b89f51b2880ebd0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 16:03:04 -0600 Subject: altos/avr: SPI mutex is now held by the caller, not the SPI driver SPI transactions generally require a read followed by a write, with the chip select held the whole time. As a result, the SPI bus must be held across multiple transactions. To make this reliable, the caller must hold the SPI mutex, instead of the underlying SPI driver. Signed-off-by: Keith Packard --- src/avr/ao_spi_usart.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src') diff --git a/src/avr/ao_spi_usart.c b/src/avr/ao_spi_usart.c index 6ed708ff..1996fcd9 100644 --- a/src/avr/ao_spi_usart.c +++ b/src/avr/ao_spi_usart.c @@ -33,14 +33,12 @@ ao_spi_send(void __xdata *block, uint16_t len) __reentrant { uint8_t *d = block; - ao_mutex_get(&ao_spi_mutex); while (len--) { while (!(UCSR1A & (1 << UDRE1))); UDR1 = *d++; while (!(UCSR1A & (1 << RXC1))); (void) UDR1; } - ao_mutex_put(&ao_spi_mutex); } /* Receive bytes over SPI. @@ -54,14 +52,12 @@ ao_spi_recv(void __xdata *block, uint16_t len) __reentrant { uint8_t *d = block; - ao_mutex_get(&ao_spi_mutex); while (len--) { while (!(UCSR1A & (1 << UDRE1))); UDR1 = 0; while (!(UCSR1A & (1 << RXC1))); *d++ = UDR1; } - ao_mutex_put(&ao_spi_mutex); } /* -- cgit v1.2.3 From f3453068b0feb640b9d11dbeb021c535ce8b4a31 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 17:39:06 -0600 Subject: altos/avr: Print newline after dumping ADC values Cleans up the formating a bit. Signed-off-by: Keith Packard --- src/avr/ao_adc_avr.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c index 8c0cade0..4f6f0e60 100644 --- a/src/avr/ao_adc_avr.c +++ b/src/avr/ao_adc_avr.c @@ -138,6 +138,7 @@ ao_adc_dump(void) __reentrant printf("tick: %5u", packet.tick); for (i = 0; i < NUM_ADC; i++) printf (" %2d: %5u", i, packet.adc[i]); + printf("\n"); #ifdef TELEPYRO -- cgit v1.2.3 From 0a186e92c5773c5d908e9cee889d645a8172dcdc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 17:39:35 -0600 Subject: altos/avr: Make ao_arch_critical argument be a statement Wrap the argument to ao_arch_critical in do { } while (0); to make sure it gets correctly checked as a statement. Signed-off-by: Keith Packard --- src/avr/ao_arch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index c695a725..2be4abee 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -143,7 +143,7 @@ extern uint8_t ao_cpu_sleep_disable; asm("ret"); \ } while(0) -#define ao_arch_critical(b) do { cli(); b; sei(); } while (0) +#define ao_arch_critical(b) do { cli(); do { b } while (0); sei(); } while (0) #define AO_TELESCIENCE_NUM_ADC 12 -- cgit v1.2.3 From 3bda859caf1501f8408703dca81412d70ba00e04 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 17:42:24 -0600 Subject: altos/avr: telescience does not have a serial port The USART is used for SPI to talk to the flash part. Signed-off-by: Keith Packard --- src/avr/ao_pins.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index 6b72530b..ddd37a7b 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -37,12 +37,12 @@ #define HAS_USB 1 #define HAS_LOG 1 #define TEENSY 0 - #define USE_SERIAL_STDIN 1 - #define HAS_SERIAL_1 1 - #define HAS_USB 1 + #define USE_SERIAL_STDIN 0 + #define HAS_SERIAL_1 0 #define HAS_ADC 1 #define PACKET_HAS_SLAVE 0 #define HAS_BEEP 0 + #define HAS_STORAGE_DEBUG 1 #define AVR_VCC_5V 0 #define AVR_VCC_3V3 1 -- cgit v1.2.3 From af4470f8025116179ef83726a8287e47c465907b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 17:44:02 -0600 Subject: altos/avr: Register stdio handler when using serial for stdin This code was left in a bit of a mess; just clean it up. Signed-off-by: Keith Packard --- src/avr/ao_serial_avr.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/avr/ao_serial_avr.c b/src/avr/ao_serial_avr.c index 2fe39755..6885c339 100644 --- a/src/avr/ao_serial_avr.c +++ b/src/avr/ao_serial_avr.c @@ -154,13 +154,9 @@ ao_serial_init(void) (1 << TXEN1) | /* Enable transmitter */ (1 << RXCIE1) | /* Enable receive interrupts */ (1 << UDRIE1)); /* Enable transmit empty interrupts */ -#if 0 #if USE_SERIAL_STDIN - int8_t i; - i = ao_add_stdio(ao_serial_pollchar, - ao_serial_putchar, - NULL); - printf("Register serial stdio as %d\n", i); -#endif + ao_add_stdio(ao_serial_pollchar, + ao_serial_putchar, + NULL); #endif } -- cgit v1.2.3 From e60c470b426b7be08a33133e7d8c94201d7e96d4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 17:44:40 -0600 Subject: altos/avr: Pull-up on the SPI slave select pin This makes the board work even when disconnected from TeleMetrum. Signed-off-by: Keith Packard --- src/avr/ao_spi_slave.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/avr/ao_spi_slave.c b/src/avr/ao_spi_slave.c index 76f574c6..3aa0b97f 100644 --- a/src/avr/ao_spi_slave.c +++ b/src/avr/ao_spi_slave.c @@ -87,7 +87,7 @@ ao_spi_slave_init(void) (1 << 3) | /* MISO, output */ (0 << 2) | /* MOSI, no pull-up */ (0 << 1) | /* SCK, no pull-up */ - (0 << 0)); /* SS, no pull-up */ + (1 << 0)); /* SS, pull-up */ #endif #if SPI_SLAVE_PIN_2_5 PCMSK0 |= (1 << PCINT2); /* Enable PCINT2 pin change */ @@ -103,7 +103,7 @@ ao_spi_slave_init(void) (0 << 5) | /* SCK, no pull-up */ (1 << 4) | /* MISO, output */ (0 << 3) | /* MOSI, no pull-up */ - (0 << 2)); /* SS, no pull-up */ + (1 << 2)); /* SS, pull-up */ #endif SPCR = (0 << SPIE) | /* Disable SPI interrupts */ -- cgit v1.2.3 From 3a28846d3ff8f82b0e97c211b9debf6d67ee5af5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 18:10:45 -0600 Subject: altos/avr: Clear SPI receive buffer before clocking new data in I don't know why this is necessary, but the receive buffer gets 'extra' data added somehow. Signed-off-by: Keith Packard --- src/avr/ao_spi_usart.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/avr/ao_spi_usart.c b/src/avr/ao_spi_usart.c index 1996fcd9..5ea11da6 100644 --- a/src/avr/ao_spi_usart.c +++ b/src/avr/ao_spi_usart.c @@ -43,15 +43,17 @@ ao_spi_send(void __xdata *block, uint16_t len) __reentrant /* Receive bytes over SPI. * - * This sets up tow DMA engines, one reading the data and another - * writing constant values to the SPI transmitter as that is what - * clocks the data coming in. + * Poll, sending zeros and reading data back */ void ao_spi_recv(void __xdata *block, uint16_t len) __reentrant { uint8_t *d = block; + /* Clear any pending data */ + while (UCSR1A & (1 << RXC1)) + (void) UDR1; + while (len--) { while (!(UCSR1A & (1 << UDRE1))); UDR1 = 0; -- cgit v1.2.3 From ac0bebc44bc657b303db4c41fa0c9624f3df9f4f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 18:11:56 -0600 Subject: altos: Make HAS_STORAGE_DEBUG define consistent This allows products to include the 'w' command for testing flash writing as needed. Signed-off-by: Keith Packard --- src/core/ao_storage.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/ao_storage.c b/src/core/ao_storage.c index 6ffca0e5..ff4747d0 100644 --- a/src/core/ao_storage.c +++ b/src/core/ao_storage.c @@ -103,7 +103,7 @@ ao_storage_dump(void) __reentrant } } -#if 0 +#if HAS_STORAGE_DEBUG /* not enough space for this today */ @@ -160,6 +160,7 @@ ao_storage_zapall(void) __reentrant void ao_storage_info(void) __reentrant { + ao_storage_setup(); printf("Storage size: %ld\n", ao_storage_total); printf("Storage erase unit: %ld\n", ao_storage_block); ao_storage_device_info(); @@ -168,7 +169,7 @@ ao_storage_info(void) __reentrant __code struct ao_cmds ao_storage_cmds[] = { { ao_storage_info, "f\0Show storage" }, { ao_storage_dump, "e \0Dump flash" }, -#ifdef HAS_STORAGE_DBG +#if HAS_STORAGE_DEBUG { ao_storage_store, "w ...\0Write data to flash" }, #endif { ao_storage_zap, "z \0Erase " }, -- cgit v1.2.3 From cb837d9bb9e6736fcdfca7692b1f9490ea090838 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 18:13:00 -0600 Subject: altos: Allow ao_science_slave to not log data This is mostly for debugging with flash writes disabled. Signed-off-by: Keith Packard --- src/drivers/ao_science_slave.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/drivers/ao_science_slave.c b/src/drivers/ao_science_slave.c index e902318f..78941255 100644 --- a/src/drivers/ao_science_slave.c +++ b/src/drivers/ao_science_slave.c @@ -49,6 +49,7 @@ void ao_spi_slave(void) return; } +#if HAS_LOG ao_log_single_write_data.telescience.tm_tick = ao_companion_command.tick; if (ao_log_single_write_data.telescience.tm_state != ao_companion_command.flight_state) { ao_log_single_write_data.telescience.tm_state = ao_companion_command.flight_state; @@ -59,4 +60,5 @@ void ao_spi_slave(void) ao_log_single_stop(); } } +#endif } -- cgit v1.2.3 From f1573a752425121d4c6a14285f1eb0fef3a8bea5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 18:44:48 -0600 Subject: altos/avr: Shrink default stack size to use less ram Not that we have any way of knowing how much stack we're using, but at least this seems to work. Signed-off-by: Keith Packard --- src/avr/ao_arch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index 2be4abee..c189ccba 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -37,7 +37,7 @@ * AVR definitions and code fragments for AltOS */ -#define AO_STACK_SIZE 128 +#define AO_STACK_SIZE 116 /* Various definitions to make GCC look more like SDCC */ -- cgit v1.2.3 From b80f8ffb61566cbd134c399ea6ccf9290075490b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 18:45:51 -0600 Subject: altos/avr: Must leave space for init stack in ram The stack used during system initialization lives at the top of RAM, so leave some space for that. Signed-off-by: Keith Packard --- src/util/check-avr-mem | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/util/check-avr-mem b/src/util/check-avr-mem index c73edbd1..7956f0aa 100644 --- a/src/util/check-avr-mem +++ b/src/util/check-avr-mem @@ -2,8 +2,10 @@ nm "$@" | grep ' N _end' | awk '{ iram = strtonum("0x" $1) % 0x10000; -if ( iram > 0xaff) { - printf ("%d bytes of ram more than %d available\n", iram, 0xaff); +if ( iram > 0xacf) { + printf ("%d bytes of ram more than %d available\n", iram, 0xacf); exit(1); -} else - exit(0); }' +} else { + printf("%d bytes of ram\n", iram); + exit(0); +} }' -- cgit v1.2.3 From 75960500d1f290fa9f82183431443ac122f12c19 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 18:48:11 -0600 Subject: altos/avr: telescience doesn't have room for the flash write code This is useful for debugging the SPI and flash drivers, but not necessary in production code. Signed-off-by: Keith Packard --- src/avr/ao_pins.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index ddd37a7b..bf02db1b 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -42,7 +42,7 @@ #define HAS_ADC 1 #define PACKET_HAS_SLAVE 0 #define HAS_BEEP 0 - #define HAS_STORAGE_DEBUG 1 + #define HAS_STORAGE_DEBUG 0 #define AVR_VCC_5V 0 #define AVR_VCC_3V3 1 -- cgit v1.2.3 From 652c024ed37bfed5de17f45c772796d5cbe4599f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 18:48:55 -0600 Subject: altos/telescience: Add more header dependencies Signed-off-by: Keith Packard --- src/telescience-v0.1/Makefile | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index a6797cbe..be99f10d 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -20,9 +20,9 @@ endif INC = \ ao.h \ + ao_arch.h \ ao_usb.h \ - ao_pins.h \ - altitude.h + ao_pins.h # # Common AltOS sources @@ -30,7 +30,11 @@ INC = \ TELESCIENCE_STORAGE= \ ao_m25.c \ ao_spi_usart.c \ - ao_storage.c \ + ao_storage.c + +TELESCIENCE_LOG= \ + ao_log_single.c \ + ao_log_telescience.c ALTOS_SRC = \ ao_clock.c \ @@ -48,9 +52,8 @@ ALTOS_SRC = \ ao_adc_avr.c \ ao_science_slave.c \ ao_spi_slave.c \ - ao_log_single.c \ - ao_log_telescience.c \ - $(TELESCIENCE_STORAGE) + $(TELESCIENCE_STORAGE)\ + $(TELESCIENCE_LOG) PRODUCT=TeleScience-v0.1 MCU=atmega32u4 @@ -90,9 +93,6 @@ $(PROG).hex: $(PROG) load: $(PROG).hex $(LOADCMD) $(LOADARG)$(PROG).hex -../altitude.h: make-altitude - nickle $< > $@ - ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ @@ -109,4 +109,4 @@ install: uninstall: -$(OBJ): ao.h ao_product.h ao_usb.h +$(OBJ): ao_product.h $(INC) -- cgit v1.2.3 From 47c2c0b79dc516d2566ae149605b7d70ef2dca98 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 20:58:04 -0600 Subject: Bump to 1.0.9.3 TeleScience and TelePyro now work. Signed-off-by: Keith Packard --- configure.ac | 2 +- src/avr/ao_spi_slave.c | 4 ++-- src/avr/ao_usb_avr.c | 3 --- src/core/ao.h | 4 ++-- src/drivers/ao_pyro_slave.c | 12 ++++++------ src/drivers/ao_science_slave.c | 12 ++++++------ 6 files changed, 17 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/configure.ac b/configure.ac index 57d2f196..19db6d27 100644 --- a/configure.ac +++ b/configure.ac @@ -18,7 +18,7 @@ dnl dnl Process this file with autoconf to create configure. AC_PREREQ(2.57) -AC_INIT([altos], 1.0.9.2) +AC_INIT([altos], 1.0.9.3) AC_CONFIG_SRCDIR([src/core/ao.h]) AM_INIT_AUTOMAKE([foreign dist-bzip2]) AM_MAINTAINER_MODE diff --git a/src/avr/ao_spi_slave.c b/src/avr/ao_spi_slave.c index 3aa0b97f..b742d29a 100644 --- a/src/avr/ao_spi_slave.c +++ b/src/avr/ao_spi_slave.c @@ -18,7 +18,7 @@ #include "ao.h" uint8_t -ao_spi_read(uint8_t *buf, uint8_t len) +ao_spi_slave_recv(uint8_t *buf, uint8_t len) { while (len--) { while (!(SPSR & (1 << SPIF))) @@ -30,7 +30,7 @@ ao_spi_read(uint8_t *buf, uint8_t len) } void -ao_spi_write(uint8_t *buf, uint8_t len) +ao_spi_slave_send(uint8_t *buf, uint8_t len) { while (len--) { SPDR = *buf++; diff --git a/src/avr/ao_usb_avr.c b/src/avr/ao_usb_avr.c index 74bdea23..fc8899d8 100644 --- a/src/avr/ao_usb_avr.c +++ b/src/avr/ao_usb_avr.c @@ -303,9 +303,6 @@ ao_usb_ep0_setup(void) } break; case AO_USB_RECIP_INTERFACE: -#ifndef AVR - #pragma disable_warning 110 -#endif debug ("Interface setup packet\n"); switch(ao_usb_setup.request) { case AO_USB_REQ_GET_STATUS: diff --git a/src/core/ao.h b/src/core/ao.h index c0474729..94526bc3 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -975,10 +975,10 @@ ao_spi_init(void); */ uint8_t -ao_spi_read(uint8_t *buf, uint8_t len); +ao_spi_slave_recv(uint8_t *buf, uint8_t len); void -ao_spi_write(uint8_t *buf, uint8_t len); +ao_spi_slave_send(uint8_t *buf, uint8_t len); void ao_spi_slave_init(void); diff --git a/src/drivers/ao_pyro_slave.c b/src/drivers/ao_pyro_slave.c index e6c73a3c..5ef42b5a 100644 --- a/src/drivers/ao_pyro_slave.c +++ b/src/drivers/ao_pyro_slave.c @@ -29,19 +29,19 @@ static const struct ao_companion_setup ao_telepyro_setup = { void ao_spi_slave(void) { - if (!ao_spi_read((uint8_t *) &ao_companion_command, - sizeof (ao_companion_command))) + if (!ao_spi_slave_recv((uint8_t *) &ao_companion_command, + sizeof (ao_companion_command))) return; /* Figure out the outbound data */ switch (ao_companion_command.command) { case AO_COMPANION_SETUP: - ao_spi_write((uint8_t *) &ao_telepyro_setup, - sizeof (ao_telepyro_setup)); + ao_spi_slave_send((uint8_t *) &ao_telepyro_setup, + sizeof (ao_telepyro_setup)); break; case AO_COMPANION_FETCH: - ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, - AO_TELEPYRO_NUM_ADC * sizeof (uint16_t)); + ao_spi_slave_send((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, + AO_TELEPYRO_NUM_ADC * sizeof (uint16_t)); break; case AO_COMPANION_NOTIFY: break; diff --git a/src/drivers/ao_science_slave.c b/src/drivers/ao_science_slave.c index 78941255..1ebb1480 100644 --- a/src/drivers/ao_science_slave.c +++ b/src/drivers/ao_science_slave.c @@ -29,19 +29,19 @@ static const struct ao_companion_setup ao_telescience_setup = { void ao_spi_slave(void) { - if (!ao_spi_read((uint8_t *) &ao_companion_command, - sizeof (ao_companion_command))) + if (!ao_spi_slave_recv((uint8_t *) &ao_companion_command, + sizeof (ao_companion_command))) return; /* Figure out the outbound data */ switch (ao_companion_command.command) { case AO_COMPANION_SETUP: - ao_spi_write((uint8_t *) &ao_telescience_setup, - sizeof (ao_telescience_setup)); + ao_spi_slave_send((uint8_t *) &ao_telescience_setup, + sizeof (ao_telescience_setup)); break; case AO_COMPANION_FETCH: - ao_spi_write((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, - AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); + ao_spi_slave_send((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, + AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); break; case AO_COMPANION_NOTIFY: break; -- cgit v1.2.3 From badda0d910c56135401dce9adc9e6abebdba2ad7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 23:28:02 -0600 Subject: altos: Split out arch-specific bits of LCD driver The arch-specific section just puts a single nibble to the device. Signed-off-by: Keith Packard --- src/avr/ao_lcd_port.c | 74 ++++++++++++++++++++++++ src/cc1111/ao_lcd_port.c | 41 ++++++++++++++ src/cc1111/ao_packet.c | 4 ++ src/core/ao.h | 28 ++++++++++ src/core/ao_monitor.c | 13 ++++- src/drivers/ao_lcd.c | 142 ++++++++++------------------------------------- 6 files changed, 186 insertions(+), 116 deletions(-) create mode 100644 src/avr/ao_lcd_port.c create mode 100644 src/cc1111/ao_lcd_port.c (limited to 'src') diff --git a/src/avr/ao_lcd_port.c b/src/avr/ao_lcd_port.c new file mode 100644 index 00000000..b1e8aa17 --- /dev/null +++ b/src/avr/ao_lcd_port.c @@ -0,0 +1,74 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +#define LCD_PORT PORTB +#define LCD_DDR DDRB + +#define PIN_RS 4 +#define PIN_E 5 +#define PIN_RW 6 + +static void +ao_lcd_port_set_bits(uint8_t bits) +{ +#if 0 + printf("\tLCD data %x RS %d R/W %d E %d\n", + bits & 0xf, + (bits & (1 << PIN_RS)) ? 1 : 0, + (bits & (1 << PIN_RW)) ? 1 : 0, + (bits & (1 << PIN_E)) ? 1 : 0); +#endif + LCD_PORT = bits; +#if 0 + ao_delay(1); + if (bits & (1 << PIN_RW)) + printf("\tLCD input %x\n", PINB); +#endif +} + +uint8_t +ao_lcd_port_get_nibble(uint8_t rs) +{ + uint8_t data = (rs ? (1 << PIN_RS) : 0) | (1 << PIN_RW); + uint8_t n; + + DDRB = (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); + ao_lcd_port_set_bits(data); + ao_lcd_port_set_bits(data | (1 << PIN_E)); + n = PINB & 0xf; + ao_lcd_port_set_bits(data); + return n; +} + +void +ao_lcd_port_put_nibble(uint8_t rs, uint8_t data) +{ + data = (data & 0xf) | (rs ? (1 << PIN_RS) : 0); + DDRB = (0xf) | (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); + ao_lcd_port_set_bits(data); + ao_lcd_port_set_bits(data | (1 << PIN_E)); + ao_lcd_port_set_bits(data); +} + +void +ao_lcd_port_init(void) +{ + DDRB = (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); + PORTB = 0; +} diff --git a/src/cc1111/ao_lcd_port.c b/src/cc1111/ao_lcd_port.c new file mode 100644 index 00000000..324cc3d3 --- /dev/null +++ b/src/cc1111/ao_lcd_port.c @@ -0,0 +1,41 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +void +ao_lcd_port_put_nibble(uint8_t rs, uint8_t nibble) +{ + P0 = (P0 & 0xf0) | (nibble & 0x0f); + P1_1 = rs; + P1_0 = 1; + ao_delay(1); + P1_0 = 0; + ao_delay(1); +} + +void +ao_lcd_port_init(void) +{ + /* LCD_E and LCD_RS are GPIO outputs */ + P1DIR |= 0x03; + P1SEL &= ~0x03; + + /* LCD D4-D7 are GPIO outputs */ + P0DIR |= 0x0f; + P0SEL &= ~0x0f; +} diff --git a/src/cc1111/ao_packet.c b/src/cc1111/ao_packet.c index 37ba92e0..f502d67c 100644 --- a/src/cc1111/ao_packet.c +++ b/src/cc1111/ao_packet.c @@ -32,7 +32,9 @@ __xdata uint8_t ao_packet_master_sleeping; void ao_packet_send(void) { +#ifdef AO_LED_RED ao_led_on(AO_LED_RED); +#endif /* If any tx data is pending then copy it into the tx packet */ if (ao_packet_tx_used && ao_tx_packet.len == 0) { ao_xmemcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); @@ -42,7 +44,9 @@ ao_packet_send(void) ao_wakeup(&tx_data); } ao_radio_send(&ao_tx_packet, sizeof (ao_tx_packet)); +#ifdef AO_LED_RED ao_led_off(AO_LED_RED); +#endif } uint8_t diff --git a/src/core/ao.h b/src/core/ao.h index 94526bc3..c800f1fc 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1667,9 +1667,37 @@ ao_companion_init(void); /* ao_lcd.c */ +void +ao_lcd_putchar(uint8_t data); + +void +ao_lcd_putstring(char *string); + +void +ao_lcd_contrast_set(uint8_t contrast); + +void +ao_lcd_clear(void); + +#define AO_LCD_ADDR(row,col) ((row << 6) | (col)) + +void +ao_lcd_goto(uint8_t addr); + +void +ao_lcd_start(void); + void ao_lcd_init(void); +/* ao_lcd_port.c */ + +void +ao_lcd_port_put_nibble(uint8_t rs, uint8_t data); + +void +ao_lcd_port_init(void); + /* ao_aes.c */ __xdata uint8_t ao_aes_mutex; diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 1a8bb52a..5a6f61dd 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -22,6 +22,10 @@ #error Must define HAS_MONITOR to 1 #endif +#ifndef LEGACY_MONITOR +#error Must define LEGACY_MONITOR +#endif + __data uint8_t ao_monitoring; __pdata uint8_t ao_monitor_led; @@ -39,12 +43,14 @@ ao_monitor_get(void) case 0: ao_sleep(DATA_TO_XDATA(&ao_monitoring)); continue; +#if LEGACY_MONITOR case AO_MONITORING_ORIG: size = sizeof (struct ao_telemetry_orig_recv); break; case AO_MONITORING_TINY: size = sizeof (struct ao_telemetry_tiny_recv); break; +#endif default: if (ao_monitoring > AO_MAX_TELEMETRY) ao_monitoring = AO_MAX_TELEMETRY; @@ -70,12 +76,13 @@ ao_monitor_blink(void) void ao_monitor_put(void) { +#if LEGACY_MONITOR __xdata char callsign[AO_MAX_CALLSIGN+1]; - + int16_t rssi; +#endif uint8_t ao_monitor_tail; uint8_t state; uint8_t sum, byte; - int16_t rssi; __xdata union ao_monitor *m; #define recv_raw ((m->raw)) @@ -89,6 +96,7 @@ ao_monitor_put(void) m = &ao_monitor_ring[ao_monitor_tail]; ao_monitor_tail = ao_monitor_ring_next(ao_monitor_tail); switch (ao_monitoring) { +#if LEGACY_MONITOR case AO_MONITORING_ORIG: state = recv_orig.telemetry_orig.flight_state; @@ -231,6 +239,7 @@ ao_monitor_put(void) printf("CRC INVALID RSSI %3d\n", rssi); } break; +#endif /* LEGACY_MONITOR */ default: printf ("TELEM %02x", ao_monitoring + 2); sum = 0x5a; diff --git a/src/drivers/ao_lcd.c b/src/drivers/ao_lcd.c index 5bc89bbd..e62247ae 100644 --- a/src/drivers/ao_lcd.c +++ b/src/drivers/ao_lcd.c @@ -17,100 +17,9 @@ #include "ao.h" -#define LCD_PORT PORTB -#define LCD_DDR DDRB - -#define PIN_RS 4 -#define PIN_E 5 -#define PIN_RW 6 - -void -ao_lcd_set_bits(uint8_t bits) -{ -#if 0 - printf("\tLCD data %x RS %d R/W %d E %d\n", - bits & 0xf, - (bits & (1 << PIN_RS)) ? 1 : 0, - (bits & (1 << PIN_RW)) ? 1 : 0, - (bits & (1 << PIN_E)) ? 1 : 0); -#endif - LCD_PORT = bits; -#if 0 - ao_delay(1); - if (bits & (1 << PIN_RW)) - printf("\tLCD input %x\n", PINB); -#endif -} - -uint8_t -ao_lcd_get_nibble(uint8_t rs) -{ - uint8_t data = (rs ? (1 << PIN_RS) : 0) | (1 << PIN_RW); - uint8_t n; - - DDRB = (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); - ao_lcd_set_bits(data); - ao_lcd_set_bits(data | (1 << PIN_E)); - n = PINB & 0xf; - ao_lcd_set_bits(data); - return n; -} - -uint8_t -ao_lcd_get_status(void) -{ - uint8_t high, low; - uint8_t data; - - high = ao_lcd_get_nibble(0); - low = ao_lcd_get_nibble(0); - data = (high << 4) | low; - printf ("\tLCD status %02x\n", data); - return data; -} - -uint8_t -ao_lcd_get_data(void) -{ - uint8_t high, low; - uint8_t data; - - high = ao_lcd_get_nibble(1); - low = ao_lcd_get_nibble(1); - data = (high << 4) | low; - printf ("\tLCD data %02x\n", data); - return data; -} - -void -ao_lcd_wait_idle(void) -{ - uint8_t status; - uint8_t count = 0; - - do { - status = ao_lcd_get_status(); - count++; - if (count > 100) { - printf("idle timeout\n"); - break; - } - } while (0); /* status & 0x80); */ -} - -void -ao_lcd_send_nibble(uint8_t rs, uint8_t data) -{ - data = (data & 0xf) | (rs ? (1 << PIN_RS) : 0); - DDRB = (0xf) | (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); - ao_lcd_set_bits(data); - ao_lcd_set_bits(data | (1 << PIN_E)); - ao_lcd_set_bits(data); -} - static uint16_t ao_lcd_time = 3; -void +static void ao_lcd_delay(void) { volatile uint16_t count; @@ -119,34 +28,34 @@ ao_lcd_delay(void) ; } -void -ao_lcd_send_ins(uint8_t data) +static void +ao_lcd_send_ins(uint8_t ins) { -// printf("send ins %02x\n", data); +// printf("send ins %02x\n", ins); // ao_lcd_wait_idle(); // ao_delay(1); ao_lcd_delay(); - ao_lcd_send_nibble(0, data >> 4); - ao_lcd_send_nibble(0, data & 0xf); + ao_lcd_port_put_nibble(0, ins >> 4); + ao_lcd_port_put_nibble(0, ins & 0xf); } void -ao_lcd_send_data(uint8_t data) +ao_lcd_put_byte(uint8_t c) { -// printf ("send data %02x\n", data); +// printf ("send data %02x\n", c); // ao_lcd_wait_idle(); ao_lcd_delay(); - ao_lcd_send_nibble(1, data >> 4); - ao_lcd_send_nibble(1, data & 0x0f); + ao_lcd_port_put_nibble(1, c >> 4); + ao_lcd_port_put_nibble(1, c & 0x0f); } void -ao_lcd_send_string(char *string) +ao_lcd_putstring(char *string) { - uint8_t c; + char c; while ((c = (uint8_t) *string++)) - ao_lcd_send_data(c); + ao_lcd_put_byte((uint8_t) c); } #define AO_LCD_POWER_CONTROL 0x54 @@ -167,14 +76,21 @@ ao_lcd_clear(void) ao_lcd_send_ins(0x04 | 0x02); } +void +ao_lcd_goto(uint8_t addr) +{ + ao_lcd_send_ins(0x80 | addr); + ao_lcd_send_ins(0x04 | 0x02); +} + void ao_lcd_start(void) { /* get to 4bit mode */ - ao_lcd_send_nibble(0, 0x3); - ao_lcd_send_nibble(0, 0x3); - ao_lcd_send_nibble(0, 0x3); - ao_lcd_send_nibble(0, 0x2); + ao_lcd_port_put_nibble(0, 0x3); + ao_lcd_port_put_nibble(0, 0x3); + ao_lcd_port_put_nibble(0, 0x3); + ao_lcd_port_put_nibble(0, 0x2); /* function set */ ao_lcd_send_ins(0x28); @@ -199,7 +115,6 @@ ao_lcd_start(void) /* Clear */ ao_lcd_clear(); - } void @@ -229,7 +144,7 @@ void ao_lcd_string(void) { uint8_t col = 0; - uint8_t c; + char c; ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) @@ -244,12 +159,12 @@ ao_lcd_string(void) ao_cmd_lex(); c |= ao_cmd_hex_nibble(); } - ao_lcd_send_data(c); + ao_lcd_put_byte(c); ao_cmd_lex(); col++; } while (col < 16) { - ao_lcd_send_data(' '); + ao_lcd_put_byte(' '); col++; } } @@ -275,7 +190,6 @@ __code struct ao_cmds ao_lcd_cmds[] = { void ao_lcd_init(void) { - DDRB = (1 << PIN_RS) | (1 << PIN_E) | (1 << PIN_RW); - PORTB = 0; + ao_lcd_port_init(); ao_cmd_register(&ao_lcd_cmds[0]); } -- cgit v1.2.3 From 65873a3ad1d8e8b5ec002be2576c6f496543306a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 23:29:24 -0600 Subject: altos: oops -- forgot to add the cc1111 string code This is required for all cc1111 builds now; it provides xdata string functions. Signed-off-by: Keith Packard --- src/cc1111/ao_string.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 src/cc1111/ao_string.c (limited to 'src') diff --git a/src/cc1111/ao_string.c b/src/cc1111/ao_string.c new file mode 100644 index 00000000..daa5c14b --- /dev/null +++ b/src/cc1111/ao_string.c @@ -0,0 +1,43 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +void +_ao_xmemcpy(__xdata uint8_t *dst, __xdata uint8_t *src, uint8_t count) +{ + while (count--) + *dst++ = *src++; +} + +void +_ao_xmemset(__xdata uint8_t *dst, uint8_t v, uint8_t count) +{ + while (count--) + *dst++ = v; +} + +int8_t +_ao_xmemcmp(__xdata uint8_t *a, __xdata uint8_t *b, uint8_t count) +{ + while (count--) { + int8_t d = *a++ - *b++; + if (d) + return d; + } + return 0; +} -- cgit v1.2.3 From 0debe7ffc2aab2b4d08f42e488cb783ae91c36ab Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 11 Oct 2011 23:30:53 -0600 Subject: altos: Add TeleTerra v0.2 product This includes most of the necessary drivers. Signed-off-by: Keith Packard --- src/product/ao_teleterra_0_2.c | 36 +++++++ src/teleterra-v0.2/Makefile | 104 ++++++++++++++++++++ src/teleterra-v0.2/ao_pins.h | 214 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 354 insertions(+) create mode 100644 src/product/ao_teleterra_0_2.c create mode 100644 src/teleterra-v0.2/Makefile create mode 100644 src/teleterra-v0.2/ao_pins.h (limited to 'src') diff --git a/src/product/ao_teleterra_0_2.c b/src/product/ao_teleterra_0_2.c new file mode 100644 index 00000000..a6c10158 --- /dev/null +++ b/src/product/ao_teleterra_0_2.c @@ -0,0 +1,36 @@ +/* + * 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_ADC_ISR 1 +#include "ao.h" + +void +main(void) +{ + ao_clock_init(); + + ao_timer_init(); + ao_beep_init(); + ao_cmd_init(); + ao_usb_init(); + ao_serial_init(); + ao_gps_init(); + ao_monitor_init(0, TRUE); + ao_radio_init(); + ao_config_init(); + ao_start_scheduler(); +} diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile new file mode 100644 index 00000000..892c37e2 --- /dev/null +++ b/src/teleterra-v0.2/Makefile @@ -0,0 +1,104 @@ +# +# TeleTerra build file +# + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + ao_product.h + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_monitor.c \ + ao_log_single.c \ + ao_log_telem.c \ + ao_mutex.c \ + ao_panic.c \ + ao_rssi.c \ + ao_state.c \ + ao_stdio.c \ + ao_storage.c \ + ao_task.c + +CC1111_SRC = \ + ao_beep.c \ + ao_dbg.c \ + ao_dma.c \ + ao_led.c \ + ao_packet.c \ + ao_packet_master.c \ + ao_radio.c \ + ao_romconfig.c \ + ao_serial.c \ + ao_spi.c \ + ao_string.c \ + ao_timer.c \ + ao_usb.c \ + ao_lcd_port.c \ + _bp.c + +DRIVER_SRC = \ + ao_m25.c \ + ao_lcd.c \ + ao_gps_skytraq.c + +PRODUCT_SRC = \ + ao_teleterra_0_2.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +TELETERRA_VER=0.2 +TELETERRA_DEF=0_2 +PROG = teleterra-v$(TELETERRA_VER)-$(VERSION).ihx +PRODUCT=TeleTerra-v$(TELETERRA_VER) +PRODUCT_DEF=-DTELETERRA_V_$(TELETERRA_DEF) +IDPRODUCT=0x000d + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: + diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h new file mode 100644 index 00000000..671d3876 --- /dev/null +++ b/src/teleterra-v0.2/ao_pins.h @@ -0,0 +1,214 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#ifdef TELETERRA_V_0_2 + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define HAS_ADC 0 + #define USE_SERIAL_STDIN 0 + #define HAS_EEPROM 1 + #define HAS_LOG 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + + #define HAS_COMPANION 0 + + #define LEDS_AVAILABLE 0 + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL_REF 0 + #define HAS_ACCEL 0 + #define HAS_IGNITE 0 + #define HAS_MONITOR 1 + #define LEGACY_MONITOR 0 + #define HAS_RSSI 0 + #define HAS_AES 0 + + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x04 + #define M25_MAX_CHIPS 1 +#endif + +#if DBG_ON_P1 + + #define DBG_CLOCK (1 << 4) /* mi0 */ + #define DBG_DATA (1 << 5) /* mo0 */ + #define DBG_RESET_N (1 << 3) /* c0 */ + + #define DBG_CLOCK_PIN (P1_4) + #define DBG_DATA_PIN (P1_5) + #define DBG_RESET_N_PIN (P1_3) + + #define DBG_PORT_NUM 1 + #define DBG_PORT P1 + #define DBG_PORT_SEL P1SEL + #define DBG_PORT_INP P1INP + #define DBG_PORT_DIR P1DIR + +#endif /* DBG_ON_P1 */ + +#if DBG_ON_P0 + + #define DBG_CLOCK (1 << 3) + #define DBG_DATA (1 << 4) + #define DBG_RESET_N (1 << 5) + + #define DBG_CLOCK_PIN (P0_3) + #define DBG_DATA_PIN (P0_4) + #define DBG_RESET_N_PIN (P0_5) + + #define DBG_PORT_NUM 0 + #define DBG_PORT P0 + #define DBG_PORT_SEL P0SEL + #define DBG_PORT_INP P0INP + #define DBG_PORT_DIR P0DIR + +#endif /* DBG_ON_P0 */ + +#if COMPANION_CS_ON_P1 + #define COMPANION_CS_PORT P1 + #define COMPANION_CS_SEL P1SEL + #define COMPANION_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P1 + #define SPI_CS_PORT P1 + #define SPI_CS_SEL P1SEL + #define SPI_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P0 + #define SPI_CS_PORT P0 + #define SPI_CS_SEL P0SEL + #define SPI_CS_DIR P0DIR +#endif + +#ifndef IGNITE_ON_P2 +#error Please define IGNITE_ON_P2 +#endif + +#ifndef IGNITE_ON_P0 +#error Please define IGNITE_ON_P0 +#endif + +#ifndef HAS_SERIAL_1 +#error Please define HAS_SERIAL_1 +#endif + +#ifndef USE_SERIAL_STDIN +#error Please define USE_SERIAL_STDIN +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#ifndef HAS_EEPROM +#error Please define HAS_EEPROM +#endif + +#ifndef HAS_LOG +#error Please define HAS_LOG +#endif + +#if HAS_EEPROM +#ifndef USE_INTERNAL_FLASH +#error Please define USE_INTERNAL_FLASH +#endif +#endif + +#ifndef HAS_DBG +#error Please define HAS_DBG +#endif + +#ifndef HAS_IGNITE +#error Please define HAS_IGNITE +#endif + +#if HAS_IGNITE +#define HAS_IGNITE_REPORT 1 +#endif + +#ifndef PACKET_HAS_MASTER +#error Please define PACKET_HAS_MASTER +#endif + +#ifndef PACKET_HAS_SLAVE +#error Please define PACKET_HAS_SLAVE +#endif + +#ifndef HAS_MONITOR +#error Please define HAS_MONITOR +#endif + +#if HAS_MONITOR +#ifndef HAS_RSSI +#error Please define HAS_RSSI +#endif +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#if HAS_ADC + +#if HAS_ACCEL +#ifndef HAS_ACCEL_REF +#error Please define HAS_ACCEL_REF +#endif +#else +#define HAS_ACCEL_REF 0 +#endif + +#endif /* HAS_ADC */ + +#if IGNITE_ON_P2 +#define AO_IGNITER_DROGUE P2_3 +#define AO_IGNITER_MAIN P2_4 +#define AO_IGNITER_DIR P2DIR +#define AO_IGNITER_DROGUE_BIT (1 << 3) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +#if IGNITE_ON_P0 +#define AO_IGNITER_DROGUE P0_5 +#define AO_IGNITER_MAIN P0_4 +#define AO_IGNITER_DIR P0DIR +#define AO_IGNITER_DROGUE_BIT (1 << 5) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +/* test these values with real igniters */ +#define AO_IGNITER_OPEN 1000 +#define AO_IGNITER_CLOSED 7000 +#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) +#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) + +#endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From a10aa835a06b71e2cefeb6b10daaf8cc394603b6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 15 Oct 2011 22:54:40 -0700 Subject: altos: Add LEGACY_MONITOR defines to more programs Make all monitoring programs define whether they want all of the old telemetry formats too. Signed-off-by: Keith Packard --- src/cc1111/ao_pins.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index d2fbb209..7c5b4574 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -112,6 +112,7 @@ #define SPI_CS_ON_P0 0 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define LEGACY_MONITOR 1 #define HAS_RSSI 1 #define HAS_AES 1 #endif @@ -222,6 +223,7 @@ #define SPI_CS_ON_P0 1 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define LEGACY_MONITOR 1 #define HAS_RSSI 1 #define HAS_AES 1 #endif @@ -248,6 +250,7 @@ #define SPI_CS_ON_P0 1 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define LEGACY_MONITOR 1 #define HAS_RSSI 1 #define HAS_AES 1 #endif @@ -281,6 +284,7 @@ #define BT_LINK_PIN_INDEX 7 #define BT_LINK_PIN P2_1 #define HAS_MONITOR 1 + #define LEGACY_MONITOR 1 #define HAS_RSSI 0 #define HAS_AES 1 #endif @@ -321,6 +325,7 @@ #define BT_LINK_PIN_INDEX 7 #define BT_LINK_PIN P1_7 #define HAS_MONITOR 1 + #define LEGACY_MONITOR 1 #define HAS_RSSI 0 #define HAS_AES 1 #endif -- cgit v1.2.3 From eb61f7aa2c8b692bd892b85e782f249187c80e5c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 21 Oct 2011 11:30:43 -0700 Subject: altos: Add teleballoon-v1.1 directory This is an alternate firmware load for telemetrum v1.1. Signed-off-by: Keith Packard --- src/core/ao_log_big.c | 2 + src/core/ao_telemetry.c | 2 +- src/teleballoon-v1.1/.gitignore | 2 + src/teleballoon-v1.1/Makefile | 122 +++++++++++++++++++ src/teleballoon-v1.1/ao_balloon.c | 155 ++++++++++++++++++++++++ src/teleballoon-v1.1/ao_pins.h | 220 ++++++++++++++++++++++++++++++++++ src/teleballoon-v1.1/ao_teleballoon.c | 77 ++++++++++++ 7 files changed, 579 insertions(+), 1 deletion(-) create mode 100644 src/teleballoon-v1.1/.gitignore create mode 100644 src/teleballoon-v1.1/Makefile create mode 100644 src/teleballoon-v1.1/ao_balloon.c create mode 100644 src/teleballoon-v1.1/ao_pins.h create mode 100644 src/teleballoon-v1.1/ao_teleballoon.c (limited to 'src') diff --git a/src/core/ao_log_big.c b/src/core/ao_log_big.c index 74d94c4b..43b3aa0c 100644 --- a/src/core/ao_log_big.c +++ b/src/core/ao_log_big.c @@ -65,9 +65,11 @@ static __data uint8_t ao_log_adc_pos; /* a hack to make sure that ao_log_records fill the eeprom block in even units */ typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; +#ifndef AO_SENSOR_INTERVAL_ASCENT #define AO_SENSOR_INTERVAL_ASCENT 1 #define AO_SENSOR_INTERVAL_DESCENT 10 #define AO_OTHER_INTERVAL 32 +#endif void ao_log(void) diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index d909bea5..e66598d1 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -35,7 +35,7 @@ static __pdata uint16_t ao_rdf_time; #define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) #define AO_RDF_LENGTH_MS 500 -#if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) +#if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) || defined(TELEBALLOON_V_1_1) #define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMETRUM #endif diff --git a/src/teleballoon-v1.1/.gitignore b/src/teleballoon-v1.1/.gitignore new file mode 100644 index 00000000..21b236c0 --- /dev/null +++ b/src/teleballoon-v1.1/.gitignore @@ -0,0 +1,2 @@ +teleballoon-* +ao_product.h diff --git a/src/teleballoon-v1.1/Makefile b/src/teleballoon-v1.1/Makefile new file mode 100644 index 00000000..89471cf4 --- /dev/null +++ b/src/teleballoon-v1.1/Makefile @@ -0,0 +1,122 @@ +# +# TeleBalloon build file +# +# The various telemetrum versions differ only +# in which flash and GPS drivers are included, +# so the per-board makefiles simply define +# TM_VER, TM_DEF, TM_INC and TM_SRC and include +# this file + +TELEBALLOON_VER=1.1 +TELEBALLOON_DEF=1_1 + +TELEBALLOON_INC = + +TELEBALLOON_SRC = \ + ao_companion.c \ + ao_gps_skytraq.c \ + ao_m25.c + +vpath %.c ..:../core:../cc1111:../drivers:../product:. +vpath %.h ..:../core:../cc1111:../drivers:../product:. +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + altitude.h \ + ao_kalman.h \ + ao_product.h \ + $(TELEBALLOON_INC) + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_convert.c \ + ao_gps_report.c \ + ao_mutex.c \ + ao_panic.c \ + ao_stdio.c \ + ao_storage.c \ + ao_task.c \ + ao_balloon.c \ + ao_sample.c \ + ao_kalman.c \ + ao_log.c \ + ao_log_big.c \ + ao_report.c \ + ao_telemetry.c + +CC1111_SRC = \ + ao_adc.c \ + ao_beep.c \ + ao_dbg.c \ + ao_dma.c \ + ao_led.c \ + ao_packet.c \ + ao_packet_slave.c \ + ao_radio.c \ + ao_romconfig.c \ + ao_serial.c \ + ao_string.c \ + ao_spi.c \ + ao_timer.c \ + ao_usb.c \ + _bp.c + +DRIVER_SRC = \ + $(TELEBALLOON_SRC) + +PRODUCT_SRC = \ + ao_teleballoon.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROG = teleballoon-v$(TELEBALLOON_VER)-$(VERSION).ihx +PRODUCT=TeleBalloon-v$(TELEBALLOON_VER) +PRODUCT_DEF=-DTELEBALLOON_V_$(TELEBALLOON_DEF) +IDPRODUCT=0x000b + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: + diff --git a/src/teleballoon-v1.1/ao_balloon.c b/src/teleballoon-v1.1/ao_balloon.c new file mode 100644 index 00000000..08a3ae1e --- /dev/null +++ b/src/teleballoon-v1.1/ao_balloon.c @@ -0,0 +1,155 @@ +/* + * 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. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#endif + +#ifndef HAS_ACCEL +#error Please define HAS_ACCEL +#endif + +#ifndef HAS_GPS +#error Please define HAS_GPS +#endif + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + +/* Main flight thread. */ + +__pdata enum ao_flight_state ao_flight_state; /* current flight state */ + +__pdata uint8_t ao_flight_force_idle; + +void +ao_flight(void) +{ + ao_sample_init(); + ao_flight_state = ao_flight_startup; + for (;;) { + + /* + * Process ADC samples, just looping + * until the sensors are calibrated. + */ + if (!ao_sample()) + continue; + + switch (ao_flight_state) { + case ao_flight_startup: + + /* Check to see what mode we should go to. + * - Invalid mode if accel cal appears to be out + * - pad mode if we're upright, + * - idle mode otherwise + */ +#if HAS_ACCEL + if (ao_config.accel_plus_g == 0 || + ao_config.accel_minus_g == 0 || + ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || + ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) + { + /* Detected an accel value outside -1.5g to 1.5g + * (or uncalibrated values), so we go into invalid mode + */ + ao_flight_state = ao_flight_invalid; + + /* Turn on packet system in invalid mode on TeleMetrum */ + ao_packet_slave_start(); + } else +#endif + if (!ao_flight_force_idle +#if HAS_ACCEL + && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP +#endif + ) + { + /* Set pad mode - we can fly! */ + ao_flight_state = ao_flight_pad; +#if HAS_USB + /* Disable the USB controller in flight mode + * to save power + */ + ao_usb_disable(); +#endif + +#if !HAS_ACCEL + /* Disable packet mode in pad state on TeleMini */ + ao_packet_slave_stop(); +#endif + + /* Turn on telemetry system */ + ao_rdf_set(1); + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_BALLOON); + + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } else { + /* Set idle mode */ + ao_flight_state = ao_flight_idle; + +#if HAS_ACCEL + /* Turn on packet system in idle mode on TeleMetrum */ + ao_packet_slave_start(); +#endif + + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } + /* wakeup threads due to state change */ + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + + break; + case ao_flight_pad: + + /* pad to coast: + * + * barometer: > 20m vertical motion + */ + if (ao_height > AO_M_TO_HEIGHT(20)) + { + ao_flight_state = ao_flight_drogue; + + /* start logging data */ + ao_log_start(); + +#if HAS_GPS + /* Record current GPS position by waking up GPS log tasks */ + ao_wakeup(&ao_gps_data); + ao_wakeup(&ao_gps_tracking_data); +#endif + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + case ao_flight_drogue: + break; + + } + } +} + +static __xdata struct ao_task flight_task; + +void +ao_flight_init(void) +{ + ao_flight_state = ao_flight_startup; + ao_add_task(&flight_task, ao_flight, "flight"); +} diff --git a/src/teleballoon-v1.1/ao_pins.h b/src/teleballoon-v1.1/ao_pins.h new file mode 100644 index 00000000..a96c6f2b --- /dev/null +++ b/src/teleballoon-v1.1/ao_pins.h @@ -0,0 +1,220 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#if defined(TELEBALLOON_V_1_1) + + #define AO_SENSOR_INTERVAL_ASCENT AO_MS_TO_TICKS(1000) + #define AO_SENSOR_INTERVAL_DESCENT AO_MS_TO_TICKS(1000) + #define AO_OTHER_INTERVAL AO_MS_TO_TICKS(1000) + #define AO_TELEMETRY_INTERVAL_BALLOON AO_MS_TO_TICKS(1000) + + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define HAS_LOG 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define HAS_COMPANION 1 + #define COMPANION_CS_ON_P1 1 + #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ + #define COMPANION_CS P1_2 + + #define AO_LED_RED 1 + #define LEDS_AVAILABLE (AO_LED_RED) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL_REF 1 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ + #define M25_MAX_CHIPS 1 + #define HAS_ACCEL 1 + #define HAS_IGNITE 0 + #define HAS_MONITOR 0 +#endif + +#if DBG_ON_P1 + + #define DBG_CLOCK (1 << 4) /* mi0 */ + #define DBG_DATA (1 << 5) /* mo0 */ + #define DBG_RESET_N (1 << 3) /* c0 */ + + #define DBG_CLOCK_PIN (P1_4) + #define DBG_DATA_PIN (P1_5) + #define DBG_RESET_N_PIN (P1_3) + + #define DBG_PORT_NUM 1 + #define DBG_PORT P1 + #define DBG_PORT_SEL P1SEL + #define DBG_PORT_INP P1INP + #define DBG_PORT_DIR P1DIR + +#endif /* DBG_ON_P1 */ + +#if DBG_ON_P0 + + #define DBG_CLOCK (1 << 3) + #define DBG_DATA (1 << 4) + #define DBG_RESET_N (1 << 5) + + #define DBG_CLOCK_PIN (P0_3) + #define DBG_DATA_PIN (P0_4) + #define DBG_RESET_N_PIN (P0_5) + + #define DBG_PORT_NUM 0 + #define DBG_PORT P0 + #define DBG_PORT_SEL P0SEL + #define DBG_PORT_INP P0INP + #define DBG_PORT_DIR P0DIR + +#endif /* DBG_ON_P0 */ + +#if COMPANION_CS_ON_P1 + #define COMPANION_CS_PORT P1 + #define COMPANION_CS_SEL P1SEL + #define COMPANION_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P1 + #define SPI_CS_PORT P1 + #define SPI_CS_SEL P1SEL + #define SPI_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P0 + #define SPI_CS_PORT P0 + #define SPI_CS_SEL P0SEL + #define SPI_CS_DIR P0DIR +#endif + +#ifndef IGNITE_ON_P2 +#error Please define IGNITE_ON_P2 +#endif + +#ifndef IGNITE_ON_P0 +#error Please define IGNITE_ON_P0 +#endif + +#ifndef HAS_SERIAL_1 +#error Please define HAS_SERIAL_1 +#endif + +#ifndef USE_SERIAL_STDIN +#error Please define USE_SERIAL_STDIN +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#ifndef HAS_EEPROM +#error Please define HAS_EEPROM +#endif + +#ifndef HAS_LOG +#error Please define HAS_LOG +#endif + +#if HAS_EEPROM +#ifndef USE_INTERNAL_FLASH +#error Please define USE_INTERNAL_FLASH +#endif +#endif + +#ifndef HAS_DBG +#error Please define HAS_DBG +#endif + +#ifndef HAS_IGNITE +#error Please define HAS_IGNITE +#endif + +#if HAS_IGNITE +#define HAS_IGNITE_REPORT 1 +#endif + +#ifndef PACKET_HAS_MASTER +#error Please define PACKET_HAS_MASTER +#endif + +#ifndef PACKET_HAS_SLAVE +#error Please define PACKET_HAS_SLAVE +#endif + +#ifndef HAS_MONITOR +#error Please define HAS_MONITOR +#endif + +#if HAS_MONITOR +#ifndef HAS_RSSI +#error Please define HAS_RSSI +#endif +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#if HAS_ADC + +#if HAS_ACCEL +#ifndef HAS_ACCEL_REF +#error Please define HAS_ACCEL_REF +#endif +#else +#define HAS_ACCEL_REF 0 +#endif + +#endif /* HAS_ADC */ + +#if IGNITE_ON_P2 +#define AO_IGNITER_DROGUE P2_3 +#define AO_IGNITER_MAIN P2_4 +#define AO_IGNITER_DIR P2DIR +#define AO_IGNITER_DROGUE_BIT (1 << 3) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +#if IGNITE_ON_P0 +#define AO_IGNITER_DROGUE P0_5 +#define AO_IGNITER_MAIN P0_4 +#define AO_IGNITER_DIR P0DIR +#define AO_IGNITER_DROGUE_BIT (1 << 5) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +/* test these values with real igniters */ +#define AO_IGNITER_OPEN 1000 +#define AO_IGNITER_CLOSED 7000 +#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) +#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) + +#endif /* _AO_PINS_H_ */ diff --git a/src/teleballoon-v1.1/ao_teleballoon.c b/src/teleballoon-v1.1/ao_teleballoon.c new file mode 100644 index 00000000..a48e21d2 --- /dev/null +++ b/src/teleballoon-v1.1/ao_teleballoon.c @@ -0,0 +1,77 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +void +ao_ignite_set_pins(void) +{ + AO_IGNITER_DROGUE = 0; + AO_IGNITER_MAIN = 0; + AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; +} + +void +main(void) +{ + /* + * Reduce the transient on the ignite pins at startup by + * pulling the pins low as soon as possible at power up + */ + ao_ignite_set_pins(); + + ao_clock_init(); + + /* Turn on the red LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + + /* A hack -- look at the SPI clock pin, if it's sitting at + * ground, then we force the computer to idle mode instead of + * flight mode + */ + if (P1_3 == 0) { + ao_flight_force_idle = 1; + while (P1_3 == 0) + ; + } + ao_timer_init(); + ao_adc_init(); + ao_beep_init(); + ao_cmd_init(); + ao_spi_init(); + ao_storage_init(); + ao_flight_init(); + ao_log_init(); + ao_report_init(); + ao_usb_init(); + ao_serial_init(); + ao_gps_init(); + ao_gps_report_init(); + ao_telemetry_init(); + ao_radio_init(); + ao_packet_slave_init(FALSE); +#if HAS_DBG + ao_dbg_init(); +#endif +#if HAS_COMPANION + ao_companion_init(); +#endif + ao_config_init(); + ao_start_scheduler(); +} -- cgit v1.2.3 From 85b259c5bba7edbd2a79471bb1104bcf3904d536 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 21 Oct 2011 14:58:26 -0700 Subject: src/teleballoon-v1.1: Use Tm style initial state stuff Come up in pad mode unless someone talks to us while in idle mode. Signed-off-by: Keith Packard --- src/teleballoon-v1.1/ao_balloon.c | 30 ++---------------------------- src/teleballoon-v1.1/ao_teleballoon.c | 2 +- 2 files changed, 3 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/teleballoon-v1.1/ao_balloon.c b/src/teleballoon-v1.1/ao_balloon.c index 08a3ae1e..e8972655 100644 --- a/src/teleballoon-v1.1/ao_balloon.c +++ b/src/teleballoon-v1.1/ao_balloon.c @@ -59,26 +59,7 @@ ao_flight(void) * - pad mode if we're upright, * - idle mode otherwise */ -#if HAS_ACCEL - if (ao_config.accel_plus_g == 0 || - ao_config.accel_minus_g == 0 || - ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || - ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) - { - /* Detected an accel value outside -1.5g to 1.5g - * (or uncalibrated values), so we go into invalid mode - */ - ao_flight_state = ao_flight_invalid; - - /* Turn on packet system in invalid mode on TeleMetrum */ - ao_packet_slave_start(); - } else -#endif - if (!ao_flight_force_idle -#if HAS_ACCEL - && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP -#endif - ) + if (!ao_flight_force_idle) { /* Set pad mode - we can fly! */ ao_flight_state = ao_flight_pad; @@ -89,10 +70,8 @@ ao_flight(void) ao_usb_disable(); #endif -#if !HAS_ACCEL - /* Disable packet mode in pad state on TeleMini */ + /* Disable packet mode in pad state */ ao_packet_slave_stop(); -#endif /* Turn on telemetry system */ ao_rdf_set(1); @@ -104,11 +83,6 @@ ao_flight(void) /* Set idle mode */ ao_flight_state = ao_flight_idle; -#if HAS_ACCEL - /* Turn on packet system in idle mode on TeleMetrum */ - ao_packet_slave_start(); -#endif - /* signal successful initialization by turning off the LED */ ao_led_off(AO_LED_RED); } diff --git a/src/teleballoon-v1.1/ao_teleballoon.c b/src/teleballoon-v1.1/ao_teleballoon.c index a48e21d2..3f12a59c 100644 --- a/src/teleballoon-v1.1/ao_teleballoon.c +++ b/src/teleballoon-v1.1/ao_teleballoon.c @@ -65,7 +65,7 @@ main(void) ao_gps_report_init(); ao_telemetry_init(); ao_radio_init(); - ao_packet_slave_init(FALSE); + ao_packet_slave_init(TRUE); #if HAS_DBG ao_dbg_init(); #endif -- cgit v1.2.3 From 07d4477b2e8477e96a2f155a25f95e14a9a47efa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 23 Oct 2011 12:51:05 -0700 Subject: altos/teleterra_0_2: Initialize LCD driver Initialize the LCD for testing. Signed-off-by: Keith Packard --- src/product/ao_teleterra_0_2.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/product/ao_teleterra_0_2.c b/src/product/ao_teleterra_0_2.c index a6c10158..4019469b 100644 --- a/src/product/ao_teleterra_0_2.c +++ b/src/product/ao_teleterra_0_2.c @@ -32,5 +32,6 @@ main(void) ao_monitor_init(0, TRUE); ao_radio_init(); ao_config_init(); + ao_lcd_init(); ao_start_scheduler(); } -- cgit v1.2.3 From 8e2736226fcd7c1ab1ba93a5ebac9b285ebf4733 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 23 Oct 2011 12:55:35 -0700 Subject: src/teleterra-v0.2: Initialize more hardware Initialize the flash storage and flight state reporting beeper. Signed-off-by: Keith Packard --- src/product/ao_telebt.c | 2 +- src/product/ao_teleterra_0_2.c | 4 ++++ src/teleterra-v0.2/Makefile | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index 9e409db7..c4b40dfc 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -37,7 +37,7 @@ main(void) ao_storage_init(); #endif ao_usb_init(); - ao_monitor_init(AO_LED_RED, sizeof (union ao_telemetry_all)); + ao_monitor_init(AO_LED_RED, TRUE); #if HAS_LOG ao_report_init(); #endif diff --git a/src/product/ao_teleterra_0_2.c b/src/product/ao_teleterra_0_2.c index 4019469b..05085860 100644 --- a/src/product/ao_teleterra_0_2.c +++ b/src/product/ao_teleterra_0_2.c @@ -26,10 +26,14 @@ main(void) ao_timer_init(); ao_beep_init(); ao_cmd_init(); + ao_spi_init(); + ao_storage_init(); ao_usb_init(); ao_serial_init(); ao_gps_init(); ao_monitor_init(0, TRUE); + ao_report_init(); + ao_log_single_init(); ao_radio_init(); ao_config_init(); ao_lcd_init(); diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile index 892c37e2..eda67a2a 100644 --- a/src/teleterra-v0.2/Makefile +++ b/src/teleterra-v0.2/Makefile @@ -24,6 +24,7 @@ CORE_SRC = \ ao_log_telem.c \ ao_mutex.c \ ao_panic.c \ + ao_report.c \ ao_rssi.c \ ao_state.c \ ao_stdio.c \ -- cgit v1.2.3 From 7e7a10c06a0486e9f869e361e46f2c98db9897b0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 23 Oct 2011 14:08:59 -0700 Subject: altos: Add button driver and sample user Hook up the teleterra buttons and have them beep Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 15 ++++++++ src/cc1111/ao_button.c | 86 ++++++++++++++++++++++++++++++++++++++++++ src/cc1111/ao_usb.c | 3 ++ src/core/ao.h | 7 ++++ src/product/ao_teleterra_0_2.c | 1 + src/product/ao_terraui.c | 45 ++++++++++++++++++++++ src/teleterra-v0.2/Makefile | 4 +- src/teleterra-v0.2/ao_pins.h | 4 ++ 8 files changed, 164 insertions(+), 1 deletion(-) create mode 100644 src/cc1111/ao_button.c create mode 100644 src/product/ao_terraui.c (limited to 'src') diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 02e36189..23589e66 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -204,6 +204,21 @@ struct ao_adc { #define AO_ADC_RING 32 +/* ao_button.c */ +void +ao_p2_isr(void); + +void +ao_button_init(void); + +#if HAS_BUTTON_P0 +void +ao_p0_isr(void) ao_arch_interrupt(13); +#endif + +char +ao_button_get(void) __critical; + /* ao_string.c */ void diff --git a/src/cc1111/ao_button.c b/src/cc1111/ao_button.c new file mode 100644 index 00000000..547d71ac --- /dev/null +++ b/src/cc1111/ao_button.c @@ -0,0 +1,86 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +volatile __xdata struct ao_fifo ao_button_fifo; + +#define BUTTON_1_PIN (P0_4) +#define BUTTON_1_MASK (1 << 4) /* P0_4 */ + +#define BUTTON_2_PIN (P2_3) +#define BUTTON_2_MASK (1 << 3) /* P2_3 */ + +#define BUTTON_3_PIN (P2_4) +#define BUTTON_3_MASK (1 << 4) /* P2_4 */ + +static void +ao_button_insert(char n) +{ + ao_fifo_insert(ao_button_fifo, n); + ao_wakeup(&ao_button_fifo); +} + +char +ao_button_get(void) __critical +{ + char b; + + while (ao_fifo_empty(ao_button_fifo)) + ao_sleep(&ao_button_fifo); + ao_fifo_remove(ao_button_fifo, b); + return b; +} + +void +ao_p2_isr(void) +{ + if (P2IFG & BUTTON_2_MASK) + ao_button_insert(2); + if (P2IFG & BUTTON_3_MASK) + ao_button_insert(3); + P2IFG = 0; +} + +void +ao_p0_isr(void) ao_arch_interrupt(13) +{ + P0IF = 0; + if (P0IFG & BUTTON_1_MASK) + ao_button_insert(1); + P0IFG = 0; +} + +void +ao_button_init(void) +{ + /* Pins are configured as inputs with pull-up by default */ + + /* Enable interrupts for P2_0 - P2_4 + * Enable interrupts for P0_4 - P0_7 + * Set P2 interrupts to falling edge + * Set P0 interrupts to falling edge + */ + + PICTL |= PICTL_P2IEN | PICTL_P0IENH | PICTL_P2ICON | PICTL_P0ICON; + + /* Enable interrupts for P0 inputs */ + IEN1 |= IEN1_P0IE; + + /* Enable interrupts for P2 inputs */ + IEN2 |= IEN2_P2IE; +} diff --git a/src/cc1111/ao_usb.c b/src/cc1111/ao_usb.c index 08cb7390..35c9ac20 100644 --- a/src/cc1111/ao_usb.c +++ b/src/cc1111/ao_usb.c @@ -62,6 +62,9 @@ ao_usb_isr(void) __interrupt 6 ao_btm_isr(); #endif #endif +#if HAS_P2_ISR + ao_p2_isr(); +#endif } struct ao_usb_setup { diff --git a/src/core/ao.h b/src/core/ao.h index c800f1fc..43d4e0e3 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1851,4 +1851,11 @@ ao_log_single(void); #define ao_xmemcmp(d,s,c) memcmp(d,s,c) #endif +/* + * ao_terraui.c + */ + +void +ao_terraui_init(void); + #endif /* _AO_H_ */ diff --git a/src/product/ao_teleterra_0_2.c b/src/product/ao_teleterra_0_2.c index 05085860..b38f2907 100644 --- a/src/product/ao_teleterra_0_2.c +++ b/src/product/ao_teleterra_0_2.c @@ -37,5 +37,6 @@ main(void) ao_radio_init(); ao_config_init(); ao_lcd_init(); + ao_terraui_init(); ao_start_scheduler(); } diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c new file mode 100644 index 00000000..3885db4e --- /dev/null +++ b/src/product/ao_terraui.c @@ -0,0 +1,45 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static void +ao_terraui(void) +{ + for (;;) { + char b = ao_button_get(); + switch (b) { + case 1: + ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(200)); + break; + case 2: + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + break; + case 3: + ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(200)); + break; + } + } +} + +__xdata static struct ao_task ao_terraui_task; + +void +ao_terraui_init(void) +{ + ao_add_task(&ao_terraui_task, ao_terraui, "ui"); +} diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile index eda67a2a..8e4569a9 100644 --- a/src/teleterra-v0.2/Makefile +++ b/src/teleterra-v0.2/Makefile @@ -33,6 +33,7 @@ CORE_SRC = \ CC1111_SRC = \ ao_beep.c \ + ao_button.c \ ao_dbg.c \ ao_dma.c \ ao_led.c \ @@ -54,7 +55,8 @@ DRIVER_SRC = \ ao_gps_skytraq.c PRODUCT_SRC = \ - ao_teleterra_0_2.c + ao_teleterra_0_2.c \ + ao_terraui.c SRC = \ $(CORE_SRC) \ diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 671d3876..7b6f08b2 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -53,6 +53,10 @@ #define SPI_CS_ON_P0 0 #define M25_CS_MASK 0x04 #define M25_MAX_CHIPS 1 + + #define HAS_P2_ISR 1 + #define HAS_BUTTON_P0 1 + #define HAS_BUTTON_P2 1 #endif #if DBG_ON_P1 -- cgit v1.2.3 From f70553106707e3496d07eecb83f0c0a1acad7f77 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 23 Oct 2011 14:51:32 -0700 Subject: altos: Add battery voltage sampling driver For devices without a full ADC compliment, this just samples the battery pin and converts to mV. Signed-off-by: Keith Packard --- src/cc1111/ao_battery.c | 60 ++++++++++++++++++++++++++++++++++++++++++ src/core/ao.h | 15 +++++++++++ src/product/ao_teleterra_0_2.c | 1 + src/teleterra-v0.2/Makefile | 1 + src/teleterra-v0.2/ao_pins.h | 2 ++ 5 files changed, 79 insertions(+) create mode 100644 src/cc1111/ao_battery.c (limited to 'src') diff --git a/src/cc1111/ao_battery.c b/src/cc1111/ao_battery.c new file mode 100644 index 00000000..070f682f --- /dev/null +++ b/src/cc1111/ao_battery.c @@ -0,0 +1,60 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +static __data union { + uint8_t d[2]; + int16_t v; +} ao_battery_value; + +void +ao_battery_isr(void) ao_arch_interrupt(1) +{ + ao_battery_value.d[0] = ADCL; + ao_battery_value.d[1] = ADCH; + ao_wakeup(DATA_TO_XDATA(&ao_battery_value)); +} + +uint16_t +ao_battery_get(void) +{ + ao_arch_critical( + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | BATTERY_PIN; + ao_sleep(DATA_TO_XDATA(&ao_battery_value)); + ); + return (uint16_t) ((int32_t) ao_battery_value.v * (int32_t) 3333 >> 15); +} + +static void +ao_battery_show(void) +{ + printf("Battery: %u mV\n", ao_battery_get()); +} + +__code struct ao_cmds ao_battery_cmds[] = { + { ao_battery_show, "B\0Show battery voltage" }, + { 0, NULL }, +}; + +void +ao_battery_init(void) +{ + ADCCFG = (1 << BATTERY_PIN); + ADCIF = 0; + IEN0 |= IEN0_ADCIE; + ao_cmd_register(&ao_battery_cmds[0]); +} diff --git a/src/core/ao.h b/src/core/ao.h index 43d4e0e3..558d0e38 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1858,4 +1858,19 @@ ao_log_single(void); void ao_terraui_init(void); +/* + * ao_battery.c + */ + +#ifdef BATTERY_PIN +void +ao_battery_isr(void) ao_arch_interrupt(1); + +uint16_t +ao_battery_get(void); + +void +ao_battery_init(void); +#endif /* BATTERY_PIN */ + #endif /* _AO_H_ */ diff --git a/src/product/ao_teleterra_0_2.c b/src/product/ao_teleterra_0_2.c index b38f2907..3272970f 100644 --- a/src/product/ao_teleterra_0_2.c +++ b/src/product/ao_teleterra_0_2.c @@ -38,5 +38,6 @@ main(void) ao_config_init(); ao_lcd_init(); ao_terraui_init(); + ao_battery_init(); ao_start_scheduler(); } diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile index 8e4569a9..36f523a3 100644 --- a/src/teleterra-v0.2/Makefile +++ b/src/teleterra-v0.2/Makefile @@ -32,6 +32,7 @@ CORE_SRC = \ ao_task.c CC1111_SRC = \ + ao_battery.c \ ao_beep.c \ ao_button.c \ ao_dbg.c \ diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 7b6f08b2..36f3c199 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -57,6 +57,8 @@ #define HAS_P2_ISR 1 #define HAS_BUTTON_P0 1 #define HAS_BUTTON_P2 1 + + #define BATTERY_PIN 5 #endif #if DBG_ON_P1 -- cgit v1.2.3 From 90e738a3379d258a48a7c92f6708040fc39c373a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 23 Oct 2011 15:20:50 -0700 Subject: altos: Fix battery voltage computation. Full scale is 4.95V, not 3.333V. Signed-off-by: Keith Packard --- src/cc1111/ao_battery.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/cc1111/ao_battery.c b/src/cc1111/ao_battery.c index 070f682f..b9845fb3 100644 --- a/src/cc1111/ao_battery.c +++ b/src/cc1111/ao_battery.c @@ -36,7 +36,7 @@ ao_battery_get(void) ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | BATTERY_PIN; ao_sleep(DATA_TO_XDATA(&ao_battery_value)); ); - return (uint16_t) ((int32_t) ao_battery_value.v * (int32_t) 3333 >> 15); + return (uint16_t) ((int32_t) ao_battery_value.v * (int32_t) 4950 >> 15); } static void -- cgit v1.2.3 From 8e4cceedb5b758faae684978299e667c4bb06f4d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 23 Oct 2011 15:24:02 -0700 Subject: altos: Flip button IRQ initialization around This matches what the docs suggest Signed-off-by: Keith Packard --- src/cc1111/ao_button.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_button.c b/src/cc1111/ao_button.c index 547d71ac..3516d559 100644 --- a/src/cc1111/ao_button.c +++ b/src/cc1111/ao_button.c @@ -76,11 +76,11 @@ ao_button_init(void) * Set P0 interrupts to falling edge */ - PICTL |= PICTL_P2IEN | PICTL_P0IENH | PICTL_P2ICON | PICTL_P0ICON; - /* Enable interrupts for P0 inputs */ IEN1 |= IEN1_P0IE; /* Enable interrupts for P2 inputs */ IEN2 |= IEN2_P2IE; + + PICTL |= PICTL_P2IEN | PICTL_P0IENH | PICTL_P2ICON | PICTL_P0ICON; } -- cgit v1.2.3 From da330c5975b9f565d059ef8084dfdacc20f34246 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 26 Oct 2011 22:49:11 -0700 Subject: altos: Bring up basic TeleTerra v0.2 UI Lots of fun stuff here -- multiple panes of information. Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 14 +- src/cc1111/ao_button.c | 115 ++++++--- src/cc1111/ao_lcd_port.c | 13 +- src/core/ao.h | 24 +- src/core/ao_monitor.c | 10 +- src/core/ao_sqrt.c | 46 ++++ src/drivers/ao_lcd.c | 12 +- src/product/Makefile.telemetrum | 6 +- src/product/ao_teleterra_0_2.c | 3 +- src/product/ao_terraui.c | 497 +++++++++++++++++++++++++++++++++++++- src/telelaunch-v0.1/.gitignore | 2 +- src/telemetrum-v0.1-sirf/Makefile | 1 + src/telemetrum-v0.1-sky/Makefile | 1 + src/teleterra-v0.2/.gitignore | 2 + src/teleterra-v0.2/.sdcdbrc | 1 + src/teleterra-v0.2/Makefile | 1 + src/teleterra-v0.2/ao_pins.h | 14 +- 17 files changed, 710 insertions(+), 52 deletions(-) create mode 100644 src/core/ao_sqrt.c create mode 100644 src/teleterra-v0.2/.gitignore create mode 100644 src/teleterra-v0.2/.sdcdbrc (limited to 'src') diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 23589e66..f0f0daae 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -205,17 +205,23 @@ struct ao_adc { #define AO_ADC_RING 32 /* ao_button.c */ +#ifdef HAS_BUTTON void -ao_p2_isr(void); +ao_p0_isr(void) ao_arch_interrupt(13); void -ao_button_init(void); +ao_p1_isr(void) ao_arch_interrupt(15); -#if HAS_BUTTON_P0 void -ao_p0_isr(void) ao_arch_interrupt(13); +ao_p2_isr(void); + +#define HAS_P2_ISR 1 + #endif +void +ao_button_init(void); + char ao_button_get(void) __critical; diff --git a/src/cc1111/ao_button.c b/src/cc1111/ao_button.c index 3516d559..77a8dde8 100644 --- a/src/cc1111/ao_button.c +++ b/src/cc1111/ao_button.c @@ -19,14 +19,22 @@ volatile __xdata struct ao_fifo ao_button_fifo; -#define BUTTON_1_PIN (P0_4) -#define BUTTON_1_MASK (1 << 4) /* P0_4 */ +static __code struct { + uint8_t mask; + uint8_t reg; +} ao_buttons[] = { +#ifdef BUTTON_1_MASK + { BUTTON_1_MASK, BUTTON_1_REG }, +#endif +#ifdef BUTTON_2_MASK + { BUTTON_2_MASK, BUTTON_2_REG }, +#endif +#ifdef BUTTON_3_MASK + { BUTTON_3_MASK, BUTTON_3_REG }, +#endif +}; -#define BUTTON_2_PIN (P2_3) -#define BUTTON_2_MASK (1 << 3) /* P2_3 */ - -#define BUTTON_3_PIN (P2_4) -#define BUTTON_3_MASK (1 << 4) /* P2_4 */ +#define NUM_BUTTONS ((sizeof ao_buttons) / sizeof (ao_buttons[0])) static void ao_button_insert(char n) @@ -35,52 +43,101 @@ ao_button_insert(char n) ao_wakeup(&ao_button_fifo); } +static void +ao_button_isr(uint8_t flag, uint8_t reg) +{ + uint8_t b; + + for (b = 0; b < NUM_BUTTONS; b++) + if (ao_buttons[b].reg == reg && (ao_buttons[b].mask & flag)) + ao_button_insert(b + 1); +} + +static uint8_t +ao_button_mask(uint8_t reg) +{ + uint8_t b; + uint8_t mask = 0; + + for (b = 0; b < NUM_BUTTONS; b++) + if (ao_buttons[b].reg == reg) + mask |= ao_buttons[b].mask; + return mask; +} + char ao_button_get(void) __critical { char b; while (ao_fifo_empty(ao_button_fifo)) - ao_sleep(&ao_button_fifo); + if (ao_sleep(&ao_button_fifo)) + return 0; ao_fifo_remove(ao_button_fifo, b); return b; } void -ao_p2_isr(void) +ao_p0_isr(void) ao_arch_interrupt(13) { - if (P2IFG & BUTTON_2_MASK) - ao_button_insert(2); - if (P2IFG & BUTTON_3_MASK) - ao_button_insert(3); - P2IFG = 0; + P0IF = 0; + ao_button_isr(P0IFG, 0); + P0IFG = 0; } void -ao_p0_isr(void) ao_arch_interrupt(13) +ao_p1_isr(void) ao_arch_interrupt(15) { - P0IF = 0; - if (P0IFG & BUTTON_1_MASK) - ao_button_insert(1); - P0IFG = 0; + P1IF = 0; + ao_button_isr(P1IFG, 1); + P1IFG = 0; +} + +/* Shared with USB */ +void +ao_p2_isr(void) +{ + ao_button_isr(P2IFG, 2); + P2IFG = 0; } void ao_button_init(void) { + uint8_t mask; + /* Pins are configured as inputs with pull-up by default */ - /* Enable interrupts for P2_0 - P2_4 - * Enable interrupts for P0_4 - P0_7 - * Set P2 interrupts to falling edge - * Set P0 interrupts to falling edge - */ - /* Enable interrupts for P0 inputs */ - IEN1 |= IEN1_P0IE; + mask = ao_button_mask(0); + if (mask) { + if (mask & 0x0f) + PICTL |= PICTL_P0IENL; + if (mask & 0xf0) + PICTL |= PICTL_P0IENH; + P0IFG = 0; + P0IF = 0; + IEN1 |= IEN1_P0IE; + PICTL |= PICTL_P0ICON; + } - /* Enable interrupts for P2 inputs */ - IEN2 |= IEN2_P2IE; + /* Enable interrupts for P1 inputs */ + mask = ao_button_mask(1); + if (mask) { + P1IEN |= mask; + P1IFG = 0; + P1IF = 0; + IEN2 |= IEN2_P1IE; + PICTL |= PICTL_P1ICON; + } - PICTL |= PICTL_P2IEN | PICTL_P0IENH | PICTL_P2ICON | PICTL_P0ICON; + /* Enable interrupts for P2 inputs */ + mask = ao_button_mask(2); + if (mask) { + PICTL |= PICTL_P2IEN; + P2IFG = 0; + P2IF = 0; + IEN2 |= IEN2_P2IE; + PICTL |= PICTL_P2ICON; + } } diff --git a/src/cc1111/ao_lcd_port.c b/src/cc1111/ao_lcd_port.c index 324cc3d3..e61b1a60 100644 --- a/src/cc1111/ao_lcd_port.c +++ b/src/cc1111/ao_lcd_port.c @@ -17,15 +17,24 @@ #include "ao.h" +static void +ao_lcd_port_delay(void) +{ + uint8_t i; + + for (i = 0; i < 100; i++) + ao_arch_nop(); +} + void ao_lcd_port_put_nibble(uint8_t rs, uint8_t nibble) { P0 = (P0 & 0xf0) | (nibble & 0x0f); P1_1 = rs; P1_0 = 1; - ao_delay(1); + ao_lcd_port_delay(); P1_0 = 0; - ao_delay(1); + ao_lcd_port_delay(); } void diff --git a/src/core/ao.h b/src/core/ao.h index 558d0e38..9b8d3270 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -996,7 +996,11 @@ ao_spi_slave(void); */ #define AO_MAX_CALLSIGN 8 #define AO_MAX_VERSION 8 +#if LEGACY_MONITOR #define AO_MAX_TELEMETRY 128 +#else +#define AO_MAX_TELEMETRY 32 +#endif struct ao_telemetry_generic { uint16_t serial; /* 0 */ @@ -1156,6 +1160,12 @@ union ao_telemetry_all { struct ao_telemetry_baro baro; }; +struct ao_telemetry_all_recv { + union ao_telemetry_all telemetry; + int8_t rssi; + uint8_t status; +}; + /* * ao_gps.c */ @@ -1372,9 +1382,10 @@ extern const char const * const ao_state_names[]; #define AO_MONITOR_RING 8 union ao_monitor { - struct ao_telemetry_raw_recv raw; - struct ao_telemetry_orig_recv orig; - struct ao_telemetry_tiny_recv tiny; + struct ao_telemetry_raw_recv raw; + struct ao_telemetry_all_recv all; + struct ao_telemetry_orig_recv orig; + struct ao_telemetry_tiny_recv tiny; }; extern __xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING]; @@ -1873,4 +1884,11 @@ void ao_battery_init(void); #endif /* BATTERY_PIN */ +/* + * ao_sqrt.c + */ + +uint32_t +ao_sqrt(uint32_t op); + #endif /* _AO_H_ */ diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 5a6f61dd..f7795fe4 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -26,6 +26,10 @@ #error Must define LEGACY_MONITOR #endif +#ifndef HAS_MONITOR_PUT +#define HAS_MONIOTOR_PUT 1 +#endif + __data uint8_t ao_monitoring; __pdata uint8_t ao_monitor_led; @@ -73,6 +77,7 @@ ao_monitor_blink(void) } } +#if HAS_MONITOR_PUT void ao_monitor_put(void) { @@ -260,9 +265,10 @@ ao_monitor_put(void) ao_usb_flush(); } } +__xdata struct ao_task ao_monitor_put_task; +#endif __xdata struct ao_task ao_monitor_get_task; -__xdata struct ao_task ao_monitor_put_task; __xdata struct ao_task ao_monitor_blink_task; void @@ -293,7 +299,9 @@ ao_monitor_init(uint8_t monitor_led, uint8_t monitoring) __reentrant ao_monitoring = monitoring; ao_cmd_register(&ao_monitor_cmds[0]); ao_add_task(&ao_monitor_get_task, ao_monitor_get, "monitor_get"); +#if HAS_MONITOR_PUT ao_add_task(&ao_monitor_put_task, ao_monitor_put, "monitor_put"); +#endif if (ao_monitor_led) ao_add_task(&ao_monitor_blink_task, ao_monitor_blink, "monitor_blink"); } diff --git a/src/core/ao_sqrt.c b/src/core/ao_sqrt.c new file mode 100644 index 00000000..09c2e319 --- /dev/null +++ b/src/core/ao_sqrt.c @@ -0,0 +1,46 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +/* Adapted from int_sqrt.c in the linux kernel, which is licensed GPLv2 */ +/** + * int_sqrt - rough approximation to sqrt + * @x: integer of which to calculate the sqrt + * + * A very rough approximation to the sqrt() function. + */ + +uint32_t +ao_sqrt(uint32_t op) +{ + uint32_t res = 0; + uint32_t one = 1UL << (sizeof (one) * 8 - 2); + + while (one > op) + one >>= 2; + + while (one != 0) { + if (op >= res + one) { + op = op - (res + one); + res = res + 2 * one; + } + res /= 2; + one /= 4; + } + return res; +} diff --git a/src/drivers/ao_lcd.c b/src/drivers/ao_lcd.c index e62247ae..8745b3f6 100644 --- a/src/drivers/ao_lcd.c +++ b/src/drivers/ao_lcd.c @@ -19,6 +19,8 @@ static uint16_t ao_lcd_time = 3; +static __xdata uint8_t ao_lcd_mutex; + static void ao_lcd_delay(void) { @@ -39,7 +41,7 @@ ao_lcd_send_ins(uint8_t ins) ao_lcd_port_put_nibble(0, ins & 0xf); } -void +static void ao_lcd_put_byte(uint8_t c) { // printf ("send data %02x\n", c); @@ -54,8 +56,10 @@ ao_lcd_putstring(char *string) { char c; + ao_mutex_get(&ao_lcd_mutex); while ((c = (uint8_t) *string++)) ao_lcd_put_byte((uint8_t) c); + ao_mutex_put(&ao_lcd_mutex); } #define AO_LCD_POWER_CONTROL 0x54 @@ -63,24 +67,30 @@ ao_lcd_putstring(char *string) void ao_lcd_contrast_set(uint8_t contrast) { + ao_mutex_get(&ao_lcd_mutex); ao_lcd_send_ins(AO_LCD_POWER_CONTROL | ((contrast >> 4) & 0x3)); ao_lcd_send_ins(0x70 | (contrast & 0xf)); + ao_mutex_put(&ao_lcd_mutex); } void ao_lcd_clear(void) { + ao_mutex_get(&ao_lcd_mutex); ao_lcd_send_ins(0x01); ao_delay(1); /* Entry mode */ ao_lcd_send_ins(0x04 | 0x02); + ao_mutex_put(&ao_lcd_mutex); } void ao_lcd_goto(uint8_t addr) { + ao_mutex_get(&ao_lcd_mutex); ao_lcd_send_ins(0x80 | addr); ao_lcd_send_ins(0x04 | 0x02); + ao_mutex_put(&ao_lcd_mutex); } void diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index 4f4195a9..40fc6bc2 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -7,8 +7,8 @@ # TM_VER, TM_DEF, TM_INC and TM_SRC and include # this file -vpath %.c ..:../core:../cc1111:../drivers:../product -vpath %.h ..:../core:../cc1111:../drivers:../product +vpath %.c .:..:../core:../cc1111:../drivers:../product +vpath %.h .:..:../core:../cc1111:../drivers:../product vpath ao-make-product.5c ../util ifndef VERSION @@ -72,7 +72,7 @@ SRC = \ $(DRIVER_SRC) \ $(PRODUCT_SRC) -PROG = telemetrum-v$(TM_VER)-$(VERSION).ihx +PROG = telemetrum-v$(TM_VER)-$(VERSION)$(TM_EXTRA).ihx PRODUCT=TeleMetrum-v$(TM_VER) PRODUCT_DEF=-DTELEMETRUM_V_$(TM_DEF) IDPRODUCT=0x000b diff --git a/src/product/ao_teleterra_0_2.c b/src/product/ao_teleterra_0_2.c index 3272970f..6ce29894 100644 --- a/src/product/ao_teleterra_0_2.c +++ b/src/product/ao_teleterra_0_2.c @@ -31,13 +31,14 @@ main(void) ao_usb_init(); ao_serial_init(); ao_gps_init(); - ao_monitor_init(0, TRUE); + ao_monitor_init(0, sizeof (struct ao_telemetry_generic)); ao_report_init(); ao_log_single_init(); ao_radio_init(); ao_config_init(); ao_lcd_init(); ao_terraui_init(); + ao_button_init(); ao_battery_init(); ao_start_scheduler(); } diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c index 3885db4e..cfbfb1fb 100644 --- a/src/product/ao_terraui.c +++ b/src/product/ao_terraui.c @@ -16,21 +16,450 @@ */ #include "ao.h" +#include + +static __xdata struct ao_telemetry_sensor ao_tel_sensor; +static __xdata struct ao_telemetry_location ao_tel_location; +static __xdata struct ao_telemetry_configuration ao_tel_config; +static __xdata int16_t ao_tel_max_speed; +static __xdata int16_t ao_tel_max_height; +static int8_t ao_tel_rssi; + +static __xdata char ao_lcd_line[17]; +static __xdata char ao_state_name[] = "SIPBFCDMLI"; + +static void +ao_terraui_line(uint8_t addr) +{ + ao_lcd_goto(addr); + ao_lcd_putstring(ao_lcd_line); +} + +#define ao_terraui_state() (ao_state_name[ao_tel_sensor.state]) + +static char +ao_terraui_igniter(int16_t sense) +{ + if (sense < AO_IGNITER_OPEN) + return '-'; + if (sense > AO_IGNITER_CLOSED) + return '+'; + return '?'; +} + +static char +ao_terraui_battery(void) +{ + if (ao_tel_sensor.v_batt > 25558) + return '+'; + return '-'; +} + +static char +ao_terraui_gps(void) +{ + if (ao_tel_location.flags & (1 << 4)) { + if ((ao_tel_location.flags & 0xf) >= 4) + return '+'; + } + return '-'; +} + +static char +ao_terraui_local_gps(void) +{ + if (ao_gps_data.flags & (1 << 4)) { + if ((ao_gps_data.flags & 0xf) >= 4) + return '+'; + } + return '-'; +} + +static char +ao_terraui_logging(void) +{ + if (ao_tel_config.flight != 0) + return '+'; + return '-'; +} + +static __code char ao_progress[4] = { '\011', '\012', '\014', '\013' }; + +static uint8_t ao_telem_progress; +static uint8_t ao_gps_progress; + +static void +ao_terraui_info(void) +{ + sprintf(ao_lcd_line, "S %4d %7.7s %c", + ao_tel_sensor.serial, + ao_tel_config.callsign, + ao_terraui_state()); + ao_terraui_line(AO_LCD_ADDR(0,0)); + sprintf(ao_lcd_line, "F %4d RSSI%4d%c", + ao_tel_config.flight, + ao_tel_rssi, + ao_progress[ao_telem_progress]); + ao_terraui_line(AO_LCD_ADDR(1,0)); +} + +static void +ao_terraui_pad(void) +{ + sprintf(ao_lcd_line, "B%c A%c M%c L%c G%c %c", + ao_terraui_battery(), + ao_terraui_igniter(ao_tel_sensor.sense_d), + ao_terraui_igniter(ao_tel_sensor.sense_m), + ao_terraui_logging(), + ao_terraui_gps(), + ao_terraui_state()); + ao_terraui_line(AO_LCD_ADDR(0,0)); + sprintf(ao_lcd_line, "SAT %2d RSSI%4d%c", + ao_tel_location.flags & 0xf, + ao_tel_rssi, + ao_progress[ao_telem_progress]); + ao_terraui_line(AO_LCD_ADDR(1,0)); +} + +static void +ao_terraui_ascent(void) +{ + sprintf(ao_lcd_line, "S %5d S\011%5d%c", + ao_tel_sensor.speed >> 4, + ao_tel_max_speed >> 4, + ao_terraui_state()); + ao_terraui_line(AO_LCD_ADDR(0,0)); + sprintf(ao_lcd_line, "H %5d H\011%5d%c", + ao_tel_sensor.height >> 4, + ao_tel_max_height >> 4, + ao_progress[ao_telem_progress]); + ao_terraui_line(AO_LCD_ADDR(1,0)); +} + +static int16_t mag(int32_t d) +{ + if (d < 0) + d = -d; + if (d > 0x7fff) + d = 0x7fff; + return d; +} + +static uint32_t +dist(int32_t d) +{ + int32_t m; + + if (d < 0) + d = -d; + + m = 1000000; + while (d >= (2147483647 / 111198)) { + d /= 10; + m /= 10; + } + return (d * 111198) / m; +} + +static __code uint8_t cos_table[] = { + 0, /* 0 */ + 0, /* 1 */ + 0, /* 2 */ + 255, /* 3 */ + 254, /* 4 */ + 253, /* 5 */ + 252, /* 6 */ + 251, /* 7 */ + 249, /* 8 */ + 247, /* 9 */ + 245, /* 10 */ + 243, /* 11 */ + 240, /* 12 */ + 238, /* 13 */ + 235, /* 14 */ + 232, /* 15 */ + 228, /* 16 */ + 225, /* 17 */ + 221, /* 18 */ + 217, /* 19 */ + 213, /* 20 */ + 209, /* 21 */ + 205, /* 22 */ + 200, /* 23 */ + 195, /* 24 */ + 190, /* 25 */ + 185, /* 26 */ + 180, /* 27 */ + 175, /* 28 */ + 169, /* 29 */ + 163, /* 30 */ + 158, /* 31 */ + 152, /* 32 */ + 145, /* 33 */ + 139, /* 34 */ + 133, /* 35 */ + 126, /* 36 */ + 120, /* 37 */ + 113, /* 38 */ + 106, /* 39 */ + 100, /* 40 */ + 93, /* 41 */ + 86, /* 42 */ + 79, /* 43 */ + 71, /* 44 */ + 64, /* 45 */ + 57, /* 46 */ + 49, /* 47 */ + 42, /* 48 */ + 35, /* 49 */ + 27, /* 50 */ + 20, /* 51 */ + 12, /* 52 */ + 5, /* 53 */ + 1, /* 54 */ +}; + +static __code uint8_t tan_table[] = { + 0, /* 0 */ + 4, /* 1 */ + 9, /* 2 */ + 13, /* 3 */ + 18, /* 4 */ + 22, /* 5 */ + 27, /* 6 */ + 31, /* 7 */ + 36, /* 8 */ + 41, /* 9 */ + 45, /* 10 */ + 50, /* 11 */ + 54, /* 12 */ + 59, /* 13 */ + 64, /* 14 */ + 69, /* 15 */ + 73, /* 16 */ + 78, /* 17 */ + 83, /* 18 */ + 88, /* 19 */ + 93, /* 20 */ + 98, /* 21 */ + 103, /* 22 */ + 109, /* 23 */ + 114, /* 24 */ + 119, /* 25 */ + 125, /* 26 */ + 130, /* 27 */ + 136, /* 28 */ + 142, /* 29 */ + 148, /* 30 */ + 154, /* 31 */ + 160, /* 32 */ + 166, /* 33 */ + 173, /* 34 */ + 179, /* 35 */ + 186, /* 36 */ + 193, /* 37 */ + 200, /* 38 */ + 207, /* 39 */ + 215, /* 40 */ + 223, /* 41 */ + 231, /* 42 */ + 239, /* 43 */ + 247, /* 44 */ +}; + +int16_t ao_atan2(int32_t dy, int32_t dx) __reentrant +{ + int8_t m = 1; + int16_t a = 0; + uint8_t r; + int8_t t; + + if (dx == 0) { + if (dy > 0) + return 90; + if (dy < 0) + return -90; + return 0; + } + + if (dx < 0) { + a = 180; + m = -m; + dx = -dx; + } + + if (dy < 0) { + m = -m; + a = -a; + dy = -dy; + } + + if (dy > dx) { + int t; + + t = dy; dy = dx; dx = t; + a = a + m * 90; + m = -m; + } + + r = ((dy << 8) + (dx >> 1)) / dx; + for (t = 0; t < 44; t++) + if (tan_table[t] >= r) + break; + return t * m + a; +} + +static __pdata uint32_t lon_dist, lat_dist; +static __pdata uint32_t ground_dist, range; +static __pdata int16_t bearing, elevation; + +static void +ao_terraui_lat_dist(void) +{ + lat_dist = dist (ao_tel_location.latitude - ao_gps_data.latitude); +} + +static void +ao_terraui_lon_dist(void) +{ + uint8_t c = cos_table[ao_gps_data.latitude >> 24]; + lon_dist = dist(ao_tel_location.longitude - ao_gps_data.longitude); + if (c) + lon_dist = ((uint32_t) lon_dist * c) >> 8; +} + +static void +ao_terraui_compute(void) +{ + ao_terraui_lat_dist(); + ao_terraui_lon_dist(); + ground_dist = ao_sqrt (lat_dist * lat_dist + lon_dist * lon_dist); + range = ao_sqrt(ground_dist * ground_dist + ao_tel_sensor.height * ao_tel_sensor.height); + bearing = ao_atan2(lat_dist, lon_dist); + elevation = ao_atan2(ao_tel_sensor.height, ground_dist); +} + +static void +ao_terraui_descent(void) +{ + ao_terraui_compute(); + sprintf(ao_lcd_line, "\007 %4d \005 %3d %c", + bearing, elevation, + ao_terraui_state()); + ao_terraui_line(AO_LCD_ADDR(0,0)); + sprintf(ao_lcd_line, "H:%5d S:%5d%c", + ao_tel_sensor.height, ao_tel_sensor.speed >> 4, + ao_progress[ao_telem_progress]); + ao_terraui_line(AO_LCD_ADDR(1,0)); +} + +static void +ao_terraui_coord(int32_t c, char plus, char minus, char extra) __reentrant +{ + uint16_t d; + uint8_t m; + uint16_t f; + + if (c < 0) { + plus = minus; + c = -c; + } + d = c / 10000000; + c = c % 10000000; + c = c * 60; + m = c / 10000000; + c = c % 10000000; + f = (c + 500) / 1000; + sprintf(ao_lcd_line, "%c %3d\362 %2d.%04d\"%c", + plus, d, m, f, extra); +} + +static void +ao_terraui_remote(void) +{ + ao_terraui_coord(ao_tel_location.latitude, 'N', 'S', ao_terraui_state()); + ao_terraui_line(AO_LCD_ADDR(0,0)); + ao_terraui_coord(ao_tel_location.longitude, 'E', 'W', ao_progress[ao_telem_progress]); + ao_terraui_line(AO_LCD_ADDR(1,0)); +} + +static void +ao_terraui_local(void) __reentrant +{ + ao_terraui_coord(ao_gps_data.latitude, 'n', 's', + ao_terraui_local_gps()); + ao_terraui_line(AO_LCD_ADDR(0,0)); + ao_terraui_coord(ao_gps_data.longitude, 'e', 'w', ao_progress[ao_gps_progress]); + ao_terraui_line(AO_LCD_ADDR(1,0)); +} + +static void +ao_terraui_config(void) +{ + +} + +enum ao_page { + ao_page_info, + ao_page_pad, + ao_page_ascent, + ao_page_descent, + ao_page_remote, + ao_page_local, +}; static void ao_terraui(void) { + enum ao_page cur_page = ao_page_info; + + ao_lcd_start(); for (;;) { - char b = ao_button_get(); + char b; + switch (cur_page) { + case ao_page_info: + ao_terraui_info(); + break; + case ao_page_pad: + ao_terraui_pad(); + break; + case ao_page_ascent: + ao_terraui_ascent(); + break; + case ao_page_descent: + ao_terraui_descent(); + break; + case ao_page_remote: + ao_terraui_remote(); + break; + case ao_page_local: + ao_terraui_local(); + break; + } + + ao_alarm(AO_SEC_TO_TICKS(1)); + b = ao_button_get(); + ao_clear_alarm(); + switch (b) { + case 0: + break; case 1: - ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(200)); + if (cur_page == ao_page_local) + cur_page = ao_page_info; + else + cur_page++; + ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(50)); break; case 2: - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(200)); break; case 3: - ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(200)); + if (cur_page == ao_page_info) + cur_page = ao_page_local; + else + cur_page--; + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(50)); break; } } @@ -38,8 +467,68 @@ ao_terraui(void) __xdata static struct ao_task ao_terraui_task; +static void +ao_terramonitor(void) +{ + uint8_t monitor; + + monitor = ao_monitor_head; + for (monitor = ao_monitor_head;; + monitor = ao_monitor_ring_next(monitor)) + { + while (monitor == ao_monitor_head) + ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); + if (ao_monitoring != sizeof (union ao_telemetry_all)) + continue; + if (!(ao_monitor_ring[monitor].all.status & PKT_APPEND_STATUS_1_CRC_OK)) + continue; + ao_tel_rssi = (ao_monitor_ring[monitor].all.rssi >> 1) - 74; + switch (ao_monitor_ring[monitor].all.telemetry.generic.type) { + case AO_TELEMETRY_SENSOR_TELEMETRUM: + case AO_TELEMETRY_SENSOR_TELEMINI: + case AO_TELEMETRY_SENSOR_TELENANO: + ao_xmemcpy(&ao_tel_sensor, &ao_monitor_ring[monitor], sizeof (ao_tel_sensor)); + if (ao_tel_sensor.state < ao_flight_boost) { + ao_tel_max_speed = 0; + ao_tel_max_height = 0; + } else { + if (ao_tel_sensor.speed > ao_tel_max_speed) + ao_tel_max_speed = ao_tel_sensor.speed; + if (ao_tel_sensor.height > ao_tel_max_height) + ao_tel_max_height = ao_tel_sensor.height; + } + ao_telem_progress = (ao_telem_progress + 1) & 0x3; + break; + case AO_TELEMETRY_LOCATION: + ao_xmemcpy(&ao_tel_location, &ao_monitor_ring[monitor], sizeof (ao_tel_location)); + break; + case AO_TELEMETRY_CONFIGURATION: + ao_xmemcpy(&ao_tel_config, &ao_monitor_ring[monitor], sizeof (ao_tel_config)); + } + } +} + +__xdata static struct ao_task ao_terramonitor_task; + +static void +ao_terragps(void) +{ + uint16_t gps_tick = ao_gps_progress; + + for (;;) { + while (ao_gps_tick == gps_tick) + ao_sleep(&ao_gps_data); + gps_tick = ao_gps_tick; + ao_gps_progress = (ao_gps_progress + 1) & 3; + } +} + +__xdata static struct ao_task ao_terragps_task; + void ao_terraui_init(void) { ao_add_task(&ao_terraui_task, ao_terraui, "ui"); + ao_add_task(&ao_terramonitor_task, ao_terramonitor, "monitor"); + ao_add_task(&ao_terragps_task, ao_terragps, "gps"); } diff --git a/src/telelaunch-v0.1/.gitignore b/src/telelaunch-v0.1/.gitignore index d25d7ad9..e2cf954c 100644 --- a/src/telelaunch-v0.1/.gitignore +++ b/src/telelaunch-v0.1/.gitignore @@ -1,2 +1,2 @@ -telemetrum-v0.1-sky* +telelaunch* ao_product.h diff --git a/src/telemetrum-v0.1-sirf/Makefile b/src/telemetrum-v0.1-sirf/Makefile index 00cdc9c5..d138b5ef 100644 --- a/src/telemetrum-v0.1-sirf/Makefile +++ b/src/telemetrum-v0.1-sirf/Makefile @@ -4,6 +4,7 @@ TM_VER=0.1 TM_DEF=0_1 +TM_EXTRA=-sirf TM_INC = \ ao_25lc1024.h diff --git a/src/telemetrum-v0.1-sky/Makefile b/src/telemetrum-v0.1-sky/Makefile index e3c61db6..69cd3461 100644 --- a/src/telemetrum-v0.1-sky/Makefile +++ b/src/telemetrum-v0.1-sky/Makefile @@ -4,6 +4,7 @@ TM_VER=0.1 TM_DEF=0_1 +TM_EXTRA=-sky TM_INC = \ ao_25lc1024.h diff --git a/src/teleterra-v0.2/.gitignore b/src/teleterra-v0.2/.gitignore new file mode 100644 index 00000000..9daebc3e --- /dev/null +++ b/src/teleterra-v0.2/.gitignore @@ -0,0 +1,2 @@ +teleterra-v0.2* +ao_product.h diff --git a/src/teleterra-v0.2/.sdcdbrc b/src/teleterra-v0.2/.sdcdbrc new file mode 100644 index 00000000..fbe9a599 --- /dev/null +++ b/src/teleterra-v0.2/.sdcdbrc @@ -0,0 +1 @@ +--directory=../cc1111:../product:../core:../drivers:. diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile index 36f523a3..583805f6 100644 --- a/src/teleterra-v0.2/Makefile +++ b/src/teleterra-v0.2/Makefile @@ -26,6 +26,7 @@ CORE_SRC = \ ao_panic.c \ ao_report.c \ ao_rssi.c \ + ao_sqrt.c \ ao_state.c \ ao_stdio.c \ ao_storage.c \ diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 36f3c199..9c35b06a 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -45,6 +45,7 @@ #define HAS_ACCEL 0 #define HAS_IGNITE 0 #define HAS_MONITOR 1 + #define HAS_MONITOR_PUT 0 #define LEGACY_MONITOR 0 #define HAS_RSSI 0 #define HAS_AES 0 @@ -54,11 +55,18 @@ #define M25_CS_MASK 0x04 #define M25_MAX_CHIPS 1 - #define HAS_P2_ISR 1 - #define HAS_BUTTON_P0 1 - #define HAS_BUTTON_P2 1 + #define HAS_BUTTON 1 + #define BUTTON_1_REG 0 + #define BUTTON_1_MASK (1 << 4) /* P0_4 */ + + #define BUTTON_2_REG 2 + #define BUTTON_2_MASK (1 << 3) /* P2_3 */ + + #define BUTTON_3_REG 2 + #define BUTTON_3_MASK (1 << 4) /* P2_4 */ #define BATTERY_PIN 5 + #endif #if DBG_ON_P1 -- cgit v1.2.3 From c7e14a2750d437e8b77d68a944a0711e7a0c882b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 27 Oct 2011 00:35:35 -0700 Subject: altos: Fix distance/bearing computations. Deal with large values Lots of little math errors dealing with large distances; easily tested as the GPS currently reports lat 24 lon 121, which is a long ways from Portland. Now reports distances in km when large, otherwise in m. Signed-off-by: Keith Packard --- src/product/ao_terraui.c | 79 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 65 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c index cfbfb1fb..22bab5d6 100644 --- a/src/product/ao_terraui.c +++ b/src/product/ao_terraui.c @@ -145,20 +145,26 @@ static int16_t mag(int32_t d) return d; } -static uint32_t +static int32_t dist(int32_t d) { - int32_t m; + __pdata uint32_t m; + uint8_t neg = 0; - if (d < 0) + if (d < 0) { d = -d; + neg = 1; + } - m = 1000000; + m = 10000000; while (d >= (2147483647 / 111198)) { d /= 10; m /= 10; } - return (d * 111198) / m; + d = (d * 111198) / m; + if (neg) + d = -d; + return d; } static __code uint8_t cos_table[] = { @@ -295,22 +301,25 @@ int16_t ao_atan2(int32_t dy, int32_t dx) __reentrant } if (dy > dx) { - int t; + int32_t t; t = dy; dy = dx; dx = t; a = a + m * 90; m = -m; } - r = ((dy << 8) + (dx >> 1)) / dx; + dy = dy << 8; + dy = (dy + (dx >> 1)) / dx; + r = dy; for (t = 0; t < 44; t++) if (tan_table[t] >= r) break; return t * m + a; } -static __pdata uint32_t lon_dist, lat_dist; +static __pdata int32_t lon_dist, lat_dist; static __pdata uint32_t ground_dist, range; +static __pdata uint8_t dist_in_km; static __pdata int16_t bearing, elevation; static void @@ -320,22 +329,45 @@ ao_terraui_lat_dist(void) } static void -ao_terraui_lon_dist(void) +ao_terraui_lon_dist(void) __reentrant { uint8_t c = cos_table[ao_gps_data.latitude >> 24]; - lon_dist = dist(ao_tel_location.longitude - ao_gps_data.longitude); - if (c) - lon_dist = ((uint32_t) lon_dist * c) >> 8; + lon_dist = ao_tel_location.longitude; + + /* check if it's shorter to go the other way around */ + if ((int16_t) (lon_dist >> 24) < (int16_t) (ao_gps_data.longitude >> 24) - (int16_t) (1800000000 >> 24)) + lon_dist += 3600000000ul; + lon_dist = dist(lon_dist - ao_gps_data.longitude); + if (c) { + if (lon_dist & 0x7f800000) + lon_dist = (lon_dist >> 8) * c; + else + lon_dist = (lon_dist * (int16_t) c) >> 8; + } } +static int32_t sqr(int32_t x) { return x * x; } + static void ao_terraui_compute(void) { + uint16_t h = ao_tel_sensor.height; + ao_terraui_lat_dist(); ao_terraui_lon_dist(); - ground_dist = ao_sqrt (lat_dist * lat_dist + lon_dist * lon_dist); + if (lat_dist > 32767 || lon_dist > 32767) { + dist_in_km = 1; + ground_dist = sqr(lat_dist/1000) + sqr(lon_dist/1000); + h = h/1000; + } else { + dist_in_km = 0; + ground_dist = sqr(lat_dist) + sqr(lon_dist); + } + ground_dist = ao_sqrt (ground_dist); range = ao_sqrt(ground_dist * ground_dist + ao_tel_sensor.height * ao_tel_sensor.height); - bearing = ao_atan2(lat_dist, lon_dist); + bearing = ao_atan2(lon_dist, lat_dist); + if (bearing < 0) + bearing += 360; elevation = ao_atan2(ao_tel_sensor.height, ground_dist); } @@ -353,6 +385,21 @@ ao_terraui_descent(void) ao_terraui_line(AO_LCD_ADDR(1,0)); } +static void +ao_terraui_recover(void) +{ + ao_terraui_compute(); + sprintf(ao_lcd_line, "\007 %4d \005 %3d %c", + bearing, elevation, + ao_terraui_state()); + ao_terraui_line(AO_LCD_ADDR(0,0)); + sprintf(ao_lcd_line, "R%5ld%cRSSI%4d%c", + ground_dist, dist_in_km ? 'k' : ' ', + ao_tel_rssi, + ao_progress[ao_telem_progress]); + ao_terraui_line(AO_LCD_ADDR(1,0)); +} + static void ao_terraui_coord(int32_t c, char plus, char minus, char extra) __reentrant { @@ -404,6 +451,7 @@ enum ao_page { ao_page_pad, ao_page_ascent, ao_page_descent, + ao_page_recover, ao_page_remote, ao_page_local, }; @@ -429,6 +477,9 @@ ao_terraui(void) case ao_page_descent: ao_terraui_descent(); break; + case ao_page_recover: + ao_terraui_recover(); + break; case ao_page_remote: ao_terraui_remote(); break; -- cgit v1.2.3 From a7b285ec0945830b8b31877115157ddd12d6a9fb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 27 Oct 2011 00:57:45 -0700 Subject: altos: Add i2c driver for avr chip Signed-off-by: Keith Packard --- src/avr/ao_i2c_usart.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 src/avr/ao_i2c_usart.c (limited to 'src') diff --git a/src/avr/ao_i2c_usart.c b/src/avr/ao_i2c_usart.c new file mode 100644 index 00000000..60e35f8c --- /dev/null +++ b/src/avr/ao_i2c_usart.c @@ -0,0 +1,101 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +/* + * Atmega32u4 TWI master mode (I2C) + */ + +__xdata uint8_t ao_i2c_mutex; + +/* Send bytes over I2C. + * + * This just polls; the I2C is set to go as fast as possible, + * so using interrupts would take way too long + */ +void +ao_i2c_send(void __xdata *block, uint16_t len) __reentrant +{ + uint8_t *d = block; + + ao_mutex_get(&ao_i2c_mutex); + while (len--) { + while (!(UCSR1A & (1 << UDRE1))); + UDR1 = *d++; + while (!(UCSR1A & (1 << RXC1))); + (void) UDR1; + } + ao_mutex_put(&ao_i2c_mutex); +} + +/* Receive bytes over I2C. + * + * This sets up tow DMA engines, one reading the data and another + * writing constant values to the I2C transmitter as that is what + * clocks the data coming in. + */ +void +ao_i2c_recv(void __xdata *block, uint16_t len) __reentrant +{ + uint8_t *d = block; + + ao_mutex_get(&ao_i2c_mutex); + while (len--) { + while (!(UCSR1A & (1 << UDRE1))); + UDR1 = 0; + while (!(UCSR1A & (1 << RXC1))); + *d++ = UDR1; + } + ao_mutex_put(&ao_i2c_mutex); +} + +#define XCK1_DDR DDRD +#define XCK1_PORT PORTD +#define XCK1 PORTD5 +#define XMS1_DDR DDRE +#define XMS1_PORT PORTE +#define XMS1 PORTE6 + +void +ao_i2c_init(void) +{ + /* Ensure the TWI is powered */ + + /* + * Set pin directions + */ + XCK1_DDR |= (1 << XCK1); + + /* Clear chip select (which is negated) */ + XMS1_PORT |= (1 < XMS1); + XMS1_DDR |= (1 << XMS1); + + /* Set baud register to zero (required before turning transmitter on) */ + UBRR1 = 0; + + UCSR1C = ((0x3 << UMSEL10) | /* Master I2C mode */ + (0 << UCSZ10) | /* I2C mode 0 */ + (0 << UCPOL1)); /* I2C mode 0 */ + + /* Enable transmitter and receiver */ + UCSR1B = ((1 << RXEN1) | + (1 << TXEN1)); + + /* It says that 0 is a legal value; we'll see... */ + UBRR1 = 0; +} -- cgit v1.2.3 From df08b2f6de464f4546c1809b931eb4910d88b558 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 27 Oct 2011 01:01:11 -0700 Subject: altos: A bunch of missing .gitignore files (mostly) Signed-off-by: Keith Packard --- ao-tools/ao-telem/.gitignore | 1 + src/.gitignore | 1 + src/avr-demo/.gitignore | 3 + src/telepyro-v0.1/.gitignore | 2 + src/telescience-v0.1/.gitignore | 2 + src/teleterra-v0.1/.gitignore | 2 + src/teleterra-v0.1/ao_pins.h | 217 ++++++++++++++++++++++++++++++++++++++++ src/test/run-full | 31 ++++++ src/test/run-noisy | 23 +++++ 9 files changed, 282 insertions(+) create mode 100644 ao-tools/ao-telem/.gitignore create mode 100644 src/.gitignore create mode 100644 src/avr-demo/.gitignore create mode 100644 src/telepyro-v0.1/.gitignore create mode 100644 src/telescience-v0.1/.gitignore create mode 100644 src/teleterra-v0.1/.gitignore create mode 100644 src/teleterra-v0.1/ao_pins.h create mode 100755 src/test/run-full create mode 100755 src/test/run-noisy (limited to 'src') diff --git a/ao-tools/ao-telem/.gitignore b/ao-tools/ao-telem/.gitignore new file mode 100644 index 00000000..5ab6f649 --- /dev/null +++ b/ao-tools/ao-telem/.gitignore @@ -0,0 +1 @@ +ao-telem diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 00000000..7a5d6ef5 --- /dev/null +++ b/src/.gitignore @@ -0,0 +1 @@ +altitude.h diff --git a/src/avr-demo/.gitignore b/src/avr-demo/.gitignore new file mode 100644 index 00000000..e7d16343 --- /dev/null +++ b/src/avr-demo/.gitignore @@ -0,0 +1,3 @@ +avr-demo +avr-demo.hex +ao_product.h diff --git a/src/telepyro-v0.1/.gitignore b/src/telepyro-v0.1/.gitignore new file mode 100644 index 00000000..5166481c --- /dev/null +++ b/src/telepyro-v0.1/.gitignore @@ -0,0 +1,2 @@ +telepyro-v0.1* +ao_product.h diff --git a/src/telescience-v0.1/.gitignore b/src/telescience-v0.1/.gitignore new file mode 100644 index 00000000..dfccadf8 --- /dev/null +++ b/src/telescience-v0.1/.gitignore @@ -0,0 +1,2 @@ +telescience-v0.1* +ao_product.h diff --git a/src/teleterra-v0.1/.gitignore b/src/teleterra-v0.1/.gitignore new file mode 100644 index 00000000..447007ce --- /dev/null +++ b/src/teleterra-v0.1/.gitignore @@ -0,0 +1,2 @@ +teleterra-v0.1* +ao_product.h diff --git a/src/teleterra-v0.1/ao_pins.h b/src/teleterra-v0.1/ao_pins.h new file mode 100644 index 00000000..33de055e --- /dev/null +++ b/src/teleterra-v0.1/ao_pins.h @@ -0,0 +1,217 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#ifdef TELETERRA_V_0_1 + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_GPS 0 + #define HAS_SERIAL_1 0 + #define HAS_ADC 0 + #define USE_SERIAL_STDIN 0 + #define HAS_EEPROM 1 + #define HAS_LOG 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + + #define HAS_COMPANION 1 + #define COMPANION_CS_ON_P1 1 + #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ + #define COMPANION_CS P1_2 + + #define AO_LED_RED 1 + #define LEDS_AVAILABLE (AO_LED_RED) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL_REF 0 + #define HAS_ACCEL 0 + #define HAS_IGNITE 0 + #define HAS_MONITOR 1 + #define HAS_RSSI 0 + #define HAS_AES 1 + + #define SPI_CS_ON_P1 0 + #define SPI_CS_ON_P0 1 + #define M25_CS_MASK 0xf + #define M25_MAX_CHIPS 4 +#endif + +#if DBG_ON_P1 + + #define DBG_CLOCK (1 << 4) /* mi0 */ + #define DBG_DATA (1 << 5) /* mo0 */ + #define DBG_RESET_N (1 << 3) /* c0 */ + + #define DBG_CLOCK_PIN (P1_4) + #define DBG_DATA_PIN (P1_5) + #define DBG_RESET_N_PIN (P1_3) + + #define DBG_PORT_NUM 1 + #define DBG_PORT P1 + #define DBG_PORT_SEL P1SEL + #define DBG_PORT_INP P1INP + #define DBG_PORT_DIR P1DIR + +#endif /* DBG_ON_P1 */ + +#if DBG_ON_P0 + + #define DBG_CLOCK (1 << 3) + #define DBG_DATA (1 << 4) + #define DBG_RESET_N (1 << 5) + + #define DBG_CLOCK_PIN (P0_3) + #define DBG_DATA_PIN (P0_4) + #define DBG_RESET_N_PIN (P0_5) + + #define DBG_PORT_NUM 0 + #define DBG_PORT P0 + #define DBG_PORT_SEL P0SEL + #define DBG_PORT_INP P0INP + #define DBG_PORT_DIR P0DIR + +#endif /* DBG_ON_P0 */ + +#if COMPANION_CS_ON_P1 + #define COMPANION_CS_PORT P1 + #define COMPANION_CS_SEL P1SEL + #define COMPANION_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P1 + #define SPI_CS_PORT P1 + #define SPI_CS_SEL P1SEL + #define SPI_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P0 + #define SPI_CS_PORT P0 + #define SPI_CS_SEL P0SEL + #define SPI_CS_DIR P0DIR +#endif + +#ifndef IGNITE_ON_P2 +#error Please define IGNITE_ON_P2 +#endif + +#ifndef IGNITE_ON_P0 +#error Please define IGNITE_ON_P0 +#endif + +#ifndef HAS_SERIAL_1 +#error Please define HAS_SERIAL_1 +#endif + +#ifndef USE_SERIAL_STDIN +#error Please define USE_SERIAL_STDIN +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#ifndef HAS_EEPROM +#error Please define HAS_EEPROM +#endif + +#ifndef HAS_LOG +#error Please define HAS_LOG +#endif + +#if HAS_EEPROM +#ifndef USE_INTERNAL_FLASH +#error Please define USE_INTERNAL_FLASH +#endif +#endif + +#ifndef HAS_DBG +#error Please define HAS_DBG +#endif + +#ifndef HAS_IGNITE +#error Please define HAS_IGNITE +#endif + +#if HAS_IGNITE +#define HAS_IGNITE_REPORT 1 +#endif + +#ifndef PACKET_HAS_MASTER +#error Please define PACKET_HAS_MASTER +#endif + +#ifndef PACKET_HAS_SLAVE +#error Please define PACKET_HAS_SLAVE +#endif + +#ifndef HAS_MONITOR +#error Please define HAS_MONITOR +#endif + +#if HAS_MONITOR +#ifndef HAS_RSSI +#error Please define HAS_RSSI +#endif +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#if HAS_ADC + +#if HAS_ACCEL +#ifndef HAS_ACCEL_REF +#error Please define HAS_ACCEL_REF +#endif +#else +#define HAS_ACCEL_REF 0 +#endif + +#endif /* HAS_ADC */ + +#if IGNITE_ON_P2 +#define AO_IGNITER_DROGUE P2_3 +#define AO_IGNITER_MAIN P2_4 +#define AO_IGNITER_DIR P2DIR +#define AO_IGNITER_DROGUE_BIT (1 << 3) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +#if IGNITE_ON_P0 +#define AO_IGNITER_DROGUE P0_5 +#define AO_IGNITER_MAIN P0_4 +#define AO_IGNITER_DIR P0DIR +#define AO_IGNITER_DROGUE_BIT (1 << 5) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +/* test these values with real igniters */ +#define AO_IGNITER_OPEN 1000 +#define AO_IGNITER_CLOSED 7000 +#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) +#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) + +#endif /* _AO_PINS_H_ */ diff --git a/src/test/run-full b/src/test/run-full new file mode 100755 index 00000000..50ab7b5b --- /dev/null +++ b/src/test/run-full @@ -0,0 +1,31 @@ +#!/bin/sh + +for i in "$@"; do +./ao_flight_test "$i" > run-out.full + +#./ao_flight_test_accel "$i" > run-out.accel +#"run-out.accel" using 1:9 with lines lt 4 axes x1y1 title "accel height",\ +#"run-out.accel" using 1:11 with lines lt 4 axes x1y2 title "accel speed",\ +#"run-out.accel" using 1:13 with lines lt 4 axes x1y2 title "accel accel",\ +#"run-out.accel" using 1:15 with lines lt 4 axes x1y1 title "accel drogue",\ +#"run-out.accel" using 1:17 with lines lt 4 axes x1y1 title "accel main",\ +# + +gnuplot << EOF +set ylabel "altitude (m)" +set y2label "velocity (m/s), acceleration(m/s²)" +set xlabel "time (s)" +set xtics border out nomirror +set ytics border out nomirror +set y2tics border out nomirror +set title "$i" +plot "run-out.full" using 1:3 with lines lw 2 lt 1 axes x1y1 title "raw height",\ +"run-out.full" using 1:5 with lines lw 2 lt 2 axes x1y2 title "raw accel",\ +"run-out.full" using 1:9 with lines lt 3 axes x1y1 title "full height",\ +"run-out.full" using 1:11 with lines lt 4 axes x1y2 title "full speed",\ +"run-out.full" using 1:13 with lines lt 5 axes x1y2 title "full accel",\ +"run-out.full" using 1:17 with lines lt 6 axes x1y1 title "full drogue",\ +"run-out.full" using 1:19 with lines lt 7 axes x1y1 title "full main" +pause mouse close +EOF +done \ No newline at end of file diff --git a/src/test/run-noisy b/src/test/run-noisy new file mode 100755 index 00000000..2e3cddc7 --- /dev/null +++ b/src/test/run-noisy @@ -0,0 +1,23 @@ +#!/bin/sh + +for i in "$@"; do +./ao_flight_test_noisy_accel "$i" > run-out.noisy + +gnuplot << EOF +set ylabel "altitude (m)" +set y2label "velocity (m/s), acceleration(m/s²)" +set xlabel "time (s)" +set xtics border out nomirror +set ytics border out nomirror +set y2tics border out nomirror +set title "$i" +plot "run-out.noisy" using 1:3 with lines lw 2 lt 1 axes x1y1 title "raw height",\ +"run-out.noisy" using 1:5 with lines lw 2 lt 2 axes x1y2 title "raw accel",\ +"run-out.noisy" using 1:9 with lines lt 3 axes x1y1 title "noisy height",\ +"run-out.noisy" using 1:11 with lines lt 4 axes x1y2 title "noisy speed",\ +"run-out.noisy" using 1:13 with lines lt 5 axes x1y2 title "noisy accel",\ +"run-out.noisy" using 1:17 with lines lt 6 axes x1y1 title "noisy drogue",\ +"run-out.noisy" using 1:19 with lines lt 7 axes x1y1 title "noisy main" +pause mouse close +EOF +done \ No newline at end of file -- cgit v1.2.3 From 8266d8d39c0103e68ef3e476b9639574d9a48771 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 11 Nov 2011 16:54:18 -0800 Subject: altos: Shrink code size of Skytraq NMEA parser Just mess around with the code to make it smaller. These patches save 173 bytes. Signed-off-by: Keith Packard --- src/drivers/ao_gps_skytraq.c | 62 +++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index 6e65d651..d88ded8b 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -25,17 +25,17 @@ static __code char ao_gps_header[] = "GP"; __xdata uint8_t ao_gps_mutex; static __data char ao_gps_char; -static __pdata uint8_t ao_gps_cksum; -static __pdata uint8_t ao_gps_error; +static __data uint8_t ao_gps_cksum; +static __data uint8_t ao_gps_error; __pdata uint16_t ao_gps_tick; __xdata struct ao_telemetry_location ao_gps_data; __xdata struct ao_telemetry_satellite ao_gps_tracking_data; static __pdata uint16_t ao_gps_next_tick; -static __xdata struct ao_telemetry_location ao_gps_next; +static __pdata struct ao_telemetry_location ao_gps_next; static __pdata uint8_t ao_gps_date_flags; -static __xdata struct ao_telemetry_satellite ao_gps_tracking_next; +static __pdata struct ao_telemetry_satellite ao_gps_tracking_next; #define STQ_S 0xa0, 0xa1 #define STQ_E 0x0d, 0x0a @@ -68,34 +68,41 @@ static __code uint8_t ao_gps_config[] = { static void ao_gps_lexchar(void) { + char c; if (ao_gps_error) - ao_gps_char = '\n'; + c = '\n'; else - ao_gps_char = ao_serial_getchar(); - ao_gps_cksum ^= ao_gps_char; + c = ao_serial_getchar(); + ao_gps_cksum ^= c; + ao_gps_char = c; } void ao_gps_skip_field(void) { - while (ao_gps_char != ',' && ao_gps_char != '*' && ao_gps_char != '\n') + for (;;) { + char c = ao_gps_char; + if (c == ',' || c == '*' || c == '\n') + break; ao_gps_lexchar(); + } } void ao_gps_skip_sep(void) { - if (ao_gps_char == ',' || ao_gps_char == '.' || ao_gps_char == '*') + char c = ao_gps_char; + if (c == ',' || c == '.' || c == '*') ao_gps_lexchar(); } -__pdata static uint8_t ao_gps_num_width; +__data static uint8_t ao_gps_num_width; static int16_t ao_gps_decimal(uint8_t max_width) { int16_t v; - __pdata uint8_t neg = 0; + uint8_t neg = 0; ao_gps_skip_sep(); if (ao_gps_char == '-') { @@ -105,9 +112,10 @@ ao_gps_decimal(uint8_t max_width) v = 0; ao_gps_num_width = 0; while (ao_gps_num_width < max_width) { - if (ao_gps_char < '0' || '9' < ao_gps_char) + uint8_t c = ao_gps_char; + if (c < (uint8_t) '0' || (uint8_t) '9' < c) break; - v = v * (int16_t) 10 + ao_gps_char - '0'; + v = v * 10 + (uint8_t) (c - (uint8_t) '0'); ao_gps_num_width++; ao_gps_lexchar(); } @@ -117,23 +125,25 @@ ao_gps_decimal(uint8_t max_width) } static uint8_t -ao_gps_hex(uint8_t max_width) +ao_gps_hex(void) { - uint8_t v, d; + uint8_t v; ao_gps_skip_sep(); v = 0; ao_gps_num_width = 0; - while (ao_gps_num_width < max_width) { - if ('0' <= ao_gps_char && ao_gps_char <= '9') - d = ao_gps_char - '0'; - else if ('A' <= ao_gps_char && ao_gps_char <= 'F') - d = ao_gps_char - 'A' + 10; - else if ('a' <= ao_gps_char && ao_gps_char <= 'f') - d = ao_gps_char - 'a' + 10; + while (ao_gps_num_width < 2) { + uint8_t c = ao_gps_char; + uint8_t d; + if ((uint8_t) '0' <= c && c <= (uint8_t) '9') + d = - '0'; + else if ((uint8_t) 'A' <= c && c <= (uint8_t) 'F') + d = - 'A' + 10; + else if ((uint8_t) 'a' <= c && c <= (uint8_t) 'f') + d = - 'a' + 10; else break; - v = (v << 4) | d; + v = (v << 4) | (c + d); ao_gps_num_width++; ao_gps_lexchar(); } @@ -258,7 +268,7 @@ ao_nmea_gga() } if (ao_gps_char == '*') { uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex(2)) + if (cksum != ao_gps_hex()) ao_gps_error = 1; } else ao_gps_error = 1; @@ -318,7 +328,7 @@ ao_nmea_gsv(void) } if (ao_gps_char == '*') { uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex(2)) + if (cksum != ao_gps_hex()) ao_gps_error = 1; } else @@ -378,7 +388,7 @@ ao_nmea_rmc(void) } if (ao_gps_char == '*') { uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex(2)) + if (cksum != ao_gps_hex()) ao_gps_error = 1; } else ao_gps_error = 1; -- cgit v1.2.3 From d3e8275572550b700563b3bde73cd7a43b608f17 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 11 Nov 2011 17:11:39 -0800 Subject: altos: shrink Skytraq NMEA parsing more This cuts another 78 bytes Signed-off-by: Keith Packard --- src/drivers/ao_gps_skytraq.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index d88ded8b..dd8d70ab 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -153,13 +153,15 @@ ao_gps_hex(void) static int32_t ao_gps_parse_pos(uint8_t deg_width) __reentrant { - int32_t d; - int32_t m; - int32_t f; + static __pdata uint16_t d; + static __pdata uint8_t m; + static __pdata uint16_t f; + char c; d = ao_gps_decimal(deg_width); m = ao_gps_decimal(2); - if (ao_gps_char == '.') { + c = ao_gps_char; + if (c == '.') { f = ao_gps_decimal(4); while (ao_gps_num_width < 4) { f *= 10; @@ -167,17 +169,14 @@ ao_gps_parse_pos(uint8_t deg_width) __reentrant } } else { f = 0; - if (ao_gps_char != ',') + if (c != ',') ao_gps_error = 1; } - d = d * 10000000l; - m = m * 10000l + f; - d = d + m * 50 / 3; - return d; + return d * 10000000l + (m * 10000l + f) * 50 / 3; } static uint8_t -ao_gps_parse_flag(char no_c, char yes_c) __reentrant +ao_gps_parse_flag(char no_c, char yes_c) { uint8_t ret = 0; ao_gps_skip_sep(); -- cgit v1.2.3 From 713bd503902526c17a7657c18be947ef8fa6a47a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 11 Nov 2011 17:18:08 -0800 Subject: altos: Shrink Skytraq NMEA parsing - common nmea_finish code This shares the checksum testing across all three lines, saving another 103 bytes. Signed-off-by: Keith Packard --- src/drivers/ao_gps_skytraq.c | 59 ++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index dd8d70ab..1d457a1f 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -191,7 +191,27 @@ ao_gps_parse_flag(char no_c, char yes_c) } static void -ao_nmea_gga() +ao_nmea_finish(void) +{ + char c; + /* Skip remaining fields */ + for (;;) { + c = ao_gps_char; + if (c == '*' || c == '\n' || c == '\r') + break; + ao_gps_lexchar(); + ao_gps_skip_field(); + } + if (c == '*') { + uint8_t cksum = ao_gps_cksum ^ '*'; + if (cksum != ao_gps_hex()) + ao_gps_error = 1; + } else + ao_gps_error = 1; +} + +static void +ao_nmea_gga(void) { uint8_t i; @@ -260,17 +280,8 @@ ao_nmea_gga() ao_gps_next.altitude = ao_gps_decimal(0xff); ao_gps_skip_field(); /* skip any fractional portion */ - /* Skip remaining fields */ - while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { - ao_gps_lexchar(); - ao_gps_skip_field(); - } - if (ao_gps_char == '*') { - uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex()) - ao_gps_error = 1; - } else - ao_gps_error = 1; + ao_nmea_finish(); + if (!ao_gps_error) { ao_mutex_get(&ao_gps_mutex); ao_gps_tick = ao_gps_next_tick; @@ -325,13 +336,9 @@ ao_nmea_gsv(void) ao_gps_tracking_next.channels = i + 1; } } - if (ao_gps_char == '*') { - uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex()) - ao_gps_error = 1; - } - else - ao_gps_error = 1; + + ao_nmea_finish(); + if (ao_gps_error) ao_gps_tracking_next.channels = 0; else if (done) { @@ -380,17 +387,9 @@ ao_nmea_rmc(void) a = ao_gps_decimal(2); c = ao_gps_decimal(2); i = ao_gps_decimal(2); - /* Skip remaining fields */ - while (ao_gps_char != '*' && ao_gps_char != '\n' && ao_gps_char != '\r') { - ao_gps_lexchar(); - ao_gps_skip_field(); - } - if (ao_gps_char == '*') { - uint8_t cksum = ao_gps_cksum ^ '*'; - if (cksum != ao_gps_hex()) - ao_gps_error = 1; - } else - ao_gps_error = 1; + + ao_nmea_finish(); + if (!ao_gps_error) { ao_gps_next.year = i; ao_gps_next.month = c; -- cgit v1.2.3 From b132eefc5f63412bb4a98a4bb72b9055e40d5d42 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 11 Nov 2011 22:30:17 -0800 Subject: altos: Make ao_xmem funcs require __xdata void * instead of casting Having an explicit cast in the ao_xmem wrapper macros caused the compiler to generate garbage values for pdata addresses, making the upper byte 0x00 instead of the required 0xf0. Removing the casts from the ao_xmem macros exposed this problem, so a new PDATA_TO_XDATA macros was added, along with a CODE_TO_XDATA macro which serve to cast pointers, with suitable address modifications, so that things work again. Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 18 ++++++++++++------ src/cc1111/ao_string.c | 23 +++++++++++++++-------- src/core/ao.h | 6 ++++++ src/core/ao_config.c | 2 +- src/core/ao_host.h | 4 ++++ src/core/ao_telemetry.c | 8 ++++---- src/drivers/ao_gps_skytraq.c | 5 ++--- 7 files changed, 44 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index f0f0daae..001165fa 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -27,6 +27,12 @@ /* Convert a __data pointer into an __xdata pointer */ #define DATA_TO_XDATA(a) ((void __xdata *) ((uint8_t) (a) | 0xff00)) +/* Code and xdata use the same address space */ +#define CODE_TO_XDATA(a) ((__xdata void *) ((uint16_t) (a))) + +/* Pdata lives at the start of xdata */ +#define PDATA_TO_XDATA(a) ((void __xdata *) ((uint8_t) (a) | 0xf000)) + /* Stack runs from above the allocated __data space to 0xfe, which avoids * writing to 0xff as that triggers the stack overflow indicator */ @@ -228,18 +234,18 @@ ao_button_get(void) __critical; /* ao_string.c */ void -_ao_xmemcpy(__xdata uint8_t *dst, __xdata uint8_t *src, uint8_t count); +_ao_xmemcpy(__xdata void *dst, __xdata void *src, uint8_t count); -#define ao_xmemcpy(d,s,c) _ao_xmemcpy((__xdata uint8_t *) (d), (__xdata uint8_t *) (s), (c)) +#define ao_xmemcpy(d,s,c) _ao_xmemcpy(d,s,c) void -_ao_xmemset(__xdata uint8_t *dst, uint8_t value, uint8_t count); +_ao_xmemset(__xdata void *dst, uint8_t value, uint8_t count); -#define ao_xmemset(d,v,c) _ao_xmemset((__xdata uint8_t *) (d), (v), (c)) +#define ao_xmemset(d,v,c) _ao_xmemset(d,v,c) int8_t -_ao_xmemcmp(__xdata uint8_t *a, __xdata uint8_t *b, uint8_t count); +_ao_xmemcmp(__xdata void *a, __xdata void *b, uint8_t count); -#define ao_xmemcmp(d,s,c) _ao_xmemcmp((__xdata uint8_t *) (d), (__xdata uint8_t *) (s), (c)) +#define ao_xmemcmp(d,s,c) _ao_xmemcmp((d), (s), (c)) #endif /* _AO_ARCH_H_ */ diff --git a/src/cc1111/ao_string.c b/src/cc1111/ao_string.c index daa5c14b..3a07e47e 100644 --- a/src/cc1111/ao_string.c +++ b/src/cc1111/ao_string.c @@ -18,26 +18,33 @@ #include "ao.h" void -_ao_xmemcpy(__xdata uint8_t *dst, __xdata uint8_t *src, uint8_t count) +_ao_xmemcpy(__xdata void *dst, __xdata void *src, uint8_t count) { - while (count--) - *dst++ = *src++; + while (count--) { + *(__xdata uint8_t *) dst = *(__xdata uint8_t *) src; + dst = (__xdata uint8_t *) dst + 1; + src = (__xdata uint8_t *) src + 1; + } } void -_ao_xmemset(__xdata uint8_t *dst, uint8_t v, uint8_t count) +_ao_xmemset(__xdata void *dst, uint8_t v, uint8_t count) { - while (count--) - *dst++ = v; + while (count--) { + *(__xdata uint8_t *) dst = v; + dst = (__xdata uint8_t *) dst + 1; + } } int8_t -_ao_xmemcmp(__xdata uint8_t *a, __xdata uint8_t *b, uint8_t count) +_ao_xmemcmp(__xdata void *a, __xdata void *b, uint8_t count) { while (count--) { - int8_t d = *a++ - *b++; + int8_t d = *(__xdata int8_t *) a - *(__xdata int8_t *) b; if (d) return d; + a = (__xdata int8_t *) a + 1; + b = (__xdata int8_t *) b + 1; } return 0; } diff --git a/src/core/ao.h b/src/core/ao.h index 9b8d3270..cbe2f8dc 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -32,6 +32,12 @@ #ifndef DATA_TO_XDATA #define DATA_TO_XDATA(a) (a) #endif +#ifndef PDATA_TO_XDATA +#define PDATA_TO_XDATA(a) (a) +#endif +#ifndef CODE_TO_XDATA +#define CODE_TO_XDATA(a) (a) +#endif /* An AltOS task */ struct ao_task { diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 08cc79b1..f0a576ee 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -79,7 +79,7 @@ _ao_config_get(void) ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; ao_xmemset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); - ao_xmemcpy(&ao_config.callsign, AO_CONFIG_DEFAULT_CALLSIGN, + ao_xmemcpy(&ao_config.callsign, CODE_TO_XDATA(AO_CONFIG_DEFAULT_CALLSIGN), sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); ao_config_dirty = 1; } diff --git a/src/core/ao_host.h b/src/core/ao_host.h index f2b2f0c9..6eb752c9 100644 --- a/src/core/ao_host.h +++ b/src/core/ao_host.h @@ -46,6 +46,10 @@ struct ao_adc { #define __code #define __reentrant +#define DATA_TO_XDATA(a) (a) +#define PDATA_TO_XDATA(a) (a) +#define CODE_TO_XDATA(a) (a) + enum ao_flight_state { ao_flight_startup = 0, ao_flight_idle = 1, diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index e66598d1..c68f1589 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -132,11 +132,11 @@ ao_send_configuration(void) telemetry.configuration.main_deploy = ao_config.main_deploy; telemetry.configuration.flight_log_max = ao_config.flight_log_max >> 10; ao_xmemcpy (telemetry.configuration.callsign, - ao_config.callsign, - AO_MAX_CALLSIGN); + ao_config.callsign, + AO_MAX_CALLSIGN); ao_xmemcpy (telemetry.configuration.version, - ao_version, - AO_MAX_VERSION); + CODE_TO_XDATA(ao_version), + AO_MAX_VERSION); ao_radio_send(&telemetry, sizeof (telemetry)); ao_telemetry_config_cur = ao_telemetry_config_max; } diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index 1d457a1f..62909606 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -285,7 +285,7 @@ ao_nmea_gga(void) if (!ao_gps_error) { ao_mutex_get(&ao_gps_mutex); ao_gps_tick = ao_gps_next_tick; - ao_xmemcpy(&ao_gps_data, &ao_gps_next, sizeof (ao_gps_data)); + ao_xmemcpy(&ao_gps_data, PDATA_TO_XDATA(&ao_gps_next), sizeof (ao_gps_data)); ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_data); } @@ -343,8 +343,7 @@ ao_nmea_gsv(void) ao_gps_tracking_next.channels = 0; else if (done) { ao_mutex_get(&ao_gps_mutex); - ao_xmemcpy(&ao_gps_tracking_data, &ao_gps_tracking_next, - sizeof(ao_gps_tracking_data)); + ao_xmemcpy(&ao_gps_tracking_data, PDATA_TO_XDATA(&ao_gps_tracking_next), sizeof(ao_gps_tracking_data)); ao_mutex_put(&ao_gps_mutex); ao_wakeup(&ao_gps_tracking_data); } -- cgit v1.2.3 From ad41b5820c2e252627959e4627473f07784be23e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:29:38 -0800 Subject: altos: Build TeleTerra v0.2 by default Signed-off-by: Keith Packard --- src/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 5da7c855..61b1a835 100644 --- a/src/Makefile +++ b/src/Makefile @@ -19,7 +19,8 @@ SUBDIRS=\ telebt-v0.0 telebt-v0.1 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ telelaunch-v0.1 \ - tidongle test telescience-v0.1 telepyro-v0.1 + tidongle test telescience-v0.1 telepyro-v0.1 \ + teleterra-v0.2 all: all-local all-recursive -- cgit v1.2.3 From 4de8bf6da4d725bb0514d032b0708c5cf420e8fa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:30:56 -0800 Subject: altos: debounce buttons Provide API to clear out any button events that happen during startup, and then discard button events 'too close' together. Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 3 +++ src/cc1111/ao_button.c | 19 +++++++++++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 001165fa..eb8ce9be 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -231,6 +231,9 @@ ao_button_init(void); char ao_button_get(void) __critical; +void +ao_button_clear(void) __critical; + /* ao_string.c */ void diff --git a/src/cc1111/ao_button.c b/src/cc1111/ao_button.c index 77a8dde8..69f3475f 100644 --- a/src/cc1111/ao_button.c +++ b/src/cc1111/ao_button.c @@ -36,11 +36,17 @@ static __code struct { #define NUM_BUTTONS ((sizeof ao_buttons) / sizeof (ao_buttons[0])) +static __xdata uint16_t ao_button_tick[NUM_BUTTONS]; + static void ao_button_insert(char n) { - ao_fifo_insert(ao_button_fifo, n); - ao_wakeup(&ao_button_fifo); + uint16_t now = ao_time(); + if ((now - ao_button_tick[n]) > 20) { + ao_button_tick[n] = now; + ao_fifo_insert(ao_button_fifo, n); + ao_wakeup(&ao_button_fifo); + } } static void @@ -77,6 +83,15 @@ ao_button_get(void) __critical return b; } +void +ao_button_clear(void) __critical +{ + char b; + + while (!ao_fifo_empty(ao_button_fifo)) + ao_fifo_remove(ao_button_fifo, b); +} + void ao_p0_isr(void) ao_arch_interrupt(13) { -- cgit v1.2.3 From 0a705b62829d492e3a48c81077907cee61afb860 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:31:46 -0800 Subject: altos: Initialize DMA config address at boot time Instead of resetting these each time a transfer is started, just set them once at boot time. Signed-off-by: Keith Packard --- src/cc1111/ao_dma.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_dma.c b/src/cc1111/ao_dma.c index 6052964a..ca33facb 100644 --- a/src/cc1111/ao_dma.c +++ b/src/cc1111/ao_dma.c @@ -46,6 +46,10 @@ ao_dma_alloc(__xdata uint8_t *done) DMAIRQ = 0; DMAIF = 0; IEN1 |= IEN1_DMAIE; + DMA0CFGH = ((uint16_t) (&ao_dma_config[0])) >> 8; + DMA0CFGL = ((uint16_t) (&ao_dma_config[0])); + DMA1CFGH = ((uint16_t) (&ao_dma_config[1])) >> 8; + DMA1CFGL = ((uint16_t) (&ao_dma_config[1])); } return id; @@ -69,13 +73,6 @@ ao_dma_set_transfer(uint8_t id, ao_dma_config[id].len_low = count; ao_dma_config[id].cfg0 = cfg0; ao_dma_config[id].cfg1 = cfg1 | DMA_CFG1_IRQMASK; - if (id == 0) { - DMA0CFGH = ((uint16_t) (&ao_dma_config[0])) >> 8; - DMA0CFGL = ((uint16_t) (&ao_dma_config[0])); - } else { - DMA1CFGH = ((uint16_t) (&ao_dma_config[1])) >> 8; - DMA1CFGL = ((uint16_t) (&ao_dma_config[1])); - } } #define nop() _asm nop _endasm; @@ -85,9 +82,11 @@ ao_dma_start(uint8_t id) { uint8_t mask = (1 << id); DMAIRQ &= ~mask; - DMAARM = 0x80 | mask; - nop(); nop(); nop(); nop(); - nop(); nop(); nop(); nop(); + if (DMAARM & mask) { + DMAARM = 0x80 | mask; + nop(); nop(); nop(); nop(); + nop(); nop(); nop(); nop(); + } *(ao_dma_done[id]) = 0; DMAARM = mask; nop(); nop(); nop(); nop(); -- cgit v1.2.3 From 2bce71eba9f44b6fcf64e307c8174824c3a0fb57 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:32:49 -0800 Subject: altos: Set SPI fill value each time it is used. This ensures that the final MOSI pin value will be high after a receive is finished. Signed-off-by: Keith Packard --- src/cc1111/ao_spi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cc1111/ao_spi.c b/src/cc1111/ao_spi.c index fbe613c7..1fa8e128 100644 --- a/src/cc1111/ao_spi.c +++ b/src/cc1111/ao_spi.c @@ -28,7 +28,7 @@ __xdata uint8_t ao_spi_dma_out_done; uint8_t ao_spi_dma_out_id; uint8_t ao_spi_dma_in_id; -static __xdata uint8_t ao_spi_const = 0xff; +static __xdata uint8_t ao_spi_const; /* Send bytes over SPI. * @@ -89,6 +89,8 @@ ao_spi_recv(void __xdata *block, uint16_t len) __reentrant DMA_CFG1_DESTINC_1 | DMA_CFG1_PRIORITY_NORMAL); + ao_spi_const = 0xff; + ao_dma_set_transfer(ao_spi_dma_out_id, &ao_spi_const, &U0DBUFXADDR, -- cgit v1.2.3 From ef7f86453d686a49882e8c1b88a59228c4c631a9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:37:53 -0800 Subject: altos: Check pdata+xdata memory usage during build The sdcc linker doesn't check the sum of pdata+xdata memory usage, it only ensures that xdata itself is small enough. This doesn't keep xdata below the end of usable ram on the cc1111 though (0xfe000). Fix up the check-stack program to also make sure all of xdata fits in available memory. Signed-off-by: Keith Packard --- src/product/Makefile.telebt | 2 +- src/product/Makefile.teledongle | 2 +- src/product/Makefile.telelaunch | 2 +- src/product/Makefile.telemetrum | 2 +- src/product/Makefile.telemini | 2 +- src/product/Makefile.telenano | 2 +- src/teleballoon-v1.1/Makefile | 2 +- src/teleterra-v0.2/Makefile | 5 +---- src/tidongle/Makefile | 2 +- src/util/check-stack | 10 ++++++++-- 10 files changed, 17 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index 8f7c7429..ea18ff18 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -81,7 +81,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle index c1b422c0..cf33d1f1 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -81,7 +81,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch index b40f61a2..97764517 100644 --- a/src/product/Makefile.telelaunch +++ b/src/product/Makefile.telelaunch @@ -84,7 +84,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index 40fc6bc2..52c723ca 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -94,7 +94,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini index 9f90b01f..75beeae4 100644 --- a/src/product/Makefile.telemini +++ b/src/product/Makefile.telemini @@ -83,7 +83,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index eff3ea97..b30ca789 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -82,7 +82,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/teleballoon-v1.1/Makefile b/src/teleballoon-v1.1/Makefile index 89471cf4..fb88787b 100644 --- a/src/teleballoon-v1.1/Makefile +++ b/src/teleballoon-v1.1/Makefile @@ -103,7 +103,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile index 583805f6..0747bfbf 100644 --- a/src/teleterra-v0.2/Makefile +++ b/src/teleterra-v0.2/Makefile @@ -25,9 +25,7 @@ CORE_SRC = \ ao_mutex.c \ ao_panic.c \ ao_report.c \ - ao_rssi.c \ ao_sqrt.c \ - ao_state.c \ ao_stdio.c \ ao_storage.c \ ao_task.c @@ -38,7 +36,6 @@ CC1111_SRC = \ ao_button.c \ ao_dbg.c \ ao_dma.c \ - ao_led.c \ ao_packet.c \ ao_packet_master.c \ ao_radio.c \ @@ -90,7 +87,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile index 58b9d735..698d612c 100644 --- a/src/tidongle/Makefile +++ b/src/tidongle/Makefile @@ -76,7 +76,7 @@ all: ../$(PROG) ../$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. - $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/util/check-stack b/src/util/check-stack index 1e8044e0..3b639d70 100755 --- a/src/util/check-stack +++ b/src/util/check-stack @@ -4,10 +4,16 @@ MEM=$2 HEADER_STACK=`awk '/#define AO_STACK_START/ {print strtonum($3)}' $HEADER` MEM_STACK=`awk '/Stack starts at/ {print strtonum ($4)}' $MEM` +XRAM_END=`awk '/EXTERNAL RAM/ { print strtonum ($4)}' $MEM` if [ "$HEADER_STACK" -lt "$MEM_STACK" ]; then echo $MEM_STACK | awk '{ printf ("Set AO_STACK_START to at least 0x%x\n", $1); }' exit 1 -else - exit 0 fi +if [ "$XRAM_END" -ge 65024 ]; then + echo $XRAM_END | awk '{ printf ("Uses too much XRAM, 0x%x >= 0x%x\n", $1, 65024); }' + exit 1 +fi + +exit 0 + -- cgit v1.2.3 From 5972c642f0de0789e90268bfa19ef8b51c06eebc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:44:36 -0800 Subject: altos: Handle internal and external telem monitoring requests Record separate internal vs external monitoring state, allowing both to happen at the same time, and when either is turned off, the other keeps working. This also adds disable/enable so that other radio users can temporarily take over the radio; monitoring will resume when the other radio user is finished. Signed-off-by: Keith Packard --- src/ao_radio_cmac.c | 4 +- src/cc1111/ao_packet_master.c | 5 +- src/cc1111/ao_pins.h | 5 ++ src/cc1111/ao_radio.c | 5 +- src/core/ao.h | 11 ++- src/core/ao_log_telem.c | 2 + src/core/ao_monitor.c | 151 ++++++++++++++++++----------------------- src/product/ao_telebt.c | 2 +- src/product/ao_teledongle.c | 2 +- src/product/ao_teleterra_0_2.c | 2 +- src/product/ao_tidongle.c | 2 +- src/teleterra-v0.2/ao_pins.h | 3 +- 12 files changed, 96 insertions(+), 98 deletions(-) (limited to 'src') diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c index 41fbbe1f..e263f0db 100644 --- a/src/ao_radio_cmac.c +++ b/src/ao_radio_cmac.c @@ -78,7 +78,7 @@ radio_cmac_send(uint8_t len) __reentrant ao_config_get(); #if HAS_MONITOR - ao_set_monitor(0); + ao_monitor_set(0); #endif ao_mutex_get(&ao_aes_mutex); @@ -107,7 +107,7 @@ radio_cmac_recv(uint8_t len, uint16_t timeout) __reentrant len = round_len(len); #if HAS_MONITOR - ao_set_monitor(0); + ao_monitor_set(0); #endif if (timeout) ao_alarm(timeout); diff --git a/src/cc1111/ao_packet_master.c b/src/cc1111/ao_packet_master.c index ab19f979..66f94288 100644 --- a/src/cc1111/ao_packet_master.c +++ b/src/cc1111/ao_packet_master.c @@ -114,7 +114,7 @@ ao_packet_forward(void) __reentrant flush(); #if HAS_MONITOR - ao_set_monitor(0); + ao_monitor_disable(); #endif ao_add_task(&ao_packet_task, ao_packet_master, "master"); ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); @@ -132,6 +132,9 @@ ao_packet_forward(void) __reentrant ao_wakeup(&ao_stdin_ready); ao_delay(AO_MS_TO_TICKS(10)); } +#if HAS_MONITOR + ao_monitor_enable(); +#endif } diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 7c5b4574..2b6232a4 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -107,6 +107,7 @@ #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 1 #define AO_LED_GREEN 2 + #define AO_MONITOR_LED AO_LED_GREEN #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 @@ -218,6 +219,7 @@ #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 2 #define AO_LED_GREEN 1 + #define AO_MONITOR_LED AO_LED_GREEN #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define SPI_CS_ON_P1 0 #define SPI_CS_ON_P0 1 @@ -245,6 +247,7 @@ #define PACKET_HAS_MASTER 1 #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 2 + #define AO_MONITOR_LED AO_LED_RED #define LEDS_AVAILABLE (AO_LED_RED) #define SPI_CS_ON_P1 0 #define SPI_CS_ON_P0 1 @@ -274,6 +277,7 @@ #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 2 #define AO_LED_GREEN 1 + #define AO_MONITOR_LED AO_LED_RED #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 @@ -312,6 +316,7 @@ #define PACKET_HAS_SLAVE 0 #define AO_LED_RED 1 #define AO_LED_GREEN 2 + #define AO_MONITOR_LED AO_LED_RED #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index 75f241d4..ee506f89 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -421,7 +421,7 @@ ao_radio_test(void) mode++; if ((mode & 2) && !radio_on) { #if HAS_MONITOR - ao_set_monitor(0); + ao_monitor_disable(); #endif #if PACKET_HAS_SLAVE ao_packet_slave_stop(); @@ -439,6 +439,9 @@ ao_radio_test(void) ao_radio_idle(); ao_radio_put(); radio_on = 0; +#if HAS_MONITOR + ao_monitor_enable(); +#endif } } diff --git a/src/core/ao.h b/src/core/ao.h index cbe2f8dc..f57398ce 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1406,13 +1406,18 @@ ao_monitor(void); #define AO_MONITORING_OFF 0 #define AO_MONITORING_ORIG 1 -#define AO_MONITORING_TINY 2 void -ao_set_monitor(uint8_t monitoring); +ao_monitor_set(uint8_t monitoring); void -ao_monitor_init(uint8_t led, uint8_t monitoring) __reentrant; +ao_monitor_disable(void); + +void +ao_monitor_enable(void); + +void +ao_monitor_init(void) __reentrant; /* * ao_stdio.c diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index 096ad919..9e1b06d3 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -90,6 +90,8 @@ ao_log_single(void) ao_log_running = 1; ao_log_single_restart(); ao_flight_state = ao_flight_startup; + ao_monitor_set(sizeof(struct ao_telemetry_generic)); + for (;;) { while (!ao_log_running) ao_sleep(&ao_log_running); diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index f7795fe4..7960208e 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -30,13 +30,35 @@ #define HAS_MONIOTOR_PUT 1 #endif +#ifndef AO_MONITOR_LED +#error Must define AO_MONITOR_LED +#endif + __data uint8_t ao_monitoring; -__pdata uint8_t ao_monitor_led; +static __data uint8_t ao_monitor_disabled; +static __data uint8_t ao_internal_monitoring; +static __data uint8_t ao_external_monitoring; __xdata union ao_monitor ao_monitor_ring[AO_MONITOR_RING]; __data uint8_t ao_monitor_head; +static void +_ao_monitor_adjust(void) +{ + if (ao_monitoring) + ao_radio_recv_abort(); + if (ao_monitor_disabled) + ao_monitoring = 0; + else { + if (ao_external_monitoring) + ao_monitoring = ao_external_monitoring; + else + ao_monitoring = ao_internal_monitoring; + } + ao_wakeup(DATA_TO_XDATA(&ao_monitoring)); +} + void ao_monitor_get(void) { @@ -51,9 +73,6 @@ ao_monitor_get(void) case AO_MONITORING_ORIG: size = sizeof (struct ao_telemetry_orig_recv); break; - case AO_MONITORING_TINY: - size = sizeof (struct ao_telemetry_tiny_recv); - break; #endif default: if (ao_monitoring > AO_MAX_TELEMETRY) @@ -68,16 +87,21 @@ ao_monitor_get(void) } } +#if AO_MONITOR_LED +__xdata struct ao_task ao_monitor_blink_task; + void ao_monitor_blink(void) { for (;;) { ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); - ao_led_for(ao_monitor_led, AO_MS_TO_TICKS(100)); + ao_led_for(AO_MONITOR_LED, AO_MS_TO_TICKS(100)); } } +#endif #if HAS_MONITOR_PUT + void ao_monitor_put(void) { @@ -96,11 +120,15 @@ ao_monitor_put(void) ao_monitor_tail = ao_monitor_head; for (;;) { - while (ao_monitor_tail == ao_monitor_head) + while (!ao_external_monitoring) + ao_sleep(DATA_TO_XDATA(&ao_external_monitoring)); + while (ao_monitor_tail == ao_monitor_head && ao_external_monitoring) ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); m = &ao_monitor_ring[ao_monitor_tail]; ao_monitor_tail = ao_monitor_ring_next(ao_monitor_tail); switch (ao_monitoring) { + case 0: + break; #if LEGACY_MONITOR case AO_MONITORING_ORIG: state = recv_orig.telemetry_orig.flight_state; @@ -172,71 +200,6 @@ ao_monitor_put(void) ao_gps_print(&recv_orig.telemetry_orig.gps); ao_gps_tracking_print(&recv_orig.telemetry_orig.gps_tracking); putchar('\n'); -#if HAS_RSSI - ao_rssi_set(rssi); -#endif - } else { - printf("CRC INVALID RSSI %3d\n", rssi); - } - break; - case AO_MONITORING_TINY: - state = recv_tiny.telemetry_tiny.flight_state; - - /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ - rssi = (int16_t) (recv_tiny.rssi >> 1) - 74; - ao_xmemcpy(callsign, recv_tiny.telemetry_tiny.callsign, AO_MAX_CALLSIGN); - if (state > ao_flight_invalid) - state = ao_flight_invalid; - if (recv_tiny.status & PKT_APPEND_STATUS_1_CRC_OK) { - /* General header fields */ - printf(AO_TELEM_VERSION " %d " - AO_TELEM_CALL " %s " - AO_TELEM_SERIAL " %d " - AO_TELEM_FLIGHT " %d " - AO_TELEM_RSSI " %d " - AO_TELEM_STATE " %s " - AO_TELEM_TICK " %d ", - AO_TELEMETRY_VERSION, - callsign, - recv_tiny.telemetry_tiny.serial, - recv_tiny.telemetry_tiny.flight, - rssi, - ao_state_names[state], - recv_tiny.telemetry_tiny.adc.tick); - - /* Raw sensor values */ - printf(AO_TELEM_RAW_BARO " %d " - AO_TELEM_RAW_THERMO " %d " - AO_TELEM_RAW_BATT " %d " - AO_TELEM_RAW_DROGUE " %d " - AO_TELEM_RAW_MAIN " %d ", - recv_tiny.telemetry_tiny.adc.pres, - recv_tiny.telemetry_tiny.adc.temp, - recv_tiny.telemetry_tiny.adc.v_batt, - recv_tiny.telemetry_tiny.adc.sense_d, - recv_tiny.telemetry_tiny.adc.sense_m); - - /* Sensor calibration values */ - printf(AO_TELEM_CAL_BARO_GROUND " %d ", - recv_tiny.telemetry_tiny.ground_pres); - -#if 1 - /* Kalman state values */ - printf(AO_TELEM_KALMAN_HEIGHT " %d " - AO_TELEM_KALMAN_SPEED " %d " - AO_TELEM_KALMAN_ACCEL " %d\n", - recv_tiny.telemetry_tiny.height, - recv_tiny.telemetry_tiny.speed, - recv_tiny.telemetry_tiny.accel); -#else - /* Ad-hoc flight values */ - printf(AO_TELEM_ADHOC_ACCEL " %d " - AO_TELEM_ADHOC_SPEED " %ld " - AO_TELEM_ADHOC_BARO " %d\n", - recv_tiny.telemetry_tiny.flight_accel, - recv_tiny.telemetry_tiny.flight_vel, - recv_tiny.telemetry_tiny.flight_pres); -#endif #if HAS_RSSI ao_rssi_set(rssi); #endif @@ -265,43 +228,59 @@ ao_monitor_put(void) ao_usb_flush(); } } + __xdata struct ao_task ao_monitor_put_task; #endif __xdata struct ao_task ao_monitor_get_task; -__xdata struct ao_task ao_monitor_blink_task; void -ao_set_monitor(uint8_t monitoring) +ao_monitor_set(uint8_t monitoring) { - if (ao_monitoring) - ao_radio_recv_abort(); - ao_monitoring = monitoring; - ao_wakeup(DATA_TO_XDATA(&ao_monitoring)); + ao_internal_monitoring = monitoring; + _ao_monitor_adjust(); } +void +ao_monitor_disable(void) +{ + ++ao_monitor_disabled; + _ao_monitor_adjust(); +} + +void +ao_monitor_enable(void) +{ + --ao_monitor_disabled; + _ao_monitor_adjust(); +} + +#if HAS_MONITOR_PUT static void set_monitor(void) { ao_cmd_hex(); - ao_set_monitor(ao_cmd_lex_i); + ao_external_monitoring = ao_cmd_lex_i; + ao_wakeup(DATA_TO_XDATA(&ao_external_monitoring)); + ao_wakeup(DATA_TO_XDATA(&ao_monitor_head)); + _ao_monitor_adjust(); } __code struct ao_cmds ao_monitor_cmds[] = { - { set_monitor, "m <0 off, 1 full, 2 tiny>\0Enable/disable radio monitoring" }, + { set_monitor, "m <0 off, 1 old, 20 std>\0Enable/disable radio monitoring" }, { 0, NULL }, }; +#endif void -ao_monitor_init(uint8_t monitor_led, uint8_t monitoring) __reentrant +ao_monitor_init(void) __reentrant { - ao_monitor_led = monitor_led; - ao_monitoring = monitoring; - ao_cmd_register(&ao_monitor_cmds[0]); - ao_add_task(&ao_monitor_get_task, ao_monitor_get, "monitor_get"); #if HAS_MONITOR_PUT + ao_cmd_register(&ao_monitor_cmds[0]); ao_add_task(&ao_monitor_put_task, ao_monitor_put, "monitor_put"); #endif - if (ao_monitor_led) - ao_add_task(&ao_monitor_blink_task, ao_monitor_blink, "monitor_blink"); + ao_add_task(&ao_monitor_get_task, ao_monitor_get, "monitor_get"); +#if AO_MONITOR_LED + ao_add_task(&ao_monitor_blink_task, ao_monitor_blink, "monitor_blink"); +#endif } diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index c4b40dfc..97c9d792 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -37,7 +37,7 @@ main(void) ao_storage_init(); #endif ao_usb_init(); - ao_monitor_init(AO_LED_RED, TRUE); + ao_monitor_init(); #if HAS_LOG ao_report_init(); #endif diff --git a/src/product/ao_teledongle.c b/src/product/ao_teledongle.c index b8be9f45..49b80500 100644 --- a/src/product/ao_teledongle.c +++ b/src/product/ao_teledongle.c @@ -28,7 +28,7 @@ main(void) ao_timer_init(); ao_cmd_init(); ao_usb_init(); - ao_monitor_init(AO_LED_GREEN, TRUE); + ao_monitor_init(); ao_rssi_init(AO_LED_RED); ao_radio_init(); ao_packet_master_init(); diff --git a/src/product/ao_teleterra_0_2.c b/src/product/ao_teleterra_0_2.c index 6ce29894..1a268c99 100644 --- a/src/product/ao_teleterra_0_2.c +++ b/src/product/ao_teleterra_0_2.c @@ -31,7 +31,7 @@ main(void) ao_usb_init(); ao_serial_init(); ao_gps_init(); - ao_monitor_init(0, sizeof (struct ao_telemetry_generic)); + ao_monitor_init(); ao_report_init(); ao_log_single_init(); ao_radio_init(); diff --git a/src/product/ao_tidongle.c b/src/product/ao_tidongle.c index 5adbb05c..a504a747 100644 --- a/src/product/ao_tidongle.c +++ b/src/product/ao_tidongle.c @@ -30,7 +30,7 @@ main(void) ao_timer_init(); ao_cmd_init(); ao_usb_init(); - ao_monitor_init(AO_LED_RED, TRUE); + ao_monitor_init(); ao_rssi_init(AO_LED_RED); ao_radio_init(); ao_dbg_init(); diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 9c35b06a..72ded004 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -39,13 +39,14 @@ #define HAS_COMPANION 0 + #define AO_MONITOR_LED 0 #define LEDS_AVAILABLE 0 #define HAS_EXTERNAL_TEMP 0 #define HAS_ACCEL_REF 0 #define HAS_ACCEL 0 #define HAS_IGNITE 0 #define HAS_MONITOR 1 - #define HAS_MONITOR_PUT 0 + #define HAS_MONITOR_PUT 1 #define LEGACY_MONITOR 0 #define HAS_RSSI 0 #define HAS_AES 0 -- cgit v1.2.3 From 20282ef00afe70e3f3193f6f0200254cb2c33e93 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:47:08 -0800 Subject: altos: Set default flight log max to 127k on TM v0.1 The flash part on v0.1 boards is only 128kB. Signed-off-by: Keith Packard --- src/cc1111/ao_pins.h | 1 + src/core/ao_config.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'src') diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 2b6232a4..ca85c39f 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -199,6 +199,7 @@ #define HAS_ACCEL 1 #define HAS_IGNITE 1 #define HAS_MONITOR 0 + #define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 127 * (uint32_t) 1024) #endif #if defined(TELEDONGLE_V_0_1) diff --git a/src/core/ao_config.c b/src/core/ao_config.c index f0a576ee..921a2480 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -34,11 +34,13 @@ __xdata uint8_t ao_config_mutex; #error Please define USE_INTERNAL_FLASH #endif #endif +#ifndef AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX #if USE_INTERNAL_FLASH #define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ao_storage_config #else #define AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX ((uint32_t) 192 * (uint32_t) 1024) #endif +#endif #if HAS_EEPROM static void -- cgit v1.2.3 From 2ba946fea29ff134ffaeaea9d7932f4bd4e953aa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:48:07 -0800 Subject: altos: Export 'ao_cmd_is_white' for use by other code This function tests the current input character. Signed-off-by: Keith Packard --- src/core/ao.h | 3 +++ src/core/ao_cmd.c | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index f57398ce..2139983c 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -349,6 +349,9 @@ ao_cmd_put8(uint8_t v); void ao_cmd_put16(uint16_t v); +uint8_t +ao_cmd_is_white(void); + void ao_cmd_white(void); diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 0c902f6b..14cb7569 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -121,10 +121,16 @@ ao_cmd_put8(uint8_t v) putnibble(v & 0xf); } +uint8_t +ao_cmd_is_white(void) +{ + return ao_cmd_lex_c == ' ' || ao_cmd_lex_c == '\t'; +} + void ao_cmd_white(void) { - while (ao_cmd_lex_c == ' ' || ao_cmd_lex_c == '\t') + while (ao_cmd_is_white()) ao_cmd_lex(); } -- cgit v1.2.3 From 75a8490a7bee2a2c7afd559b13f1d9c40c2aa08f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:49:17 -0800 Subject: altos: Add configurable set of channels for TT This adds the channel list for TT, which will be configured by AltosUI. Signed-off-by: Keith Packard --- src/core/ao.h | 17 ++++++++++++++- src/core/ao_config.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 2139983c..3c1aa156 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1495,9 +1495,21 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 9 +#define AO_CONFIG_MINOR 10 #define AO_AES_LEN 16 +#if HAS_RADIO_CHANNELS +#define AO_CHANNEL_NAME_LEN 10 + +#define AO_NUM_CHANNELS 10 + +struct ao_radio_channel { + char name[AO_CHANNEL_NAME_LEN]; + uint32_t kHz; + uint32_t radio_setting; +}; +#endif + struct ao_config { uint8_t major; uint8_t minor; @@ -1514,6 +1526,9 @@ struct ao_config { uint32_t radio_setting; /* minor version 7 */ uint8_t radio_enable; /* minor version 8 */ uint8_t aes_key[AO_AES_LEN]; /* minor version 9 */ +#if HAS_RADIO_CHANNELS + struct ao_radio_channel radio_channels[AO_NUM_CHANNELS]; /* minor version 10 */ +#endif }; #define AO_IGNITE_MODE_DUAL 0 diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 921a2480..86bbc473 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -111,6 +111,15 @@ _ao_config_get(void) ao_config.radio_enable = TRUE; if (ao_config.minor < 9) memset(&ao_config.aes_key, 0, AO_AES_LEN); +#if HAS_RADIO_CHANNELS + if (ao_config.minor < 10) { + ao_xmemset(&ao_config.radio_channels, '\0', sizeof (ao_config.radio_channels)); + ao_xmemcpy(&ao_config.radio_channels[0].name[0], + CODE_TO_XDATA("Channel 0"), sizeof("Channel 0")); + ao_config.radio_channels[0].kHz = 434550; + ao_config.radio_channels[0].radio_setting = ao_config.radio_cal; + } +#endif ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -448,6 +457,53 @@ ao_config_key_set(void) __reentrant } #endif +#if HAS_RADIO_CHANNELS +void +ao_config_radio_config_show(void) __reentrant +{ + uint8_t i; + for (i = 0; i < AO_NUM_CHANNELS; i++) + if (ao_config.radio_channels[i].name[0]) { + printf("%2d %-16.16s %ld %ld\n", + i, + ao_config.radio_channels[i].name, + ao_config.radio_channels[i].kHz, + ao_config.radio_channels[i].radio_setting); + } +} + +void +ao_config_radio_config_set(void) __reentrant +{ + __xdata struct ao_radio_channel * ch; + uint8_t i; + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + if ((uint8_t) ao_cmd_lex_i >= AO_NUM_CHANNELS) { + ao_cmd_status = ao_cmd_syntax_error; + return; + } + ch = &ao_config.radio_channels[(uint8_t) ao_cmd_lex_i]; + _ao_config_edit_start(); + ao_cmd_white(); + i = 0; + while (ao_cmd_lex_c != '/' && ao_cmd_lex_c != '\n' && i < AO_CHANNEL_NAME_LEN) { + ch->name[i++] = ao_cmd_lex_c; + ao_cmd_lex(); + } + if (i < AO_CHANNEL_NAME_LEN) { + ch->name[i] = '\0'; + ao_cmd_lex(); + } + ao_cmd_decimal(); + ch->kHz = ao_cmd_lex_u32; + ao_cmd_decimal(); + ch->radio_setting = ao_cmd_lex_u32; + _ao_config_edit_finish(); +} +#endif + struct ao_config_var { __code char *str; void (*set)(void) __reentrant; @@ -499,6 +555,10 @@ __code struct ao_config_var ao_config_vars[] = { #if HAS_AES { "k <32 hex digits>\0Set AES encryption key", ao_config_key_set, ao_config_key_show }, +#endif +#if HAS_RADIO_CHANNELS + { "C / \0Set radio chan config", + ao_config_radio_config_set,ao_config_radio_config_show }, #endif { "s\0Show", ao_config_show, 0 }, -- cgit v1.2.3 From 430b439b9a5cc98b32273a233505de2c2f975c59 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:51:03 -0800 Subject: altosui: Add ao_lcd_cursor_on/off This shows or hides a blinking cursor on the LCD. Signed-off-by: Keith Packard --- src/core/ao.h | 6 ++++++ src/drivers/ao_lcd.c | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 3c1aa156..8bd7a3d2 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1719,6 +1719,12 @@ ao_lcd_contrast_set(uint8_t contrast); void ao_lcd_clear(void); +void +ao_lcd_cursor_on(void); + +void +ao_lcd_cursor_off(void); + #define AO_LCD_ADDR(row,col) ((row << 6) | (col)) void diff --git a/src/drivers/ao_lcd.c b/src/drivers/ao_lcd.c index 8745b3f6..8ce32233 100644 --- a/src/drivers/ao_lcd.c +++ b/src/drivers/ao_lcd.c @@ -73,6 +73,22 @@ ao_lcd_contrast_set(uint8_t contrast) ao_mutex_put(&ao_lcd_mutex); } +void +ao_lcd_cursor_on(void) +{ + ao_mutex_get(&ao_lcd_mutex); + ao_lcd_send_ins(0x08 | 0x04 | 0x02 | 0x01); + ao_mutex_put(&ao_lcd_mutex); +} + +void +ao_lcd_cursor_off(void) +{ + ao_mutex_get(&ao_lcd_mutex); + ao_lcd_send_ins(0x08 | 0x04); + ao_mutex_put(&ao_lcd_mutex); +} + void ao_lcd_clear(void) { -- cgit v1.2.3 From 0f7d7a4fbede63b51208bf051e08aa73dfbf35a0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:51:31 -0800 Subject: altos: Remove LCD debugging code This isn't needed anymore. Signed-off-by: Keith Packard --- src/drivers/ao_lcd.c | 71 ---------------------------------------------------- 1 file changed, 71 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_lcd.c b/src/drivers/ao_lcd.c index 8ce32233..6def0c80 100644 --- a/src/drivers/ao_lcd.c +++ b/src/drivers/ao_lcd.c @@ -143,79 +143,8 @@ ao_lcd_start(void) ao_lcd_clear(); } -void -ao_lcd_contrast(void) -{ - ao_cmd_hex(); - if (ao_cmd_status == ao_cmd_success) { - printf("setting contrast to %02x\n", ao_cmd_lex_i); - ao_lcd_contrast_set(ao_cmd_lex_i & 0x3f); - } -} - -static uint8_t -ao_cmd_hex_nibble(void) -{ - if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9') - return ao_cmd_lex_c - '0'; - if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f') - return ao_cmd_lex_c - ('a' - 10); - if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F') - return ao_cmd_lex_c - ('A' - 10); - ao_cmd_status = ao_cmd_syntax_error; - return 0; -} - -void -ao_lcd_string(void) -{ - uint8_t col = 0; - char c; - - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - ao_lcd_send_ins(0x80 | (ao_cmd_lex_i ? 0x40 : 0x00)); - ao_cmd_white(); - while (ao_cmd_lex_c != '\n') { - c = ao_cmd_lex_c; - if (c == '\\') { - ao_cmd_lex(); - c = ao_cmd_hex_nibble() << 4; - ao_cmd_lex(); - c |= ao_cmd_hex_nibble(); - } - ao_lcd_put_byte(c); - ao_cmd_lex(); - col++; - } - while (col < 16) { - ao_lcd_put_byte(' '); - col++; - } -} - -void -ao_lcd_delay_set(void) -{ - ao_cmd_decimal(); - if (ao_cmd_status == ao_cmd_success) { - printf("setting LCD delay to %d\n", ao_cmd_lex_i); - ao_lcd_time = ao_cmd_lex_i; - } -} - -__code struct ao_cmds ao_lcd_cmds[] = { - { ao_lcd_start, "S\0Start LCD" }, - { ao_lcd_contrast, "C \0Set LCD contrast" }, - { ao_lcd_string, "s \0Send string to LCD" }, - { ao_lcd_delay_set, "t \0Set LCD delay" }, - { 0, NULL }, -}; - void ao_lcd_init(void) { ao_lcd_port_init(); - ao_cmd_register(&ao_lcd_cmds[0]); } -- cgit v1.2.3 From d3dcb9451f40506abced72783966104645a73bc7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:52:02 -0800 Subject: altos: Allow TT/TBT reports to escape landed state The TM altitude reporting code kept beeping out state and altitude forever, which isn't very useful on TBT or TT. Signed-off-by: Keith Packard --- src/core/ao_report.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/core/ao_report.c b/src/core/ao_report.c index 70f0b49d..7c928792 100644 --- a/src/core/ao_report.c +++ b/src/core/ao_report.c @@ -99,14 +99,10 @@ ao_report_altitude(void) agl /= 10; } while (agl); - for (;;) { - ao_report_beep(); - i = ndigits; - do - ao_report_digit(digits[--i]); - while (i != 0); - pause(AO_SEC_TO_TICKS(5)); - } + i = ndigits; + do + ao_report_digit(digits[--i]); + while (i != 0); } #if HAS_IGNITE_REPORT @@ -159,9 +155,14 @@ ao_report(void) { ao_report_state = ao_flight_state; for(;;) { - if (ao_flight_state == ao_flight_landed) - ao_report_altitude(); ao_report_beep(); + if (ao_flight_state == ao_flight_landed) { + ao_report_altitude(); +#if HAS_FLIGHT + ao_delay(AO_SEC_TO_TICKS(5)); + continue; +#endif + } #if HAS_IGNITE_REPORT if (ao_flight_state == ao_flight_idle) ao_report_continuity(); @@ -173,11 +174,10 @@ ao_report(void) pause(AO_MS_TO_TICKS(100)); } #endif - __critical { - while (ao_report_state == ao_flight_state) - ao_sleep(DATA_TO_XDATA(&ao_flight_state)); - ao_report_state = ao_flight_state; - } + + while (ao_report_state == ao_flight_state) + ao_sleep(DATA_TO_XDATA(&ao_flight_state)); + ao_report_state = ao_flight_state; } } -- cgit v1.2.3 From 7f9e76e0d3492dcc8bf4b5b1f07c3c727cfdc0ef Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 18:54:14 -0800 Subject: altos: Trim skytraq NMEA messages. Shrink NMEA header matching code Tell the skytraq to not bother sending a bunch of the NMEA messages that we don't parse. Explicitly look for 'G' follows by 'P' instead of having some general header matching code. Signed-off-by: Keith Packard --- src/drivers/ao_gps_skytraq.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index 62909606..050573e8 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -19,10 +19,6 @@ #include "ao.h" #endif -#define AO_GPS_LEADER 2 - -static __code char ao_gps_header[] = "GP"; - __xdata uint8_t ao_gps_mutex; static __data char ao_gps_char; static __data uint8_t ao_gps_cksum; @@ -50,7 +46,7 @@ static __pdata struct ao_telemetry_satellite ao_gps_tracking_next; (id^a^b^c^d^e^f^g^h^i^j^k^l^m^n), STQ_E static __code uint8_t ao_gps_config[] = { - SKYTRAQ_MSG_8(0x08, 1, 1, 1, 1, 1, 1, 1, 0), /* configure nmea */ + SKYTRAQ_MSG_8(0x08, 1, 0, 1, 0, 1, 0, 0, 0), /* configure nmea */ /* gga interval */ /* gsa interval */ /* gsv interval */ @@ -418,11 +414,12 @@ ao_gps_nmea_parse(void) ao_gps_cksum = 0; ao_gps_error = 0; - for (a = 0; a < AO_GPS_LEADER; a++) { - ao_gps_lexchar(); - if (ao_gps_char != ao_gps_header[a]) - return; - } + ao_gps_lexchar(); + if (ao_gps_char != 'G') + return; + ao_gps_lexchar(); + if (ao_gps_char != 'P') + return; ao_gps_lexchar(); a = ao_gps_char; @@ -459,7 +456,6 @@ ao_gps(void) __reentrant if (ao_serial_getchar() == '$') { ao_gps_nmea_parse(); } - } } -- cgit v1.2.3 From e7044fd95472449e2fb860cef902fa458b91ccac Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 19:18:23 -0800 Subject: altos: Fix sdcdb settings for telemetrum v1.0 Signed-off-by: Keith Packard --- src/telemetrum-v1.0/.sdcdbrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/telemetrum-v1.0/.sdcdbrc b/src/telemetrum-v1.0/.sdcdbrc index 710b4a2f..fbe9a599 100644 --- a/src/telemetrum-v1.0/.sdcdbrc +++ b/src/telemetrum-v1.0/.sdcdbrc @@ -1 +1 @@ ---directory=.. +--directory=../cc1111:../product:../core:../drivers:. -- cgit v1.2.3 From 02b4e52a5349217df43105eaa1fff6bfc7dac4cc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 19:18:53 -0800 Subject: altos: Enable packet master and debug in TT The code was already getting linked in, so we might as well use it. Signed-off-by: Keith Packard --- src/product/ao_teleterra_0_2.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/product/ao_teleterra_0_2.c b/src/product/ao_teleterra_0_2.c index 1a268c99..68f02596 100644 --- a/src/product/ao_teleterra_0_2.c +++ b/src/product/ao_teleterra_0_2.c @@ -35,7 +35,9 @@ main(void) ao_report_init(); ao_log_single_init(); ao_radio_init(); + ao_packet_master_init(); ao_config_init(); + ao_dbg_init(); ao_lcd_init(); ao_terraui_init(); ao_button_init(); -- cgit v1.2.3 From c1e293ff4953b51c19af8b52f2999419ea84e7e5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 12 Nov 2011 19:19:40 -0800 Subject: altos: Add startup and config (view only) pages to TT The config page needs a pile of work before it's useful. Signed-off-by: Keith Packard --- src/product/ao_terraui.c | 111 +++++++++++++++++++++++++------------------ src/teleterra-v0.2/ao_pins.h | 3 ++ 2 files changed, 68 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c index 22bab5d6..05157cb1 100644 --- a/src/product/ao_terraui.c +++ b/src/product/ao_terraui.c @@ -88,6 +88,15 @@ static __code char ao_progress[4] = { '\011', '\012', '\014', '\013' }; static uint8_t ao_telem_progress; static uint8_t ao_gps_progress; +static void +ao_terraui_startup(void) +{ + sprintf(ao_lcd_line, "%-16.16s", ao_product); + ao_terraui_line(AO_LCD_ADDR(0,0)); + sprintf(ao_lcd_line, "%-8.8s %5u ", ao_version, ao_serial_number); + ao_terraui_line(AO_LCD_ADDR(1,0)); +} + static void ao_terraui_info(void) { @@ -441,76 +450,85 @@ ao_terraui_local(void) __reentrant } static void -ao_terraui_config(void) +ao_terraui_config(void) __reentrant { + uint8_t chan; + uint32_t kHz; + uint16_t MHz; + uint16_t frac; + + for (chan = 0; chan < AO_NUM_CHANNELS; chan++) + if (ao_config.radio_channels[chan].radio_setting == ao_config.radio_setting) + break; + if (chan == AO_NUM_CHANNELS) + chan = 0; + kHz = ao_config.radio_channels[chan].kHz; + MHz = kHz / 1000; + frac = kHz % 1000; + sprintf(ao_lcd_line, "%2d: %-10.10s ", chan, ao_config.radio_channels[chan].name); + ao_terraui_line(AO_LCD_ADDR(0,0)); + sprintf(ao_lcd_line, "%-8.8s %3d.%03d", ao_config.callsign, MHz, frac); + ao_terraui_line(AO_LCD_ADDR(1,0)); + ao_lcd_goto(AO_LCD_ADDR(0,1)); + ao_lcd_cursor_on(); } -enum ao_page { - ao_page_info, - ao_page_pad, - ao_page_ascent, - ao_page_descent, - ao_page_recover, - ao_page_remote, - ao_page_local, +static __code void (*__code ao_terraui_page[])(void) = { + ao_terraui_startup, + ao_terraui_info, + ao_terraui_pad, + ao_terraui_ascent, + ao_terraui_descent, + ao_terraui_recover, + ao_terraui_remote, + ao_terraui_local, + ao_terraui_config, }; +#define NUM_PAGE (sizeof (ao_terraui_page)/sizeof (ao_terraui_page[0])) + +__pdata uint8_t ao_current_page = 0; +__pdata uint8_t ao_shown_about = 3; + static void ao_terraui(void) { - enum ao_page cur_page = ao_page_info; - ao_lcd_start(); + + ao_delay(AO_MS_TO_TICKS(100)); + ao_button_clear(); + for (;;) { char b; - switch (cur_page) { - case ao_page_info: - ao_terraui_info(); - break; - case ao_page_pad: - ao_terraui_pad(); - break; - case ao_page_ascent: - ao_terraui_ascent(); - break; - case ao_page_descent: - ao_terraui_descent(); - break; - case ao_page_recover: - ao_terraui_recover(); - break; - case ao_page_remote: - ao_terraui_remote(); - break; - case ao_page_local: - ao_terraui_local(); - break; - } - + ao_terraui_page[ao_current_page](); ao_alarm(AO_SEC_TO_TICKS(1)); b = ao_button_get(); ao_clear_alarm(); + if (b > 0) { + ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(10)); + ao_shown_about = 0; + } + switch (b) { case 0: + if (ao_shown_about) { + if (--ao_shown_about == 0) + ao_current_page = 2; + } break; case 1: - if (cur_page == ao_page_local) - cur_page = ao_page_info; - else - cur_page++; - ao_beep_for(AO_BEEP_HIGH, AO_MS_TO_TICKS(50)); + ao_current_page++; + if (ao_current_page >= NUM_PAGE) + ao_current_page = 0; break; case 2: - ao_beep_for(AO_BEEP_LOW, AO_MS_TO_TICKS(200)); break; case 3: - if (cur_page == ao_page_info) - cur_page = ao_page_local; - else - cur_page--; - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(50)); + if (ao_current_page == 0) + ao_current_page = NUM_PAGE; + ao_current_page--; break; } } @@ -524,6 +542,7 @@ ao_terramonitor(void) uint8_t monitor; monitor = ao_monitor_head; + ao_monitor_set(sizeof (struct ao_telemetry_generic)); for (monitor = ao_monitor_head;; monitor = ao_monitor_ring_next(monitor)) { diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 72ded004..44a372cc 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -36,6 +36,7 @@ #define IGNITE_ON_P0 0 #define PACKET_HAS_MASTER 1 #define PACKET_HAS_SLAVE 0 + #define HAS_RADIO_CHANNELS 1 #define HAS_COMPANION 0 @@ -66,6 +67,8 @@ #define BUTTON_3_REG 2 #define BUTTON_3_MASK (1 << 4) /* P2_4 */ + #define HAS_P2_ISR 1 + #define BATTERY_PIN 5 #endif -- cgit v1.2.3 From dbf7c0c59854e040b65f068069d80716f02fc1bc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 13 Nov 2011 23:03:22 -0800 Subject: altos: Fix pad orientation for pre-1.1 boards They use a different code path for accel as they don't have the VCC compensation code in place. Signed-off-by: Keith Packard --- src/core/ao_sample.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c index b2b8e9f6..2bf9632f 100644 --- a/src/core/ao_sample.c +++ b/src/core/ao_sample.c @@ -182,6 +182,11 @@ ao_sample(void) if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) ao_sample_accel = 0x7fff - ao_sample_accel; ao_adc->accel = ao_sample_accel; +#else + if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) { + ao_sample_accel = 0x7fff - ao_sample_accel; + ao_adc->accel = ao_sample_accel; + } #endif #endif -- cgit v1.2.3 From eff8611e3eb19853b06acfcd7e978c9046cd5f78 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 17 Dec 2011 17:05:06 -0800 Subject: altos: Create TeleMetrum v1.2 directory The hardware is software-compatible with v1.1, but it's nice to have the right version number in all of the files. Signed-off-by: Keith Packard --- altosui/Makefile.am | 3 ++- altosui/altos-windows.nsi | 1 + doc/altusmetrum.xsl | 8 ++++---- src/Makefile | 2 +- src/cc1111/ao_pins.h | 37 +++++++++++++++++++++++++++++++++++++ src/core/ao_telemetry.c | 2 +- src/telemetrum-v1.2/.gitignore | 2 ++ src/telemetrum-v1.2/.sdcdbrc | 1 + src/telemetrum-v1.2/Makefile | 16 ++++++++++++++++ 9 files changed, 65 insertions(+), 7 deletions(-) create mode 100644 src/telemetrum-v1.2/.gitignore create mode 100644 src/telemetrum-v1.2/.sdcdbrc create mode 100644 src/telemetrum-v1.2/Makefile (limited to 'src') diff --git a/altosui/Makefile.am b/altosui/Makefile.am index 7cd383ac..fc024fff 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -171,7 +171,8 @@ FIRMWARE_TD=$(FIRMWARE_TD_0_2) FIRMWARE_TM_1_0=$(top_srcdir)/src/telemetrum-v1.0-$(VERSION).ihx FIRMWARE_TM_1_1=$(top_srcdir)/src/telemetrum-v1.1-$(VERSION).ihx -FIRMWARE_TM=$(FIRMWARE_TM_1_0) $(FIRMWARE_TM_1_1) +FIRMWARE_TM_1_2=$(top_srcdir)/src/telemetrum-v1.2-$(VERSION).ihx +FIRMWARE_TM=$(FIRMWARE_TM_1_0) $(FIRMWARE_TM_1_1) $(FIRMWARE_TM_1_2) FIRMWARE_TELEMINI_1_0=$(top_srcdir)/src/telemini-v1.0-$(VERSION).ihx FIRMWARE_TELEMINI=$(FIRMWARE_TELEMINI_1_0) diff --git a/altosui/altos-windows.nsi b/altosui/altos-windows.nsi index cbcb389d..e5e01d79 100644 --- a/altosui/altos-windows.nsi +++ b/altosui/altos-windows.nsi @@ -112,6 +112,7 @@ Section "TeleMetrum and TeleDongle Firmware" File "../src/telemetrum-v1.0/telemetrum-v1.0-${VERSION}.ihx" File "../src/telemetrum-v1.1/telemetrum-v1.1-${VERSION}.ihx" + File "../src/telemetrum-v1.2/telemetrum-v1.2-${VERSION}.ihx" File "../src/telemini-v1.0/telemini-v1.0-${VERSION}.ihx" File "../src/teledongle-v0.2/teledongle-v0.2-${VERSION}.ihx" diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index 606c8b99..5c18fec3 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -586,7 +586,7 @@ NAR #88757, TRA #12200
Maximum Flight Log - TeleMetrum version 1.1 has 2MB of on-board flash storage, + TeleMetrum version 1.1 and 1.2 have 2MB of on-board flash storage, enough to hold over 40 minutes of data at full data rate (100 samples/second). TeleMetrum 1.0 has 1MB of on-board storage. As data are stored at a reduced rate during descent @@ -602,7 +602,7 @@ NAR #88757, TRA #12200 All of the configuration data is also stored in the flash - memory, which consumes 64kB on TeleMetrum v1.1 and 256B on + memory, which consumes 64kB on TeleMetrum v1.1/v1.2 and 256B on TeleMetrum v1.0. This configuration space is not available for storing flight log data. @@ -619,7 +619,7 @@ NAR #88757, TRA #12200 The default size, 192kB, allows for 10 flights of storage on - TeleMetrum v1.1 and 5 flights on TeleMetrum v1.0. This + TeleMetrum v1.1/v1.2 and 5 flights on TeleMetrum v1.0. This ensures that you won't need to erase the memory before flying each time while still allowing more than sufficient storage for each flight. @@ -1842,7 +1842,7 @@ NAR #88757, TRA #12200 Select the image you want put on the TeleMetrum, which should have a - name in the form telemetrum-v1.1-1.0.0.ihx. It should be visible + name in the form telemetrum-v1.2-1.0.0.ihx. It should be visible in the default directory, if not you may have to poke around your system to find it. diff --git a/src/Makefile b/src/Makefile index 61b1a835..d3173254 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,7 +13,7 @@ vpath matrix.5c kalman include Version SUBDIRS=\ - telemetrum-v1.1 telemetrum-v1.0 \ + telemetrum-v1.2 telemetrum-v1.1 telemetrum-v1.0 \ teledongle-v0.2 teledongle-v0.1 \ telemini-v1.0 telenano-v0.1 \ telebt-v0.0 telebt-v0.1 \ diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index ca85c39f..a18c74c8 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -89,6 +89,43 @@ #define HAS_MONITOR 0 #endif +#if defined(TELEMETRUM_V_1_2) + #define HAS_FLIGHT 1 + #define HAS_USB 1 + #define HAS_BEEP 1 + #define HAS_GPS 1 + #define HAS_SERIAL_1 1 + #define USE_SERIAL_STDIN 0 + #define HAS_ADC 1 + #define HAS_EEPROM 1 + #define HAS_LOG 1 + #define USE_INTERNAL_FLASH 0 + #define HAS_DBG 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 1 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 + + #define HAS_COMPANION 1 + #define COMPANION_CS_ON_P1 1 + #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ + #define COMPANION_CS P1_2 + + #define AO_LED_RED 1 + #define LEDS_AVAILABLE (AO_LED_RED) + #define HAS_EXTERNAL_TEMP 0 + #define HAS_ACCEL_REF 1 + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ + #define M25_MAX_CHIPS 1 + #define HAS_ACCEL 1 + #define HAS_IGNITE 1 + #define HAS_MONITOR 0 +#endif + #if defined(TELEDONGLE_V_0_2) #define HAS_FLIGHT 0 #define HAS_USB 1 diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index c68f1589..eb614b0f 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -35,7 +35,7 @@ static __pdata uint16_t ao_rdf_time; #define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) #define AO_RDF_LENGTH_MS 500 -#if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) || defined(TELEBALLOON_V_1_1) +#if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) || defined(TELEBALLOON_V_1_1) || defined(TELEMETRUM_V_1_2) #define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMETRUM #endif diff --git a/src/telemetrum-v1.2/.gitignore b/src/telemetrum-v1.2/.gitignore new file mode 100644 index 00000000..c2212151 --- /dev/null +++ b/src/telemetrum-v1.2/.gitignore @@ -0,0 +1,2 @@ +telemetrum-* +ao_product.h diff --git a/src/telemetrum-v1.2/.sdcdbrc b/src/telemetrum-v1.2/.sdcdbrc new file mode 100644 index 00000000..710b4a2f --- /dev/null +++ b/src/telemetrum-v1.2/.sdcdbrc @@ -0,0 +1 @@ +--directory=.. diff --git a/src/telemetrum-v1.2/Makefile b/src/telemetrum-v1.2/Makefile new file mode 100644 index 00000000..4b650adf --- /dev/null +++ b/src/telemetrum-v1.2/Makefile @@ -0,0 +1,16 @@ +# +# AltOS build +# +# + +TM_VER=1.2 +TM_DEF=1_2 + +TM_INC = + +TM_SRC = \ + ao_companion.c \ + ao_gps_skytraq.c \ + ao_m25.c + +include ../product/Makefile.telemetrum -- cgit v1.2.3 From 791c137728dd3398bd7275be13cc9e6be96d7af4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Dec 2011 15:37:28 -0800 Subject: altos: Add teleshield directory and bring-up code This is cobbled together from various existing bits, but should at least provide some ability to test a teleshield board. Signed-off-by: Keith Packard --- src/teleshield-v0.1/.gitignore | 2 + src/teleshield-v0.1/Makefile | 112 +++++++++++++++++++ src/teleshield-v0.1/ao_pins.h | 217 ++++++++++++++++++++++++++++++++++++ src/teleshield-v0.1/ao_teleshield.c | 48 ++++++++ 4 files changed, 379 insertions(+) create mode 100644 src/teleshield-v0.1/.gitignore create mode 100644 src/teleshield-v0.1/Makefile create mode 100644 src/teleshield-v0.1/ao_pins.h create mode 100644 src/teleshield-v0.1/ao_teleshield.c (limited to 'src') diff --git a/src/teleshield-v0.1/.gitignore b/src/teleshield-v0.1/.gitignore new file mode 100644 index 00000000..3ae78d33 --- /dev/null +++ b/src/teleshield-v0.1/.gitignore @@ -0,0 +1,2 @@ +teleshield-* +ao_product.h diff --git a/src/teleshield-v0.1/Makefile b/src/teleshield-v0.1/Makefile new file mode 100644 index 00000000..58c2b65a --- /dev/null +++ b/src/teleshield-v0.1/Makefile @@ -0,0 +1,112 @@ +# +# TeleShield build file +# +# The various telemetrum versions differ only +# in which flash and GPS drivers are included, +# so the per-board makefiles simply define +# TM_VER, TM_DEF, TM_INC and TM_SRC and include +# this file + +TELESHIELD_VER=0.1 +TELESHIELD_DEF=0_1 + +TELESHIELD_INC = + +TELESHIELD_SRC = \ + ao_beep.c \ + ao_btm.c \ + ao_spi.c + +vpath %.c ..:../core:../cc1111:../drivers:../product:. +vpath %.h ..:../core:../cc1111:../drivers:../product:. +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + cc1111.h \ + ao_product.h \ + $(TELESHIELD_INC) + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_monitor.c \ + ao_mutex.c \ + ao_panic.c \ + ao_state.c \ + ao_storage.c \ + ao_stdio.c \ + ao_task.c + +CC1111_SRC = \ + ao_dbg.c \ + ao_dma.c \ + ao_led.c \ + ao_intflash.c \ + ao_packet.c \ + ao_packet_master.c \ + ao_radio.c \ + ao_romconfig.c \ + ao_serial.c \ + ao_string.c \ + ao_timer.c \ + ao_usb.c \ + _bp.c + +DRIVER_SRC = \ + $(TELESHIELD_SRC) + +PRODUCT_SRC = \ + ao_teleshield.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROG = teleshield-v$(TELESHIELD_VER)-$(VERSION).ihx +PRODUCT=TeleShield-v$(TELESHIELD_VER) +PRODUCT_DEF=-DTELESHIELD_V_$(TELESHIELD_DEF) +IDPRODUCT=0x0013 +CODESIZE=0x7800 + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) + rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) + rm -f ao_product.h + rm -f ../$(PROG) ../$(PMAP) + +install: + +uninstall: + diff --git a/src/teleshield-v0.1/ao_pins.h b/src/teleshield-v0.1/ao_pins.h new file mode 100644 index 00000000..cbedb238 --- /dev/null +++ b/src/teleshield-v0.1/ao_pins.h @@ -0,0 +1,217 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#if defined(TELESHIELD_V_0_1) + #define HAS_FLIGHT 0 + #define HAS_USB 1 + #define HAS_BEEP 0 + #define HAS_SERIAL_1 1 + #define HAS_SERIAL_1_ALT_1 1 + #define HAS_SERIAL_1_ALT_2 0 + #define HAS_SERIAL_1_HW_FLOW 1 + #define USE_SERIAL_STDIN 1 + #define HAS_ADC 0 + #define HAS_DBG 1 + #define HAS_EEPROM 0 + #define HAS_LOG 0 + #define USE_INTERNAL_FLASH 1 + #define HAS_BTM 1 + #define DBG_ON_P1 1 + #define DBG_ON_P0 0 + #define IGNITE_ON_P2 0 + #define IGNITE_ON_P0 0 + #define PACKET_HAS_MASTER 1 + #define PACKET_HAS_SLAVE 0 + #define AO_LED_RED 1 + #define AO_LED_GREEN 2 + #define AO_MONITOR_LED AO_LED_RED + #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) + #define SPI_CS_ON_P1 1 + #define SPI_CS_ON_P0 0 + #define HAS_ACCEL 0 + #define HAS_IGNITE 0 + #define HAS_IGNITE_REPORT 0 + #define BT_LINK_ON_P2 0 + #define BT_LINK_ON_P1 1 + #define BT_LINK_PIN_INDEX 7 + #define BT_LINK_PIN P1_7 + #define HAS_MONITOR 1 + #define LEGACY_MONITOR 0 + #define HAS_RSSI 0 + #define HAS_AES 0 +#endif + +#if DBG_ON_P1 + + #define DBG_CLOCK (1 << 4) /* mi0 */ + #define DBG_DATA (1 << 5) /* mo0 */ + #define DBG_RESET_N (1 << 3) /* c0 */ + + #define DBG_CLOCK_PIN (P1_4) + #define DBG_DATA_PIN (P1_5) + #define DBG_RESET_N_PIN (P1_3) + + #define DBG_PORT_NUM 1 + #define DBG_PORT P1 + #define DBG_PORT_SEL P1SEL + #define DBG_PORT_INP P1INP + #define DBG_PORT_DIR P1DIR + +#endif /* DBG_ON_P1 */ + +#if DBG_ON_P0 + + #define DBG_CLOCK (1 << 3) + #define DBG_DATA (1 << 4) + #define DBG_RESET_N (1 << 5) + + #define DBG_CLOCK_PIN (P0_3) + #define DBG_DATA_PIN (P0_4) + #define DBG_RESET_N_PIN (P0_5) + + #define DBG_PORT_NUM 0 + #define DBG_PORT P0 + #define DBG_PORT_SEL P0SEL + #define DBG_PORT_INP P0INP + #define DBG_PORT_DIR P0DIR + +#endif /* DBG_ON_P0 */ + +#if COMPANION_CS_ON_P1 + #define COMPANION_CS_PORT P1 + #define COMPANION_CS_SEL P1SEL + #define COMPANION_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P1 + #define SPI_CS_PORT P1 + #define SPI_CS_SEL P1SEL + #define SPI_CS_DIR P1DIR +#endif + +#if SPI_CS_ON_P0 + #define SPI_CS_PORT P0 + #define SPI_CS_SEL P0SEL + #define SPI_CS_DIR P0DIR +#endif + +#ifndef IGNITE_ON_P2 +#error Please define IGNITE_ON_P2 +#endif + +#ifndef IGNITE_ON_P0 +#error Please define IGNITE_ON_P0 +#endif + +#ifndef HAS_SERIAL_1 +#error Please define HAS_SERIAL_1 +#endif + +#ifndef USE_SERIAL_STDIN +#error Please define USE_SERIAL_STDIN +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#ifndef HAS_EEPROM +#error Please define HAS_EEPROM +#endif + +#ifndef HAS_LOG +#error Please define HAS_LOG +#endif + +#if HAS_EEPROM +#ifndef USE_INTERNAL_FLASH +#error Please define USE_INTERNAL_FLASH +#endif +#endif + +#ifndef HAS_DBG +#error Please define HAS_DBG +#endif + +#ifndef HAS_IGNITE +#error Please define HAS_IGNITE +#endif + +#if HAS_IGNITE +#define HAS_IGNITE_REPORT 1 +#endif + +#ifndef PACKET_HAS_MASTER +#error Please define PACKET_HAS_MASTER +#endif + +#ifndef PACKET_HAS_SLAVE +#error Please define PACKET_HAS_SLAVE +#endif + +#ifndef HAS_MONITOR +#error Please define HAS_MONITOR +#endif + +#if HAS_MONITOR +#ifndef HAS_RSSI +#error Please define HAS_RSSI +#endif +#endif + +#ifndef HAS_ADC +#error Please define HAS_ADC +#endif + +#if HAS_ADC + +#if HAS_ACCEL +#ifndef HAS_ACCEL_REF +#error Please define HAS_ACCEL_REF +#endif +#else +#define HAS_ACCEL_REF 0 +#endif + +#endif /* HAS_ADC */ + +#if IGNITE_ON_P2 +#define AO_IGNITER_DROGUE P2_3 +#define AO_IGNITER_MAIN P2_4 +#define AO_IGNITER_DIR P2DIR +#define AO_IGNITER_DROGUE_BIT (1 << 3) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +#if IGNITE_ON_P0 +#define AO_IGNITER_DROGUE P0_5 +#define AO_IGNITER_MAIN P0_4 +#define AO_IGNITER_DIR P0DIR +#define AO_IGNITER_DROGUE_BIT (1 << 5) +#define AO_IGNITER_MAIN_BIT (1 << 4) +#endif + +/* test these values with real igniters */ +#define AO_IGNITER_OPEN 1000 +#define AO_IGNITER_CLOSED 7000 +#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) +#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) + +#endif /* _AO_PINS_H_ */ diff --git a/src/teleshield-v0.1/ao_teleshield.c b/src/teleshield-v0.1/ao_teleshield.c new file mode 100644 index 00000000..fc203537 --- /dev/null +++ b/src/teleshield-v0.1/ao_teleshield.c @@ -0,0 +1,48 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +__code uint8_t ao_log_format = AO_LOG_FORMAT_NONE; /* until we actually log stuff */ + +void +main(void) +{ + ao_clock_init(); + + /* Turn on the LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + ao_timer_init(); + ao_cmd_init(); + ao_spi_init(); + ao_storage_init(); + ao_usb_init(); + ao_monitor_init(); + ao_radio_init(); + ao_packet_master_init(); + ao_btm_init(); +#if HAS_DBG + ao_dbg_init(); +#endif +#if HAS_AES + ao_aes_init(); + ao_radio_cmac_init(); +#endif + ao_config_init(); + ao_start_scheduler(); +} -- cgit v1.2.3 From 4783ac9653fd4f816f839452795e0d2e52129d5b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Dec 2011 15:47:54 -0800 Subject: altos: Switch teleshield to use radio slave mode And bring it up at startup time by default Signed-off-by: Keith Packard --- src/teleshield-v0.1/Makefile | 2 +- src/teleshield-v0.1/ao_pins.h | 4 ++-- src/teleshield-v0.1/ao_teleshield.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/teleshield-v0.1/Makefile b/src/teleshield-v0.1/Makefile index 58c2b65a..b63a81d6 100644 --- a/src/teleshield-v0.1/Makefile +++ b/src/teleshield-v0.1/Makefile @@ -49,7 +49,7 @@ CC1111_SRC = \ ao_led.c \ ao_intflash.c \ ao_packet.c \ - ao_packet_master.c \ + ao_packet_slave.c \ ao_radio.c \ ao_romconfig.c \ ao_serial.c \ diff --git a/src/teleshield-v0.1/ao_pins.h b/src/teleshield-v0.1/ao_pins.h index cbedb238..1f659739 100644 --- a/src/teleshield-v0.1/ao_pins.h +++ b/src/teleshield-v0.1/ao_pins.h @@ -37,8 +37,8 @@ #define DBG_ON_P0 0 #define IGNITE_ON_P2 0 #define IGNITE_ON_P0 0 - #define PACKET_HAS_MASTER 1 - #define PACKET_HAS_SLAVE 0 + #define PACKET_HAS_MASTER 0 + #define PACKET_HAS_SLAVE 1 #define AO_LED_RED 1 #define AO_LED_GREEN 2 #define AO_MONITOR_LED AO_LED_RED diff --git a/src/teleshield-v0.1/ao_teleshield.c b/src/teleshield-v0.1/ao_teleshield.c index fc203537..3e07a955 100644 --- a/src/teleshield-v0.1/ao_teleshield.c +++ b/src/teleshield-v0.1/ao_teleshield.c @@ -34,7 +34,7 @@ main(void) ao_usb_init(); ao_monitor_init(); ao_radio_init(); - ao_packet_master_init(); + ao_packet_slave_init(1); ao_btm_init(); #if HAS_DBG ao_dbg_init(); -- cgit v1.2.3 From bbb94a6a25a106316414a9a281e924f6c56e9f38 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Dec 2011 12:27:35 -0800 Subject: altos: SDCC 3.1 wants __at instead of at Older SDCC would accept __at, so just replace all occurances unconditionally. Signed-off-by: Keith Packard --- src/cc1111/cc1111.h | 162 ++++++++++++++++++++++++++-------------------------- 1 file changed, 81 insertions(+), 81 deletions(-) (limited to 'src') diff --git a/src/cc1111/cc1111.h b/src/cc1111/cc1111.h index 11ea8bbb..70e8c9c7 100644 --- a/src/cc1111/cc1111.h +++ b/src/cc1111/cc1111.h @@ -442,12 +442,12 @@ __xdata __at (0xde17) volatile uint8_t USBCNTH; __xdata __at (0xde20) volatile uint8_t USBFIFO[12]; /* ADC Data register, low and high */ -__sfr at 0xBA ADCL; -__sfr at 0xBB ADCH; +__sfr __at 0xBA ADCL; +__sfr __at 0xBB ADCH; __xdata __at (0xDFBA) volatile uint16_t ADCXDATA; /* ADC Control Register 1 */ -__sfr at 0xB4 ADCCON1; +__sfr __at 0xB4 ADCCON1; # define ADCCON1_EOC (1 << 7) /* conversion complete */ # define ADCCON1_ST (1 << 6) /* start conversion */ @@ -463,7 +463,7 @@ __sfr at 0xB4 ADCCON1; # define ADCCON1_RCTRL_CLOCK_LFSR (1 << 2) /* Clock the LFSR once */ /* ADC Control Register 2 */ -__sfr at 0xB5 ADCCON2; +__sfr __at 0xB5 ADCCON2; # define ADCCON2_SREF_MASK (3 << 6) /* reference voltage */ # define ADCCON2_SREF_1_25V (0 << 6) /* internal 1.25V */ @@ -498,7 +498,7 @@ __sfr at 0xB5 ADCCON2; /* ADC Control Register 3 */ -__sfr at 0xB6 ADCCON3; +__sfr __at 0xB6 ADCCON3; # define ADCCON3_EREF_MASK (3 << 6) /* extra conversion reference */ # define ADCCON3_EREF_1_25 (0 << 6) /* internal 1.25V */ @@ -533,13 +533,13 @@ __sfr at 0xB6 ADCCON3; * ADC configuration register, this selects which * GPIO pins are to be used as ADC inputs */ -__sfr at 0xF2 ADCCFG; +__sfr __at 0xF2 ADCCFG; /* * Watchdog timer */ -__sfr at 0xc9 WDCTL; +__sfr __at 0xc9 WDCTL; #define WDCTL_CLEAR_FIRST (0xa << 4) #define WDCTL_CLEAR_SECOND (0x5 << 4) @@ -556,9 +556,9 @@ __sfr at 0xc9 WDCTL; * Pin selectors, these set which pins are * using their peripheral function */ -__sfr at 0xF3 P0SEL; -__sfr at 0xF4 P1SEL; -__sfr at 0xF5 P2SEL; +__sfr __at 0xF3 P0SEL; +__sfr __at 0xF4 P1SEL; +__sfr __at 0xF5 P2SEL; #define P2SEL_PRI3P1_USART0 (0 << 6) #define P2SEL_PRI3P1_USART1 (1 << 6) @@ -585,9 +585,9 @@ __sfr at 0xF5 P2SEL; /* * For pins used as GPIOs, these set which are used as outputs */ -__sfr at 0xFD P0DIR; -__sfr at 0xFE P1DIR; -__sfr at 0xFF P2DIR; +__sfr __at 0xFD P0DIR; +__sfr __at 0xFE P1DIR; +__sfr __at 0xFF P2DIR; #define P2DIR_PRIP0_USART0_USART1 (0 << 6) #define P2DIR_PRIP0_USART1_USART0 (1 << 6) @@ -595,7 +595,7 @@ __sfr at 0xFF P2DIR; #define P2DIR_PRIP0_TIMER1_2_USART0 (3 << 6) #define P2DIR_PRIP0_MASK (3 << 6) -__sfr at 0x8F P0INP; +__sfr __at 0x8F P0INP; /* Select between tri-state and pull up/down * for pins P0_0 - P0_7. @@ -617,7 +617,7 @@ __sfr at 0x8F P0INP; #define P0INP_MDP0_0_PULL (0 << 0) #define P0INP_MDP0_0_TRISTATE (1 << 0) -__sfr at 0xF6 P1INP; +__sfr __at 0xF6 P1INP; /* Select between tri-state and pull up/down * for pins P1_2 - P1_7. Pins P1_0 and P1_1 are @@ -636,7 +636,7 @@ __sfr at 0xF6 P1INP; #define P1INP_MDP1_2_PULL (0 << 2) #define P1INP_MDP1_2_TRISTATE (1 << 2) -__sfr at 0xF7 P2INP; +__sfr __at 0xF7 P2INP; /* P2INP has three extra bits which are used to choose * between pull-up and pull-down when they are not tri-stated */ @@ -662,13 +662,13 @@ __sfr at 0xF7 P2INP; #define P2INP_MDP2_0_TRISTATE (1 << 0) /* GPIO interrupt status flags */ -__sfr at 0x89 P0IFG; -__sfr at 0x8A P1IFG; -__sfr at 0x8B P2IFG; +__sfr __at 0x89 P0IFG; +__sfr __at 0x8A P1IFG; +__sfr __at 0x8B P2IFG; #define P0IFG_USB_RESUME (1 << 7) -__sfr at 0x8C PICTL; +__sfr __at 0x8C PICTL; #define PICTL_P2IEN (1 << 5) #define PICTL_P0IENH (1 << 4) #define PICTL_P0IENL (1 << 3) @@ -677,35 +677,35 @@ __sfr at 0x8C PICTL; #define PICTL_P0ICON (1 << 0) /* GPIO pins */ -__sfr at 0x80 P0; - -sbit at 0x80 P0_0; -sbit at 0x81 P0_1; -sbit at 0x82 P0_2; -sbit at 0x83 P0_3; -sbit at 0x84 P0_4; -sbit at 0x85 P0_5; -sbit at 0x86 P0_6; -sbit at 0x87 P0_7; - -__sfr at 0x90 P1; - -sbit at 0x90 P1_0; -sbit at 0x91 P1_1; -sbit at 0x92 P1_2; -sbit at 0x93 P1_3; -sbit at 0x94 P1_4; -sbit at 0x95 P1_5; -sbit at 0x96 P1_6; -sbit at 0x97 P1_7; - -__sfr at 0xa0 P2; - -sbit at 0xa0 P2_0; -sbit at 0xa1 P2_1; -sbit at 0xa2 P2_2; -sbit at 0xa3 P2_3; -sbit at 0xa4 P2_4; +__sfr __at 0x80 P0; + +sbit __at 0x80 P0_0; +sbit __at 0x81 P0_1; +sbit __at 0x82 P0_2; +sbit __at 0x83 P0_3; +sbit __at 0x84 P0_4; +sbit __at 0x85 P0_5; +sbit __at 0x86 P0_6; +sbit __at 0x87 P0_7; + +__sfr __at 0x90 P1; + +sbit __at 0x90 P1_0; +sbit __at 0x91 P1_1; +sbit __at 0x92 P1_2; +sbit __at 0x93 P1_3; +sbit __at 0x94 P1_4; +sbit __at 0x95 P1_5; +sbit __at 0x96 P1_6; +sbit __at 0x97 P1_7; + +__sfr __at 0xa0 P2; + +sbit __at 0xa0 P2_0; +sbit __at 0xa1 P2_1; +sbit __at 0xa2 P2_2; +sbit __at 0xa3 P2_3; +sbit __at 0xa4 P2_4; /* DMA controller */ struct cc_dma_channel { @@ -794,7 +794,7 @@ struct cc_dma_channel { * DMAARM - DMA Channel Arm */ -__sfr at 0xD6 DMAARM; +__sfr __at 0xD6 DMAARM; # define DMAARM_ABORT (1 << 7) # define DMAARM_DMAARM4 (1 << 4) @@ -807,7 +807,7 @@ __sfr at 0xD6 DMAARM; * DMAREQ - DMA Channel Start Request and Status */ -__sfr at 0xD7 DMAREQ; +__sfr __at 0xD7 DMAREQ; # define DMAREQ_DMAREQ4 (1 << 4) # define DMAREQ_DMAREQ3 (1 << 3) @@ -819,21 +819,21 @@ __sfr at 0xD7 DMAREQ; * DMA configuration 0 address */ -__sfr at 0xD5 DMA0CFGH; -__sfr at 0xD4 DMA0CFGL; +__sfr __at 0xD5 DMA0CFGH; +__sfr __at 0xD4 DMA0CFGL; /* * DMA configuration 1-4 address */ -__sfr at 0xD3 DMA1CFGH; -__sfr at 0xD2 DMA1CFGL; +__sfr __at 0xD3 DMA1CFGH; +__sfr __at 0xD2 DMA1CFGL; /* * DMAIRQ - DMA Interrupt Flag */ -__sfr at 0xD1 DMAIRQ; +__sfr __at 0xD1 DMAIRQ; # define DMAIRQ_DMAIF4 (1 << 4) # define DMAIRQ_DMAIF3 (1 << 3) @@ -846,8 +846,8 @@ __sfr at 0xD1 DMAIRQ; */ /* USART config/status registers */ -__sfr at 0x86 U0CSR; -__sfr at 0xF8 U1CSR; +__sfr __at 0x86 U0CSR; +__sfr __at 0xF8 U1CSR; # define UxCSR_MODE_UART (1 << 7) # define UxCSR_MODE_SPI (0 << 7) @@ -861,8 +861,8 @@ __sfr at 0xF8 U1CSR; # define UxCSR_ACTIVE (1 << 0) /* UART configuration registers */ -__sfr at 0xc4 U0UCR; -__sfr at 0xfb U1UCR; +__sfr __at 0xc4 U0UCR; +__sfr __at 0xfb U1UCR; # define UxUCR_FLUSH (1 << 7) # define UxUCR_FLOW_DISABLE (0 << 6) @@ -881,8 +881,8 @@ __sfr at 0xfb U1UCR; # define UxUCR_START_HIGH (1 << 0) /* USART General configuration registers (mostly SPI) */ -__sfr at 0xc5 U0GCR; -__sfr at 0xfc U1GCR; +__sfr __at 0xc5 U0GCR; +__sfr __at 0xfc U1GCR; # define UxGCR_CPOL_NEGATIVE (0 << 7) # define UxGCR_CPOL_POSITIVE (1 << 7) @@ -894,18 +894,18 @@ __sfr at 0xfc U1GCR; # define UxGCR_BAUD_E_SHIFT 0 /* USART data registers */ -__sfr at 0xc1 U0DBUF; +__sfr __at 0xc1 U0DBUF; __xdata __at (0xDFC1) volatile uint8_t U0DBUFXADDR; -__sfr at 0xf9 U1DBUF; +__sfr __at 0xf9 U1DBUF; __xdata __at (0xDFF9) volatile uint8_t U1DBUFXADDR; /* USART baud rate registers, M value */ -__sfr at 0xc2 U0BAUD; -__sfr at 0xfa U1BAUD; +__sfr __at 0xc2 U0BAUD; +__sfr __at 0xfa U1BAUD; /* Flash controller */ -__sfr at 0xAE FCTL; +__sfr __at 0xAE FCTL; #define FCTL_BUSY (1 << 7) #define FCTL_SWBSY (1 << 6) #define FCTL_CONTRD_ENABLE (1 << 4) @@ -913,22 +913,22 @@ __sfr at 0xAE FCTL; #define FCTL_ERASE (1 << 0) /* Flash write data. Write two bytes here */ -__sfr at 0xAF FWDATA; +__sfr __at 0xAF FWDATA; __xdata __at (0xDFAF) volatile uint8_t FWDATAXADDR; /* Flash write/erase address */ -__sfr at 0xAD FADDRH; -__sfr at 0xAC FADDRL; +__sfr __at 0xAD FADDRH; +__sfr __at 0xAC FADDRL; /* Flash timing */ -__sfr at 0xAB FWT; +__sfr __at 0xAB FWT; /* Radio */ -__sfr at 0xD9 RFD; -__xdata at (0xDFD9) volatile uint8_t RFDXADDR; +__sfr __at 0xD9 RFD; +__xdata __at (0xDFD9) volatile uint8_t RFDXADDR; -__sfr at 0xE9 RFIF; +__sfr __at 0xE9 RFIF; #define RFIF_IM_TXUNF (1 << 7) #define RFIF_IM_RXOVF (1 << 6) #define RFIF_IM_TIMEOUT (1 << 5) @@ -938,7 +938,7 @@ __sfr at 0xE9 RFIF; #define RFIF_IM_CCA (1 << 1) #define RFIF_IM_SFD (1 << 0) -__sfr at 0x91 RFIM; +__sfr __at 0x91 RFIM; #define RFIM_IM_TXUNF (1 << 7) #define RFIM_IM_RXOVF (1 << 6) #define RFIM_IM_TIMEOUT (1 << 5) @@ -948,7 +948,7 @@ __sfr at 0x91 RFIM; #define RFIM_IM_CCA (1 << 1) #define RFIM_IM_SFD (1 << 0) -__sfr at 0xE1 RFST; +__sfr __at 0xE1 RFST; #define RFST_SFSTXON 0x00 #define RFST_SCAL 0x01 @@ -1305,12 +1305,12 @@ __xdata __at (0xdf3d) uint8_t RF_VCO_VC_DAC; /* AES engine */ -__sfr at 0xB1 ENCDI; -__sfr at 0xB2 ENCDO; -__xdata at (0xDFB1) volatile uint8_t ENCDIXADDR; -__xdata at (0xDFB2) volatile uint8_t ENCDOXADDR; +__sfr __at 0xB1 ENCDI; +__sfr __at 0xB2 ENCDO; +__xdata __at (0xDFB1) volatile uint8_t ENCDIXADDR; +__xdata __at (0xDFB2) volatile uint8_t ENCDOXADDR; -__sfr at 0xB3 ENCCCS; +__sfr __at 0xB3 ENCCCS; #define ENCCCS_MODE_CBC (0 << 4) #define ENCCCS_MODE_CFB (1 << 4) -- cgit v1.2.3 From 614ab6a991258a5caad0ca12ae35d0288a5b7503 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Dec 2011 15:38:32 -0800 Subject: altos: Clean up for SDCC 3.1 - more keywords _asm -> __asm sbit -> __sbit remove variables named 'data' Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 14 ++++---- src/cc1111/cc1111.h | 100 +++++++++++++++++++++++++-------------------------- src/core/ao.h | 12 +++---- 3 files changed, 63 insertions(+), 63 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index eb8ce9be..e6c27a1e 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -45,7 +45,7 @@ ao_delay(AO_SEC_TO_TICKS(2)); \ } while (0) -#define ao_arch_nop() _asm nop _endasm +#define ao_arch_nop() __asm nop __endasm #define ao_arch_interrupt(n) __interrupt n #define ao_arch_naked_declare __naked @@ -106,7 +106,7 @@ extern __code __at (0x00a6) uint32_t ao_radio_cal; /* Save current context */ #define ao_arch_save_regs() \ - _asm \ + __asm \ /* Push ACC first, as when restoring the context it must be restored \ * last (it is used to set the IE register). */ \ push ACC \ @@ -125,11 +125,11 @@ extern __code __at (0x00a6) uint32_t ao_radio_cal; push ar0 \ push ar1 \ push PSW \ - _endasm; \ + __endasm; \ PSW = 0; \ - _asm \ + __asm \ push _bp \ - _endasm + __endasm #define ao_arch_save_stack() { \ uint8_t stack_len; \ @@ -166,7 +166,7 @@ extern __code __at (0x00a6) uint32_t ao_radio_cal; *stack_ptr++ = *save_ptr++; \ while (--stack_len); \ \ - _asm \ + __asm \ pop _bp \ pop PSW \ pop ar1 \ @@ -193,7 +193,7 @@ extern __code __at (0x00a6) uint32_t ao_radio_cal; /* Finally pop off the ACC, which was the first register saved. */ \ pop ACC \ ret \ - _endasm; \ + __endasm; \ } #define ao_arch_critical(b) __critical { b } diff --git a/src/cc1111/cc1111.h b/src/cc1111/cc1111.h index 70e8c9c7..80d3fb70 100644 --- a/src/cc1111/cc1111.h +++ b/src/cc1111/cc1111.h @@ -42,14 +42,14 @@ __sfr __at 0xA8 IEN0; /* Interrupt Enable 0 Register */ -sbit __at 0xA8 RFTXRXIE; /* RF TX/RX done interrupt enable */ -sbit __at 0xA9 ADCIE; /* ADC interrupt enable */ -sbit __at 0xAA URX0IE; /* USART0 RX interrupt enable */ -sbit __at 0xAB URX1IE; /* USART1 RX interrupt enable (shared with I2S RX) */ -sbit __at 0xAB I2SRXIE; /* I2S RX interrupt enable (shared with USART1 RX) */ -sbit __at 0xAC ENCIE; /* AES encryption/decryption interrupt enable */ -sbit __at 0xAD STIE; /* Sleep Timer interrupt enable */ -sbit __at 0xAF EA; /* Enable All */ +__sbit __at 0xA8 RFTXRXIE; /* RF TX/RX done interrupt enable */ +__sbit __at 0xA9 ADCIE; /* ADC interrupt enable */ +__sbit __at 0xAA URX0IE; /* USART0 RX interrupt enable */ +__sbit __at 0xAB URX1IE; /* USART1 RX interrupt enable (shared with I2S RX) */ +__sbit __at 0xAB I2SRXIE; /* I2S RX interrupt enable (shared with USART1 RX) */ +__sbit __at 0xAC ENCIE; /* AES encryption/decryption interrupt enable */ +__sbit __at 0xAD STIE; /* Sleep Timer interrupt enable */ +__sbit __at 0xAF EA; /* Enable All */ #define IEN0_EA (1 << 7) #define IEN0_STIE (1 << 5) @@ -135,11 +135,11 @@ __sfr __at 0x87 PCON; /* Power Mode Control Register */ */ __sfr __at 0x88 TCON; /* CPU Interrupt Flag 1 */ -sbit __at 0x8F URX1IF; /* USART1 RX interrupt flag. Automatically cleared */ -sbit __at 0x8F I2SRXIF; /* I2S RX interrupt flag. Automatically cleared */ -sbit __at 0x8D ADCIF; /* ADC interrupt flag. Automatically cleared */ -sbit __at 0x8B URX0IF; /* USART0 RX interrupt flag. Automatically cleared */ -sbit __at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically cleared */ +__sbit __at 0x8F URX1IF; /* USART1 RX interrupt flag. Automatically cleared */ +__sbit __at 0x8F I2SRXIF; /* I2S RX interrupt flag. Automatically cleared */ +__sbit __at 0x8D ADCIF; /* ADC interrupt flag. Automatically cleared */ +__sbit __at 0x8B URX0IF; /* USART0 RX interrupt flag. Automatically cleared */ +__sbit __at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically cleared */ #define TCON_URX1IF (1 << 7) #define TCON_I2SRXIF (1 << 7) @@ -152,8 +152,8 @@ sbit __at 0x89 RFTXRXIF; /* RF TX/RX complete interrupt flag. Automatically clea */ __sfr __at 0x98 S0CON; /* CPU Interrupt Flag 2 */ -sbit __at 0x98 ENCIF_0; /* AES interrupt 0. */ -sbit __at 0x99 ENCIF_1; /* AES interrupt 1. */ +__sbit __at 0x98 ENCIF_0; /* AES interrupt 0. */ +__sbit __at 0x99 ENCIF_1; /* AES interrupt 1. */ #define S0CON_ENCIF_1 (1 << 1) #define S0CON_ENCIF_0 (1 << 0) @@ -171,13 +171,13 @@ __sfr __at 0x9B S1CON; /* CPU Interrupt Flag 3 */ */ __sfr __at 0xC0 IRCON; /* CPU Interrupt Flag 4 */ -sbit __at 0xC0 DMAIF; /* DMA complete interrupt flag */ -sbit __at 0xC1 T1IF; /* Timer 1 interrupt flag. Automatically cleared */ -sbit __at 0xC2 T2IF; /* Timer 2 interrupt flag. Automatically cleared */ -sbit __at 0xC3 T3IF; /* Timer 3 interrupt flag. Automatically cleared */ -sbit __at 0xC4 T4IF; /* Timer 4 interrupt flag. Automatically cleared */ -sbit __at 0xC5 P0IF; /* Port0 interrupt flag */ -sbit __at 0xC7 STIF; /* Sleep Timer interrupt flag */ +__sbit __at 0xC0 DMAIF; /* DMA complete interrupt flag */ +__sbit __at 0xC1 T1IF; /* Timer 1 interrupt flag. Automatically cleared */ +__sbit __at 0xC2 T2IF; /* Timer 2 interrupt flag. Automatically cleared */ +__sbit __at 0xC3 T3IF; /* Timer 3 interrupt flag. Automatically cleared */ +__sbit __at 0xC4 T4IF; /* Timer 4 interrupt flag. Automatically cleared */ +__sbit __at 0xC5 P0IF; /* Port0 interrupt flag */ +__sbit __at 0xC7 STIF; /* Sleep Timer interrupt flag */ #define IRCON_DMAIF (1 << 0) /* DMA complete interrupt flag */ #define IRCON_T1IF (1 << 1) /* Timer 1 interrupt flag. Automatically cleared */ @@ -192,13 +192,13 @@ sbit __at 0xC7 STIF; /* Sleep Timer interrupt flag */ */ __sfr __at 0xE8 IRCON2; /* CPU Interrupt Flag 5 */ -sbit __at 0xE8 USBIF; /* USB interrupt flag (shared with Port2) */ -sbit __at 0xE8 P2IF; /* Port2 interrupt flag (shared with USB) */ -sbit __at 0xE9 UTX0IF; /* USART0 TX interrupt flag */ -sbit __at 0xEA UTX1IF; /* USART1 TX interrupt flag (shared with I2S TX) */ -sbit __at 0xEA I2STXIF; /* I2S TX interrupt flag (shared with USART1 TX) */ -sbit __at 0xEB P1IF; /* Port1 interrupt flag */ -sbit __at 0xEC WDTIF; /* Watchdog timer interrupt flag */ +__sbit __at 0xE8 USBIF; /* USB interrupt flag (shared with Port2) */ +__sbit __at 0xE8 P2IF; /* Port2 interrupt flag (shared with USB) */ +__sbit __at 0xE9 UTX0IF; /* USART0 TX interrupt flag */ +__sbit __at 0xEA UTX1IF; /* USART1 TX interrupt flag (shared with I2S TX) */ +__sbit __at 0xEA I2STXIF; /* I2S TX interrupt flag (shared with USART1 TX) */ +__sbit __at 0xEB P1IF; /* Port1 interrupt flag */ +__sbit __at 0xEC WDTIF; /* Watchdog timer interrupt flag */ #define IRCON2_USBIF (1 << 0) /* USB interrupt flag (shared with Port2) */ #define IRCON2_P2IF (1 << 0) /* Port2 interrupt flag (shared with USB) */ @@ -679,33 +679,33 @@ __sfr __at 0x8C PICTL; /* GPIO pins */ __sfr __at 0x80 P0; -sbit __at 0x80 P0_0; -sbit __at 0x81 P0_1; -sbit __at 0x82 P0_2; -sbit __at 0x83 P0_3; -sbit __at 0x84 P0_4; -sbit __at 0x85 P0_5; -sbit __at 0x86 P0_6; -sbit __at 0x87 P0_7; +__sbit __at 0x80 P0_0; +__sbit __at 0x81 P0_1; +__sbit __at 0x82 P0_2; +__sbit __at 0x83 P0_3; +__sbit __at 0x84 P0_4; +__sbit __at 0x85 P0_5; +__sbit __at 0x86 P0_6; +__sbit __at 0x87 P0_7; __sfr __at 0x90 P1; -sbit __at 0x90 P1_0; -sbit __at 0x91 P1_1; -sbit __at 0x92 P1_2; -sbit __at 0x93 P1_3; -sbit __at 0x94 P1_4; -sbit __at 0x95 P1_5; -sbit __at 0x96 P1_6; -sbit __at 0x97 P1_7; +__sbit __at 0x90 P1_0; +__sbit __at 0x91 P1_1; +__sbit __at 0x92 P1_2; +__sbit __at 0x93 P1_3; +__sbit __at 0x94 P1_4; +__sbit __at 0x95 P1_5; +__sbit __at 0x96 P1_6; +__sbit __at 0x97 P1_7; __sfr __at 0xa0 P2; -sbit __at 0xa0 P2_0; -sbit __at 0xa1 P2_1; -sbit __at 0xa2 P2_2; -sbit __at 0xa3 P2_3; -sbit __at 0xa4 P2_4; +__sbit __at 0xa0 P2_0; +__sbit __at 0xa1 P2_1; +__sbit __at 0xa2 P2_2; +__sbit __at 0xa3 P2_3; +__sbit __at 0xa4 P2_4; /* DMA controller */ struct cc_dma_channel { diff --git a/src/core/ao.h b/src/core/ao.h index 8bd7a3d2..1fbcf7df 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -376,7 +376,7 @@ struct ao_cmds { }; void -ao_cmd_register(__code struct ao_cmds *cmds); +ao_cmd_register(const __code struct ao_cmds *cmds); void ao_cmd_init(void); @@ -1352,10 +1352,10 @@ void ao_radio_set_packet(void); void -ao_radio_send(__xdata void *data, uint8_t size) __reentrant; +ao_radio_send(__xdata void *d, uint8_t size) __reentrant; uint8_t -ao_radio_recv(__xdata void *data, uint8_t size) __reentrant; +ao_radio_recv(__xdata void *d, uint8_t size) __reentrant; void ao_radio_recv_abort(void); @@ -1708,7 +1708,7 @@ ao_companion_init(void); /* ao_lcd.c */ void -ao_lcd_putchar(uint8_t data); +ao_lcd_putchar(uint8_t d); void ao_lcd_putstring(char *string); @@ -1739,14 +1739,14 @@ ao_lcd_init(void); /* ao_lcd_port.c */ void -ao_lcd_port_put_nibble(uint8_t rs, uint8_t data); +ao_lcd_port_put_nibble(uint8_t rs, uint8_t d); void ao_lcd_port_init(void); /* ao_aes.c */ -__xdata uint8_t ao_aes_mutex; +extern __xdata uint8_t ao_aes_mutex; /* AES keys and blocks are 128 bits */ -- cgit v1.2.3 From 085625ff3992454b59583d95a3c415597c51f754 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 30 Dec 2011 15:42:28 -0800 Subject: altos: More _asm -> __asm changes Missed a few last time Signed-off-by: Keith Packard --- src/cc1111/ao_dbg.c | 6 +++--- src/cc1111/ao_dma.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_dbg.c b/src/cc1111/ao_dbg.c index d4c9567f..847b5aaf 100644 --- a/src/cc1111/ao_dbg.c +++ b/src/cc1111/ao_dbg.c @@ -22,10 +22,10 @@ static void ao_dbg_send_bits(uint8_t msk, uint8_t val) __reentrant { DBG_PORT = (DBG_PORT & ~msk) | (val & msk); - _asm + __asm nop nop - _endasm; + __endasm; } void @@ -187,7 +187,7 @@ ao_dbg_long_delay(void) uint8_t n; for (n = 0; n < 20; n++) - _asm nop _endasm; + __asm nop __endasm; } #define AO_RESET_LOW_DELAY AO_MS_TO_TICKS(100) diff --git a/src/cc1111/ao_dma.c b/src/cc1111/ao_dma.c index ca33facb..8779ddf4 100644 --- a/src/cc1111/ao_dma.c +++ b/src/cc1111/ao_dma.c @@ -75,7 +75,7 @@ ao_dma_set_transfer(uint8_t id, ao_dma_config[id].cfg1 = cfg1 | DMA_CFG1_IRQMASK; } -#define nop() _asm nop _endasm; +#define nop() __asm nop __endasm; void ao_dma_start(uint8_t id) -- cgit v1.2.3 From 7a42f2e0f145d2d520aed8e241fa39f7cb62b19f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Jan 2012 20:41:15 -0800 Subject: altos: Add support for UART0 in async mode And copy bytes from it to stdout. Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 7 ++ src/cc1111/ao_serial.c | 5 +- src/cc1111/ao_serial0.c | 152 +++++++++++++++++++++++++++++++++++ src/core/ao.h | 29 +++++++ src/teleshield-v0.1/Makefile | 4 +- src/teleshield-v0.1/ao_ardu_serial.c | 38 +++++++++ src/teleshield-v0.1/ao_pins.h | 8 ++ src/teleshield-v0.1/ao_teleshield.c | 1 + 8 files changed, 239 insertions(+), 5 deletions(-) create mode 100644 src/cc1111/ao_serial0.c create mode 100644 src/teleshield-v0.1/ao_ardu_serial.c (limited to 'src') diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index e6c27a1e..360b35c8 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -251,4 +251,11 @@ _ao_xmemcmp(__xdata void *a, __xdata void *b, uint8_t count); #define ao_xmemcmp(d,s,c) _ao_xmemcmp((d), (s), (c)) +struct ao_serial_speed { + uint8_t baud; + uint8_t gcr; +}; + +extern const __code struct ao_serial_speed ao_serial_speeds[]; + #endif /* _AO_ARCH_H_ */ diff --git a/src/cc1111/ao_serial.c b/src/cc1111/ao_serial.c index 82370c64..4d5b9abd 100644 --- a/src/cc1111/ao_serial.c +++ b/src/cc1111/ao_serial.c @@ -91,10 +91,7 @@ ao_serial_drain(void) __critical ao_sleep(&ao_usart1_tx_fifo); } -static __code struct { - uint8_t baud; - uint8_t gcr; -} ao_serial_speeds[] = { +const __code struct ao_serial_speed ao_serial_speeds[] = { /* [AO_SERIAL_SPEED_4800] = */ { /* .baud = */ 163, /* .gcr = */ (7 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB diff --git a/src/cc1111/ao_serial0.c b/src/cc1111/ao_serial0.c new file mode 100644 index 00000000..140721b1 --- /dev/null +++ b/src/cc1111/ao_serial0.c @@ -0,0 +1,152 @@ +/* + * 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" + +volatile __xdata struct ao_fifo ao_usart0_rx_fifo; +volatile __xdata struct ao_fifo ao_usart0_tx_fifo; + +void +ao_serial0_rx0_isr(void) __interrupt 2 +{ + if (!ao_fifo_full(ao_usart0_rx_fifo)) + ao_fifo_insert(ao_usart0_rx_fifo, U0DBUF); + ao_wakeup(&ao_usart0_rx_fifo); +} + +static __xdata uint8_t ao_serial0_tx0_started; + +static void +ao_serial0_tx0_start(void) +{ + if (!ao_fifo_empty(ao_usart0_tx_fifo) && + !ao_serial0_tx0_started) + { + ao_serial0_tx0_started = 1; + ao_fifo_remove(ao_usart0_tx_fifo, U0DBUF); + } +} + +void +ao_serial0_tx0_isr(void) __interrupt 7 +{ + UTX0IF = 0; + ao_serial0_tx0_started = 0; + ao_serial0_tx0_start(); + ao_wakeup(&ao_usart0_tx_fifo); +} + +char +ao_serial0_getchar(void) __critical +{ + char c; + while (ao_fifo_empty(ao_usart0_rx_fifo)) + ao_sleep(&ao_usart0_rx_fifo); + ao_fifo_remove(ao_usart0_rx_fifo, c); + return c; +} + +#if USE_SERIAL_STDIN +char +ao_serial0_pollchar(void) __critical +{ + char c; + if (ao_fifo_empty(ao_usart0_rx_fifo)) + return AO_READ_AGAIN; + ao_fifo_remove(ao_usart0_rx_fifo,c); + return c; +} +#endif + +void +ao_serial0_putchar(char c) __critical +{ + while (ao_fifo_full(ao_usart0_tx_fifo)) + ao_sleep(&ao_usart0_tx_fifo); + ao_fifo_insert(ao_usart0_tx_fifo, c); + ao_serial0_tx0_start(); +} + +void +ao_serial0_drain(void) __critical +{ + while (!ao_fifo_empty(ao_usart0_tx_fifo)) + ao_sleep(&ao_usart0_tx_fifo); +} + +void +ao_serial0_set_speed(uint8_t speed) +{ + ao_serial0_drain(); + if (speed > AO_SERIAL_SPEED_57600) + return; + U1UCR |= UxUCR_FLUSH; + U1BAUD = ao_serial_speeds[speed].baud; + U1GCR = ao_serial_speeds[speed].gcr; +} + +void +ao_serial0_init(void) +{ +#if HAS_SERIAL_0_ALT_1 + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_1; + + P2DIR = (P2DIR & ~P2DIR_PRIP0_MASK) | P2DIR_PRIP0_USART0_USART1; + + /* Make the USART pins be controlled by the USART */ + P0SEL |= (1 << 2) | (1 << 3); +#if HAS_SERIAL_0_HW_FLOW + P0SEL |= (1 << 4) | (1 << 5); +#endif +#else + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2; + + P2SEL = (P2SEL & ~(P2SEL_PRI3P1_MASK | P2SEL_PRI0P1_MASK)) | + (P2SEL_PRI3P1_USART0 | P2SEL_PRI0P1_USART0); + + /* Make the USART pins be controlled by the USART */ + P1SEL |= (1 << 2) | (1 << 3); +#if HAS_SERIAL_0_HW_FLOW + P1SEL |= (1 << 5) | (1 << 4); +#endif +#endif + + /* UART mode with receiver enabled */ + U0CSR = (UxCSR_MODE_UART | UxCSR_RE); + + /* Pick a 9600 baud rate */ + ao_serial0_set_speed(AO_SERIAL_SPEED_9600); + + /* Reasonable serial parameters */ + U0UCR = (UxUCR_FLUSH | +#if HAS_SERIAL_0_HW_FLOW + UxUCR_FLOW_ENABLE | +#else + UxUCR_FLOW_DISABLE | +#endif + UxUCR_D9_EVEN_PARITY | + UxUCR_BIT9_8_BITS | + UxUCR_PARITY_DISABLE | + UxUCR_SPB_1_STOP_BIT | + UxUCR_STOP_HIGH | + UxUCR_START_LOW); + + IEN0 |= IEN0_URX0IE; + IEN2 |= IEN2_UTX0IE; +} diff --git a/src/core/ao.h b/src/core/ao.h index 1fbcf7df..494993f1 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -938,6 +938,35 @@ void ao_serial_init(void); #endif +#ifndef HAS_SERIAL_0 +#define HAS_SERIAL_0 0 +#endif + +#if HAS_SERIAL_0 +void +ao_serial0_rx0_isr(void) ao_arch_interrupt(2); + +void +ao_serial0_tx0_isr(void) ao_arch_interrupt(7); + +char +ao_serial0_getchar(void) __critical; + +void +ao_serial0_putchar(char c) __critical; + +void +ao_serial0_drain(void) __critical; + +void +ao_serial0_set_speed(uint8_t speed); + +void +ao_serial0_init(void); + +#endif + + /* * ao_spi.c */ diff --git a/src/teleshield-v0.1/Makefile b/src/teleshield-v0.1/Makefile index b63a81d6..a21a6052 100644 --- a/src/teleshield-v0.1/Makefile +++ b/src/teleshield-v0.1/Makefile @@ -53,6 +53,7 @@ CC1111_SRC = \ ao_radio.c \ ao_romconfig.c \ ao_serial.c \ + ao_serial0.c \ ao_string.c \ ao_timer.c \ ao_usb.c \ @@ -62,7 +63,8 @@ DRIVER_SRC = \ $(TELESHIELD_SRC) PRODUCT_SRC = \ - ao_teleshield.c + ao_teleshield.c \ + ao_ardu_serial.c SRC = \ $(CORE_SRC) \ diff --git a/src/teleshield-v0.1/ao_ardu_serial.c b/src/teleshield-v0.1/ao_ardu_serial.c new file mode 100644 index 00000000..7d4dc0db --- /dev/null +++ b/src/teleshield-v0.1/ao_ardu_serial.c @@ -0,0 +1,38 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static void +ao_ardu_serial_recv(void) +{ + char c; + + for (;;) { + c = ao_serial0_getchar(); + putchar (c); + } +} + +static __xdata struct ao_task ao_ardu_serial_recv_task; + +void +ao_ardu_serial_init (void) +{ + ao_serial0_init(); + ao_add_task(&ao_ardu_serial_recv_task, ao_ardu_serial_recv, "recv"); +} diff --git a/src/teleshield-v0.1/ao_pins.h b/src/teleshield-v0.1/ao_pins.h index 1f659739..a907e2a5 100644 --- a/src/teleshield-v0.1/ao_pins.h +++ b/src/teleshield-v0.1/ao_pins.h @@ -27,6 +27,10 @@ #define HAS_SERIAL_1_ALT_2 0 #define HAS_SERIAL_1_HW_FLOW 1 #define USE_SERIAL_STDIN 1 + #define HAS_SERIAL_0 1 + #define HAS_SERIAL_0_ALT_1 0 + #define HAS_SERIAL_0_ALT_2 1 + #define HAS_SERIAL_0_HW_FLOW 0 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 @@ -214,4 +218,8 @@ #define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) #define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) +void +ao_ardu_serial_init (void); + + #endif /* _AO_PINS_H_ */ diff --git a/src/teleshield-v0.1/ao_teleshield.c b/src/teleshield-v0.1/ao_teleshield.c index 3e07a955..fd12ce7a 100644 --- a/src/teleshield-v0.1/ao_teleshield.c +++ b/src/teleshield-v0.1/ao_teleshield.c @@ -43,6 +43,7 @@ main(void) ao_aes_init(); ao_radio_cmac_init(); #endif + ao_ardu_serial_init(); ao_config_init(); ao_start_scheduler(); } -- cgit v1.2.3 From 65b9b5d0d91fef2c7452dc77017f31f176672304 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Jan 2012 20:42:41 -0800 Subject: Build teleshield by default --- src/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index d3173254..e5d0c960 100644 --- a/src/Makefile +++ b/src/Makefile @@ -20,7 +20,7 @@ SUBDIRS=\ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ telelaunch-v0.1 \ tidongle test telescience-v0.1 telepyro-v0.1 \ - teleterra-v0.2 + teleterra-v0.2 teleshield-v0.1 all: all-local all-recursive -- cgit v1.2.3 From c6821ae734a7efaf2e069f6c5edf9605a9dbe125 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Jan 2012 20:46:25 -0800 Subject: altos: flush stdout when fifo from arduino serial port is empty This avoids leaving bytes pending inside altos Signed-off-by: Keith Packard --- src/core/ao.h | 4 ++++ src/teleshield-v0.1/ao_ardu_serial.c | 2 ++ 2 files changed, 6 insertions(+) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 494993f1..8c5335c4 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -943,6 +943,10 @@ ao_serial_init(void); #endif #if HAS_SERIAL_0 + +extern volatile __xdata struct ao_fifo ao_usart0_rx_fifo; +extern volatile __xdata struct ao_fifo ao_usart0_tx_fifo; + void ao_serial0_rx0_isr(void) ao_arch_interrupt(2); diff --git a/src/teleshield-v0.1/ao_ardu_serial.c b/src/teleshield-v0.1/ao_ardu_serial.c index 7d4dc0db..7ff859af 100644 --- a/src/teleshield-v0.1/ao_ardu_serial.c +++ b/src/teleshield-v0.1/ao_ardu_serial.c @@ -23,6 +23,8 @@ ao_ardu_serial_recv(void) char c; for (;;) { + if (ao_fifo_empty(ao_usart0_rx_fifo)) + flush(); c = ao_serial0_getchar(); putchar (c); } -- cgit v1.2.3 From f450f8bc70f857053b26c4379f54a318062e89a1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Jan 2012 22:27:59 -0800 Subject: altos: Set correct registers for serial0 baud oops. not going to work very well setting serial 1. Signed-off-by: Keith Packard --- src/cc1111/ao_serial0.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_serial0.c b/src/cc1111/ao_serial0.c index 140721b1..e8c1eb35 100644 --- a/src/cc1111/ao_serial0.c +++ b/src/cc1111/ao_serial0.c @@ -94,9 +94,9 @@ ao_serial0_set_speed(uint8_t speed) ao_serial0_drain(); if (speed > AO_SERIAL_SPEED_57600) return; - U1UCR |= UxUCR_FLUSH; - U1BAUD = ao_serial_speeds[speed].baud; - U1GCR = ao_serial_speeds[speed].gcr; + U0UCR |= UxUCR_FLUSH; + U0BAUD = ao_serial_speeds[speed].baud; + U0GCR = ao_serial_speeds[speed].gcr; } void -- cgit v1.2.3 From 77639dae0fb9975219c2e211ea6dd6c7965eeea2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Sep 2011 23:50:43 -0700 Subject: altos: Require callsign match in packet code Ignore packets with mismatching callsigns to avoid accidental connections between devices controlled by different stations. As a special case, if the device is configured with the default callsign (N0CALL), then let anyone connect. This allows configuration of new devices without needing to change the ground station callsign. Signed-off-by: Keith Packard --- src/cc1111/ao_packet.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/cc1111/ao_packet.c b/src/cc1111/ao_packet.c index f502d67c..7eeb0710 100644 --- a/src/cc1111/ao_packet.c +++ b/src/cc1111/ao_packet.c @@ -68,6 +68,15 @@ ao_packet_recv(void) if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) return 0; + /* Accept packets with matching call signs, or any packet if + * our callsign hasn't been configured + */ + if (ao_xmemcmp(ao_rx_packet.packet.callsign, + ao_config.callsign, + AO_MAX_CALLSIGN) != 0 && + ao_xmemcmp(ao_config.callsign, CODE_TO_XDATA("N0CALL"), 7) != 0) + return 0; + /* SYN packets carry no data */ if (ao_rx_packet.packet.len == AO_PACKET_SYN) { rx_seq = ao_rx_packet.packet.seq; -- cgit v1.2.3 From c1d12a117b36de7fe8dd992959b890bfd1163e81 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 26 Mar 2012 23:35:35 -0700 Subject: Do radio settings solely by frequency Compute the radio setting needed based on the calibration value provided and the requested frequency. Signed-off-by: Keith Packard --- src/core/ao.h | 8 ++++- src/core/ao_cmd.c | 6 ++-- src/core/ao_config.c | 68 ++++++++++++++++++++++------------------- src/core/ao_freq.c | 52 +++++++++++++++++++++++++++++++ src/product/Makefile.telebt | 3 +- src/product/Makefile.teledongle | 3 +- src/product/Makefile.telelaunch | 3 +- src/product/Makefile.telemetrum | 3 +- src/product/Makefile.telemini | 3 +- src/product/Makefile.telenano | 3 +- src/product/ao_terraui.c | 2 +- src/teleshield-v0.1/Makefile | 3 +- src/teleterra-v0.2/Makefile | 3 +- src/tidongle/Makefile | 3 +- 14 files changed, 117 insertions(+), 46 deletions(-) create mode 100644 src/core/ao_freq.c (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 8c5335c4..ce9a1f70 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1539,7 +1539,6 @@ ao_igniter_init(void); struct ao_radio_channel { char name[AO_CHANNEL_NAME_LEN]; uint32_t kHz; - uint32_t radio_setting; }; #endif @@ -1559,6 +1558,7 @@ struct ao_config { uint32_t radio_setting; /* minor version 7 */ uint8_t radio_enable; /* minor version 8 */ uint8_t aes_key[AO_AES_LEN]; /* minor version 9 */ + uint32_t frequency; /* minor version 10 */ #if HAS_RADIO_CHANNELS struct ao_radio_channel radio_channels[AO_NUM_CHANNELS]; /* minor version 10 */ #endif @@ -1959,4 +1959,10 @@ ao_battery_init(void); uint32_t ao_sqrt(uint32_t op); +/* + * ao_freq.c + */ + +int32_t ao_freq_to_set(int32_t freq, int32_t cal); + #endif /* _AO_H_ */ diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 14cb7569..cde68b39 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -263,9 +263,9 @@ static __pdata uint8_t ao_ncmds; static void help(void) { - register uint8_t cmds; - register uint8_t cmd; - register __code struct ao_cmds * cs; + __pdata uint8_t cmds; + __pdata uint8_t cmd; + __code struct ao_cmds * __pdata cs; for (cmds = 0; cmds < ao_ncmds; cmds++) { cs = ao_cmds[cmds]; diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 86bbc473..6fcebe1e 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -64,6 +64,12 @@ ao_config_put(void) } #endif +static void +ao_config_set_radio(void) +{ + ao_config.radio_setting = ao_freq_to_set(ao_config.frequency, ao_config.radio_cal); +} + static void _ao_config_get(void) { @@ -105,24 +111,23 @@ _ao_config_get(void) ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; if (ao_config.minor < 6) ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; - if (ao_config.minor < 7) - ao_config.radio_setting = ao_config.radio_cal; if (ao_config.minor < 8) ao_config.radio_enable = TRUE; if (ao_config.minor < 9) memset(&ao_config.aes_key, 0, AO_AES_LEN); -#if HAS_RADIO_CHANNELS if (ao_config.minor < 10) { + ao_config.frequency = 434550; +#if HAS_RADIO_CHANNELS ao_xmemset(&ao_config.radio_channels, '\0', sizeof (ao_config.radio_channels)); ao_xmemcpy(&ao_config.radio_channels[0].name[0], CODE_TO_XDATA("Channel 0"), sizeof("Channel 0")); ao_config.radio_channels[0].kHz = 434550; - ao_config.radio_channels[0].radio_setting = ao_config.radio_cal; - } #endif + } ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } + ao_config_set_radio(); ao_config_loaded = 1; } @@ -196,6 +201,26 @@ ao_config_radio_channel_set(void) __reentrant ao_radio_recv_abort(); } +void +ao_config_frequency_show(void) __reentrant +{ + printf("Frequency: %ld\n", + ao_config.frequency); +} + +void +ao_config_frequency_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.frequency = ao_cmd_lex_u32; + ao_config_set_radio(); + _ao_config_edit_finish(); + ao_radio_recv_abort(); +} + #if HAS_ADC void @@ -315,7 +340,8 @@ ao_config_radio_cal_set(void) __reentrant if (ao_cmd_status != ao_cmd_success) return; _ao_config_edit_start(); - ao_config.radio_setting = ao_config.radio_cal = ao_cmd_lex_u32; + ao_config.radio_cal = ao_cmd_lex_u32; + ao_config_set_radio(); _ao_config_edit_finish(); } @@ -394,25 +420,6 @@ ao_config_pad_orientation_set(void) __reentrant } #endif -void -ao_config_radio_setting_show(void) __reentrant -{ - printf("Radio setting: %ld\n", ao_config.radio_setting); -} - -void -ao_config_radio_setting_set(void) __reentrant -{ - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - ao_config.radio_setting = ao_cmd_lex_u32; - ao_config.radio_channel = 0; - _ao_config_edit_finish(); - ao_radio_recv_abort(); -} - void ao_config_radio_enable_show(void) __reentrant { @@ -464,11 +471,10 @@ ao_config_radio_config_show(void) __reentrant uint8_t i; for (i = 0; i < AO_NUM_CHANNELS; i++) if (ao_config.radio_channels[i].name[0]) { - printf("%2d %-16.16s %ld %ld\n", + printf("%2d %-16.16s %ld\n", i, ao_config.radio_channels[i].name, - ao_config.radio_channels[i].kHz, - ao_config.radio_channels[i].radio_setting); + ao_config.radio_channels[i].kHz); } } @@ -498,8 +504,6 @@ ao_config_radio_config_set(void) __reentrant } ao_cmd_decimal(); ch->kHz = ao_cmd_lex_u32; - ao_cmd_decimal(); - ch->radio_setting = ao_cmd_lex_u32; _ao_config_edit_finish(); } #endif @@ -528,10 +532,10 @@ __code struct ao_config_var ao_config_vars[] = { #endif /* HAS_ADC */ { "r \0Radio channel (freq = 434.550 + chan * .1)", ao_config_radio_channel_set, ao_config_radio_channel_show }, + { "F \0Frequency (kHz)", + ao_config_frequency_set, ao_config_frequency_show }, { "c \0Callsign (8 char max)", ao_config_callsign_set, ao_config_callsign_show }, - { "R \0Radio freq control (freq = 434.550 * setting/cal)", - ao_config_radio_setting_set, ao_config_radio_setting_show }, { "e <0 disable, 1 enable>\0Enable telemetry and RDF", ao_config_radio_enable_set, ao_config_radio_enable_show }, #if HAS_ACCEL diff --git a/src/core/ao_freq.c b/src/core/ao_freq.c new file mode 100644 index 00000000..13bcb383 --- /dev/null +++ b/src/core/ao_freq.c @@ -0,0 +1,52 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include + +/* + * The provided 'calibration' value is + * that needed to tune the radio to precisely 434550kHz. + * Use that to 'walk' to the target frequency by following + * a 'bresenham' line from 434550kHz to the target + * frequency, and updating the radio setting along the way + */ + +int32_t ao_freq_to_set(int32_t freq, int32_t cal) { + __pdata int32_t set = 0; + uint8_t neg = 0; + __pdata int32_t error = -434550 / 2; + + freq -= 434550; + if (freq < 0) { + neg = 1; + freq = -freq; + } + for (;;) { + if (freq == 0 && error <= 0) + break; + if (error > 0) { + error -= 434550; + set++; + } else { + error += cal; + freq--; + } + } + if (neg) + set = -set; + return cal + set; +} diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index ea18ff18..e53aa2c4 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -28,7 +28,8 @@ CORE_SRC = \ ao_panic.c \ ao_state.c \ ao_stdio.c \ - ao_task.c + ao_task.c \ + ao_freq.c CC1111_SRC = \ ao_aes.c \ diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle index cf33d1f1..27e7d24b 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -31,7 +31,8 @@ CORE_SRC = \ ao_rssi.c \ ao_state.c \ ao_stdio.c \ - ao_task.c + ao_task.c \ + ao_freq.c CC1111_SRC = \ ao_aes.c \ diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch index 97764517..8aab50e0 100644 --- a/src/product/Makefile.telelaunch +++ b/src/product/Makefile.telelaunch @@ -27,7 +27,8 @@ CORE_SRC = \ ao_panic.c \ ao_stdio.c \ ao_storage.c \ - ao_task.c + ao_task.c \ + ao_freq.c CC1111_SRC = \ ao_adc.c \ diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index 52c723ca..e4f55f88 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -40,7 +40,8 @@ CORE_SRC = \ ao_log.c \ ao_log_big.c \ ao_report.c \ - ao_telemetry.c + ao_telemetry.c \ + ao_freq.c CC1111_SRC = \ ao_adc.c \ diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini index 75beeae4..82ec42a2 100644 --- a/src/product/Makefile.telemini +++ b/src/product/Makefile.telemini @@ -33,7 +33,8 @@ CORE_SRC = \ ao_stdio.c \ ao_storage.c \ ao_task.c \ - ao_telemetry.c + ao_telemetry.c \ + ao_freq.c CC1111_SRC = \ ao_adc.c \ diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index b30ca789..cf27527c 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -33,7 +33,8 @@ CORE_SRC = \ ao_stdio.c \ ao_storage.c \ ao_task.c \ - ao_telemetry.c + ao_telemetry.c \ + ao_freq.c CC1111_SRC = \ ao_adc.c \ diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c index 05157cb1..9b40c42a 100644 --- a/src/product/ao_terraui.c +++ b/src/product/ao_terraui.c @@ -459,7 +459,7 @@ ao_terraui_config(void) __reentrant for (chan = 0; chan < AO_NUM_CHANNELS; chan++) - if (ao_config.radio_channels[chan].radio_setting == ao_config.radio_setting) + if (ao_config.radio_channels[chan].kHz == ao_config.frequency) break; if (chan == AO_NUM_CHANNELS) chan = 0; diff --git a/src/teleshield-v0.1/Makefile b/src/teleshield-v0.1/Makefile index a21a6052..44780476 100644 --- a/src/teleshield-v0.1/Makefile +++ b/src/teleshield-v0.1/Makefile @@ -41,7 +41,8 @@ CORE_SRC = \ ao_state.c \ ao_storage.c \ ao_stdio.c \ - ao_task.c + ao_task.c \ + ao_freq.c CC1111_SRC = \ ao_dbg.c \ diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile index 0747bfbf..4967d187 100644 --- a/src/teleterra-v0.2/Makefile +++ b/src/teleterra-v0.2/Makefile @@ -28,7 +28,8 @@ CORE_SRC = \ ao_sqrt.c \ ao_stdio.c \ ao_storage.c \ - ao_task.c + ao_task.c \ + ao_freq.c CC1111_SRC = \ ao_battery.c \ diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile index 698d612c..149b00c5 100644 --- a/src/tidongle/Makefile +++ b/src/tidongle/Makefile @@ -26,7 +26,8 @@ CORE_SRC = \ ao_rssi.c \ ao_state.c \ ao_stdio.c \ - ao_task.c + ao_task.c \ + ao_freq.c CC1111_SRC = \ ao_aes.c \ -- cgit v1.2.3 From 7dd1d62676c1e605fe69a4c0acfe7638c6b79aa5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Mar 2012 18:19:05 -0700 Subject: altos: Optimize ao_freq_to_set a bit Reduces size from 327 bytes to 287 bytes Signed-off-by: Keith Packard --- src/core/ao_freq.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/core/ao_freq.c b/src/core/ao_freq.c index 13bcb383..67b0b037 100644 --- a/src/core/ao_freq.c +++ b/src/core/ao_freq.c @@ -30,20 +30,18 @@ int32_t ao_freq_to_set(int32_t freq, int32_t cal) { uint8_t neg = 0; __pdata int32_t error = -434550 / 2; - freq -= 434550; - if (freq < 0) { + if ((freq -= 434550) < 0) { neg = 1; freq = -freq; } for (;;) { - if (freq == 0 && error <= 0) - break; if (error > 0) { error -= 434550; set++; } else { error += cal; - freq--; + if (--freq < 0) + break; } } if (neg) -- cgit v1.2.3 From b6c7ae2c1f8cba7351cd139c49322280d9d3af47 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 27 Mar 2012 22:53:08 -0700 Subject: altos: Reset config version if it's too large as well Any future config values will get trashed if we down grade the firmware, so we must reset the firmware version whenever it gets written. Signed-off-by: Keith Packard --- src/core/ao_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 6fcebe1e..350ebcbe 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -91,7 +91,7 @@ _ao_config_get(void) sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); ao_config_dirty = 1; } - if (ao_config.minor < AO_CONFIG_MINOR) { + if (ao_config.minor != AO_CONFIG_MINOR) { /* Fixups for minor version 1 */ if (ao_config.minor < 1) ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; -- cgit v1.2.3 From d60862fce6ac27a97ad6337eea32a4b48645d158 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Mar 2012 00:38:37 -0700 Subject: altos: Make sure config values are loaded in 'c s' command ao_config_get may not have been called when ao_config_show is invoked by the user, so make sure the config values are loaded before showing uninitialized data. Signed-off-by: Keith Packard --- src/core/ao_config.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 350ebcbe..08e6deea 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -609,6 +609,7 @@ static void ao_config_show(void) __reentrant { uint8_t cmd; + ao_config_get(); printf("Config version: %d.%d\n", ao_config.major, ao_config.minor); for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) -- cgit v1.2.3 From 3c7d1f6cfffb43299041f2850a48177f4e9b83a5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 22 Feb 2012 23:26:03 +1300 Subject: 'stdin' is a special name in some compiler environments, don't use it. Switch to 'in' in the prototype for altos_serial_set_stdin. Signed-off-by: Keith Packard --- src/core/ao.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index ce9a1f70..ac51c270 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -917,7 +917,7 @@ char ao_serial_pollchar(void) __critical; void -ao_serial_set_stdin(uint8_t stdin); +ao_serial_set_stdin(uint8_t in); #endif void -- cgit v1.2.3 From 9279fd42793123784ce83ca151df6f4630487722 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 16 Mar 2012 20:21:09 -0700 Subject: Add STM platform and stm-bringup demo program The stm-bringup doesn't run altos, it just initializes the device and writes stuff over a serial port. Works on the STM32L Discovery board at least, should do stuff on other boards too. Signed-off-by: Keith Packard --- ao-bringup/stm/Makefile | 35 --- ao-bringup/stm/bringup.c | 306 --------------------- src/stm-bringup/Makefile | 35 +++ src/stm-bringup/bringup.c | 306 +++++++++++++++++++++ src/stm/altos-ram.ld | 69 +++++ src/stm/altos.ld | 72 +++++ src/stm/ao_arch.h | 129 +++++++++ src/stm/ao_interrupt.c | 169 ++++++++++++ src/stm/ao_led.c | 69 +++++ src/stm/ao_serial_stm.c | 184 +++++++++++++ src/stm/ao_timer.c | 167 ++++++++++++ src/stm/registers.ld | 47 ++++ src/stm/stm32l.h | 662 ++++++++++++++++++++++++++++++++++++++++++++++ 13 files changed, 1909 insertions(+), 341 deletions(-) delete mode 100644 ao-bringup/stm/Makefile delete mode 100644 ao-bringup/stm/bringup.c create mode 100644 src/stm-bringup/Makefile create mode 100644 src/stm-bringup/bringup.c create mode 100644 src/stm/altos-ram.ld create mode 100644 src/stm/altos.ld create mode 100644 src/stm/ao_arch.h create mode 100644 src/stm/ao_interrupt.c create mode 100644 src/stm/ao_led.c create mode 100644 src/stm/ao_serial_stm.c create mode 100644 src/stm/ao_timer.c create mode 100644 src/stm/registers.ld create mode 100644 src/stm/stm32l.h (limited to 'src') diff --git a/ao-bringup/stm/Makefile b/ao-bringup/stm/Makefile deleted file mode 100644 index 49966a4f..00000000 --- a/ao-bringup/stm/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -CC=arm-none-eabi-gcc -OBJCOPY=arm-none-eabi-objcopy - -C_LIB=/local/src/pdclib/pdclib.a -C_INC=-I/local/src/pdclib/includes -I/local/src/pdclib/internals - -DEF_CFLAGS=-g -std=gnu99 -O0 -mlittle-endian -mthumb -ffreestanding -nostdlib -I../../src/stm $(C_INC) - -# to run from SRAM -LD_FLAGS_RAM=-Wl,-Taltos-ram.ld -LD_FLAGS=-Wl,-Taltos.ld - -CFLAGS=$(DEF_CFLAGS) -mcpu=cortex-m3 -DCONFIG_STM32L_DISCOVERY - -OBJS=bringup.o - -all: bringup-ram.elf bringup.elf - -%.bin: %.elf - $(OBJCOPY) -O binary $^ $@ - -bringup.elf: $(OBJS) $(C_LIB) altos.ld - $(CC) $(CFLAGS) $(LD_FLAGS) -o $@ $(OBJS) $(C_LIB) -lgcc - -bringup-ram.elf: $(OBJS) $(C_LIB) altos-ram.ld - $(CC) $(CFLAGS) $(LD_FLAGS_RAM) -o $@ $(OBJS) $(C_LIB) -lgcc - -bringup.o: bringup.c - $(CC) -c $(CFLAGS) bringup.c - -clean: - rm -rf *.elf - rm -rf *.bin - -.PHONY: all clean diff --git a/ao-bringup/stm/bringup.c b/ao-bringup/stm/bringup.c deleted file mode 100644 index b6fe458d..00000000 --- a/ao-bringup/stm/bringup.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include - -#include -#include "stm32l.h" - -void delay(void); - -static void -set_clock(void) -{ - uint32_t cfgr; - uint32_t cr; - - /* Set flash latency to tolerate 32MHz SYSCLK -> 1 wait state */ - uint32_t acr = stm_flash.acr; - - /* Enable 64-bit access and prefetch */ - acr |= (1 << STM_FLASH_ACR_ACC64) | (1 << STM_FLASH_ACR_PRFEN); - stm_flash.acr = acr; - - /* Enable 1 wait state so the CPU can run at 32MHz */ - /* (haven't managed to run the CPU at 32MHz yet, it's at 16MHz) */ - acr |= (1 << STM_FLASH_ACR_LATENCY); - stm_flash.acr = acr; - - /* HCLK to 16MHz -> AHB prescaler = /1 */ - cfgr = stm_rcc.cfgr; - cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE); - cfgr |= (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE); - stm_rcc.cfgr = cfgr; - while ((stm_rcc.cfgr & (STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE)) != - (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE)) - asm ("nop"); -#define STM_AHB_PRESCALER 1 - - /* PCLK1 to 16MHz -> APB1 Prescaler = 1 */ - cfgr = stm_rcc.cfgr; - cfgr &= ~(STM_RCC_CFGR_PPRE1_MASK << STM_RCC_CFGR_PPRE1); - cfgr |= (STM_RCC_CFGR_PPRE1_DIV_1 << STM_RCC_CFGR_PPRE1); - stm_rcc.cfgr = cfgr; -#define STM_APB1_PRESCALER 1 - - /* PCLK2 to 16MHz -> APB2 Prescaler = 1 */ - cfgr = stm_rcc.cfgr; - cfgr &= ~(STM_RCC_CFGR_PPRE2_MASK << STM_RCC_CFGR_PPRE2); - cfgr |= (STM_RCC_CFGR_PPRE2_DIV_1 << STM_RCC_CFGR_PPRE2); - stm_rcc.cfgr = cfgr; -#define STM_APB2_PRESCALER 1 - - /* Enable power interface clock */ - stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); - - /* Set voltage range to 1.8V */ - - /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ - while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) - asm("nop"); - - /* Configure voltage scaling range */ - cr = stm_pwr.cr; - cr &= ~(STM_PWR_CR_VOS_MASK << STM_PWR_CR_VOS); - cr |= (STM_PWR_CR_VOS_1_8 << STM_PWR_CR_VOS); - stm_pwr.cr = cr; - - /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ - while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) - asm("nop"); - - /* Enable HSI RC clock 16MHz */ - if (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) { - stm_rcc.cr |= (1 << STM_RCC_CR_HSION); - while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) - asm("nop"); - } -#define STM_HSI 16000000 - - /* Switch to direct HSI for SYSCLK */ - if ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != - (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) { - cfgr = stm_rcc.cfgr; - cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); - cfgr |= (STM_RCC_CFGR_SW_HSI << STM_RCC_CFGR_SW); - stm_rcc.cfgr = cfgr; - while ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != - (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) - asm("nop"); - } - - /* Disable the PLL */ - stm_rcc.cr &= ~(1 << STM_RCC_CR_PLLON); - while (stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY)) - asm("nop"); - - /* PLLVCO to 96MHz (for USB) -> PLLMUL = 6, PLLDIV = 4 */ - cfgr = stm_rcc.cfgr; - cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL); - cfgr &= ~(STM_RCC_CFGR_PLLDIV_MASK << STM_RCC_CFGR_PLLDIV); - -// cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); -// cfgr |= (STM_RCC_CFGR_PLLDIV_3 << STM_RCC_CFGR_PLLDIV); - - cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); - cfgr |= (STM_RCC_CFGR_PLLDIV_4 << STM_RCC_CFGR_PLLDIV); - -#define STM_PLLMUL 6 -#define STM_PLLDIV 4 - - /* PLL source to HSI */ - cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC); - -#define STM_PLLSRC STM_HSI - - stm_rcc.cfgr = cfgr; - - /* Enable the PLL and wait for it */ - stm_rcc.cr |= (1 << STM_RCC_CR_PLLON); - while (!(stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY))) - asm("nop"); - - /* Switch to the PLL for the system clock */ - - cfgr = stm_rcc.cfgr; - cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); - cfgr |= (STM_RCC_CFGR_SW_PLL << STM_RCC_CFGR_SW); - stm_rcc.cfgr = cfgr; - for (;;) { - uint32_t c, part, mask, val; - - c = stm_rcc.cfgr; - mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS); - val = (STM_RCC_CFGR_SWS_PLL << STM_RCC_CFGR_SWS); - part = c & mask; - if (part == val) - break; - } -} - -#define STM_PLLVCO (STM_PLLSRC * STM_PLLMUL) -#define STM_SYSCLK (STM_PLLVCO / STM_PLLDIV) -#define STM_HCLK (STM_SYSCLK / STM_AHB_PRESCALER) -#define STM_APB1 (STM_HCLK / STM_APB1_PRESCALER) -#define STM_APB2 (STM_HCLK / STM_APB2_PRESCALER) - -#define BAUD_9600 (STM_APB2 / 9600) - -void -set_serial() -{ - uint32_t moder, afr; - - /* Enable GPIOA */ - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); - - /* Hook PA9, PA10 to USART1 (AFIO7) */ - stm_moder_set(&stm_gpioa, 9, STM_MODER_ALTERNATE); - stm_moder_set(&stm_gpioa, 10, STM_MODER_ALTERNATE); - stm_afr_set(&stm_gpioa, 9, STM_AFR_AF7); - stm_afr_set(&stm_gpioa, 10, STM_AFR_AF7); - - /* Enable USART1 */ - stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN); - - /* 9.6KBps. PCLK1 = 16MHz. OVER8 = 0 */ - - /* USARTDIV = PCLK1 / (16 * 9600) = 104.1{6} - * round to 104.1875 (1667 / 16) - * - * actual baud rate = 16e6 / (16 * 104.1875) = 9598Bps - */ - - stm_usart1.brr = BAUD_9600; - - stm_usart1.cr1 = ((0 << STM_USART_CR1_OVER8) | - (1 << STM_USART_CR1_UE) | - (0 << STM_USART_CR1_M) | - (0 << STM_USART_CR1_WAKE) | - (0 << STM_USART_CR1_PCE) | - (0 << STM_USART_CR1_PS) | - (0 << STM_USART_CR1_PEIE) | - (0 << STM_USART_CR1_TXEIE) | - (0 << STM_USART_CR1_TCIE) | - (0 << STM_USART_CR1_RXNEIE) | - (0 << STM_USART_CR1_IDLEIE) | - (1 << STM_USART_CR1_TE) | - (1 << STM_USART_CR1_RE) | - (0 << STM_USART_CR1_RWU) | - (0 << STM_USART_CR1_SBK)); - - stm_usart1.cr2 = ((0 << STM_USART_CR2_LINEN) | - (STM_USART_CR2_STOP_1 << STM_USART_CR2_STOP) | - (0 << STM_USART_CR2_CLKEN) | - (0 << STM_USART_CR2_CPOL) | - (0 << STM_USART_CR2_CPHA) | - (0 << STM_USART_CR2_LBCL) | - (0 << STM_USART_CR2_LBDIE) | - (0 << STM_USART_CR2_LBDL) | - (0 << STM_USART_CR2_ADD)); - - stm_usart1.cr3 = ((0 << STM_USART_CR3_ONEBITE) | - (0 << STM_USART_CR3_CTSIE) | - (0 << STM_USART_CR3_CTSE) | - (0 << STM_USART_CR3_RTSE) | - (0 << STM_USART_CR3_DMAT) | - (0 << STM_USART_CR3_DMAR) | - (0 << STM_USART_CR3_SCEN) | - (0 << STM_USART_CR3_NACK) | - (0 << STM_USART_CR3_HDSEL) | - (0 << STM_USART_CR3_IRLP) | - (0 << STM_USART_CR3_IREN) | - (0 << STM_USART_CR3_EIE)); -} - -void -outbyte(char c) -{ - if (c == '\n') - outbyte('\r'); - while (!(stm_usart1.sr & (1 << STM_USART_SR_TXE))) - ; - stm_usart1.dr = c; -} - -int putc( int c, FILE * stream ) { - outbyte(c); -} - -void -serial_string(char *string) -{ - char c; - - while (c = *string++) - outbyte(c); -} - -void -set_timer6(void) -{ - /* Turn on timer 6 */ - stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN); - - -} - -void -main (void) -{ - set_clock(); - set_serial(); - set_timer6(); - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); - stm_moder_set(&stm_gpiob, 7, STM_MODER_OUTPUT); - stm_moder_set(&stm_gpiob, 6, STM_MODER_OUTPUT); - for (;;) { - stm_gpiob.odr = (1 << 7); - printf ("hello, "); - delay(); - stm_gpiob.odr = (1 << 6); - printf ("world\n"); - delay(); - } -} - -void -delay(void) -{ - int i; - for (i = 0; i < 1000000; i++) - __asm__ __volatile__ ("nop\n\t":::"memory"); -} - -static int x = 7; - -extern char __stack__; -extern char __text_start__, __text_end__; -extern char __data_start__, __data_end__; -extern char __bss_start__, __bss_end__; - -void start(void) { - memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__); - memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__); - main(); -} - -__attribute__ ((section(".interrupt"))) -static const void *interrupt[] = { - &__stack__, - start, -}; diff --git a/src/stm-bringup/Makefile b/src/stm-bringup/Makefile new file mode 100644 index 00000000..49966a4f --- /dev/null +++ b/src/stm-bringup/Makefile @@ -0,0 +1,35 @@ +CC=arm-none-eabi-gcc +OBJCOPY=arm-none-eabi-objcopy + +C_LIB=/local/src/pdclib/pdclib.a +C_INC=-I/local/src/pdclib/includes -I/local/src/pdclib/internals + +DEF_CFLAGS=-g -std=gnu99 -O0 -mlittle-endian -mthumb -ffreestanding -nostdlib -I../../src/stm $(C_INC) + +# to run from SRAM +LD_FLAGS_RAM=-Wl,-Taltos-ram.ld +LD_FLAGS=-Wl,-Taltos.ld + +CFLAGS=$(DEF_CFLAGS) -mcpu=cortex-m3 -DCONFIG_STM32L_DISCOVERY + +OBJS=bringup.o + +all: bringup-ram.elf bringup.elf + +%.bin: %.elf + $(OBJCOPY) -O binary $^ $@ + +bringup.elf: $(OBJS) $(C_LIB) altos.ld + $(CC) $(CFLAGS) $(LD_FLAGS) -o $@ $(OBJS) $(C_LIB) -lgcc + +bringup-ram.elf: $(OBJS) $(C_LIB) altos-ram.ld + $(CC) $(CFLAGS) $(LD_FLAGS_RAM) -o $@ $(OBJS) $(C_LIB) -lgcc + +bringup.o: bringup.c + $(CC) -c $(CFLAGS) bringup.c + +clean: + rm -rf *.elf + rm -rf *.bin + +.PHONY: all clean diff --git a/src/stm-bringup/bringup.c b/src/stm-bringup/bringup.c new file mode 100644 index 00000000..b6fe458d --- /dev/null +++ b/src/stm-bringup/bringup.c @@ -0,0 +1,306 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include + +#include +#include "stm32l.h" + +void delay(void); + +static void +set_clock(void) +{ + uint32_t cfgr; + uint32_t cr; + + /* Set flash latency to tolerate 32MHz SYSCLK -> 1 wait state */ + uint32_t acr = stm_flash.acr; + + /* Enable 64-bit access and prefetch */ + acr |= (1 << STM_FLASH_ACR_ACC64) | (1 << STM_FLASH_ACR_PRFEN); + stm_flash.acr = acr; + + /* Enable 1 wait state so the CPU can run at 32MHz */ + /* (haven't managed to run the CPU at 32MHz yet, it's at 16MHz) */ + acr |= (1 << STM_FLASH_ACR_LATENCY); + stm_flash.acr = acr; + + /* HCLK to 16MHz -> AHB prescaler = /1 */ + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE); + cfgr |= (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE); + stm_rcc.cfgr = cfgr; + while ((stm_rcc.cfgr & (STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE)) != + (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE)) + asm ("nop"); +#define STM_AHB_PRESCALER 1 + + /* PCLK1 to 16MHz -> APB1 Prescaler = 1 */ + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_PPRE1_MASK << STM_RCC_CFGR_PPRE1); + cfgr |= (STM_RCC_CFGR_PPRE1_DIV_1 << STM_RCC_CFGR_PPRE1); + stm_rcc.cfgr = cfgr; +#define STM_APB1_PRESCALER 1 + + /* PCLK2 to 16MHz -> APB2 Prescaler = 1 */ + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_PPRE2_MASK << STM_RCC_CFGR_PPRE2); + cfgr |= (STM_RCC_CFGR_PPRE2_DIV_1 << STM_RCC_CFGR_PPRE2); + stm_rcc.cfgr = cfgr; +#define STM_APB2_PRESCALER 1 + + /* Enable power interface clock */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); + + /* Set voltage range to 1.8V */ + + /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ + while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) + asm("nop"); + + /* Configure voltage scaling range */ + cr = stm_pwr.cr; + cr &= ~(STM_PWR_CR_VOS_MASK << STM_PWR_CR_VOS); + cr |= (STM_PWR_CR_VOS_1_8 << STM_PWR_CR_VOS); + stm_pwr.cr = cr; + + /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ + while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) + asm("nop"); + + /* Enable HSI RC clock 16MHz */ + if (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) { + stm_rcc.cr |= (1 << STM_RCC_CR_HSION); + while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) + asm("nop"); + } +#define STM_HSI 16000000 + + /* Switch to direct HSI for SYSCLK */ + if ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != + (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) { + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); + cfgr |= (STM_RCC_CFGR_SW_HSI << STM_RCC_CFGR_SW); + stm_rcc.cfgr = cfgr; + while ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != + (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) + asm("nop"); + } + + /* Disable the PLL */ + stm_rcc.cr &= ~(1 << STM_RCC_CR_PLLON); + while (stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY)) + asm("nop"); + + /* PLLVCO to 96MHz (for USB) -> PLLMUL = 6, PLLDIV = 4 */ + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL); + cfgr &= ~(STM_RCC_CFGR_PLLDIV_MASK << STM_RCC_CFGR_PLLDIV); + +// cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); +// cfgr |= (STM_RCC_CFGR_PLLDIV_3 << STM_RCC_CFGR_PLLDIV); + + cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); + cfgr |= (STM_RCC_CFGR_PLLDIV_4 << STM_RCC_CFGR_PLLDIV); + +#define STM_PLLMUL 6 +#define STM_PLLDIV 4 + + /* PLL source to HSI */ + cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC); + +#define STM_PLLSRC STM_HSI + + stm_rcc.cfgr = cfgr; + + /* Enable the PLL and wait for it */ + stm_rcc.cr |= (1 << STM_RCC_CR_PLLON); + while (!(stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY))) + asm("nop"); + + /* Switch to the PLL for the system clock */ + + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); + cfgr |= (STM_RCC_CFGR_SW_PLL << STM_RCC_CFGR_SW); + stm_rcc.cfgr = cfgr; + for (;;) { + uint32_t c, part, mask, val; + + c = stm_rcc.cfgr; + mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS); + val = (STM_RCC_CFGR_SWS_PLL << STM_RCC_CFGR_SWS); + part = c & mask; + if (part == val) + break; + } +} + +#define STM_PLLVCO (STM_PLLSRC * STM_PLLMUL) +#define STM_SYSCLK (STM_PLLVCO / STM_PLLDIV) +#define STM_HCLK (STM_SYSCLK / STM_AHB_PRESCALER) +#define STM_APB1 (STM_HCLK / STM_APB1_PRESCALER) +#define STM_APB2 (STM_HCLK / STM_APB2_PRESCALER) + +#define BAUD_9600 (STM_APB2 / 9600) + +void +set_serial() +{ + uint32_t moder, afr; + + /* Enable GPIOA */ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + + /* Hook PA9, PA10 to USART1 (AFIO7) */ + stm_moder_set(&stm_gpioa, 9, STM_MODER_ALTERNATE); + stm_moder_set(&stm_gpioa, 10, STM_MODER_ALTERNATE); + stm_afr_set(&stm_gpioa, 9, STM_AFR_AF7); + stm_afr_set(&stm_gpioa, 10, STM_AFR_AF7); + + /* Enable USART1 */ + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN); + + /* 9.6KBps. PCLK1 = 16MHz. OVER8 = 0 */ + + /* USARTDIV = PCLK1 / (16 * 9600) = 104.1{6} + * round to 104.1875 (1667 / 16) + * + * actual baud rate = 16e6 / (16 * 104.1875) = 9598Bps + */ + + stm_usart1.brr = BAUD_9600; + + stm_usart1.cr1 = ((0 << STM_USART_CR1_OVER8) | + (1 << STM_USART_CR1_UE) | + (0 << STM_USART_CR1_M) | + (0 << STM_USART_CR1_WAKE) | + (0 << STM_USART_CR1_PCE) | + (0 << STM_USART_CR1_PS) | + (0 << STM_USART_CR1_PEIE) | + (0 << STM_USART_CR1_TXEIE) | + (0 << STM_USART_CR1_TCIE) | + (0 << STM_USART_CR1_RXNEIE) | + (0 << STM_USART_CR1_IDLEIE) | + (1 << STM_USART_CR1_TE) | + (1 << STM_USART_CR1_RE) | + (0 << STM_USART_CR1_RWU) | + (0 << STM_USART_CR1_SBK)); + + stm_usart1.cr2 = ((0 << STM_USART_CR2_LINEN) | + (STM_USART_CR2_STOP_1 << STM_USART_CR2_STOP) | + (0 << STM_USART_CR2_CLKEN) | + (0 << STM_USART_CR2_CPOL) | + (0 << STM_USART_CR2_CPHA) | + (0 << STM_USART_CR2_LBCL) | + (0 << STM_USART_CR2_LBDIE) | + (0 << STM_USART_CR2_LBDL) | + (0 << STM_USART_CR2_ADD)); + + stm_usart1.cr3 = ((0 << STM_USART_CR3_ONEBITE) | + (0 << STM_USART_CR3_CTSIE) | + (0 << STM_USART_CR3_CTSE) | + (0 << STM_USART_CR3_RTSE) | + (0 << STM_USART_CR3_DMAT) | + (0 << STM_USART_CR3_DMAR) | + (0 << STM_USART_CR3_SCEN) | + (0 << STM_USART_CR3_NACK) | + (0 << STM_USART_CR3_HDSEL) | + (0 << STM_USART_CR3_IRLP) | + (0 << STM_USART_CR3_IREN) | + (0 << STM_USART_CR3_EIE)); +} + +void +outbyte(char c) +{ + if (c == '\n') + outbyte('\r'); + while (!(stm_usart1.sr & (1 << STM_USART_SR_TXE))) + ; + stm_usart1.dr = c; +} + +int putc( int c, FILE * stream ) { + outbyte(c); +} + +void +serial_string(char *string) +{ + char c; + + while (c = *string++) + outbyte(c); +} + +void +set_timer6(void) +{ + /* Turn on timer 6 */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN); + + +} + +void +main (void) +{ + set_clock(); + set_serial(); + set_timer6(); + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); + stm_moder_set(&stm_gpiob, 7, STM_MODER_OUTPUT); + stm_moder_set(&stm_gpiob, 6, STM_MODER_OUTPUT); + for (;;) { + stm_gpiob.odr = (1 << 7); + printf ("hello, "); + delay(); + stm_gpiob.odr = (1 << 6); + printf ("world\n"); + delay(); + } +} + +void +delay(void) +{ + int i; + for (i = 0; i < 1000000; i++) + __asm__ __volatile__ ("nop\n\t":::"memory"); +} + +static int x = 7; + +extern char __stack__; +extern char __text_start__, __text_end__; +extern char __data_start__, __data_end__; +extern char __bss_start__, __bss_end__; + +void start(void) { + memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__); + memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__); + main(); +} + +__attribute__ ((section(".interrupt"))) +static const void *interrupt[] = { + &__stack__, + start, +}; diff --git a/src/stm/altos-ram.ld b/src/stm/altos-ram.ld new file mode 100644 index 00000000..b8fffedc --- /dev/null +++ b/src/stm/altos-ram.ld @@ -0,0 +1,69 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +MEMORY { + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 16K +} + +C_STACK_SIZE = 512; + +INCLUDE registers.ld + +SECTIONS { + . = ORIGIN(ram); + + /* + * Rom contents + */ + + __text_start__ = .; + + .text : { + *(.interrupt) /* Interrupt vectors */ + *(.text) /* Executable code */ + *(.rodata) /* Constants */ + } > ram + + .ARM.exidx : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __text_end__ = .; + } > ram + + __data_start__ = .; + + /* Data -- relocated to RAM, but written to ROM + */ + .data : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + *(.data) /* initialized data */ + __data_end__ = .; + __bss_start__ = .; + } >ram + + .bss : { + *(.bss) + *(COMMON) + __bss_end__ = .; + } >ram + + PROVIDE(__stack__ = . + C_STACK_SIZE); + PROVIDE(end = .); + +} + +ENTRY(start); + + diff --git a/src/stm/altos.ld b/src/stm/altos.ld new file mode 100644 index 00000000..4e955666 --- /dev/null +++ b/src/stm/altos.ld @@ -0,0 +1,72 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +MEMORY { + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (!w) : ORIGIN = 0x20000000, LENGTH = 16K +} + +INCLUDE registers.ld + +EXTERN (stm_interrupt_vector) +C_STACK_SIZE = 512; + +SECTIONS { + . = ORIGIN(rom); + + /* + * Rom contents + */ + + __text_start__ = .; + + .text : { + *(.interrupt) /* Interrupt vectors */ + *(.text) /* Executable code */ + *(.rodata) /* Constants */ + } > rom + + .ARM.exidx : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __text_end__ = .; + } > rom + + . = ORIGIN(ram); + __data_start__ = .; + + /* Data -- relocated to RAM, but written to ROM + */ + .data : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + *(.data) /* initialized data */ + __data_end__ = .; + __bss_start__ = .; + } >ram + + .bss : { + *(.bss) + *(COMMON) + __bss_end__ = .; + } >ram + + PROVIDE(__stack__ = . + C_STACK_SIZE); + PROVIDE(end = .); + +} + +ENTRY(start); + + diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h new file mode 100644 index 00000000..e6f54fdb --- /dev/null +++ b/src/stm/ao_arch.h @@ -0,0 +1,129 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_ARCH_H_ +#define _AO_ARCH_H_ + +#include +#include + +/* + * STM32L definitions and code fragments for AltOS + */ + +#define AO_STACK_SIZE 256 + +/* Various definitions to make GCC look more like SDCC */ + +#define ao_arch_naked_declare __attribute__((naked)) +#define ao_arch_naked_define +#define __pdata +#define __data +#define __xdata +#define __code const +#define __reentrant +#define __critical +#define __interrupt(n) +#define __at(n) + +#define ao_arch_reboot() /* XXX */ + +#define ao_arch_nop() asm("nop") + +#define ao_arch_interrupt(n) /* nothing */ + +#undef putchar +#undef getchar +#define putchar(c) ao_putchar(c) +#define getchar ao_getchar + +extern void putchar(char c); +extern char getchar(void); +extern void ao_avr_stdio_init(void); + +extern const uint16_t ao_serial_number; + +#define ARM_PUSH32(stack, val) (*(--(stack)) = (val)) + +#define ao_arch_task_members\ + uint32_t *sp; /* saved stack pointer */ + +#define cli() asm("cpsid i") +#define sei() asm("cpsie i") + +#define ao_arch_init_stack(task, start) do { \ + uint32_t *sp = (uint32_t *) (task->stack + AO_STACK_SIZE); \ + uint16_t a = (uint16_t) start; \ + int i; \ + \ + /* Return address */ \ + ARM_PUSH32(sp, a); \ + \ + /* Invalid link register */ \ + ARM_PUSH32(sp, 0xffffffff); \ + \ + /* Clear register values */ \ + i = 13; \ + while (i--) \ + ARM_PUSH32(sp, 0); \ + \ + /* PSR with interrupts enabled */ \ + ARM_PUSH32(sp, 0x01000000); \ + task->sp = sp; \ +} while (0); + +#define ao_arch_save_regs() do { \ + asm("push {r0-r12,lr}\n"); \ + cli(); \ + asm("mrs r0,psr" "\n\t" "push {r0}"); \ + sei(); \ + } while (0) + +#define ao_arch_save_stack() do { \ + uint32_t sp; \ + asm("mov %0,sp" : "=&r" (sp) ); \ + ao_cur_task->sp = (uint32_t *) (sp); \ + } while (0) + +#define ao_arch_isr_stack() /* nothing */ + +#define ao_arch_cpu_idle() do { \ + asm("wfi"); \ + } while (0) + +#define ao_arch_restore_stack() do { \ + uint32_t sp; \ + sp = (uint32_t) ao_cur_task->sp; \ + cli(); \ + asm("mov sp, %0" : : "r" (sp) ); \ + asm("pop {r0}" "\n\t" "msr psr,r0"); \ + asm("pop {r0-r12,lr}\n"); \ + asm("bx lr"); \ + } while(0) + +#define ao_arch_critical(b) do { cli(); do { b } while (0); sei(); } while (0) + +#define AO_ARM_NUM_ADC 12 + +struct ao_adc { + uint16_t tick; /* tick when the sample was read */ + uint16_t adc[AO_ARM_NUM_ADC]; /* samples */ +}; + + +#endif /* _AO_ARCH_H_ */ + diff --git a/src/stm/ao_interrupt.c b/src/stm/ao_interrupt.c new file mode 100644 index 00000000..6b4a9700 --- /dev/null +++ b/src/stm/ao_interrupt.c @@ -0,0 +1,169 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "stm32l.h" +#include + +extern void main(void); +extern char __stack__; +extern char __text_start__, __text_end__; +extern char __data_start__, __data_end__; +extern char __bss_start__, __bss_end__; + +/* Interrupt functions */ + +void stm_halt_isr(void) +{ + for(;;); +} + +void stm_ignore_isr(void) +{ +} + +void start(void) { + memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__); + memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__); + main(); +} + +#define STRINGIFY(x) #x + +#define isr(name) \ + void __attribute__ ((weak)) stm_ ## name ## _isr(void); \ + _Pragma(STRINGIFY(weak stm_ ## name ## _isr = stm_ignore_isr)) + +#define isr_halt(name) \ + void __attribute__ ((weak)) stm_ ## name ## _isr(void); \ + _Pragma(STRINGIFY(weak stm_ ## name ## _isr = stm_halt_isr)) + +isr(nmi) +isr_halt(hardfault) +isr_halt(memmanage) +isr_halt(busfault) +isr_halt(usagefault) +isr(svc) +isr(debugmon) +isr(pendsv) +isr(systick) +isr(wwdg) +isr(pvd) +isr(tamper_stamp) +isr(rtc_wkup) +isr(flash) +isr(rcc) +isr(exti0) +isr(exti1) +isr(exti2) +isr(exti3) +isr(exti4) +isr(dma1_channel1) +isr(dma1_channel2) +isr(dma1_channel3) +isr(dma1_channel4) +isr(dma1_channel5) +isr(dma1_channel6) +isr(dma1_channel7) +isr(adc1) +isr(usb_hp) +isr(usb_lp) +isr(dac) +isr(comp) +isr(exti9_5) +isr(lcd) +isr(tim9) +isr(tim10) +isr(tim11) +isr(tim2) +isr(tim3) +isr(tim4) +isr(i2c1_ev) +isr(i2c1_er) +isr(i2c2_ev) +isr(i2c2_er) +isr(spi1) +isr(spi2) +isr(usart1) +isr(usart2) +isr(usart3) +isr(exti15_10) +isr(rtc_alarm) +isr(usb_fs_wkup) +isr(tim6) +isr(tim7) + +#define i(addr,name) [(addr)/4] = stm_ ## name ## _isr + +__attribute__ ((section(".interrupt"))) +const void *stm_interrupt_vector[] = { + [0] = &__stack__, + [1] = start, + i(0x08, nmi), + i(0x0c, hardfault), + i(0x10, memmanage), + i(0x14, busfault), + i(0x18, usagefault), + i(0x2c, svc), + i(0x30, debugmon), + i(0x38, pendsv), + i(0x3c, systick), + i(0x40, wwdg), + i(0x44, pvd), + i(0x48, tamper_stamp), + i(0x4c, rtc_wkup), + i(0x50, flash), + i(0x54, rcc), + i(0x58, exti0), + i(0x5c, exti1), + i(0x60, exti2), + i(0x64, exti3), + i(0x68, exti4), + i(0x6c, dma1_channel1), + i(0x70, dma1_channel2), + i(0x74, dma1_channel3), + i(0x78, dma1_channel4), + i(0x7c, dma1_channel5), + i(0x80, dma1_channel6), + i(0x84, dma1_channel7), + i(0x88, adc1), + i(0x8c, usb_hp), + i(0x90, usb_lp), + i(0x94, dac), + i(0x98, comp), + i(0x9c, exti9_5), + i(0xa0, lcd), + i(0xa4, tim9), + i(0xa8, tim10), + i(0xac, tim11), + i(0xb0, tim2), + i(0xb4, tim3), + i(0xb8, tim4), + i(0xbc, i2c1_ev), + i(0xc0, i2c1_er), + i(0xc4, i2c2_ev), + i(0xc8, i2c2_er), + i(0xcc, spi1), + i(0xd0, spi2), + i(0xd4, usart1), + i(0xd8, usart2), + i(0xdc, usart3), + i(0xe0, exti15_10), + i(0xe4, rtc_alarm), + i(0xe8, usb_fs_wkup), + i(0xec, tim6), + i(0xf0, tim7), +}; diff --git a/src/stm/ao_led.c b/src/stm/ao_led.c new file mode 100644 index 00000000..db65afdf --- /dev/null +++ b/src/stm/ao_led.c @@ -0,0 +1,69 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +__pdata uint8_t ao_led_enable; + +#define LED_PORT STM_GPIOD + +void +ao_led_on(uint8_t colors) +{ + LED_PORT->odr |= (colors & ao_led_enable); +} + +void +ao_led_off(uint8_t colors) +{ + LED_PORT->odr &= ~(colors & ao_led_enable); +} + +void +ao_led_set(uint8_t colors) +{ + LED_PORT->odr = (LED_PORT->odr & ~(ao_led_enable)) | (colors & ao_led_enable); +} + +void +ao_led_toggle(uint8_t colors) +{ + LED_PORT->odr ^= (colors & ao_led_enable); +} + +void +ao_led_for(uint8_t colors, uint16_t ticks) __reentrant +{ + ao_led_on(colors); + ao_delay(ticks); + ao_led_off(colors); +} + +void +ao_led_init(uint8_t enable) +{ + int bit; + + ao_led_enable = enable; + LED_PORT->odr &= ~enable; + for (bit = 0; bit < 16; bit++) { + if (enable & (1 << bit)) { + stm_moder_set(LED_PORT, bit, STM_MODER_OUTPUT); + stm_otyper_set(LED_PORT, bit, STM_OTYPER_PUSH_PULL); + } + } +} diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c new file mode 100644 index 00000000..dc446120 --- /dev/null +++ b/src/stm/ao_serial_stm.c @@ -0,0 +1,184 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include + +__xdata struct ao_fifo ao_usart1_rx_fifo; +__xdata struct ao_fifo ao_usart1_tx_fifo; + +void +ao_debug_out(char c) +{ + if (c == '\n') + ao_debug_out('\r'); + while (!(STM_USART1->usart_sr & (1 << STM_USART_SR_TXE))); + STM_USART1->usart_dr = c; +} + +#if 0 +static __xdata uint8_t ao_serial_tx1_started; + +static void +ao_serial_tx1_start(void) +{ + if (!ao_fifo_empty(ao_usart1_tx_fifo) && + !ao_serial_tx1_started) + { + ao_serial_tx1_started = 1; + ao_fifo_remove(ao_usart1_tx_fifo, STM_USART1->usart_dr); + } +} + +void usart1_isr(void) +{ + if (STM_USART1->usart_sr & (1 << STM_USART_SR_RXNE)) { + if (!ao_fifo_full(ao_usart1_rx_fifo)) + ao_fifo_insert(ao_usart1_rx_fifo, STM_USART1->usart_dr); + ao_wakeup(&ao_usart1_rx_fifo); +#if USE_SERIAL_STDIN + ao_wakeup(&ao_stdin_ready); +#endif + } + if (STM_USART1->usart_sr & (1 << STM_USART_SR_TXE)) { + ao_serial_tx1_started = 0; + ao_serial_tx1_start(); + ao_wakeup(&ao_usart1_tx_fifo); + } +} + +char +ao_serial_getchar(void) __critical +{ + char c; + cli(); + while (ao_fifo_empty(ao_usart1_rx_fifo)) + ao_sleep(&ao_usart1_rx_fifo); + ao_fifo_remove(ao_usart1_rx_fifo, c); + sei(); + return c; +} + +#if USE_SERIAL_STDIN +char +ao_serial_pollchar(void) __critical +{ + char c; + cli(); + if (ao_fifo_empty(ao_usart1_rx_fifo)) { + sei(); + return AO_READ_AGAIN; + } + ao_fifo_remove(ao_usart1_rx_fifo,c); + sei(); + return c; +} +#endif + +void +ao_serial_putchar(char c) __critical +{ + cli(); + while (ao_fifo_full(ao_usart1_tx_fifo)) + ao_sleep(&ao_usart1_tx_fifo); + ao_fifo_insert(ao_usart1_tx_fifo, c); + ao_serial_tx1_start(); + sei(); +} + +void +ao_serial_drain(void) __critical +{ + cli(); + while (!ao_fifo_empty(ao_usart1_tx_fifo)) + ao_sleep(&ao_usart1_tx_fifo); + sei(); +} + +#endif + +int _write(int file, char *ptr, int len) +{ + int l = len; + while (l--) + ao_debug_out(*ptr++); + return len; +} + +#define F_CPU 24000000 + +static const struct { + uint32_t usart_brr; +} ao_serial_speeds[] = { + [AO_SERIAL_SPEED_4800] = { + (F_CPU * 16) / (16 * 4800) + }, + [AO_SERIAL_SPEED_9600] = { + (F_CPU * 16) / (16 * 9600) + }, + [AO_SERIAL_SPEED_19200] = { + (F_CPU * 16) / (16 * 19200) + }, + [AO_SERIAL_SPEED_57600] = { + (F_CPU * 16) / (16 * 57600) + }, +}; + +void +ao_serial_set_speed(uint8_t speed) +{ +#if 0 + ao_serial_drain(); +#endif + if (speed > AO_SERIAL_SPEED_57600) + return; + STM_USART1->usart_brr = ao_serial_speeds[speed].usart_brr; +} + +void +ao_serial_init(void) +{ + STM_USART1->usart_cr1 = ((0 << STM_USART_CR1_OVER8) | + (1 << STM_USART_CR1_UE) | + (0 << STM_USART_CR1_M) | + (0 << STM_USART_CR1_WAKE) | + (0 << STM_USART_CR1_PCE) | + (0 << STM_USART_CR1_PS) | + (0 << STM_USART_CR1_PEIE) | + (0 << STM_USART_CR1_TXEIE) | /* XXX enable */ + (0 << STM_USART_CR1_TCIE) | + (0 << STM_USART_CR1_RXNEIE) | /* XXX enable */ + (0 << STM_USART_CR1_IDLEIE) | + (1 << STM_USART_CR1_TE) | + (1 << STM_USART_CR1_RE) | + (0 << STM_USART_CR1_RWU) | + (0 << STM_USART_CR1_SBK)); + + STM_USART1->usart_cr2 = 0; + STM_USART1->usart_cr3 = 0; + + /* Pick a 9600 baud rate */ + ao_serial_set_speed(AO_SERIAL_SPEED_9600); + + printf ("serial initialized\n"); +#if 0 +#if USE_SERIAL_STDIN + ao_add_stdio(ao_serial_pollchar, + ao_serial_putchar, + NULL); +#endif +#endif +} diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c new file mode 100644 index 00000000..f253e0c0 --- /dev/null +++ b/src/stm/ao_timer.c @@ -0,0 +1,167 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +static volatile __data uint16_t ao_tick_count; + +uint16_t ao_time(void) +{ + uint16_t v; + ao_arch_critical( + v = ao_tick_count; + ); + return v; +} + +static __xdata uint8_t ao_forever; + +void +ao_delay(uint16_t ticks) +{ + ao_alarm(ticks); + ao_sleep(&ao_forever); +} + +#define T2_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ +#define T2_SAMPLE_TIME 30000 /* 3e6/30000 = 100 */ + +#if HAS_ADC +volatile __data uint8_t ao_adc_interval = 1; +volatile __data uint8_t ao_adc_count; +#endif + +void +ao_debug_out(char c); + + +void tim2_isr(void) +{ + ++ao_tick_count; +#if HAS_ADC + if (++ao_adc_count == ao_adc_interval) { + ao_adc_count = 0; + ao_adc_poll(); + } +#endif +} + +#if HAS_ADC +void +ao_timer_set_adc_interval(uint8_t interval) __critical +{ + ao_adc_interval = interval; + ao_adc_count = 0; +} +#endif + +void +ao_timer_init(void) +{ +} + +void +ao_clock_init(void) +{ + uint32_t cfgr; + + /* Set flash latency to tolerate 32MHz SYSCLK -> 1 wait state */ + uint32_t acr = STM_FLASH->acr; + + /* Enable 64-bit access and prefetch */ + acr |= (1 << STM_FLASH_ACR_ACC64) | (1 << STM_FLASH_ACR_PRFEN); + STM_FLASH->acr = acr; + + /* Enable 1 wait state so the CPU can run at 32MHz */ + acr |= (1 << STM_FLASH_ACR_LATENCY); + STM_FLASH->acr = acr; + + /* Enable HSI RC clock 16MHz */ + if (!(STM_RCC->cr & (1 << STM_RCC_CR_HSIRDY))) { + STM_RCC->cr |= (1 << STM_RCC_CR_HSION); + while (!(STM_RCC->cr & (1 << STM_RCC_CR_HSIRDY))) + asm("nop"); + } + + /* Switch to direct HSI for SYSCLK */ + if ((STM_RCC->cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != + (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) { + cfgr = STM_RCC->cfgr; + cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); + cfgr |= (STM_RCC_CFGR_SW_HSI << STM_RCC_CFGR_SW); + STM_RCC->cfgr = cfgr; + while ((STM_RCC->cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != + (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) + asm("nop"); + } + + /* Disable the PLL */ + STM_RCC->cr &= ~(1 << STM_RCC_CR_PLLON); + while (STM_RCC->cr & (1 << STM_RCC_CR_PLLRDY)) + asm("nop"); + + /* PLLVCO to 96MHz (for USB) -> PLLMUL = 6 */ + cfgr = STM_RCC->cfgr; + cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL); + cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); + + /* SYSCLK to 32MHz from PLL clock -> PLLDIV = /3 */ + cfgr &= ~(STM_RCC_CFGR_PLLDIV_MASK << STM_RCC_CFGR_PLLDIV); + cfgr |= (STM_RCC_CFGR_PLLDIV_3 << STM_RCC_CFGR_PLLDIV); + + /* PLL source to HSI */ + cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC); + + STM_RCC->cfgr = cfgr; + + /* Enable the PLL and wait for it */ + STM_RCC->cr |= (1 << STM_RCC_CR_PLLON); + while (!(STM_RCC->cr & (1 << STM_RCC_CR_PLLRDY))) + asm("nop"); + + /* Switch to the PLL for the system clock */ + + cfgr = STM_RCC->cfgr; + cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); + cfgr |= (STM_RCC_CFGR_SW_PLL << STM_RCC_CFGR_SW); + STM_RCC->cfgr = cfgr; + while ((STM_RCC->cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != + (STM_RCC_CFGR_SWS_PLL << STM_RCC_CFGR_SWS)) + asm("nop"); + + /* HCLK to 32MHz -> AHB prescaler = /1 */ + cfgr = STM_RCC->cfgr; + cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE); + cfgr |= (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE); + STM_RCC->cfgr = cfgr; + while ((STM_RCC->cfgr & (STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE)) != + (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE)) + asm ("nop"); + + /* PCLK1 to 16MHz -> APB1 Prescaler = 2 */ + cfgr = STM_RCC->cfgr; + cfgr &= ~(STM_RCC_CFGR_PPRE1_MASK << STM_RCC_CFGR_PPRE1); + cfgr |= (STM_RCC_CFGR_PPRE1_DIV_2 << STM_RCC_CFGR_PPRE1); + STM_RCC->cfgr = cfgr; + + /* PCLK2 to 16MHz -> APB2 Prescaler = 2 */ + cfgr = STM_RCC->cfgr; + cfgr &= ~(STM_RCC_CFGR_PPRE2_MASK << STM_RCC_CFGR_PPRE2); + cfgr |= (STM_RCC_CFGR_PPRE2_DIV_2 << STM_RCC_CFGR_PPRE2); + STM_RCC->cfgr = cfgr; + +} diff --git a/src/stm/registers.ld b/src/stm/registers.ld new file mode 100644 index 00000000..51921444 --- /dev/null +++ b/src/stm/registers.ld @@ -0,0 +1,47 @@ +stm_fsmc = 0xa0000000; +stm_aes = 0x50060000; +stm_dma = 0x40026000; +stm_flash = 0x40023c00; +stm_rcc = 0x40023800; +stm_crc = 0x40023000; +stm_gpioh = 0x40021400; +stm_gpioe = 0x40021000; +stm_gpiod = 0x40020c00; +stm_gpioc = 0x40020800; +stm_gpiob = 0x40020400; +stm_gpioa = 0x40020000; +stm_usart1 = 0x40013800; +stm_spi1 = 0x40013000; +stm_sdio = 0x40012c00; +stm_adc = 0x40012400; +stm_tim11 = 0x40011000; +stm_tim10 = 0x40010c00; +stm_tim9 = 0x40010800; +stm_exti = 0x40010400; +stm_syscfg = 0x40010000; +stm_comp = 0x40007c00; +stm_ri = 0x40007c04; +stm_dac = 0x40007400; +stm_pwr = 0x40007000; +stm_usb_sram = 0x40006000; +stm_usb = 0x40005c00; +stm_i2c2 = 0x40005800; +stm_i2c1 = 0x40005400; +stm_usart5 = 0x40005000; +stm_usart4 = 0x40004c00; +stm_usart3 = 0x40004800; +stm_usart2 = 0x40004400; +stm_spi3 = 0x40003c00; /* docs are broken here */ +stm_spi2 = 0x40003800; /* docs are broken here */ +stm_iwdg = 0x40003000; +stm_wwdg = 0x40002c00; +stm_rtc = 0x40002800; +stm_lcd = 0x40002400; +stm_tim7 = 0x40001400; +stm_tim6 = 0x40001000; +stm_tim5 = 0x40000c00; +stm_tim4 = 0x40000800; +stm_tim3 = 0x40000400; +stm_tim2 = 0x40000000; + +stm_nvic = 0xe000e100; \ No newline at end of file diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h new file mode 100644 index 00000000..c5e2a797 --- /dev/null +++ b/src/stm/stm32l.h @@ -0,0 +1,662 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _STM32L_H_ +#define _STM32L_H_ + +#include + +typedef volatile uint32_t vuint32_t; + +struct stm_gpio { + vuint32_t moder; + vuint32_t otyper; + vuint32_t ospeedr; + vuint32_t pupdr; + + vuint32_t idr; + vuint32_t odr; + vuint32_t bsrr; + vuint32_t lckr; + + vuint32_t afrl; + vuint32_t afrh; +}; + +#define STM_MODER_SHIFT(pin) ((pin) << 1) +#define STM_MODER_MASK 3 +#define STM_MODER_INPUT 0 +#define STM_MODER_OUTPUT 1 +#define STM_MODER_ALTERNATE 2 +#define STM_MODER_ANALOG 3 + +static inline void +stm_moder_set(struct stm_gpio *gpio, int pin, vuint32_t value) { + gpio->moder = ((gpio->moder & + ~(STM_MODER_MASK << STM_MODER_SHIFT(pin))) | + value << STM_MODER_SHIFT(pin)); +} + +static inline vuint32_t +stm_moder_get(struct stm_gpio *gpio, int pin) { + return (gpio->moder >> STM_MODER_SHIFT(pin)) & STM_MODER_MASK; +} + +#define STM_OTYPER_SHIFT(pin) (pin) +#define STM_OTYPER_MASK 1 +#define STM_OTYPER_PUSH_PULL 0 +#define STM_OTYPER_OPEN_DRAIN 1 + +static inline void +stm_otyper_set(struct stm_gpio *gpio, int pin, vuint32_t value) { + gpio->otyper = ((gpio->otyper & + ~(STM_OTYPER_MASK << STM_OTYPER_SHIFT(pin))) | + value << STM_OTYPER_SHIFT(pin)); +} + +static inline vuint32_t +stm_otyper_get(struct stm_gpio *gpio, int pin) { + return (gpio->otyper >> STM_OTYPER_SHIFT(pin)) & STM_OTYPER_MASK; +} + +#define STM_OSPEEDR_SHIFT(pin) ((pin) << 1) +#define STM_OSPEEDR_MASK 3 +#define STM_OSPEEDR_400kHz 0 +#define STM_OSPEEDR_2MHz 1 +#define STM_OSPEEDR_10MHz 2 +#define STM_OSPEEDR_40MHz 3 + +static inline void +stm_ospeedr_set(struct stm_gpio *gpio, int pin, vuint32_t value) { + gpio->ospeedr = ((gpio->ospeedr & + ~(STM_OSPEEDR_MASK << STM_OSPEEDR_SHIFT(pin))) | + value << STM_OSPEEDR_SHIFT(pin)); +} + +static inline vuint32_t +stm_ospeedr_get(struct stm_gpio *gpio, int pin) { + return (gpio->ospeedr >> STM_OSPEEDR_SHIFT(pin)) & STM_OSPEEDR_MASK; +} + +#define STM_PUPDR_SHIFT(pin) ((pin) << 1) +#define STM_PUPDR_MASK 3 +#define STM_PUPDR_NONE 0 +#define STM_PUPDR_PULL_UP 1 +#define STM_PUPDR_PULL_DOWN 2 +#define STM_PUPDR_RESERVED 3 + +static inline void +stm_pupdr_set(struct stm_gpio *gpio, int pin, vuint32_t value) { + gpio->pupdr = ((gpio->pupdr & + ~(STM_PUPDR_MASK << STM_PUPDR_SHIFT(pin))) | + value << STM_PUPDR_SHIFT(pin)); +} + +static inline vuint32_t +stm_pupdr_get(struct stm_gpio *gpio, int pin) { + return (gpio->pupdr >> STM_PUPDR_SHIFT(pin)) & STM_PUPDR_MASK; +} + +#define STM_AFR_SHIFT(pin) ((pin) << 2) +#define STM_AFR_MASK 0xf +#define STM_AFR_NONE 0 +#define STM_AFR_AF0 0x0 +#define STM_AFR_AF1 0x1 +#define STM_AFR_AF2 0x2 +#define STM_AFR_AF3 0x3 +#define STM_AFR_AF4 0x4 +#define STM_AFR_AF5 0x5 +#define STM_AFR_AF6 0x6 +#define STM_AFR_AF7 0x7 +#define STM_AFR_AF8 0x8 +#define STM_AFR_AF9 0x9 +#define STM_AFR_AF10 0xa +#define STM_AFR_AF11 0xb +#define STM_AFR_AF12 0xc +#define STM_AFR_AF13 0xd +#define STM_AFR_AF14 0xe +#define STM_AFR_AF15 0xf + +static inline void +stm_afr_set(struct stm_gpio *gpio, int pin, uint32_t value) { + if (pin < 8) + gpio->afrl = ((gpio->afrl & + ~(STM_AFR_MASK << STM_AFR_SHIFT(pin))) | + value << STM_AFR_SHIFT(pin)); + else { + pin -= 8; + gpio->afrh = ((gpio->afrh & + ~(STM_AFR_MASK << STM_AFR_SHIFT(pin))) | + value << STM_AFR_SHIFT(pin)); + } +} + +static inline uint32_t +stm_afr_get(struct stm_gpio *gpio, int pin) { + if (pin < 8) + return (gpio->afrl >> STM_AFR_SHIFT(pin)) & STM_AFR_MASK; + else { + pin -= 8; + return (gpio->afrh >> STM_AFR_SHIFT(pin)) & STM_AFR_MASK; + } +} + +extern struct stm_gpio stm_gpioa; +extern struct stm_gpio stm_gpiob; +extern struct stm_gpio stm_gpioc; +extern struct stm_gpio stm_gpiod; +extern struct stm_gpio stm_gpioe; +extern struct stm_gpio stm_gpioh; + +struct stm_usart { + vuint32_t sr; /* status register */ + vuint32_t dr; /* data register */ + vuint32_t brr; /* baud rate register */ + vuint32_t cr1; /* control register 1 */ + + vuint32_t cr2; /* control register 2 */ + vuint32_t cr3; /* control register 3 */ + vuint32_t gtpr; /* guard time and prescaler */ +}; + +extern struct stm_usart stm_usart1; + +#define STM_USART_SR_CTS (9) /* CTS flag */ +#define STM_USART_SR_LBD (8) /* LIN break detection flag */ +#define STM_USART_SR_TXE (7) /* Transmit data register empty */ +#define STM_USART_SR_TC (6) /* Transmission complete */ +#define STM_USART_SR_RXNE (5) /* Read data register not empty */ +#define STM_USART_SR_IDLE (4) /* IDLE line detected */ +#define STM_USART_SR_ORE (3) /* Overrun error */ +#define STM_USART_SR_NF (2) /* Noise detected flag */ +#define STM_USART_SR_FE (1) /* Framing error */ +#define STM_USART_SR_PE (0) /* Parity error */ + +#define STM_USART_CR1_OVER8 (15) /* Oversampling mode */ +#define STM_USART_CR1_UE (13) /* USART enable */ +#define STM_USART_CR1_M (12) /* Word length */ +#define STM_USART_CR1_WAKE (11) /* Wakeup method */ +#define STM_USART_CR1_PCE (10) /* Parity control enable */ +#define STM_USART_CR1_PS (9) /* Parity selection */ +#define STM_USART_CR1_PEIE (8) /* PE interrupt enable */ +#define STM_USART_CR1_TXEIE (7) /* TXE interrupt enable */ +#define STM_USART_CR1_TCIE (6) /* Transmission complete interrupt enable */ +#define STM_USART_CR1_RXNEIE (5) /* RXNE interrupt enable */ +#define STM_USART_CR1_IDLEIE (4) /* IDLE interrupt enable */ +#define STM_USART_CR1_TE (3) /* Transmitter enable */ +#define STM_USART_CR1_RE (2) /* Receiver enable */ +#define STM_USART_CR1_RWU (1) /* Receiver wakeup */ +#define STM_USART_CR1_SBK (0) /* Send break */ + +#define STM_USART_CR2_LINEN (14) /* LIN mode enable */ +#define STM_USART_CR2_STOP (12) /* STOP bits */ +#define STM_USART_CR2_STOP_MASK 3 +#define STM_USART_CR2_STOP_1 0 +#define STM_USART_CR2_STOP_0_5 1 +#define STM_USART_CR2_STOP_2 2 +#define STM_USART_CR2_STOP_1_5 3 + +#define STM_USART_CR2_CLKEN (11) /* Clock enable */ +#define STM_USART_CR2_CPOL (10) /* Clock polarity */ +#define STM_USART_CR2_CPHA (9) /* Clock phase */ +#define STM_USART_CR2_LBCL (8) /* Last bit clock pulse */ +#define STM_USART_CR2_LBDIE (6) /* LIN break detection interrupt enable */ +#define STM_USART_CR2_LBDL (5) /* lin break detection length */ +#define STM_USART_CR2_ADD (0) +#define STM_USART_CR2_ADD_MASK 0xf + +#define STM_USART_CR3_ONEBITE (11) /* One sample bit method enable */ +#define STM_USART_CR3_CTSIE (10) /* CTS interrupt enable */ +#define STM_USART_CR3_CTSE (9) /* CTS enable */ +#define STM_USART_CR3_RTSE (8) /* RTS enable */ +#define STM_USART_CR3_DMAT (7) /* DMA enable transmitter */ +#define STM_USART_CR3_DMAR (6) /* DMA enable receiver */ +#define STM_USART_CR3_SCEN (5) /* Smartcard mode enable */ +#define STM_USART_CR3_NACK (4) /* Smartcard NACK enable */ +#define STM_USART_CR3_HDSEL (3) /* Half-duplex selection */ +#define STM_USART_CR3_IRLP (2) /* IrDA low-power */ +#define STM_USART_CR3_IREN (1) /* IrDA mode enable */ +#define STM_USART_CR3_EIE (0) /* Error interrupt enable */ + +struct stm_spi { +}; + +extern struct stm_spi stm_spi1; + +struct stm_tim { +}; + +extern struct stm_tim stm_tim9; +extern struct stm_tim stm_tim10; +extern struct stm_tim stm_tim11; + +/* Flash interface */ + +struct stm_flash { + vuint32_t acr; + vuint32_t pecr; + vuint32_t pdkeyr; + vuint32_t pekeyr; + + vuint32_t prgkeyr; + vuint32_t optkeyr; + vuint32_t sr; + vuint32_t obr; + + vuint32_t wrpr; +}; + +extern struct stm_flash stm_flash; + +#define STM_FLASH_ACR_RUN_PD (4) +#define STM_FLASH_ACR_SLEEP_PD (3) +#define STM_FLASH_ACR_ACC64 (2) +#define STM_FLASH_ACR_PRFEN (1) +#define STM_FLASH_ACR_LATENCY (0) + +struct stm_rcc { + vuint32_t cr; + vuint32_t icscr; + vuint32_t cfgr; + vuint32_t cir; + + vuint32_t ahbrstr; + vuint32_t apb2rstr; + vuint32_t abp1rstr; + vuint32_t ahbenr; + + vuint32_t apb2enr; + vuint32_t apb1enr; + vuint32_t ahblenr; + vuint32_t apb2lpenr; + + vuint32_t apb1lpenr; + vuint32_t csr; +}; + +extern struct stm_rcc stm_rcc; + +#define STM_RCC_CR_RTCPRE (29) +#define STM_RCC_CR_RTCPRE_HSE_DIV_2 0 +#define STM_RCC_CR_RTCPRE_HSE_DIV_4 1 +#define STM_RCC_CR_RTCPRE_HSE_DIV_8 2 +#define STM_RCC_CR_RTCPRE_HSE_DIV_16 3 +#define STM_RCC_CR_RTCPRE_HSE_MASK 3 + +#define STM_RCC_CR_CSSON (28) +#define STM_RCC_CR_PLLRDY (25) +#define STM_RCC_CR_PLLON (24) +#define STM_RCC_CR_HSEBYP (18) +#define STM_RCC_CR_HSERDY (17) +#define STM_RCC_CR_HSEON (16) +#define STM_RCC_CR_MSIRDY (9) +#define STM_RCC_CR_MSION (8) +#define STM_RCC_CR_HSIRDY (1) +#define STM_RCC_CR_HSION (0) + +#define STM_RCC_CFGR_MCOPRE (28) +#define STM_RCC_CFGR_MCOPRE_DIV_1 0 +#define STM_RCC_CFGR_MCOPRE_DIV_2 1 +#define STM_RCC_CFGR_MCOPRE_DIV_4 2 +#define STM_RCC_CFGR_MCOPRE_DIV_8 3 +#define STM_RCC_CFGR_MCOPRE_DIV_16 4 +#define STM_RCC_CFGR_MCOPRE_DIV_MASK 7 + +#define STM_RCC_CFGR_MCOSEL (24) +#define STM_RCC_CFGR_MCOSEL_DISABLE 0 +#define STM_RCC_CFGR_MCOSEL_SYSCLK 1 +#define STM_RCC_CFGR_MCOSEL_HSI 2 +#define STM_RCC_CFGR_MCOSEL_MSI 3 +#define STM_RCC_CFGR_MCOSEL_HSE 4 +#define STM_RCC_CFGR_MCOSEL_PLL 5 +#define STM_RCC_CFGR_MCOSEL_LSI 6 +#define STM_RCC_CFGR_MCOSEL_LSE 7 +#define STM_RCC_CFGR_MCOSEL_MASK 7 + +#define STM_RCC_CFGR_PLLDIV (22) +#define STM_RCC_CFGR_PLLDIV_2 1 +#define STM_RCC_CFGR_PLLDIV_3 2 +#define STM_RCC_CFGR_PLLDIV_4 3 +#define STM_RCC_CFGR_PLLDIV_MASK 3 + +#define STM_RCC_CFGR_PLLMUL (18) +#define STM_RCC_CFGR_PLLMUL_3 0 +#define STM_RCC_CFGR_PLLMUL_4 1 +#define STM_RCC_CFGR_PLLMUL_6 2 +#define STM_RCC_CFGR_PLLMUL_8 3 +#define STM_RCC_CFGR_PLLMUL_12 4 +#define STM_RCC_CFGR_PLLMUL_16 5 +#define STM_RCC_CFGR_PLLMUL_24 6 +#define STM_RCC_CFGR_PLLMUL_32 7 +#define STM_RCC_CFGR_PLLMUL_48 8 +#define STM_RCC_CFGR_PLLMUL_MASK 0xf + +#define STM_RCC_CFGR_PLLSRC (16) + +#define STM_RCC_CFGR_PPRE2 (11) +#define STM_RCC_CFGR_PPRE2_DIV_1 0 +#define STM_RCC_CFGR_PPRE2_DIV_2 4 +#define STM_RCC_CFGR_PPRE2_DIV_4 5 +#define STM_RCC_CFGR_PPRE2_DIV_8 6 +#define STM_RCC_CFGR_PPRE2_DIV_16 7 +#define STM_RCC_CFGR_PPRE2_MASK 7 + +#define STM_RCC_CFGR_PPRE1 (8) +#define STM_RCC_CFGR_PPRE1_DIV_1 0 +#define STM_RCC_CFGR_PPRE1_DIV_2 4 +#define STM_RCC_CFGR_PPRE1_DIV_4 5 +#define STM_RCC_CFGR_PPRE1_DIV_8 6 +#define STM_RCC_CFGR_PPRE1_DIV_16 7 +#define STM_RCC_CFGR_PPRE1_MASK 7 + +#define STM_RCC_CFGR_HPRE (4) +#define STM_RCC_CFGR_HPRE_DIV_1 0 +#define STM_RCC_CFGR_HPRE_DIV_2 8 +#define STM_RCC_CFGR_HPRE_DIV_4 9 +#define STM_RCC_CFGR_HPRE_DIV_8 0xa +#define STM_RCC_CFGR_HPRE_DIV_16 0xb +#define STM_RCC_CFGR_HPRE_DIV_64 0xc +#define STM_RCC_CFGR_HPRE_DIV_128 0xd +#define STM_RCC_CFGR_HPRE_DIV_256 0xe +#define STM_RCC_CFGR_HPRE_DIV_512 0xf +#define STM_RCC_CFGR_HPRE_MASK 0xf + +#define STM_RCC_CFGR_SWS (2) +#define STM_RCC_CFGR_SWS_MSI 0 +#define STM_RCC_CFGR_SWS_HSI 1 +#define STM_RCC_CFGR_SWS_HSE 2 +#define STM_RCC_CFGR_SWS_PLL 3 +#define STM_RCC_CFGR_SWS_MASK 3 + +#define STM_RCC_CFGR_SW (0) +#define STM_RCC_CFGR_SW_MSI 0 +#define STM_RCC_CFGR_SW_HSI 1 +#define STM_RCC_CFGR_SW_HSE 2 +#define STM_RCC_CFGR_SW_PLL 3 +#define STM_RCC_CFGR_SW_MASK 3 + +#define STM_RCC_AHBENR_DMA1EN (24) +#define STM_RCC_AHBENR_FLITFEN (15) +#define STM_RCC_AHBENR_CRCEN (12) +#define STM_RCC_AHBENR_GPIOHEN (5) +#define STM_RCC_AHBENR_GPIOEEN (4) +#define STM_RCC_AHBENR_GPIODEN (3) +#define STM_RCC_AHBENR_GPIOCEN (2) +#define STM_RCC_AHBENR_GPIOBEN (1) +#define STM_RCC_AHBENR_GPIOAEN (0) + +#define STM_RCC_APB2ENR_USART1EN (14) +#define STM_RCC_APB2ENR_SPI1EN (12) +#define STM_RCC_APB2ENR_ADC1EN (9) +#define STM_RCC_APB2ENR_TIM11EN (4) +#define STM_RCC_APB2ENR_TIM10EN (3) +#define STM_RCC_APB2ENR_TIM9EN (2) +#define STM_RCC_APB2ENR_SYSCFGEN (0) + +#define STM_RCC_APB1ENR_COMPEN (31) +#define STM_RCC_APB1ENR_DACEN (29) +#define STM_RCC_APB1ENR_PWREN (28) +#define STM_RCC_APB1ENR_USBEN (23) +#define STM_RCC_APB1ENR_I2C2EN (22) +#define STM_RCC_APB1ENR_I2C1EN (21) +#define STM_RCC_APB1ENR_USART3EN (18) +#define STM_RCC_APB1ENR_USART2EN (17) +#define STM_RCC_APB1ENR_SPI2EN (14) +#define STM_RCC_APB1ENR_WWDGEN (11) +#define STM_RCC_APB1ENR_LCDEN (9) +#define STM_RCC_APB1ENR_TIM7EN (5) +#define STM_RCC_APB1ENR_TIM6EN (4) +#define STM_RCC_APB1ENR_TIM4EN (2) +#define STM_RCC_APB1ENR_TIM3EN (1) +#define STM_RCC_APB1ENR_TIM2EN (0) + +struct stm_pwr { + vuint32_t cr; + vuint32_t csr; +}; + +extern struct stm_pwr stm_pwr; + +#define STM_PWR_CR_LPRUN (14) + +#define STM_PWR_CR_VOS (11) +#define STM_PWR_CR_VOS_1_8 1 +#define STM_PWR_CR_VOS_1_5 2 +#define STM_PWR_CR_VOS_1_2 3 +#define STM_PWR_CR_VOS_MASK 3 + +#define STM_PWR_CR_FWU (10) +#define STM_PWR_CR_ULP (9) +#define STM_PWR_CR_DBP (8) + +#define STM_PWR_CR_PLS (5) +#define STM_PWR_CR_PLS_1_9 0 +#define STM_PWR_CR_PLS_2_1 1 +#define STM_PWR_CR_PLS_2_3 2 +#define STM_PWR_CR_PLS_2_5 3 +#define STM_PWR_CR_PLS_2_7 4 +#define STM_PWR_CR_PLS_2_9 5 +#define STM_PWR_CR_PLS_3_1 6 +#define STM_PWR_CR_PLS_EXT 7 +#define STM_PWR_CR_PLS_MASK 7 + +#define STM_PWR_CR_PVDE (4) +#define STM_PWR_CR_CSBF (3) +#define STM_PWR_CR_CWUF (2) +#define STM_PWR_CR_PDDS (1) +#define STM_PWR_CR_LPSDSR (0) + +#define STM_PWR_CSR_EWUP3 (10) +#define STM_PWR_CSR_EWUP2 (9) +#define STM_PWR_CSR_EWUP1 (8) +#define STM_PWR_CSR_REGLPF (5) +#define STM_PWR_CSR_VOSF (4) +#define STM_PWR_CSR_VREFINTRDYF (3) +#define STM_PWR_CSR_PVDO (2) +#define STM_PWR_CSR_SBF (1) +#define STM_PWR_CSR_WUF (0) + +struct stm_tim67 { + vuint32_t cr1; + vuint32_t cr2; + uint32_t _unused_08; + vuint32_t dier; + + vuint32_t sr; + vuint32_t egr; + uint32_t _unused_18; + uint32_t _unused_1c; + + uint32_t _unused_20; + vuint32_t cnt; + vuint32_t psc; + vuint32_t arr; +}; + +extern struct stm_tim67 stm_tim6; + +#define STM_TIM67_CR1_ARPE (7) +#define STM_TIM67_CR1_OPM (3) +#define STM_TIM67_CR1_URS (2) +#define STM_TIM67_CR1_UDIS (1) +#define STM_TIM67_CR1_CEN (0) + +#define STM_TIM67_CR2_MMS (4) +#define STM_TIM67_CR2_MMS_RESET 0 +#define STM_TIM67_CR2_MMS_ENABLE 1 +#define STM_TIM67_CR2_MMS_UPDATE 2 +#define STM_TIM67_CR2_MMS_MASK 7 + +#define STM_TIM67_DIER_UDE (8) +#define STM_TIM67_DIER_UIE (0) + +#define STM_TIM67_SR_UIF (0) + +#define STM_TIM67_EGR_UG (0) + +struct stm_nvic { + vuint32_t iser[3]; /* 0x000 */ + + uint8_t _unused00c[0x080 - 0x00c]; + + vuint32_t icer[3]; /* 0x080 */ + + uint8_t _unused08c[0x100 - 0x08c]; + + vuint32_t ispr[3]; /* 0x100 */ + + uint8_t _unused10c[0x180 - 0x10c]; + + vuint32_t icpr[3]; /* 0x180 */ + + uint8_t _unused18c[0x200 - 0x18c]; + + vuint32_t iabr[3]; /* 0x200 */ + + uint8_t _unused20c[0x300 - 0x20c]; + + vuint32_t ipr[21]; /* 0x300 */ + + uint8_t _unused324[0xe00 - 0x324]; + + vuint32_t stir; /* 0xe00 */ +}; + +extern struct stm_nvic stm_nvic; + +#define IRQ_REG(irq) ((irq) >> 5) +#define IRQ_BIT(irq) ((irq) & 0x1f) +#define IRQ_MASK(irq) (1 << IRQ_BIT(irq)) +#define IRQ_BOOL(v,irq) (((v) >> IRQ_BIT(irq)) & 1) + +static inline void +stm_nvic_set_enable(int irq) { + stm_nvic.iser[IRQ_REG(irq)] = IRQ_MASK(irq); +} + +static inline void +stm_nvic_clear_enable(int irq) { + stm_nvic.icer[IRQ_REG(irq)] = IRQ_MASK(irq); +} + +static inline int +stm_nvic_enabled(int irq) { + return IRQ_BOOL(stm_nvic.iser[IRQ_REG(irq)], irq); +} + +static inline void +stm_nvic_set_pending(int irq) { + stm_nvic.ispr[IRQ_REG(irq)] = IRQ_MASK(irq); +} + +static inline void +stm_nvic_clear_pending(int irq) { + stm_nvic.icpr[IRQ_REG(irq)] = IRQ_MASK(irq); +} + +static inline int +stm_nvic_pending(int irq) { + return IRQ_BOOL(stm_nvic.ispr[IRQ_REG(irq)], irq); +} + +static inline int +stm_nvic_active(int irq) { + return IRQ_BOOL(stm_nvic.iabr[IRQ_REG(irq)], irq); +} + +#define IRQ_PRIO_REG(irq) ((irq) >> 2) +#define IRQ_PRIO_BIT(irq) (((irq) & 3) << 3) +#define IRQ_PRIO_MASK(irq) (0xff << IRQ_PRIO_BIT(irq)) + +static inline void +stm_nvic_set_priority(int irq, uint8_t prio) { + int n = IRQ_PRIO_REG(irq); + uint32_t v; + + v = stm_nvic.ipr[n]; + v &= ~IRQ_PRIO_MASK(irq); + v |= (prio) << IRQ_PRIO_BIT(irq); + stm_nvic.ipr[n] = v; +} + +static inline uint8_t +stm_nvic_get_priority(int irq) { + return (stm_nvic.ipr[IRQ_PRIO_REG(irq)] >> IRQ_PRIO_BIT(irq)) & IRQ_PRIO_MASK(0); +} + +#define isr(name) void stm_ ## name ## _isr(void); + +isr(nmi) +isr(hardfault) +isr(memmanage) +isr(busfault) +isr(usagefault) +isr(svc) +isr(debugmon) +isr(pendsv) +isr(systick) +isr(wwdg) +isr(pvd) +isr(tamper_stamp) +isr(rtc_wkup) +isr(flash) +isr(rcc) +isr(exti0) +isr(exti1) +isr(exti2) +isr(exti3) +isr(exti4) +isr(dma1_channel1) +isr(dma1_channel2) +isr(dma1_channel3) +isr(dma1_channel4) +isr(dma1_channel5) +isr(dma1_channel6) +isr(dma1_channel7) +isr(adc1) +isr(usb_hp) +isr(usb_lp) +isr(dac) +isr(comp) +isr(exti9_5) +isr(lcd) +isr(tim9) +isr(tim10) +isr(tim11) +isr(tim2) +isr(tim3) +isr(tim4) +isr(i2c1_ev) +isr(i2c1_er) +isr(i2c2_ev) +isr(i2c2_er) +isr(spi1) +isr(spi2) +isr(usart1) +isr(usart2) +isr(usart3) +isr(exti15_10) +isr(rtc_alarm) +isr(usb_fs_wkup) +isr(tim6) +isr(tim7) + +#define STM_ISR_TIM6_POS 43 + +#undef isr + +#endif /* _STM32L_H_ */ -- cgit v1.2.3 From b8100ea5042013bb4eed67907b4e9d4e5c196df2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 16 Mar 2012 20:23:31 -0700 Subject: Add stm bringup timers and move most of the setup code to the stm dir Signed-off-by: Keith Packard --- src/stm-bringup/Makefile | 33 +++++++++++++++++----------- src/stm-bringup/bringup.c | 56 +++++++++++++++++++++++++++++------------------ 2 files changed, 55 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/stm-bringup/Makefile b/src/stm-bringup/Makefile index 49966a4f..1ba480ba 100644 --- a/src/stm-bringup/Makefile +++ b/src/stm-bringup/Makefile @@ -1,34 +1,41 @@ +vpath % ..:../core:../product:../drivers:../stm +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + CC=arm-none-eabi-gcc OBJCOPY=arm-none-eabi-objcopy -C_LIB=/local/src/pdclib/pdclib.a -C_INC=-I/local/src/pdclib/includes -I/local/src/pdclib/internals +PDCLIB=/home/keithp/sat +C_LIB=$(PDCLIB)/lib/pdclib.a +C_INC=-I$(PDCLIB)/include -DEF_CFLAGS=-g -std=gnu99 -O0 -mlittle-endian -mthumb -ffreestanding -nostdlib -I../../src/stm $(C_INC) +DEF_CFLAGS=-g -std=gnu99 -Os -mlittle-endian -mthumb -ffreestanding -nostdlib -I../../src/stm $(C_INC) # to run from SRAM -LD_FLAGS_RAM=-Wl,-Taltos-ram.ld -LD_FLAGS=-Wl,-Taltos.ld +LD_FLAGS_RAM=-L../stm -Wl,-Taltos-ram.ld +LD_FLAGS=-L../stm -Wl,-Taltos.ld CFLAGS=$(DEF_CFLAGS) -mcpu=cortex-m3 -DCONFIG_STM32L_DISCOVERY -OBJS=bringup.o +SRC=bringup.c ao_interrupt.c +OBJ=$(SRC:.c=.o) all: bringup-ram.elf bringup.elf %.bin: %.elf $(OBJCOPY) -O binary $^ $@ -bringup.elf: $(OBJS) $(C_LIB) altos.ld - $(CC) $(CFLAGS) $(LD_FLAGS) -o $@ $(OBJS) $(C_LIB) -lgcc - -bringup-ram.elf: $(OBJS) $(C_LIB) altos-ram.ld - $(CC) $(CFLAGS) $(LD_FLAGS_RAM) -o $@ $(OBJS) $(C_LIB) -lgcc +bringup.elf: $(OBJ) $(C_LIB) altos.ld + $(CC) $(CFLAGS) $(LD_FLAGS) -o $@ $(OBJ) $(C_LIB) -lgcc -bringup.o: bringup.c - $(CC) -c $(CFLAGS) bringup.c +bringup-ram.elf: $(OBJ) $(C_LIB) altos-ram.ld + $(CC) $(CFLAGS) $(LD_FLAGS_RAM) -o $@ $(OBJ) $(C_LIB) -lgcc clean: + rm -f *.o rm -rf *.elf rm -rf *.bin diff --git a/src/stm-bringup/bringup.c b/src/stm-bringup/bringup.c index b6fe458d..c5fad4a3 100644 --- a/src/stm-bringup/bringup.c +++ b/src/stm-bringup/bringup.c @@ -250,13 +250,46 @@ serial_string(char *string) outbyte(c); } +volatile uint16_t tick_count; + +void +stm_tim6_isr(void) +{ + if (stm_tim6.sr & (1 << STM_TIM67_SR_UIF)) { + stm_tim6.sr = 0; + ++tick_count; + } +} + +#define TIMER_10kHz (STM_APB1 / 10000) + void set_timer6(void) { + stm_nvic_set_enable(STM_ISR_TIM6_POS); + stm_nvic_set_priority(STM_ISR_TIM6_POS, 1); + /* Turn on timer 6 */ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN); - + stm_tim6.psc = TIMER_10kHz; + stm_tim6.arr = 100; + stm_tim6.cnt = 0; + + /* Enable update interrupt */ + stm_tim6.dier = (1 << STM_TIM67_DIER_UIE); + + /* Poke timer to reload values */ + stm_tim6.egr |= (1 << STM_TIM67_EGR_UG); + + stm_tim6.cr2 = (STM_TIM67_CR2_MMS_RESET << STM_TIM67_CR2_MMS); + + /* And turn it on */ + stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) | + (0 << STM_TIM67_CR1_OPM) | + (1 << STM_TIM67_CR1_URS) | + (0 << STM_TIM67_CR1_UDIS) | + (1 << STM_TIM67_CR1_CEN)); } void @@ -273,7 +306,7 @@ main (void) printf ("hello, "); delay(); stm_gpiob.odr = (1 << 6); - printf ("world\n"); + printf ("world %d\n", tick_count); delay(); } } @@ -285,22 +318,3 @@ delay(void) for (i = 0; i < 1000000; i++) __asm__ __volatile__ ("nop\n\t":::"memory"); } - -static int x = 7; - -extern char __stack__; -extern char __text_start__, __text_end__; -extern char __data_start__, __data_end__; -extern char __bss_start__, __bss_end__; - -void start(void) { - memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__); - memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__); - main(); -} - -__attribute__ ((section(".interrupt"))) -static const void *interrupt[] = { - &__stack__, - start, -}; -- cgit v1.2.3 From 8ba5344514f8ed51f6fd69ca09f6c7035c4fd0da Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 17 Mar 2012 00:06:59 -0700 Subject: Add stm-demo program This runs AltOS and talks over the serial port. Signed-off-by: Keith Packard --- src/stm-demo/.gitignore | 2 + src/stm-demo/Makefile | 95 ++++++++++++++++++++++++++++ src/stm-demo/ao_demo.c | 49 ++++++++++++++ src/stm-demo/ao_pins.h | 27 ++++++++ src/stm/ao_arch.h | 4 ++ src/stm/ao_romconfig.c | 20 ++++++ src/stm/ao_serial_stm.c | 111 +++++++++++++++++++++----------- src/stm/ao_timer.c | 165 +++++++++++++++++++++++++++++++++--------------- src/stm/stm32l.h | 13 ++++ 9 files changed, 398 insertions(+), 88 deletions(-) create mode 100644 src/stm-demo/.gitignore create mode 100644 src/stm-demo/Makefile create mode 100644 src/stm-demo/ao_demo.c create mode 100644 src/stm-demo/ao_pins.h create mode 100644 src/stm/ao_romconfig.c (limited to 'src') diff --git a/src/stm-demo/.gitignore b/src/stm-demo/.gitignore new file mode 100644 index 00000000..32b08ce8 --- /dev/null +++ b/src/stm-demo/.gitignore @@ -0,0 +1,2 @@ +stm-demo +ao_product.h diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile new file mode 100644 index 00000000..e009c30c --- /dev/null +++ b/src/stm-demo/Makefile @@ -0,0 +1,95 @@ +# +# AltOS build +# +# +vpath % ..:../core:../product:../drivers:../stm +vpath make-altitude .. +vpath make-kalman .. +vpath kalman.5c ../kalman +vpath kalman_filter.5c ../kalman +vpath load_csv.5c ../kalman +vpath matrix.5c ../kalman +vpath ao-make-product.5c ../util + +#PROGRAMMER=stk500v2 -P usb +#PROGRAMMER=usbtiny +#LOADCMD=avrdude +#LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: +CC=arm-none-eabi-gcc +#OBJCOPY=avr-objcopy + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + altitude.h \ + ao_kalman.h + +# +# Common AltOS sources +# +ALTOS_SRC = \ + ao_interrupt.c \ + ao_product.c \ + ao_romconfig.c \ + ao_cmd.c \ + ao_task.c \ + ao_stdio.c \ + ao_panic.c \ + ao_timer.c \ + ao_serial_stm.c + +PRODUCT=StmDemo-v0.0 +PRODUCT_DEF=-DSTM_DEMO +IDPRODUCT=0x000a +CPU=cortex-m3 +CFLAGS = $(PRODUCT_DEF) -I. -I../stm -I../core -I.. +CFLAGS += -g -std=gnu99 -Os -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib -I../stm $(CINC) + +NICKLE=nickle + +PROG=stm-demo + +SRC=$(ALTOS_SRC) ao_demo.c +OBJ=$(SRC:.c=.o) + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: $(PROG) + +CLIB=/home/keithp/sat/lib/pdclib.a +CINC=-I/home/keithp/sat/include +LDFLAGS=-L../stm -Wl,-Taltos.ld + +$(PROG): Makefile $(OBJ) + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(CLIB) -lgcc + +../altitude.h: make-altitude + nickle $< > $@ + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +ao_product.rel: ao_product.c ao_product.h + $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< + +distclean: clean + +clean: + rm -f $(OBJ) + rm -f ao_product.h + +install: + +uninstall: + +$(OBJ): ao.h ao_product.h \ No newline at end of file diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c new file mode 100644 index 00000000..90216535 --- /dev/null +++ b/src/stm-demo/ao_demo.c @@ -0,0 +1,49 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +struct ao_task demo_task; + +void +ao_demo(void) +{ + int i = 0; + for (;;) { + printf ("hello %d\n", i++); + } +} + +void _close() { } +void _sbrk() { } +void _isatty() { } +void _lseek() { } +void _exit () { } +void _read () { } +void _fstat() { } +int +main(void) +{ + ao_clock_init(); + + ao_serial_init(); + ao_timer_init(); + ao_cmd_init(); + + ao_demo(); + return 0; +} diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h new file mode 100644 index 00000000..82d70bb6 --- /dev/null +++ b/src/stm-demo/ao_pins.h @@ -0,0 +1,27 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_SERIAL_1 1 +#define USE_SERIAL_STDIN 1 +#define HAS_USB 0 +#define HAS_BEEP 0 +#define PACKET_HAS_SLAVE 0 + +#endif /* _AO_PINS_H_ */ diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index e6f54fdb..b3c0190d 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -124,6 +124,10 @@ struct ao_adc { uint16_t adc[AO_ARM_NUM_ADC]; /* samples */ }; +/* + * For now, we're running at a weird frequency + */ +#define STM_APB1 (16000000 * 6 / 4) #endif /* _AO_ARCH_H_ */ diff --git a/src/stm/ao_romconfig.c b/src/stm/ao_romconfig.c new file mode 100644 index 00000000..bbb677e2 --- /dev/null +++ b/src/stm/ao_romconfig.c @@ -0,0 +1,20 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +const uint16_t ao_serial_number = 0; diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index dc446120..ead2570f 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -25,11 +25,16 @@ ao_debug_out(char c) { if (c == '\n') ao_debug_out('\r'); - while (!(STM_USART1->usart_sr & (1 << STM_USART_SR_TXE))); - STM_USART1->usart_dr = c; + while (!(stm_usart1.sr & (1 << STM_USART_SR_TXE))); + stm_usart1.dr = c; +} + +void +outbyte(char c) +{ + putchar(c); } -#if 0 static __xdata uint8_t ao_serial_tx1_started; static void @@ -39,21 +44,26 @@ ao_serial_tx1_start(void) !ao_serial_tx1_started) { ao_serial_tx1_started = 1; - ao_fifo_remove(ao_usart1_tx_fifo, STM_USART1->usart_dr); + ao_fifo_remove(ao_usart1_tx_fifo, stm_usart1.dr); } } -void usart1_isr(void) +void stm_usart1_isr(void) { - if (STM_USART1->usart_sr & (1 << STM_USART_SR_RXNE)) { + uint32_t sr; + cli(); + sr = stm_usart1.sr; + stm_usart1.sr = 0; + sei(); + if (sr & (1 << STM_USART_SR_RXNE)) { if (!ao_fifo_full(ao_usart1_rx_fifo)) - ao_fifo_insert(ao_usart1_rx_fifo, STM_USART1->usart_dr); + ao_fifo_insert(ao_usart1_rx_fifo, stm_usart1.dr); ao_wakeup(&ao_usart1_rx_fifo); #if USE_SERIAL_STDIN ao_wakeup(&ao_stdin_ready); #endif } - if (STM_USART1->usart_sr & (1 << STM_USART_SR_TXE)) { + if (sr & (1 << STM_USART_SR_TXE)) { ao_serial_tx1_started = 0; ao_serial_tx1_start(); ao_wakeup(&ao_usart1_tx_fifo); @@ -108,8 +118,6 @@ ao_serial_drain(void) __critical sei(); } -#endif - int _write(int file, char *ptr, int len) { int l = len; @@ -118,22 +126,20 @@ int _write(int file, char *ptr, int len) return len; } -#define F_CPU 24000000 - static const struct { - uint32_t usart_brr; + uint32_t brr; } ao_serial_speeds[] = { [AO_SERIAL_SPEED_4800] = { - (F_CPU * 16) / (16 * 4800) + STM_APB1 / 4800 }, [AO_SERIAL_SPEED_9600] = { - (F_CPU * 16) / (16 * 9600) + STM_APB1 / 9600 }, [AO_SERIAL_SPEED_19200] = { - (F_CPU * 16) / (16 * 19200) + STM_APB1 / 19200 }, [AO_SERIAL_SPEED_57600] = { - (F_CPU * 16) / (16 * 57600) + STM_APB1 / 57600 }, }; @@ -145,30 +151,60 @@ ao_serial_set_speed(uint8_t speed) #endif if (speed > AO_SERIAL_SPEED_57600) return; - STM_USART1->usart_brr = ao_serial_speeds[speed].usart_brr; + stm_usart1.brr = ao_serial_speeds[speed].brr; } void ao_serial_init(void) { - STM_USART1->usart_cr1 = ((0 << STM_USART_CR1_OVER8) | - (1 << STM_USART_CR1_UE) | - (0 << STM_USART_CR1_M) | - (0 << STM_USART_CR1_WAKE) | - (0 << STM_USART_CR1_PCE) | - (0 << STM_USART_CR1_PS) | - (0 << STM_USART_CR1_PEIE) | - (0 << STM_USART_CR1_TXEIE) | /* XXX enable */ - (0 << STM_USART_CR1_TCIE) | - (0 << STM_USART_CR1_RXNEIE) | /* XXX enable */ - (0 << STM_USART_CR1_IDLEIE) | - (1 << STM_USART_CR1_TE) | - (1 << STM_USART_CR1_RE) | - (0 << STM_USART_CR1_RWU) | - (0 << STM_USART_CR1_SBK)); - - STM_USART1->usart_cr2 = 0; - STM_USART1->usart_cr3 = 0; + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + + stm_moder_set(&stm_gpioa, 9, STM_MODER_ALTERNATE); + stm_moder_set(&stm_gpioa, 10, STM_MODER_ALTERNATE); + stm_afr_set(&stm_gpioa, 9, STM_AFR_AF7); + stm_afr_set(&stm_gpioa, 10, STM_AFR_AF7); + + /* Enable USART1 */ + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN); + + stm_usart1.cr1 = ((0 << STM_USART_CR1_OVER8) | + (1 << STM_USART_CR1_UE) | + (0 << STM_USART_CR1_M) | + (0 << STM_USART_CR1_WAKE) | + (0 << STM_USART_CR1_PCE) | + (0 << STM_USART_CR1_PS) | + (0 << STM_USART_CR1_PEIE) | + (1 << STM_USART_CR1_TXEIE) | + (0 << STM_USART_CR1_TCIE) | + (1 << STM_USART_CR1_RXNEIE) | + (0 << STM_USART_CR1_IDLEIE) | + (1 << STM_USART_CR1_TE) | + (1 << STM_USART_CR1_RE) | + (0 << STM_USART_CR1_RWU) | + (0 << STM_USART_CR1_SBK)); + + stm_usart1.cr2 = ((0 << STM_USART_CR2_LINEN) | + (STM_USART_CR2_STOP_1 << STM_USART_CR2_STOP) | + (0 << STM_USART_CR2_CLKEN) | + (0 << STM_USART_CR2_CPOL) | + (0 << STM_USART_CR2_CPHA) | + (0 << STM_USART_CR2_LBCL) | + (0 << STM_USART_CR2_LBDIE) | + (0 << STM_USART_CR2_LBDL) | + (0 << STM_USART_CR2_ADD)); + + stm_usart1.cr3 = ((0 << STM_USART_CR3_ONEBITE) | + (0 << STM_USART_CR3_CTSIE) | + (0 << STM_USART_CR3_CTSE) | + (0 << STM_USART_CR3_RTSE) | + (0 << STM_USART_CR3_DMAT) | + (0 << STM_USART_CR3_DMAR) | + (0 << STM_USART_CR3_SCEN) | + (0 << STM_USART_CR3_NACK) | + (0 << STM_USART_CR3_HDSEL) | + (0 << STM_USART_CR3_IRLP) | + (0 << STM_USART_CR3_IREN) | + (0 << STM_USART_CR3_EIE)); /* Pick a 9600 baud rate */ ao_serial_set_speed(AO_SERIAL_SPEED_9600); @@ -181,4 +217,7 @@ ao_serial_init(void) NULL); #endif #endif + + stm_nvic_set_enable(STM_ISR_USART1_POS); + stm_nvic_set_priority(STM_ISR_USART1_POS, 4); } diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index f253e0c0..76304f0e 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -37,9 +37,6 @@ ao_delay(uint16_t ticks) ao_sleep(&ao_forever); } -#define T2_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ -#define T2_SAMPLE_TIME 30000 /* 3e6/30000 = 100 */ - #if HAS_ADC volatile __data uint8_t ao_adc_interval = 1; volatile __data uint8_t ao_adc_count; @@ -49,7 +46,7 @@ void ao_debug_out(char c); -void tim2_isr(void) +void stm_tim6_isr(void) { ++ao_tick_count; #if HAS_ADC @@ -69,99 +66,163 @@ ao_timer_set_adc_interval(uint8_t interval) __critical } #endif +#define TIMER_10kHz (STM_APB1 / 10000) + void ao_timer_init(void) { + stm_nvic_set_enable(STM_ISR_TIM6_POS); + stm_nvic_set_priority(STM_ISR_TIM6_POS, 1); + + /* Turn on timer 6 */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN); + + stm_tim6.psc = TIMER_10kHz; + stm_tim6.arr = 100; + stm_tim6.cnt = 0; + + /* Enable update interrupt */ + stm_tim6.dier = (1 << STM_TIM67_DIER_UIE); + + /* Poke timer to reload values */ + stm_tim6.egr |= (1 << STM_TIM67_EGR_UG); + + stm_tim6.cr2 = (STM_TIM67_CR2_MMS_RESET << STM_TIM67_CR2_MMS); + + /* And turn it on */ + stm_tim6.cr1 = ((0 << STM_TIM67_CR1_ARPE) | + (0 << STM_TIM67_CR1_OPM) | + (1 << STM_TIM67_CR1_URS) | + (0 << STM_TIM67_CR1_UDIS) | + (1 << STM_TIM67_CR1_CEN)); } void ao_clock_init(void) { uint32_t cfgr; + uint32_t cr; /* Set flash latency to tolerate 32MHz SYSCLK -> 1 wait state */ - uint32_t acr = STM_FLASH->acr; + uint32_t acr = stm_flash.acr; /* Enable 64-bit access and prefetch */ acr |= (1 << STM_FLASH_ACR_ACC64) | (1 << STM_FLASH_ACR_PRFEN); - STM_FLASH->acr = acr; + stm_flash.acr = acr; /* Enable 1 wait state so the CPU can run at 32MHz */ + /* (haven't managed to run the CPU at 32MHz yet, it's at 16MHz) */ acr |= (1 << STM_FLASH_ACR_LATENCY); - STM_FLASH->acr = acr; + stm_flash.acr = acr; + + /* HCLK to 16MHz -> AHB prescaler = /1 */ + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE); + cfgr |= (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE); + stm_rcc.cfgr = cfgr; + while ((stm_rcc.cfgr & (STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE)) != + (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE)) + asm ("nop"); +#define STM_AHB_PRESCALER 1 + + /* PCLK1 to 16MHz -> APB1 Prescaler = 1 */ + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_PPRE1_MASK << STM_RCC_CFGR_PPRE1); + cfgr |= (STM_RCC_CFGR_PPRE1_DIV_1 << STM_RCC_CFGR_PPRE1); + stm_rcc.cfgr = cfgr; +#define STM_APB1_PRESCALER 1 + + /* PCLK2 to 16MHz -> APB2 Prescaler = 1 */ + cfgr = stm_rcc.cfgr; + cfgr &= ~(STM_RCC_CFGR_PPRE2_MASK << STM_RCC_CFGR_PPRE2); + cfgr |= (STM_RCC_CFGR_PPRE2_DIV_1 << STM_RCC_CFGR_PPRE2); + stm_rcc.cfgr = cfgr; +#define STM_APB2_PRESCALER 1 + + /* Enable power interface clock */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); + + /* Set voltage range to 1.8V */ + + /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ + while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) + asm("nop"); + + /* Configure voltage scaling range */ + cr = stm_pwr.cr; + cr &= ~(STM_PWR_CR_VOS_MASK << STM_PWR_CR_VOS); + cr |= (STM_PWR_CR_VOS_1_8 << STM_PWR_CR_VOS); + stm_pwr.cr = cr; + + /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ + while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) + asm("nop"); /* Enable HSI RC clock 16MHz */ - if (!(STM_RCC->cr & (1 << STM_RCC_CR_HSIRDY))) { - STM_RCC->cr |= (1 << STM_RCC_CR_HSION); - while (!(STM_RCC->cr & (1 << STM_RCC_CR_HSIRDY))) + if (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) { + stm_rcc.cr |= (1 << STM_RCC_CR_HSION); + while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) asm("nop"); } +#define STM_HSI 16000000 /* Switch to direct HSI for SYSCLK */ - if ((STM_RCC->cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != + if ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) { - cfgr = STM_RCC->cfgr; + cfgr = stm_rcc.cfgr; cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); cfgr |= (STM_RCC_CFGR_SW_HSI << STM_RCC_CFGR_SW); - STM_RCC->cfgr = cfgr; - while ((STM_RCC->cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != + stm_rcc.cfgr = cfgr; + while ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) asm("nop"); } /* Disable the PLL */ - STM_RCC->cr &= ~(1 << STM_RCC_CR_PLLON); - while (STM_RCC->cr & (1 << STM_RCC_CR_PLLRDY)) + stm_rcc.cr &= ~(1 << STM_RCC_CR_PLLON); + while (stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY)) asm("nop"); - /* PLLVCO to 96MHz (for USB) -> PLLMUL = 6 */ - cfgr = STM_RCC->cfgr; + /* PLLVCO to 96MHz (for USB) -> PLLMUL = 6, PLLDIV = 4 */ + cfgr = stm_rcc.cfgr; cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL); - cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); - - /* SYSCLK to 32MHz from PLL clock -> PLLDIV = /3 */ cfgr &= ~(STM_RCC_CFGR_PLLDIV_MASK << STM_RCC_CFGR_PLLDIV); - cfgr |= (STM_RCC_CFGR_PLLDIV_3 << STM_RCC_CFGR_PLLDIV); + +// cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); +// cfgr |= (STM_RCC_CFGR_PLLDIV_3 << STM_RCC_CFGR_PLLDIV); + + cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); + cfgr |= (STM_RCC_CFGR_PLLDIV_4 << STM_RCC_CFGR_PLLDIV); + +#define STM_PLLMUL 6 +#define STM_PLLDIV 4 /* PLL source to HSI */ cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC); - STM_RCC->cfgr = cfgr; +#define STM_PLLSRC STM_HSI + + stm_rcc.cfgr = cfgr; /* Enable the PLL and wait for it */ - STM_RCC->cr |= (1 << STM_RCC_CR_PLLON); - while (!(STM_RCC->cr & (1 << STM_RCC_CR_PLLRDY))) + stm_rcc.cr |= (1 << STM_RCC_CR_PLLON); + while (!(stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY))) asm("nop"); /* Switch to the PLL for the system clock */ - cfgr = STM_RCC->cfgr; + cfgr = stm_rcc.cfgr; cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); cfgr |= (STM_RCC_CFGR_SW_PLL << STM_RCC_CFGR_SW); - STM_RCC->cfgr = cfgr; - while ((STM_RCC->cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != - (STM_RCC_CFGR_SWS_PLL << STM_RCC_CFGR_SWS)) - asm("nop"); - - /* HCLK to 32MHz -> AHB prescaler = /1 */ - cfgr = STM_RCC->cfgr; - cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE); - cfgr |= (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE); - STM_RCC->cfgr = cfgr; - while ((STM_RCC->cfgr & (STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE)) != - (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE)) - asm ("nop"); - - /* PCLK1 to 16MHz -> APB1 Prescaler = 2 */ - cfgr = STM_RCC->cfgr; - cfgr &= ~(STM_RCC_CFGR_PPRE1_MASK << STM_RCC_CFGR_PPRE1); - cfgr |= (STM_RCC_CFGR_PPRE1_DIV_2 << STM_RCC_CFGR_PPRE1); - STM_RCC->cfgr = cfgr; - - /* PCLK2 to 16MHz -> APB2 Prescaler = 2 */ - cfgr = STM_RCC->cfgr; - cfgr &= ~(STM_RCC_CFGR_PPRE2_MASK << STM_RCC_CFGR_PPRE2); - cfgr |= (STM_RCC_CFGR_PPRE2_DIV_2 << STM_RCC_CFGR_PPRE2); - STM_RCC->cfgr = cfgr; - + stm_rcc.cfgr = cfgr; + for (;;) { + uint32_t c, part, mask, val; + + c = stm_rcc.cfgr; + mask = (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS); + val = (STM_RCC_CFGR_SWS_PLL << STM_RCC_CFGR_SWS); + part = c & mask; + if (part == val) + break; + } } diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index c5e2a797..5b3f6b2f 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -655,7 +655,20 @@ isr(usb_fs_wkup) isr(tim6) isr(tim7) +#define STM_ISR_TIM9_POS 25 +#define STM_ISR_TIM10_POS 26 +#define STM_ISR_TIM11_POS 27 +#define STM_ISR_TIM2_POS 28 +#define STM_ISR_TIM3_POS 29 +#define STM_ISR_TIM4_POS 30 + +#define STM_ISR_SPI1_POS 35 +#define STM_ISR_SPI2_POS 36 +#define STM_ISR_USART1_POS 37 +#define STM_ISR_USART2_POS 38 +#define STM_ISR_USART3_POS 39 #define STM_ISR_TIM6_POS 43 +#define STM_ISR_TIM7_POS 44 #undef isr -- cgit v1.2.3 From 93481fd3d9305a107b88c8a64de4194a6d94dc0e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 18 Mar 2012 22:05:46 -0700 Subject: Incorrect type in ao_task_info for wchan Would truncate 32-bit pointers on arm. Signed-off-by: Keith Packard --- src/core/ao_task.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_task.c b/src/core/ao_task.c index a19a6a6f..d7d0e8a2 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -164,7 +164,7 @@ ao_task_info(void) task = ao_tasks[i]; printf("%12s: wchan %04x\n", task->name, - (int16_t) task->wchan); + (int) task->wchan); } } -- cgit v1.2.3 From 4bfce11873f34af9621c60f83a8355f85769f6d3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 18 Mar 2012 22:07:07 -0700 Subject: When debugging, send pre-init output to ao_debug_out Before tasking is running, send output to ao_debug_out to help debug system initialization. Signed-off-by: Keith Packard --- src/core/ao_stdio.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/core/ao_stdio.c b/src/core/ao_stdio.c index c0138a30..2967e705 100644 --- a/src/core/ao_stdio.c +++ b/src/core/ao_stdio.c @@ -30,6 +30,15 @@ __pdata int8_t ao_num_stdios; void putchar(char c) { +#if LOW_LEVEL_DEBUG + if (!ao_cur_task) { + extern void ao_debug_out(char c); + if (c == '\n') + ao_debug_out('\r'); + ao_debug_out(c); + return; + } +#endif if (c == '\n') (*ao_stdios[ao_cur_stdio].putchar)('\r'); (*ao_stdios[ao_cur_stdio].putchar)(c); -- cgit v1.2.3 From 1ca46760cf903860dccb4864578558a1abb6e0fa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 18 Mar 2012 22:08:48 -0700 Subject: When debugging, send ao_panic message to ao_debug_out Use the low-level debug hooks to get the panic state sent to the serial port. Signed-off-by: Keith Packard --- src/core/ao_panic.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c index 244917a8..25dc145e 100644 --- a/src/core/ao_panic.c +++ b/src/core/ao_panic.c @@ -45,6 +45,10 @@ ao_panic(uint8_t reason) { uint8_t n; +#if LOW_LEVEL_DEBUG + ao_cur_task = NULL; + printf ("panic %d\n", reason); +#endif __critical for (;;) { ao_panic_delay(20); for (n = 0; n < 5; n++) { -- cgit v1.2.3 From 0cc01d378ae96325e429ad608b953661582939b0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 18 Mar 2012 22:09:20 -0700 Subject: Add AO_PANIC_STACK Provide a panic code for stack overflow. Signed-off-by: Keith Packard --- src/core/ao.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index ac51c270..86a943a8 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -113,6 +113,7 @@ ao_start_scheduler(void); #define AO_PANIC_FLASH 9 /* Invalid flash part (or wrong blocksize) */ #define AO_PANIC_USB 10 /* Trying to send USB packet while busy */ #define AO_PANIC_BT 11 /* Communications with bluetooth device failed */ +#define AO_PANIC_STACK 12 /* Stack overflow */ /* Stop the operating system, beeping and blinking the reason */ void -- cgit v1.2.3 From ab6ea9043b592c25948a70b6204d613756a9a250 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 18 Mar 2012 22:10:02 -0700 Subject: Basic OS running on STM32L This gets stm-demo working Signed-off-by: Keith Packard --- src/Makefile | 1 + src/stm-demo/Makefile | 2 +- src/stm-demo/ao_demo.c | 5 ++-- src/stm-demo/ao_pins.h | 2 ++ src/stm/ao_arch.h | 19 ++++++++------- src/stm/ao_serial_stm.c | 15 ++++++------ src/stm/ao_timer.c | 13 +++++++---- src/stm/stm32l.h | 61 +++++++++++++++++++++++++++++++++++++------------ 8 files changed, 77 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index e5d0c960..3603c277 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,6 +13,7 @@ vpath matrix.5c kalman include Version SUBDIRS=\ + stm-bringup stm-demo \ telemetrum-v1.2 telemetrum-v1.1 telemetrum-v1.0 \ teledongle-v0.2 teledongle-v0.1 \ telemini-v1.0 telenano-v0.1 \ diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index e009c30c..a675182e 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -47,7 +47,7 @@ PRODUCT_DEF=-DSTM_DEMO IDPRODUCT=0x000a CPU=cortex-m3 CFLAGS = $(PRODUCT_DEF) -I. -I../stm -I../core -I.. -CFLAGS += -g -std=gnu99 -Os -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib -I../stm $(CINC) +CFLAGS += -g -std=gnu99 -O0 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib -I../stm $(CINC) NICKLE=nickle diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 90216535..5fe0b154 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -42,8 +42,9 @@ main(void) ao_serial_init(); ao_timer_init(); - ao_cmd_init(); +// ao_cmd_init(); - ao_demo(); + ao_add_task(&demo_task, ao_demo, "demo"); + ao_start_scheduler(); return 0; } diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 82d70bb6..f436e9c8 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -24,4 +24,6 @@ #define HAS_BEEP 0 #define PACKET_HAS_SLAVE 0 +#define LOW_LEVEL_DEBUG 1 + #endif /* _AO_PINS_H_ */ diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index b3c0190d..205f95d7 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -25,7 +25,7 @@ * STM32L definitions and code fragments for AltOS */ -#define AO_STACK_SIZE 256 +#define AO_STACK_SIZE 1024 /* Various definitions to make GCC look more like SDCC */ @@ -67,29 +67,26 @@ extern const uint16_t ao_serial_number; #define ao_arch_init_stack(task, start) do { \ uint32_t *sp = (uint32_t *) (task->stack + AO_STACK_SIZE); \ - uint16_t a = (uint16_t) start; \ + uint32_t a = (uint32_t) start; \ int i; \ \ - /* Return address */ \ + /* Return address (goes into LR) */ \ ARM_PUSH32(sp, a); \ \ - /* Invalid link register */ \ - ARM_PUSH32(sp, 0xffffffff); \ - \ /* Clear register values */ \ i = 13; \ while (i--) \ ARM_PUSH32(sp, 0); \ \ - /* PSR with interrupts enabled */ \ - ARM_PUSH32(sp, 0x01000000); \ + /* APSR */ \ + ARM_PUSH32(sp, 0); \ task->sp = sp; \ } while (0); #define ao_arch_save_regs() do { \ asm("push {r0-r12,lr}\n"); \ cli(); \ - asm("mrs r0,psr" "\n\t" "push {r0}"); \ + asm("mrs r0,apsr" "\n\t" "push {r0}"); \ sei(); \ } while (0) @@ -97,6 +94,8 @@ extern const uint16_t ao_serial_number; uint32_t sp; \ asm("mov %0,sp" : "=&r" (sp) ); \ ao_cur_task->sp = (uint32_t *) (sp); \ + if ((uint8_t *) ao_cur_task->sp < ao_cur_task->stack) \ + ao_panic (AO_PANIC_STACK); \ } while (0) #define ao_arch_isr_stack() /* nothing */ @@ -110,7 +109,7 @@ extern const uint16_t ao_serial_number; sp = (uint32_t) ao_cur_task->sp; \ cli(); \ asm("mov sp, %0" : : "r" (sp) ); \ - asm("pop {r0}" "\n\t" "msr psr,r0"); \ + asm("pop {r0}" "\n\t" "msr apsr,r0"); \ asm("pop {r0-r12,lr}\n"); \ asm("bx lr"); \ } while(0) diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index ead2570f..38f16e5e 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -51,19 +51,20 @@ ao_serial_tx1_start(void) void stm_usart1_isr(void) { uint32_t sr; - cli(); + sr = stm_usart1.sr; stm_usart1.sr = 0; - sei(); + if (sr & (1 << STM_USART_SR_RXNE)) { + char c = stm_usart1.dr; if (!ao_fifo_full(ao_usart1_rx_fifo)) - ao_fifo_insert(ao_usart1_rx_fifo, stm_usart1.dr); + ao_fifo_insert(ao_usart1_rx_fifo, c); ao_wakeup(&ao_usart1_rx_fifo); #if USE_SERIAL_STDIN ao_wakeup(&ao_stdin_ready); #endif } - if (sr & (1 << STM_USART_SR_TXE)) { + if (sr & (1 << STM_USART_SR_TC)) { ao_serial_tx1_started = 0; ao_serial_tx1_start(); ao_wakeup(&ao_usart1_tx_fifo); @@ -174,8 +175,8 @@ ao_serial_init(void) (0 << STM_USART_CR1_PCE) | (0 << STM_USART_CR1_PS) | (0 << STM_USART_CR1_PEIE) | - (1 << STM_USART_CR1_TXEIE) | - (0 << STM_USART_CR1_TCIE) | + (0 << STM_USART_CR1_TXEIE) | + (1 << STM_USART_CR1_TCIE) | (1 << STM_USART_CR1_RXNEIE) | (0 << STM_USART_CR1_IDLEIE) | (1 << STM_USART_CR1_TE) | @@ -210,12 +211,10 @@ ao_serial_init(void) ao_serial_set_speed(AO_SERIAL_SPEED_9600); printf ("serial initialized\n"); -#if 0 #if USE_SERIAL_STDIN ao_add_stdio(ao_serial_pollchar, ao_serial_putchar, NULL); -#endif #endif stm_nvic_set_enable(STM_ISR_USART1_POS); diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 76304f0e..387df184 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -48,13 +48,16 @@ ao_debug_out(char c); void stm_tim6_isr(void) { - ++ao_tick_count; + if (stm_tim6.sr & (1 << STM_TIM67_SR_UIF)) { + stm_tim6.sr = 0; + ++ao_tick_count; #if HAS_ADC - if (++ao_adc_count == ao_adc_interval) { - ao_adc_count = 0; - ao_adc_poll(); - } + if (++ao_adc_count == ao_adc_interval) { + ao_adc_count = 0; + ao_adc_poll(); + } #endif + } } #if HAS_ADC diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 5b3f6b2f..d7c382a6 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -655,21 +655,52 @@ isr(usb_fs_wkup) isr(tim6) isr(tim7) -#define STM_ISR_TIM9_POS 25 -#define STM_ISR_TIM10_POS 26 -#define STM_ISR_TIM11_POS 27 -#define STM_ISR_TIM2_POS 28 -#define STM_ISR_TIM3_POS 29 -#define STM_ISR_TIM4_POS 30 - -#define STM_ISR_SPI1_POS 35 -#define STM_ISR_SPI2_POS 36 -#define STM_ISR_USART1_POS 37 -#define STM_ISR_USART2_POS 38 -#define STM_ISR_USART3_POS 39 -#define STM_ISR_TIM6_POS 43 -#define STM_ISR_TIM7_POS 44 - #undef isr +#define STM_ISR_WWDG_POS 0 +#define STM_ISR_PVD_POS 1 +#define STM_ISR_TAMPER_STAMP_POS 2 +#define STM_ISR_RTC_WKUP_POS 3 +#define STM_ISR_FLASH_POS 4 +#define STM_ISR_RCC_POS 5 +#define STM_ISR_EXTI0_POS 6 +#define STM_ISR_EXTI1_POS 7 +#define STM_ISR_EXTI2_POS 8 +#define STM_ISR_EXTI3_POS 9 +#define STM_ISR_EXTI4_POS 10 +#define STM_ISR_DMA1_CHANNEL1_POS 11 +#define STM_ISR_DMA2_CHANNEL1_POS 12 +#define STM_ISR_DMA3_CHANNEL1_POS 13 +#define STM_ISR_DMA4_CHANNEL1_POS 14 +#define STM_ISR_DMA5_CHANNEL1_POS 15 +#define STM_ISR_DMA6_CHANNEL1_POS 16 +#define STM_ISR_DMA7_CHANNEL1_POS 17 +#define STM_ISR_ADC1_POS 18 +#define STM_ISR_USB_HP_POS 19 +#define STM_ISR_USB_LP_POS 20 +#define STM_ISR_DAC_POS 21 +#define STM_ISR_COMP_POS 22 +#define STM_ISR_EXTI9_5_POS 23 +#define STM_ISR_LCD_POS 24 +#define STM_ISR_TIM9_POS 25 +#define STM_ISR_TIM10_POS 26 +#define STM_ISR_TIM11_POS 27 +#define STM_ISR_TIM2_POS 28 +#define STM_ISR_TIM3_POS 29 +#define STM_ISR_TIM4_POS 30 +#define STM_ISR_I2C1_EV_POS 31 +#define STM_ISR_I2C1_ER_POS 32 +#define STM_ISR_I2C2_EV_POS 33 +#define STM_ISR_I2C2_ER_POS 34 +#define STM_ISR_SPI1_POS 35 +#define STM_ISR_SPI2_POS 36 +#define STM_ISR_USART1_POS 37 +#define STM_ISR_USART2_POS 38 +#define STM_ISR_USART3_POS 39 +#define STM_ISR_EXTI15_10_POS 40 +#define STM_ISR_RTC_ALARM_POS 41 +#define STM_ISR_USB_FS_WKUP_POS 42 +#define STM_ISR_TIM6_POS 43 +#define STM_ISR_TIM7_POS 44 + #endif /* _STM32L_H_ */ -- cgit v1.2.3 From 4be74ef0d13114707fd8217907a5ec457f886160 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 18 Mar 2012 22:26:43 -0700 Subject: Fix STM LED driver and blink LEDs on discovery board This adds a task to blink the LEDs, after first fixing up the LED output code to enable the GPIO and talk to the right pins for the discovery board. Signed-off-by: Keith Packard --- src/stm-demo/Makefile | 1 + src/stm-demo/ao_demo.c | 13 +++++++++---- src/stm-demo/ao_pins.h | 11 +++++++++++ src/stm/ao_led.c | 17 ++++++++--------- 4 files changed, 29 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index a675182e..b2413a2c 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -37,6 +37,7 @@ ALTOS_SRC = \ ao_romconfig.c \ ao_cmd.c \ ao_task.c \ + ao_led.c \ ao_stdio.c \ ao_panic.c \ ao_timer.c \ diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 5fe0b154..94527089 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -22,9 +22,13 @@ struct ao_task demo_task; void ao_demo(void) { - int i = 0; for (;;) { - printf ("hello %d\n", i++); + ao_led_on(AO_LED_BLUE); + ao_delay(AO_MS_TO_TICKS(500)); + ao_led_off(AO_LED_BLUE); + ao_led_on(AO_LED_GREEN); + ao_delay(AO_MS_TO_TICKS(500)); + ao_led_off(AO_LED_GREEN); } } @@ -42,9 +46,10 @@ main(void) ao_serial_init(); ao_timer_init(); -// ao_cmd_init(); - + ao_cmd_init(); + ao_led_init(LEDS_AVAILABLE); ao_add_task(&demo_task, ao_demo, "demo"); + ao_start_scheduler(); return 0; } diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index f436e9c8..39d4fc3c 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -26,4 +26,15 @@ #define LOW_LEVEL_DEBUG 1 +#define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOBEN +#define LED_PORT stm_gpiob +#define LED_PIN_GREEN 7 +#define LED_PIN_BLUE 6 +#define AO_LED_GREEN (1 << LED_PIN_GREEN) +#define AO_LED_BLUE (1 << LED_PIN_BLUE) + +#define AO_LED_RED AO_LED_BLUE /* a patent lie */ + +#define LEDS_AVAILABLE (AO_LED_BLUE | AO_LED_GREEN) + #endif /* _AO_PINS_H_ */ diff --git a/src/stm/ao_led.c b/src/stm/ao_led.c index db65afdf..0574aa2a 100644 --- a/src/stm/ao_led.c +++ b/src/stm/ao_led.c @@ -19,30 +19,28 @@ __pdata uint8_t ao_led_enable; -#define LED_PORT STM_GPIOD - void ao_led_on(uint8_t colors) { - LED_PORT->odr |= (colors & ao_led_enable); + LED_PORT.odr |= (colors & ao_led_enable); } void ao_led_off(uint8_t colors) { - LED_PORT->odr &= ~(colors & ao_led_enable); + LED_PORT.odr &= ~(colors & ao_led_enable); } void ao_led_set(uint8_t colors) { - LED_PORT->odr = (LED_PORT->odr & ~(ao_led_enable)) | (colors & ao_led_enable); + LED_PORT.odr = (LED_PORT.odr & ~(ao_led_enable)) | (colors & ao_led_enable); } void ao_led_toggle(uint8_t colors) { - LED_PORT->odr ^= (colors & ao_led_enable); + LED_PORT.odr ^= (colors & ao_led_enable); } void @@ -58,12 +56,13 @@ ao_led_init(uint8_t enable) { int bit; + stm_rcc.ahbenr |= (1 << LED_PORT_ENABLE); ao_led_enable = enable; - LED_PORT->odr &= ~enable; + LED_PORT.odr &= ~enable; for (bit = 0; bit < 16; bit++) { if (enable & (1 << bit)) { - stm_moder_set(LED_PORT, bit, STM_MODER_OUTPUT); - stm_otyper_set(LED_PORT, bit, STM_OTYPER_PUSH_PULL); + stm_moder_set(&LED_PORT, bit, STM_MODER_OUTPUT); + stm_otyper_set(&LED_PORT, bit, STM_OTYPER_PUSH_PULL); } } } -- cgit v1.2.3 From 7662a0096a860cddac413a310305fe842830c3b5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 18 Mar 2012 22:29:51 -0700 Subject: Add .gitignore file to stm-bringup Ignore generated binaries Signed-off-by: Keith Packard --- src/stm-bringup/.gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/stm-bringup/.gitignore (limited to 'src') diff --git a/src/stm-bringup/.gitignore b/src/stm-bringup/.gitignore new file mode 100644 index 00000000..50992530 --- /dev/null +++ b/src/stm-bringup/.gitignore @@ -0,0 +1 @@ +*.elf -- cgit v1.2.3 From 6a14bee42a8431c909bcd74b0acec57329bc0284 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 19 Mar 2012 11:24:43 -0700 Subject: Don't disable interrupts before saving interrupt flag on AVR This ignores the interrupt disabled state, so we'd always leave ao_yield with interrupts disabled. Signed-off-by: Keith Packard --- src/avr/ao_arch.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index c189ccba..b816279e 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -105,7 +105,6 @@ extern uint8_t ao_cpu_sleep_disable; asm("push r14" "\n\t" "push r13" "\n\t" "push r12" "\n\t" "push r11" "\n\t" "push r10"); \ asm("push r9" "\n\t" "push r8" "\n\t" "push r7" "\n\t" "push r6" "\n\t" "push r5"); \ asm("push r4" "\n\t" "push r3" "\n\t" "push r2" "\n\t" "push r1" "\n\t" "push r0"); \ - cli(); \ asm("in r0, __SREG__" "\n\t" "push r0"); \ sei(); \ } while (0) -- cgit v1.2.3 From faf2bea4fdb3dca7fbed35423a4fe4459ee92ceb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 19 Mar 2012 11:25:40 -0700 Subject: Save/restore PRIMASK register on Cortex-M3 This preserves the interrupt-enabled bit across context switches Signed-off-by: Keith Packard --- src/stm-demo/Makefile | 9 ++++++--- src/stm/ao_arch.h | 51 +++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 45 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index b2413a2c..9e4f9e38 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -3,8 +3,8 @@ # # vpath % ..:../core:../product:../drivers:../stm -vpath make-altitude .. -vpath make-kalman .. +vpath make-altitude ../util +vpath make-kalman ../util vpath kalman.5c ../kalman vpath kalman_filter.5c ../kalman vpath load_csv.5c ../kalman @@ -24,6 +24,7 @@ endif INC = \ ao.h \ + ao_arch.h \ ao_pins.h \ altitude.h \ ao_kalman.h @@ -48,7 +49,7 @@ PRODUCT_DEF=-DSTM_DEMO IDPRODUCT=0x000a CPU=cortex-m3 CFLAGS = $(PRODUCT_DEF) -I. -I../stm -I../core -I.. -CFLAGS += -g -std=gnu99 -O0 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib -I../stm $(CINC) +CFLAGS += -g -std=gnu99 -Os -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib -I../stm $(CINC) NICKLE=nickle @@ -77,6 +78,8 @@ $(PROG): Makefile $(OBJ) ../altitude.h: make-altitude nickle $< > $@ +$(OBJ): $(INC) + ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 205f95d7..c4b98c7a 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -70,31 +70,44 @@ extern const uint16_t ao_serial_number; uint32_t a = (uint32_t) start; \ int i; \ \ + /* APSR */ \ + ARM_PUSH32(sp, 0); \ + \ + /* PRIMASK with interrupts enabled */ \ + ARM_PUSH32(sp, 0); \ + \ /* Return address (goes into LR) */ \ ARM_PUSH32(sp, a); \ \ - /* Clear register values */ \ + /* Clear register values r0-r12 */ \ i = 13; \ while (i--) \ ARM_PUSH32(sp, 0); \ \ - /* APSR */ \ - ARM_PUSH32(sp, 0); \ task->sp = sp; \ } while (0); -#define ao_arch_save_regs() do { \ +#define ao_arch_save_regs() do { \ + uint32_t apsr; \ + uint32_t primask; \ + \ + /* Save APSR */ \ + asm("mrs %0,apsr" : "=&r" (apsr)); \ + asm("push {%0}" : : "r" (apsr)); \ + \ + /* Save PRIMASK */ \ + asm("mrs %0,primask" : "=&r" (primask)); \ + asm("push {%0}" : : "r" (primask)); \ + \ + /* Save general registers */ \ asm("push {r0-r12,lr}\n"); \ - cli(); \ - asm("mrs r0,apsr" "\n\t" "push {r0}"); \ - sei(); \ } while (0) #define ao_arch_save_stack() do { \ - uint32_t sp; \ + uint32_t *sp; \ asm("mov %0,sp" : "=&r" (sp) ); \ - ao_cur_task->sp = (uint32_t *) (sp); \ - if ((uint8_t *) ao_cur_task->sp < ao_cur_task->stack) \ + ao_cur_task->sp = (sp); \ + if ((uint8_t *) sp < ao_cur_task->stack) \ ao_panic (AO_PANIC_STACK); \ } while (0) @@ -106,11 +119,25 @@ extern const uint16_t ao_serial_number; #define ao_arch_restore_stack() do { \ uint32_t sp; \ + uint32_t primask; \ + uint32_t apsr; \ sp = (uint32_t) ao_cur_task->sp; \ - cli(); \ + \ + /* Switch stacks */ \ asm("mov sp, %0" : : "r" (sp) ); \ - asm("pop {r0}" "\n\t" "msr apsr,r0"); \ + \ + /* Restore general registers */ \ asm("pop {r0-r12,lr}\n"); \ + \ + /* Restore PRIMASK */ \ + asm("pop {%0}" : "=&r" (primask) ); \ + asm("msr primask,%0" : : "r" (primask) ); \ + \ + /* Restore APSR */ \ + asm("pop {%0}" : "=&r" (apsr) ); \ + asm("msr apsr,%0" : : "r" (apsr) ); \ + \ + /* Return to calling function */ \ asm("bx lr"); \ } while(0) -- cgit v1.2.3 From f560c961ae4fedec0c9f11d5b3635fcb0d67ed8e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Mar 2012 16:18:26 -0700 Subject: Add support for multiple serial ports on STM32L Signed-off-by: Keith Packard --- src/stm-demo/ao_pins.h | 2 + src/stm/ao_serial_stm.c | 236 +++++++++++++++++++++++++++++++++--------------- src/stm/stm32l.h | 2 + 3 files changed, 168 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 39d4fc3c..c72cd04b 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -19,6 +19,8 @@ #define _AO_PINS_H_ #define HAS_SERIAL_1 1 +#define HAS_SERIAL_2 1 +#define HAS_SERIAL_3 1 #define USE_SERIAL_STDIN 1 #define HAS_USB 0 #define HAS_BEEP 0 diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index 38f16e5e..9302bdf8 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -17,8 +17,22 @@ #include -__xdata struct ao_fifo ao_usart1_rx_fifo; -__xdata struct ao_fifo ao_usart1_tx_fifo; +struct ao_stm_usart { + struct ao_fifo rx_fifo; + struct ao_fifo tx_fifo; + struct stm_usart *reg; + uint8_t tx_started; +}; + +#if HAS_SERIAL_1 +struct ao_stm_usart ao_stm_usart1; +#endif +#if HAS_SERIAL_2 +struct ao_stm_usart ao_stm_usart2; +#endif +#if HAS_SERIAL_3 +struct ao_stm_usart ao_stm_usart3; +#endif void ao_debug_out(char c) @@ -29,107 +43,106 @@ ao_debug_out(char c) stm_usart1.dr = c; } +#if 0 void outbyte(char c) { putchar(c); } - -static __xdata uint8_t ao_serial_tx1_started; +#endif static void -ao_serial_tx1_start(void) +ao_usart_tx_start(struct ao_stm_usart *usart) { - if (!ao_fifo_empty(ao_usart1_tx_fifo) && - !ao_serial_tx1_started) + if (!ao_fifo_empty(usart->tx_fifo) && !usart->tx_started) { - ao_serial_tx1_started = 1; - ao_fifo_remove(ao_usart1_tx_fifo, stm_usart1.dr); + usart->tx_started = 1; + ao_fifo_remove(usart->tx_fifo, usart->reg->dr); } } -void stm_usart1_isr(void) +static void +ao_usart_isr(struct ao_stm_usart *usart, int stdin) { uint32_t sr; - sr = stm_usart1.sr; - stm_usart1.sr = 0; + sr = usart->reg->sr; + usart->reg->sr = 0; if (sr & (1 << STM_USART_SR_RXNE)) { - char c = stm_usart1.dr; - if (!ao_fifo_full(ao_usart1_rx_fifo)) - ao_fifo_insert(ao_usart1_rx_fifo, c); - ao_wakeup(&ao_usart1_rx_fifo); -#if USE_SERIAL_STDIN - ao_wakeup(&ao_stdin_ready); -#endif + char c = usart->reg->dr; + if (!ao_fifo_full(usart->rx_fifo)) + ao_fifo_insert(usart->rx_fifo, c); + ao_wakeup(&usart->rx_fifo); + if (stdin) + ao_wakeup(&ao_stdin_ready); } if (sr & (1 << STM_USART_SR_TC)) { - ao_serial_tx1_started = 0; - ao_serial_tx1_start(); - ao_wakeup(&ao_usart1_tx_fifo); + usart->tx_started = 0; + ao_usart_tx_start(usart); + ao_wakeup(&usart->tx_fifo); } } +#if HAS_SERIAL_1 +void stm_usart1_isr(void) { ao_usart_isr(&ao_stm_usart1, USE_SERIAL_STDIN); } +#endif +#if HAS_SERIAL_2 +void stm_usart2_isr(void) { ao_usart_isr(&ao_stm_usart2, 0); } +#endif +#if HAS_SERIAL_3 +void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, 0); } +#endif + char -ao_serial_getchar(void) __critical +ao_usart_getchar(struct ao_stm_usart *usart) { - char c; + char c; cli(); - while (ao_fifo_empty(ao_usart1_rx_fifo)) - ao_sleep(&ao_usart1_rx_fifo); - ao_fifo_remove(ao_usart1_rx_fifo, c); + while (ao_fifo_empty(usart->rx_fifo)) + ao_sleep(&usart->rx_fifo); + ao_fifo_remove(usart->rx_fifo, c); sei(); return c; } -#if USE_SERIAL_STDIN char -ao_serial_pollchar(void) __critical +ao_usart_pollchar(struct ao_stm_usart *usart) { char c; cli(); - if (ao_fifo_empty(ao_usart1_rx_fifo)) { + if (ao_fifo_empty(usart->rx_fifo)) { sei(); return AO_READ_AGAIN; } - ao_fifo_remove(ao_usart1_rx_fifo,c); + ao_fifo_remove(usart->rx_fifo,c); sei(); return c; } -#endif void -ao_serial_putchar(char c) __critical +ao_usart_putchar(struct ao_stm_usart *usart, char c) { cli(); - while (ao_fifo_full(ao_usart1_tx_fifo)) - ao_sleep(&ao_usart1_tx_fifo); - ao_fifo_insert(ao_usart1_tx_fifo, c); - ao_serial_tx1_start(); + while (ao_fifo_full(usart->tx_fifo)) + ao_sleep(&usart->tx_fifo); + ao_fifo_insert(usart->tx_fifo, c); + ao_usart_tx_start(usart); sei(); } void -ao_serial_drain(void) __critical +ao_usart_drain(struct ao_stm_usart *usart) { cli(); - while (!ao_fifo_empty(ao_usart1_tx_fifo)) - ao_sleep(&ao_usart1_tx_fifo); + while (!ao_fifo_empty(usart->tx_fifo)) + ao_sleep(&usart->tx_fifo); sei(); } -int _write(int file, char *ptr, int len) -{ - int l = len; - while (l--) - ao_debug_out(*ptr++); - return len; -} - static const struct { uint32_t brr; -} ao_serial_speeds[] = { +} ao_usart_speeds[] = { [AO_SERIAL_SPEED_4800] = { STM_APB1 / 4800 }, @@ -145,30 +158,17 @@ static const struct { }; void -ao_serial_set_speed(uint8_t speed) +ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed) { -#if 0 - ao_serial_drain(); -#endif if (speed > AO_SERIAL_SPEED_57600) return; - stm_usart1.brr = ao_serial_speeds[speed].brr; + stm_usart1.brr = ao_usart_speeds[speed].brr; } void -ao_serial_init(void) +ao_usart_init(struct ao_stm_usart *usart) { - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); - - stm_moder_set(&stm_gpioa, 9, STM_MODER_ALTERNATE); - stm_moder_set(&stm_gpioa, 10, STM_MODER_ALTERNATE); - stm_afr_set(&stm_gpioa, 9, STM_AFR_AF7); - stm_afr_set(&stm_gpioa, 10, STM_AFR_AF7); - - /* Enable USART1 */ - stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN); - - stm_usart1.cr1 = ((0 << STM_USART_CR1_OVER8) | + usart->reg->cr1 = ((0 << STM_USART_CR1_OVER8) | (1 << STM_USART_CR1_UE) | (0 << STM_USART_CR1_M) | (0 << STM_USART_CR1_WAKE) | @@ -184,7 +184,7 @@ ao_serial_init(void) (0 << STM_USART_CR1_RWU) | (0 << STM_USART_CR1_SBK)); - stm_usart1.cr2 = ((0 << STM_USART_CR2_LINEN) | + usart->reg->cr2 = ((0 << STM_USART_CR2_LINEN) | (STM_USART_CR2_STOP_1 << STM_USART_CR2_STOP) | (0 << STM_USART_CR2_CLKEN) | (0 << STM_USART_CR2_CPOL) | @@ -194,7 +194,7 @@ ao_serial_init(void) (0 << STM_USART_CR2_LBDL) | (0 << STM_USART_CR2_ADD)); - stm_usart1.cr3 = ((0 << STM_USART_CR3_ONEBITE) | + usart->reg->cr3 = ((0 << STM_USART_CR3_ONEBITE) | (0 << STM_USART_CR3_CTSIE) | (0 << STM_USART_CR3_CTSE) | (0 << STM_USART_CR3_RTSE) | @@ -208,15 +208,107 @@ ao_serial_init(void) (0 << STM_USART_CR3_EIE)); /* Pick a 9600 baud rate */ - ao_serial_set_speed(AO_SERIAL_SPEED_9600); + ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600); +} + +void +ao_serial_init(void) +{ +#ifdef HAS_SERIAL_1 + /* + * TX RX + * PA9 PA10 + * PB6 PB7 + */ + + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + + stm_moder_set(&stm_gpioa, 9, STM_MODER_ALTERNATE); + stm_moder_set(&stm_gpioa, 10, STM_MODER_ALTERNATE); + stm_afr_set(&stm_gpioa, 9, STM_AFR_AF7); + stm_afr_set(&stm_gpioa, 10, STM_AFR_AF7); + + /* Enable USART */ + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN); - printf ("serial initialized\n"); + ao_stm_usart1.reg = &stm_usart1; + + stm_nvic_set_enable(STM_ISR_USART1_POS); + stm_nvic_set_priority(STM_ISR_USART1_POS, 4); #if USE_SERIAL_STDIN ao_add_stdio(ao_serial_pollchar, ao_serial_putchar, NULL); #endif +#endif - stm_nvic_set_enable(STM_ISR_USART1_POS); - stm_nvic_set_priority(STM_ISR_USART1_POS, 4); +#if HAS_SERIAL_2 + /* + * TX RX + * PA2 PA3 + * PD5 PD6 + */ + + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + + stm_moder_set(&stm_gpioa, 2, STM_MODER_ALTERNATE); + stm_moder_set(&stm_gpioa, 3, STM_MODER_ALTERNATE); + stm_afr_set(&stm_gpioa, 2, STM_AFR_AF7); + stm_afr_set(&stm_gpioa, 3, STM_AFR_AF7); + + /* Enable USART */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART2EN); + + ao_stm_usart2.reg = &stm_usart2; + + stm_nvic_set_enable(STM_ISR_USART2_POS); + stm_nvic_set_priority(STM_ISR_USART2_POS, 4); +#endif + +#if HAS_SERIAL_3 + /* + * TX RX + * PB10 PB11 + * PC10 PC11 + * PD8 PD9 + */ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); + + stm_moder_set(&stm_gpiob, 10, STM_MODER_ALTERNATE); + stm_moder_set(&stm_gpiob, 11, STM_MODER_ALTERNATE); + stm_afr_set(&stm_gpiob, 10, STM_AFR_AF7); + stm_afr_set(&stm_gpiob, 11, STM_AFR_AF7); + + /* Enable USART */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART3EN); + + ao_stm_usart3.reg = &stm_usart3; + + stm_nvic_set_enable(STM_ISR_USART3_POS); + stm_nvic_set_priority(STM_ISR_USART3_POS, 4); +#endif +} + +#if HAS_SERIAL_1 +char +ao_serial_getchar(void) +{ + return ao_usart_getchar(&ao_stm_usart1); +} + +#if USE_SERIAL_STDIN +char +ao_serial_pollchar(void) +{ + return ao_usart_pollchar(&ao_stm_usart1); +} +#endif + +void +ao_serial_putchar(char c) +{ + ao_usart_putchar(&ao_stm_usart1, c); } +#endif /* HAS_SERIAL_1 */ + + diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index d7c382a6..21dc9a14 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -174,6 +174,8 @@ struct stm_usart { }; extern struct stm_usart stm_usart1; +extern struct stm_usart stm_usart2; +extern struct stm_usart stm_usart3; #define STM_USART_SR_CTS (9) /* CTS flag */ #define STM_USART_SR_LBD (8) /* LIN break detection flag */ -- cgit v1.2.3 From 03fbc18ea17a9e77a1d4d8e0ddb97abbe5da3658 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 21 Mar 2012 16:24:06 -0700 Subject: Clean up multiple serial port support for STM32L Signed-off-by: Keith Packard --- src/stm/ao_serial_stm.c | 41 +++++++++++++---------------------------- 1 file changed, 13 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index 9302bdf8..881819db 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -24,16 +24,6 @@ struct ao_stm_usart { uint8_t tx_started; }; -#if HAS_SERIAL_1 -struct ao_stm_usart ao_stm_usart1; -#endif -#if HAS_SERIAL_2 -struct ao_stm_usart ao_stm_usart2; -#endif -#if HAS_SERIAL_3 -struct ao_stm_usart ao_stm_usart3; -#endif - void ao_debug_out(char c) { @@ -43,14 +33,6 @@ ao_debug_out(char c) stm_usart1.dr = c; } -#if 0 -void -outbyte(char c) -{ - putchar(c); -} -#endif - static void ao_usart_tx_start(struct ao_stm_usart *usart) { @@ -84,16 +66,6 @@ ao_usart_isr(struct ao_stm_usart *usart, int stdin) } } -#if HAS_SERIAL_1 -void stm_usart1_isr(void) { ao_usart_isr(&ao_stm_usart1, USE_SERIAL_STDIN); } -#endif -#if HAS_SERIAL_2 -void stm_usart2_isr(void) { ao_usart_isr(&ao_stm_usart2, 0); } -#endif -#if HAS_SERIAL_3 -void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, 0); } -#endif - char ao_usart_getchar(struct ao_stm_usart *usart) { @@ -211,6 +183,19 @@ ao_usart_init(struct ao_stm_usart *usart) ao_usart_set_speed(usart, AO_SERIAL_SPEED_9600); } +#if HAS_SERIAL_1 +struct ao_stm_usart ao_stm_usart1; +void stm_usart1_isr(void) { ao_usart_isr(&ao_stm_usart1, USE_SERIAL_STDIN); } +#endif +#if HAS_SERIAL_2 +struct ao_stm_usart ao_stm_usart2; +void stm_usart2_isr(void) { ao_usart_isr(&ao_stm_usart2, 0); } +#endif +#if HAS_SERIAL_3 +struct ao_stm_usart ao_stm_usart3; +void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, 0); } +#endif + void ao_serial_init(void) { -- cgit v1.2.3 From f6e557bc2f0bd6d4272ed00dd09554d27a83be89 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 22 Mar 2012 19:41:23 -0700 Subject: Actually enable usarts with the new usart code And move USART1 to PB6/PB7 to avoid conflicting with the LCD pins. Signed-off-by: Keith Packard --- src/stm/ao_serial_stm.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index 881819db..bd3b1e61 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -203,21 +203,22 @@ ao_serial_init(void) /* * TX RX * PA9 PA10 - * PB6 PB7 + * PB6 PB7 * */ - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); - stm_moder_set(&stm_gpioa, 9, STM_MODER_ALTERNATE); - stm_moder_set(&stm_gpioa, 10, STM_MODER_ALTERNATE); - stm_afr_set(&stm_gpioa, 9, STM_AFR_AF7); - stm_afr_set(&stm_gpioa, 10, STM_AFR_AF7); + stm_moder_set(&stm_gpiob, 6, STM_MODER_ALTERNATE); + stm_moder_set(&stm_gpiob, 7, STM_MODER_ALTERNATE); + stm_afr_set(&stm_gpiob, 6, STM_AFR_AF7); + stm_afr_set(&stm_gpiob, 7, STM_AFR_AF7); /* Enable USART */ stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN); - ao_stm_usart1.reg = &stm_usart1; + ao_usart_init(&ao_stm_usart1); + stm_nvic_set_enable(STM_ISR_USART1_POS); stm_nvic_set_priority(STM_ISR_USART1_POS, 4); #if USE_SERIAL_STDIN @@ -243,6 +244,7 @@ ao_serial_init(void) /* Enable USART */ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART2EN); + ao_usart_init(&stm_usart1); ao_stm_usart2.reg = &stm_usart2; @@ -266,6 +268,7 @@ ao_serial_init(void) /* Enable USART */ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART3EN); + ao_usart_init(&stm_usart1); ao_stm_usart3.reg = &stm_usart3; -- cgit v1.2.3 From a953ac32033ded18adf0cb3ca20134385fcd0a6d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 22 Mar 2012 19:42:18 -0700 Subject: Add defines for LCD controller and RTC clocking Signed-off-by: Keith Packard --- src/stm/stm32l.h | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 133 insertions(+) (limited to 'src') diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 21dc9a14..50e5cc34 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -426,6 +426,30 @@ extern struct stm_rcc stm_rcc; #define STM_RCC_APB1ENR_TIM3EN (1) #define STM_RCC_APB1ENR_TIM2EN (0) +#define STM_RCC_CSR_LPWRRSTF (31) +#define STM_RCC_CSR_WWDGRSTF (30) +#define STM_RCC_CSR_IWDGRSTF (29) +#define STM_RCC_CSR_SFTRSTF (28) +#define STM_RCC_CSR_PORRSTF (27) +#define STM_RCC_CSR_PINRSTF (26) +#define STM_RCC_CSR_OBLRSTF (25) +#define STM_RCC_CSR_RMVF (24) +#define STM_RCC_CSR_RTFRST (23) +#define STM_RCC_CSR_RTCEN (22) +#define STM_RCC_CSR_RTCSEL (16) + +#define STM_RCC_CSR_RTCSEL_NONE 0 +#define STM_RCC_CSR_RTCSEL_LSE 1 +#define STM_RCC_CSR_RTCSEL_LSI 2 +#define STM_RCC_CSR_RTCSEL_HSE 3 +#define STM_RCC_CSR_RTCSEL_MASK 3 + +#define STM_RCC_CSR_LSEBYP (10) +#define STM_RCC_CSR_LSERDY (9) +#define STM_RCC_CSR_LSEON (8) +#define STM_RCC_CSR_LSIRDY (1) +#define STM_RCC_CSR_LSION (0) + struct stm_pwr { vuint32_t cr; vuint32_t csr; @@ -510,6 +534,115 @@ extern struct stm_tim67 stm_tim6; #define STM_TIM67_EGR_UG (0) +struct stm_lcd { + vuint32_t cr; + vuint32_t fcr; + vuint32_t sr; + vuint32_t clr; + uint32_t unused_0x10; + vuint32_t ram[8*2]; +}; + +extern struct stm_lcd stm_lcd; + +#define STM_LCD_CR_MUX_SEG (7) + +#define STM_LCD_CR_BIAS (5) +#define STM_LCD_CR_BIAS_1_4 0 +#define STM_LCD_CR_BIAS_1_2 1 +#define STM_LCD_CR_BIAS_1_3 2 +#define STM_LCD_CR_BIAS_MASK 3 + +#define STM_LCD_CR_DUTY (2) +#define STM_LCD_CR_DUTY_STATIC 0 +#define STM_LCD_CR_DUTY_1_2 1 +#define STM_LCD_CR_DUTY_1_3 2 +#define STM_LCD_CR_DUTY_1_4 3 +#define STM_LCD_CR_DUTY_1_8 4 +#define STM_LCD_CR_DUTY_MASK 7 + +#define STM_LCD_CR_VSEL (1) +#define STM_LCD_CR_LCDEN (0) + +#define STM_LCD_FCR_PS (22) +#define STM_LCD_FCR_PS_1 0x0 +#define STM_LCD_FCR_PS_2 0x1 +#define STM_LCD_FCR_PS_4 0x2 +#define STM_LCD_FCR_PS_8 0x3 +#define STM_LCD_FCR_PS_16 0x4 +#define STM_LCD_FCR_PS_32 0x5 +#define STM_LCD_FCR_PS_64 0x6 +#define STM_LCD_FCR_PS_128 0x7 +#define STM_LCD_FCR_PS_256 0x8 +#define STM_LCD_FCR_PS_512 0x9 +#define STM_LCD_FCR_PS_1024 0xa +#define STM_LCD_FCR_PS_2048 0xb +#define STM_LCD_FCR_PS_4096 0xc +#define STM_LCD_FCR_PS_8192 0xd +#define STM_LCD_FCR_PS_16384 0xe +#define STM_LCD_FCR_PS_32768 0xf +#define STM_LCD_FCR_PS_MASK 0xf + +#define STM_LCD_FCR_DIV (18) +#define STM_LCD_FCR_DIV_16 0x0 +#define STM_LCD_FCR_DIV_17 0x1 +#define STM_LCD_FCR_DIV_18 0x2 +#define STM_LCD_FCR_DIV_19 0x3 +#define STM_LCD_FCR_DIV_20 0x4 +#define STM_LCD_FCR_DIV_21 0x5 +#define STM_LCD_FCR_DIV_22 0x6 +#define STM_LCD_FCR_DIV_23 0x7 +#define STM_LCD_FCR_DIV_24 0x8 +#define STM_LCD_FCR_DIV_25 0x9 +#define STM_LCD_FCR_DIV_26 0xa +#define STM_LCD_FCR_DIV_27 0xb +#define STM_LCD_FCR_DIV_28 0xc +#define STM_LCD_FCR_DIV_29 0xd +#define STM_LCD_FCR_DIV_30 0xe +#define STM_LCD_FCR_DIV_31 0xf +#define STM_LCD_FCR_DIV_MASK 0xf + +#define STM_LCD_FCR_BLINK (16) +#define STM_LCD_FCR_BLINK_DISABLE 0 +#define STM_LCD_FCR_BLINK_SEG0_COM0 1 +#define STM_LCD_FCR_BLINK_SEG0_COMALL 2 +#define STM_LCD_FCR_BLINK_SEGALL_COMALL 3 +#define STM_LCD_FCR_BLINK_MASK 3 + +#define STM_LCD_FCR_BLINKF (13) +#define STM_LCD_FCR_BLINKF_8 0 +#define STM_LCD_FCR_BLINKF_16 1 +#define STM_LCD_FCR_BLINKF_32 2 +#define STM_LCD_FCR_BLINKF_64 3 +#define STM_LCD_FCR_BLINKF_128 4 +#define STM_LCD_FCR_BLINKF_256 5 +#define STM_LCD_FCR_BLINKF_512 6 +#define STM_LCD_FCR_BLINKF_1024 7 +#define STM_LCD_FCR_BLINKF_MASK 7 + +#define STM_LCD_FCR_CC (10) +#define STM_LCD_FCR_CC_MASK 7 + +#define STM_LCD_FCR_DEAD (7) +#define STM_LCD_FCR_DEAD_MASK 7 + +#define STM_LCD_FCR_PON (4) +#define STM_LCD_FCR_PON_MASK 7 + +#define STM_LCD_FCR_UDDIE (3) +#define STM_LCD_FCR_SOFIE (1) +#define STM_LCD_FCR_HD (0) + +#define STM_LCD_SR_FCRSF (5) +#define STM_LCD_SR_RDY (4) +#define STM_LCD_SR_UDD (3) +#define STM_LCD_SR_UDR (2) +#define STM_LCD_SR_SOF (1) +#define STM_LCD_SR_ENS (0) + +#define STM_LCD_CLR_UDDC (3) +#define STM_LCD_CLR_SOFC (1) + struct stm_nvic { vuint32_t iser[3]; /* 0x000 */ -- cgit v1.2.3 From 6da2f5846f2d28ea1f09f60ef2cc3f68113ac62a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 22 Mar 2012 19:43:29 -0700 Subject: Add LCD device driver to STM32L port This enables the 6-digit 14-character display on the STM32L discovery board and provides an ascii output to it. Signed-off-by: Keith Packard --- src/stm-demo/Makefile | 6 +- src/stm-demo/ao_demo.c | 5 +- src/stm-demo/ao_pins.h | 59 ++- src/stm/ao-parse-font.5c | 174 +++++++ src/stm/ao_arch.h | 4 + src/stm/ao_lcd_font.c | 101 ++++ src/stm/ao_lcd_font.h | 1152 ++++++++++++++++++++++++++++++++++++++++++++++ src/stm/ao_lcd_stm.c | 393 ++++++++++++++++ 8 files changed, 1888 insertions(+), 6 deletions(-) create mode 100644 src/stm/ao-parse-font.5c create mode 100644 src/stm/ao_lcd_font.c create mode 100644 src/stm/ao_lcd_font.h create mode 100644 src/stm/ao_lcd_stm.c (limited to 'src') diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 9e4f9e38..ecdf6b7f 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -42,14 +42,16 @@ ALTOS_SRC = \ ao_stdio.c \ ao_panic.c \ ao_timer.c \ - ao_serial_stm.c + ao_serial_stm.c \ + ao_lcd_stm.c \ + ao_lcd_font.c PRODUCT=StmDemo-v0.0 PRODUCT_DEF=-DSTM_DEMO IDPRODUCT=0x000a CPU=cortex-m3 CFLAGS = $(PRODUCT_DEF) -I. -I../stm -I../core -I.. -CFLAGS += -g -std=gnu99 -Os -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib -I../stm $(CINC) +CFLAGS += -g -std=gnu99 -O0 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib -I../stm $(CINC) NICKLE=nickle diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 94527089..24566f9b 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -47,8 +47,9 @@ main(void) ao_serial_init(); ao_timer_init(); ao_cmd_init(); - ao_led_init(LEDS_AVAILABLE); - ao_add_task(&demo_task, ao_demo, "demo"); +// ao_led_init(LEDS_AVAILABLE); + ao_lcd_stm_init(); +// ao_add_task(&demo_task, ao_demo, "demo"); ao_start_scheduler(); return 0; diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index c72cd04b..8d7ed76b 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -19,8 +19,8 @@ #define _AO_PINS_H_ #define HAS_SERIAL_1 1 -#define HAS_SERIAL_2 1 -#define HAS_SERIAL_3 1 +#define HAS_SERIAL_2 0 +#define HAS_SERIAL_3 0 #define USE_SERIAL_STDIN 1 #define HAS_USB 0 #define HAS_BEEP 0 @@ -39,4 +39,59 @@ #define LEDS_AVAILABLE (AO_LED_BLUE | AO_LED_GREEN) +#define AO_LCD_STM_SEG_ENABLED_0 ( \ + (1 << 0) | /* PA1 */ \ + (1 << 1) | /* PA2 */ \ + (1 << 2) | /* PA3 */ \ + (0 << 3) | /* PA6 */ \ + (0 << 4) | /* PA7 */ \ + (0 << 5) | /* PB0 */ \ + (0 << 6) | /* PB1 */ \ + (1 << 7) | /* PB3 */ \ + (1 << 8) | /* PB4 */ \ + (1 << 9) | /* PB5 */ \ + (1 << 10) | /* PB10 */ \ + (1 << 11) | /* PB11 */ \ + (1 << 12) | /* PB12 */ \ + (1 << 13) | /* PB13 */ \ + (1 << 14) | /* PB14 */ \ + (1 << 15) | /* PB15 */ \ + (1 << 16) | /* PB8 */ \ + (1 << 17) | /* PA15 */ \ + (1 << 18) | /* PC0 */ \ + (1 << 19) | /* PC1 */ \ + (1 << 20) | /* PC2 */ \ + (1 << 21) | /* PC3 */ \ + (0 << 22) | /* PC4 */ \ + (0 << 23) | /* PC5 */ \ + (1 << 24) | /* PC6 */ \ + (1 << 25) | /* PC7 */ \ + (1 << 26) | /* PC8 */ \ + (1 << 27) | /* PC9 */ \ + (1 << 28) | /* PC10 or PD8 */ \ + (1 << 29) | /* PC11 or PD9 */ \ + (0 << 30) | /* PC12 or PD10 */ \ + (0 << 31)) /* PD2 or PD11 */ + +#define AO_LCD_STM_SEG_ENABLED_1 ( \ + (0 << 0) | /* PD12 */ \ + (0 << 1) | /* PD13 */ \ + (0 << 2) | /* PD14 */ \ + (0 << 3) | /* PD15 */ \ + (0 << 4) | /* PE0 */ \ + (0 << 5) | /* PE1 */ \ + (0 << 6) | /* PE2 */ \ + (0 << 7)) /* PE3 */ + +#define AO_LCD_STM_COM_ENABLED ( \ + (1 << 0) | /* PA8 */ \ + (1 << 1) | /* PA9 */ \ + (1 << 2) | /* PA10 */ \ + (1 << 3) | /* PB9 */ \ + (0 << 4) | /* PC10 */ \ + (0 << 5) | /* PC11 */ \ + (0 << 6)) /* PC12 */ + +#define AO_LCD_28_ON_C 1 + #endif /* _AO_PINS_H_ */ diff --git a/src/stm/ao-parse-font.5c b/src/stm/ao-parse-font.5c new file mode 100644 index 00000000..fe785854 --- /dev/null +++ b/src/stm/ao-parse-font.5c @@ -0,0 +1,174 @@ +#!/usr/bin/env nickle +# +# Parse a 14-segment font file +# and construct the bitmasks for each +# character. Output is in the same +# format as the input: +# [5] = 0x1212, +# /* +# CHAR 37 '%' +# +# | / +# | / +# +# / | +# / | +# +# */ +# +# Note that there can only be tabs before the glyph image +# as spaces are significant in the image itself. +# + +typedef struct { + int c; + bool[14] bits; +} glyph; + +exception done(); + +glyph read_glyph(file f) { + int c; + + for (;;) { + if (File::end(f)) + raise done(); + string l = File::fgets(f); + if (File::sscanf(l, "CHAR %d", &c) == 1) + break; + } + + string strip_tab(string x) { + int i = 0; + while (i < String::length(x) && x[i] == '\t') + i++; + string n = String::substr(x, i, String::length(x) - i); + while (String::length(n) < 7) + n = n + " "; + return n; + } + + string[7] lines = { [i] = strip_tab(File::fgets(f)) }; + + glyph g = { .c = c }; + + g.bits[0] = lines[0][1] == '-'; + + g.bits[1] = lines[1][0] == '|'; + g.bits[2] = lines[1][1] == '\\'; + g.bits[3] = lines[1][3] == '|'; + g.bits[4] = lines[1][5] == '/'; + g.bits[5] = lines[1][6] == '|'; + + g.bits[6] = lines[3][1] == '-'; + g.bits[7] = lines[3][4] == '-'; + + g.bits[8] = lines[5][0] == '|'; + g.bits[9] = lines[5][1] == '/'; + g.bits[10] = lines[5][3] == '|'; + g.bits[11] = lines[5][5] == '\\'; + g.bits[12] = lines[5][6] == '|'; + + g.bits[13] = lines[6][1] == '-'; + return g; +} + +string[*] glyph_image(glyph g) { + int[7][7] chars = { { ' ' ... } ... }; + + if (g.bits[0]) + for (int c = 1; c < 6; c++) + chars[0][c] = '-'; + + if (g.bits[1]) + for (int r = 1; r < 3; r++) + chars[r][0] = '|'; + if (g.bits[2]) + for (int p = 1; p < 3; p++) + chars[p][p] = '\\'; + if (g.bits[3]) + for (int p = 1; p < 3; p++) + chars[p][3] = '|'; + if (g.bits[4]) + for (int p = 1; p < 3; p++) + chars[p][6-p] = '/'; + if (g.bits[5]) + for (int p = 1; p < 3; p++) + chars[p][6] = '|'; + + if (g.bits[6]) + for (int p = 1; p < 3; p++) + chars[3][p] = '-'; + if (g.bits[7]) + for (int p = 4; p < 6; p++) + chars[3][p] = '-'; + + if (g.bits[8]) + for (int r = 4; r < 6; r++) + chars[r][0] = '|'; + if (g.bits[9]) + for (int p = 4; p < 6; p++) + chars[p][6-p] = '/'; + if (g.bits[10]) + for (int p = 4; p < 6; p++) + chars[p][3] = '|'; + if (g.bits[11]) + for (int p = 4; p < 6; p++) + chars[p][p] = '\\'; + if (g.bits[12]) + for (int p = 4; p < 6; p++) + chars[p][6] = '|'; + + if (g.bits[13]) + for (int c = 1; c < 6; c++) + chars[6][c] = '-'; + + return (string[7]) { [i] = String::new(chars[i]) }; + +} + +int glyph_value(glyph g) { + int v = 0; + + for (int b = 0; b < 14; b++) + if (g.bits[b]) + v |= (1 << b); + return v; +} + +void write_glyph(file f, glyph g) { + File::fprintf (f, "CHAR %d '%s'\n", g.c, g.c == 127 ? "DEL" : String::new(g.c)); + string[7] lines = glyph_image(g); + for (int i = 0; i < 7; i++) + File::fprintf (f, "\t%s\n", lines[i]); +} + +autoload Sort; + +glyph[*] read_font(file f) { + glyph[128 - 32] font = { [i] = read_glyph(f) }; + + Sort::qsort(&font, bool func (glyph a, glyph b) = (a.c > b.c)); + return font; +} + +glyph[*] font; +void init () { + twixt (file f = File::open("ao_lcd_font.h", "r"); File::close(f)) { + font = read_font(f); + } +} + +void dump() { + twixt(file f = File::open("ao_lcd_font.h.new", "w"); File::close(f)) { + for (int i = 0; i < dim(font); i++) { + File::fprintf (f, "\t[%d] = 0x%04x,\n", i, glyph_value(font[i])); + File::fprintf (f, "/*\n"); + write_glyph(f, font[i]); + File::fprintf (f, "*/\n\n"); + } + } +} + +init(); +dump(); diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index c4b98c7a..96cbfe85 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -155,5 +155,9 @@ struct ao_adc { */ #define STM_APB1 (16000000 * 6 / 4) +void ao_lcd_stm_init(void); + +void ao_lcd_font_string(char *s); + #endif /* _AO_ARCH_H_ */ diff --git a/src/stm/ao_lcd_font.c b/src/stm/ao_lcd_font.c new file mode 100644 index 00000000..f6074587 --- /dev/null +++ b/src/stm/ao_lcd_font.c @@ -0,0 +1,101 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include + +static const uint16_t ao_lcd_font[] = { +#include "ao_lcd_font.h" +}; + +/* + ----- 0 + |\ | /| 1 2 3 4 5 + | \|/ | @ 14 + -- -- 6 7 + | /|\ | 8 9 10 11 12 + |/ | \| @ 14 + ----- 13 + @ 15 +*/ + +static const uint8_t ao_bit_src[] = { + 8, 7, 5, 6, + 13, 12, 0, 1, + 10, 14, 4, 9, + 11, 15, 3, 2 +}; + +static const uint8_t ao_bit_dst[6][4] = { + { 0, 1, 28, 29 }, + { 2, 7, 26, 27 }, + { 8, 9, 24, 25 }, + { 10, 11, 20, 21 }, + { 12, 13, 18, 19 }, + { 14, 15, 17, 16 }, +}; + +static void +ao_draw_glyph(uint8_t pos, uint16_t glyph) { + uint8_t col, seg, src, dst; + uint32_t ram; + + for (col = 0; col < 4; col++) { + for (seg = 0; seg < 4; seg++) { + src = ao_bit_src[(col << 2) | seg]; + dst = ao_bit_dst[pos][seg]; + ram = stm_lcd.ram[col * 2]; + ram &= ~(1 << dst); + ram |= (uint32_t) ((glyph >> src) & 1) << dst; + stm_lcd.ram[col*2] = ram; + } + } +} + +#define AO_LCD_FONT_COLON (1 << 14) +#define AO_LCD_FONT_DECIMAL (1 << 15) + +void +ao_lcd_font_char(uint8_t pos, char c, uint16_t flags) { + if (pos > 5) + pos = 5; + if (c < ' ' || c > 127) + c = 127; + ao_draw_glyph(pos, ao_lcd_font[c - ' '] | flags); +} + +void +ao_lcd_font_string(char *s) { + uint8_t pos = 0; + uint16_t flags; + char c; + + while (pos < 6 && (c = *s++)) { + flags = 0; + for (;;) { + if (*s == ':') + flags |= AO_LCD_FONT_COLON; + else if (*s == '.') + flags |= AO_LCD_FONT_DECIMAL; + else + break; + s++; + } + ao_lcd_font_char(pos++, c, flags); + } + while (pos < 6) + ao_lcd_font_char(pos++, ' ', 0); +} diff --git a/src/stm/ao_lcd_font.h b/src/stm/ao_lcd_font.h new file mode 100644 index 00000000..08adc9ab --- /dev/null +++ b/src/stm/ao_lcd_font.h @@ -0,0 +1,1152 @@ + [0] = 0x0000, +/* +CHAR 32 ' ' + + + + + + + +*/ + + [1] = 0x0102, +/* +CHAR 33 '!' + + | + | + + | + | + +*/ + + [2] = 0x000a, +/* +CHAR 34 '"' + + | | + | | + + + + +*/ + + [3] = 0x05e8, +/* +CHAR 35 '#' + + | | + | | + -- -- + | | + | | + +*/ + + [4] = 0x34cb, +/* +CHAR 36 '$' + ----- + | | + | | + -- -- + | | + | | + ----- +*/ + + [5] = 0x1212, +/* +CHAR 37 '%' + + | / + | / + + / | + / | + +*/ + + [6] = 0x2955, +/* +CHAR 38 '&' + ----- + \ / + \ / + -- + | \ + | \ + ----- +*/ + + [7] = 0x0008, +/* +CHAR 39 ''' + + | + | + + + + +*/ + + [8] = 0x2103, +/* +CHAR 40 '(' + ----- + | + | + + | + | + ----- +*/ + + [9] = 0x3021, +/* +CHAR 41 ')' + ----- + | + | + + | + | + ----- +*/ + + [10] = 0x0e1c, +/* +CHAR 42 '*' + + \ | / + \|/ + + /|\ + / | \ + +*/ + + [11] = 0x04c8, +/* +CHAR 43 '+' + + | + | + -- -- + | + | + +*/ + + [12] = 0x0200, +/* +CHAR 44 ',' + + + + + / + / + +*/ + + [13] = 0x00c0, +/* +CHAR 45 '-' + + + + -- -- + + + +*/ + + [14] = 0x0800, +/* +CHAR 46 '.' + + + + + \ + \ + +*/ + + [15] = 0x0210, +/* +CHAR 47 '/' + + / + / + + / + / + +*/ + + [16] = 0x3333, +/* +CHAR 48 '0' + ----- + | /| + | / | + + | / | + |/ | + ----- +*/ + + [17] = 0x1030, +/* +CHAR 49 '1' + + /| + / | + + | + | + +*/ + + [18] = 0x21e1, +/* +CHAR 50 '2' + ----- + | + | + -- -- + | + | + ----- +*/ + + [19] = 0x30a1, +/* +CHAR 51 '3' + ----- + | + | + -- + | + | + ----- +*/ + + [20] = 0x10e2, +/* +CHAR 52 '4' + + | | + | | + -- -- + | + | + +*/ + + [21] = 0x30c3, +/* +CHAR 53 '5' + ----- + | + | + -- -- + | + | + ----- +*/ + + [22] = 0x31c3, +/* +CHAR 54 '6' + ----- + | + | + -- -- + | | + | | + ----- +*/ + + [23] = 0x0411, +/* +CHAR 55 '7' + ----- + / + / + + | + | + +*/ + + [24] = 0x31e3, +/* +CHAR 56 '8' + ----- + | | + | | + -- -- + | | + | | + ----- +*/ + + [25] = 0x10e3, +/* +CHAR 57 '9' + ----- + | | + | | + -- -- + | + | + +*/ + + [26] = 0x0408, +/* +CHAR 58 ':' + + | + | + + | + | + +*/ + + [27] = 0x0208, +/* +CHAR 59 ';' + + | + | + + / + / + +*/ + + [28] = 0x0810, +/* +CHAR 60 '<' + + / + / + + \ + \ + +*/ + + [29] = 0x20c0, +/* +CHAR 61 '=' + + + + -- -- + + + ----- +*/ + + [30] = 0x0204, +/* +CHAR 62 '>' + + \ + \ + + / + / + +*/ + + [31] = 0x0413, +/* +CHAR 63 '?' + ----- + | / + | / + + | + | + +*/ + + [32] = 0x39b3, +/* +CHAR 64 '@' + ----- + | /| + | / | + -- + | \ | + | \| + ----- +*/ + + [33] = 0x11e3, +/* +CHAR 65 'A' + ----- + | | + | | + -- -- + | | + | | + +*/ + + [34] = 0x34a9, +/* +CHAR 66 'B' + ----- + | | + | | + -- + | | + | | + ----- +*/ + + [35] = 0x2103, +/* +CHAR 67 'C' + ----- + | + | + + | + | + ----- +*/ + + [36] = 0x3429, +/* +CHAR 68 'D' + ----- + | | + | | + + | | + | | + ----- +*/ + + [37] = 0x2143, +/* +CHAR 69 'E' + ----- + | + | + -- + | + | + ----- +*/ + + [38] = 0x0143, +/* +CHAR 70 'F' + ----- + | + | + -- + | + | + +*/ + + [39] = 0x3183, +/* +CHAR 71 'G' + ----- + | + | + -- + | | + | | + ----- +*/ + + [40] = 0x11e2, +/* +CHAR 72 'H' + + | | + | | + -- -- + | | + | | + +*/ + + [41] = 0x2409, +/* +CHAR 73 'I' + ----- + | + | + + | + | + ----- +*/ + + [42] = 0x3120, +/* +CHAR 74 'J' + + | + | + + | | + | | + ----- +*/ + + [43] = 0x0952, +/* +CHAR 75 'K' + + | / + | / + -- + | \ + | \ + +*/ + + [44] = 0x2102, +/* +CHAR 76 'L' + + | + | + + | + | + ----- +*/ + + [45] = 0x1136, +/* +CHAR 77 'M' + + |\ /| + | \ / | + + | | + | | + +*/ + + [46] = 0x1926, +/* +CHAR 78 'N' + + |\ | + | \ | + + | \ | + | \| + +*/ + + [47] = 0x3123, +/* +CHAR 79 'O' + ----- + | | + | | + + | | + | | + ----- +*/ + + [48] = 0x01e3, +/* +CHAR 80 'P' + ----- + | | + | | + -- -- + | + | + +*/ + + [49] = 0x3923, +/* +CHAR 81 'Q' + ----- + | | + | | + + | \ | + | \| + ----- +*/ + + [50] = 0x09e3, +/* +CHAR 82 'R' + ----- + | | + | | + -- -- + | \ + | \ + +*/ + + [51] = 0x3085, +/* +CHAR 83 'S' + ----- + \ + \ + -- + | + | + ----- +*/ + + [52] = 0x0409, +/* +CHAR 84 'T' + ----- + | + | + + | + | + +*/ + + [53] = 0x3122, +/* +CHAR 85 'U' + + | | + | | + + | | + | | + ----- +*/ + + [54] = 0x0312, +/* +CHAR 86 'V' + + | / + | / + + | / + |/ + +*/ + + [55] = 0x1b22, +/* +CHAR 87 'W' + + | | + | | + + | / \ | + |/ \| + +*/ + + [56] = 0x0a14, +/* +CHAR 88 'X' + + \ / + \ / + + / \ + / \ + +*/ + + [57] = 0x0414, +/* +CHAR 89 'Y' + + \ / + \ / + + | + | + +*/ + + [58] = 0x2211, +/* +CHAR 90 'Z' + ----- + / + / + + / + / + ----- +*/ + + [59] = 0x2103, +/* +CHAR 91 '[' + ----- + | + | + + | + | + ----- +*/ + + [60] = 0x0804, +/* +CHAR 92 '\' + + \ + \ + + \ + \ + +*/ + + [61] = 0x3021, +/* +CHAR 93 ']' + ----- + | + | + + | + | + ----- +*/ + + [62] = 0x0023, +/* +CHAR 94 '^' + ----- + | | + | | + + + + +*/ + + [63] = 0x2000, +/* +CHAR 95 '_' + + + + + + + ----- +*/ + + [64] = 0x0004, +/* +CHAR 96 '`' + + \ + \ + + + + +*/ + + [65] = 0x2540, +/* +CHAR 97 'a' + + + + -- + | | + | | + ----- +*/ + + [66] = 0x2942, +/* +CHAR 98 'b' + + | + | + -- + | \ + | \ + ----- +*/ + + [67] = 0x21c0, +/* +CHAR 99 'c' + + + + -- -- + | + | + ----- +*/ + + [68] = 0x32a0, +/* +CHAR 100 'd' + + | + | + -- + / | + / | + ----- +*/ + + [69] = 0x2340, +/* +CHAR 101 'e' + + + + -- + | / + |/ + ----- +*/ + + [70] = 0x0143, +/* +CHAR 102 'f' + ----- + | + | + -- + | + | + +*/ + + [71] = 0x10a5, +/* +CHAR 103 'g' + ----- + \ | + \ | + -- + | + | + +*/ + + [72] = 0x11c2, +/* +CHAR 104 'h' + + | + | + -- -- + | | + | | + +*/ + + [73] = 0x0400, +/* +CHAR 105 'i' + + + + + | + | + +*/ + + [74] = 0x3000, +/* +CHAR 106 'j' + + + + + | + | + ----- +*/ + + [75] = 0x0c88, +/* +CHAR 107 'k' + + | + | + -- + |\ + | \ + +*/ + + [76] = 0x0408, +/* +CHAR 108 'l' + + | + | + + | + | + +*/ + + [77] = 0x15c0, +/* +CHAR 109 'm' + + + + -- -- + | | | + | | | + +*/ + + [78] = 0x0940, +/* +CHAR 110 'n' + + + + -- + | \ + | \ + +*/ + + [79] = 0x31c0, +/* +CHAR 111 'o' + + + + -- -- + | | + | | + ----- +*/ + + [80] = 0x0146, +/* +CHAR 112 'p' + + |\ + | \ + -- + | + | + +*/ + + [81] = 0x10b0, +/* +CHAR 113 'q' + + /| + / | + -- + | + | + +*/ + + [82] = 0x0140, +/* +CHAR 114 'r' + + + + -- + | + | + +*/ + + [83] = 0x2880, +/* +CHAR 115 's' + + + + -- + \ + \ + ----- +*/ + + [84] = 0x2142, +/* +CHAR 116 't' + + | + | + -- + | + | + ----- +*/ + + [85] = 0x3100, +/* +CHAR 117 'u' + + + + + | | + | | + ----- +*/ + + [86] = 0x0300, +/* +CHAR 118 'v' + + + + + | / + |/ + +*/ + + [87] = 0x1b00, +/* +CHAR 119 'w' + + + + + | / \ | + |/ \| + +*/ + + [88] = 0x0a14, +/* +CHAR 120 'x' + + \ / + \ / + + / \ + / \ + +*/ + + [89] = 0x3800, +/* +CHAR 121 'y' + + + + + \ | + \| + ----- +*/ + + [90] = 0x2240, +/* +CHAR 122 'z' + + + + -- + / + / + ----- +*/ + + [91] = 0x2245, +/* +CHAR 123 '{' + ----- + \ + \ + -- + / + / + ----- +*/ + + [92] = 0x0408, +/* +CHAR 124 '|' + + | + | + + | + | + +*/ + + [93] = 0x2891, +/* +CHAR 125 '}' + ----- + / + / + -- + \ + \ + ----- +*/ + + [94] = 0x000e, +/* +CHAR 126 '~' + + |\ | + | \| + + + + +*/ + + [95] = 0x3fff, +/* +CHAR 127 'DEL' + ----- + |\ | /| + | \|/ | + -- -- + | /|\ | + |/ | \| + ----- +*/ + diff --git a/src/stm/ao_lcd_stm.c b/src/stm/ao_lcd_stm.c new file mode 100644 index 00000000..2d2fa9b3 --- /dev/null +++ b/src/stm/ao_lcd_stm.c @@ -0,0 +1,393 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include + +struct ao_lcd_segment { + uint8_t reg; + uint8_t bit; +}; + +#define A 0 +#define B 1 +#define C 2 +#define D 3 +#define E 4 + +static struct stm_gpio *gpios[] = { + &stm_gpioa, + &stm_gpiob, + &stm_gpioc, + &stm_gpiod, + &stm_gpioe +}; + +static inline int ao_lcd_stm_seg_enabled(int seg) { + if (seg < 32) + return (AO_LCD_STM_SEG_ENABLED_0 >> seg) & 1; + else + return (AO_LCD_STM_SEG_ENABLED_1 >> (seg - 32)) & 1; +} + +static inline int ao_lcd_stm_com_enabled(int com) { + return (AO_LCD_STM_COM_ENABLED >> com) & 1; +} + +#define AO_LCD_STM_GPIOA_SEGS_0 ( \ + (1 << 0) | \ + (1 << 1) | \ + (1 << 2) | \ + (1 << 3) | \ + (1 << 4) | \ + (1 << 17)) + +#define AO_LCD_STM_GPIOA_SEGS_1 0 + +#define AO_LCD_STM_USES_GPIOA (!!((AO_LCD_STM_GPIOA_SEGS_0 & AO_LCD_STM_SEG_ENABLED_0) | \ + (AO_LCD_STM_GPIOA_SEGS_1 & AO_LCD_STM_SEG_ENABLED_1))) + + +#define AO_LCD_STM_GPIOB_SEGS_0 ( \ + (1 << 5) | \ + (1 << 6) | \ + (1 << 7) | \ + (1 << 8) | \ + (1 << 9) | \ + (1 << 10) | \ + (1 << 11) | \ + (1 << 12) | \ + (1 << 13) | \ + (1 << 14) | \ + (1 << 15) | \ + (1 << 16)) + +#define AO_LCD_STM_GPIOB_SEGS_1 0 + +#if AO_LCD_28_ON_C + +#define AO_LCD_STM_GPIOC_28_SEGS ( \ + (1 << 28) | \ + (1 << 29) | \ + (1 << 30)) + +#define AO_LCD_STM_GPIOD_28_SEGS ( \ + (1 << 31)) + +#else +#define AO_LCD_STM_GPIOC_28_C_SEGS 0 + +#define AO_LCD_STM_GPIOD_28_SEGS ( \ + (1 << 28) | \ + (1 << 29) | \ + (1 << 30) | \ + (1 << 31)) +#endif + +#define AO_LCD_STM_GPIOC_SEGS_0 ( \ + (1 << 18) | \ + (1 << 19) | \ + (1 << 20) | \ + (1 << 21) | \ + (1 << 22) | \ + (1 << 23) | \ + (1 << 24) | \ + (1 << 25) | \ + (1 << 26) | \ + (1 << 27) | \ + AO_LCD_STM_GPIOC_28_SEGS) + +#define AO_LCD_STM_GPIOC_SEGS_1 ( \ + (1 << (40 - 32)) | \ + (1 << (41 - 32)) | \ + (1 << (42 - 32))) + +#define AO_LCD_STM_GPIOD_SEGS_0 ( \ + AO_LCD_STM_GPIOD_28_SEGS) + +#define AO_LCD_STM_GPIOD_SEGS_1 ( \ + (1 << (32 - 32)) | \ + (1 << (33 - 32)) | \ + (1 << (34 - 32)) | \ + (1 << (35 - 32)) | \ + (1 << (43 - 32))) + +#define AO_LCD_STM_GPIOE_SEGS_0 0 + +#define AO_LCD_STM_GPIOE_SEGS_1 ( \ + (1 << (36 - 32)) | \ + (1 << (37 - 32)) | \ + (1 << (38 - 32)) | \ + (1 << (39 - 32))) + +#define AO_LCD_STM_USES_GPIOA (!!((AO_LCD_STM_GPIOA_SEGS_0 & AO_LCD_STM_SEG_ENABLED_0) | \ + (AO_LCD_STM_GPIOA_SEGS_1 & AO_LCD_STM_SEG_ENABLED_1))) + +#define AO_LCD_STM_USES_GPIOB (!!((AO_LCD_STM_GPIOB_SEGS_0 & AO_LCD_STM_SEG_ENABLED_0) | \ + (AO_LCD_STM_GPIOB_SEGS_1 & AO_LCD_STM_SEG_ENABLED_1))) + + +#define AO_LCD_STM_USES_GPIOC (!!((AO_LCD_STM_GPIOC_SEGS_0 & AO_LCD_STM_SEG_ENABLED_0) | \ + (AO_LCD_STM_GPIOC_SEGS_1 & AO_LCD_STM_SEG_ENABLED_1))) + + +#define AO_LCD_STM_USES_GPIOD (!!((AO_LCD_STM_GPIOD_SEGS_0 & AO_LCD_STM_SEG_ENABLED_0) | \ + (AO_LCD_STM_GPIOD_SEGS_1 & AO_LCD_STM_SEG_ENABLED_1))) + +#define AO_LCD_STM_USES_GPIOE (!!((AO_LCD_STM_GPIOE_SEGS_0 & AO_LCD_STM_SEG_ENABLED_0) | \ + (AO_LCD_STM_GPIOE_SEGS_1 & AO_LCD_STM_SEG_ENABLED_1))) + + +static const struct ao_lcd_segment segs[] = { + { A, 1 }, /* 0 */ + { A, 2 }, + { A, 3 }, + { A, 6 }, + + { A, 7 }, /* 4 */ + { B, 0 }, + { B, 1 }, + { B, 3 }, + + { B, 4 }, /* 8 */ + { B, 5 }, + { B, 10 }, + { B, 11 }, + + { B, 12 }, /* 12 */ + { B, 13 }, + { B, 14 }, + { B, 15 }, + + { B, 8 }, /* 16 */ + { A, 15 }, + { C, 0 }, + { C, 1 }, + + { C, 2 }, /* 20 */ + { C, 3 }, + { C, 4 }, + { C, 5 }, + + { C, 6 }, /* 24 */ + { C, 7 }, + { C, 8 }, + { C, 9 }, + +#if AO_LCD_28_ON_C + { C, 10 }, /* 28 */ + { C, 11 }, + { C, 12 }, + { D, 2 }, +#else + { D, 8 }, /* 28 */ + { D, 9 }, + { D, 10 }, + { D, 11 }, +#endif + { D, 12 }, /* 32 */ + { D, 13 }, + { D, 14 }, + { D, 15 }, + + { E, 0 }, /* 36 */ + { E, 1 }, + { E, 2 }, + { E, 3 }, + + { C, 10 }, /* 40 */ + { C, 11 }, + { C, 12 }, + { D, 2 }, +}; + +static const struct ao_lcd_segment coms[] = { + { A, 8 }, /* 0 */ + { A, 9 }, /* 1 */ + { A, 10 }, /* 2 */ + { B, 9 }, /* 3 */ + { C, 10 }, /* 4 */ + { C, 11 }, /* 5 */ + { C, 12 }, /* 6 */ +}; + +#define NSEG (sizeof segs/sizeof segs[0]) +#define NCOM (sizeof coms/sizeof coms[0]) + +static void +ao_lcd_stm_fcr_sync(void) +{ + while ((stm_lcd.sr & (1 << STM_LCD_SR_FCRSF)) == 0) + asm("nop"); +} + +static void +ao_lcd_stm_seg_set(void) +{ + int com, seg, val; + int n, bit; + ao_cmd_decimal(); + com = ao_cmd_lex_i; + ao_cmd_decimal(); + seg = ao_cmd_lex_u32; + ao_cmd_decimal(); + val = ao_cmd_lex_i; + printf ("com: %d seg: %d val: %d\n", com, seg, val); + n = (seg >> 5) & 1; + if (com >= NCOM) + com = NCOM-1; + if (seg >= NSEG) + seg = NSEG-1; + if (val) + stm_lcd.ram[com * 2 + n] |= (1 << (seg & 0x1f)); + else + stm_lcd.ram[com * 2 + n] &= ~(1 << (seg & 0x1f)); + stm_lcd.sr = (1 << STM_LCD_SR_UDR); +} + +static void +ao_lcd_stm_clear(void) +{ + int i; + + for (i = 0; i < sizeof (stm_lcd.ram) / 4; i++) + stm_lcd.ram[i] = 0; + stm_lcd.sr = (1 << STM_LCD_SR_UDR); +} + +static void +ao_lcd_stm_text(void) +{ + char string[7]; + uint8_t c = 0; + ao_cmd_white(); + while (ao_cmd_lex_c != '\n' && c < sizeof (string)) { + string[c++] = ao_cmd_lex_c; + ao_cmd_lex(); + } + string[c++] = '\0'; + ao_lcd_font_string(string); + stm_lcd.sr = (1 << STM_LCD_SR_UDR); +} + +const struct ao_cmds ao_lcd_stm_cmds[] = { + { ao_lcd_stm_seg_set, "s \0Set LCD segment" }, + { ao_lcd_stm_clear, "C\0Clear LCD" }, + { ao_lcd_stm_text, "t \0Write to LCD" }, + { 0, NULL }, +}; + +void +ao_lcd_stm_init(void) +{ + int s, c; + int r; + uint32_t csr; + + stm_rcc.ahbenr |= ((AO_LCD_STM_USES_GPIOA << STM_RCC_AHBENR_GPIOAEN) | + (AO_LCD_STM_USES_GPIOB << STM_RCC_AHBENR_GPIOBEN) | + (AO_LCD_STM_USES_GPIOC << STM_RCC_AHBENR_GPIOCEN) | + (AO_LCD_STM_USES_GPIOD << STM_RCC_AHBENR_GPIODEN) | + (AO_LCD_STM_USES_GPIOE << STM_RCC_AHBENR_GPIOEEN)); + + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_LCDEN); + + /* Turn on the LSI clock */ + if ((stm_rcc.csr & (1 << STM_RCC_CSR_LSIRDY)) == 0) { + stm_rcc.csr |= (1 << STM_RCC_CSR_LSION); + while ((stm_rcc.csr & (1 << STM_RCC_CSR_LSIRDY)) == 0) + asm("nop"); + } + + /* Enable RTC clock config (required to change the RTC/LCD clock */ + + stm_pwr.cr |= (1 << STM_PWR_CR_DBP); + + /* Configure the LCDCLK - use the LSI clock */ + + csr = stm_rcc.csr; + csr &= ~(STM_RCC_CSR_RTCSEL_MASK << STM_RCC_CSR_RTCSEL); + csr |= (STM_RCC_CSR_RTCSEL_LSI << STM_RCC_CSR_RTCSEL); + stm_rcc.csr = csr; + + for (s = 0; s < NSEG; s++) { + uint8_t reg = segs[s].reg; + uint8_t bit = segs[s].bit; + + if (ao_lcd_stm_seg_enabled(s)) { + stm_moder_set(gpios[reg], bit, STM_MODER_ALTERNATE); + stm_afr_set(gpios[reg], bit, STM_AFR_AF11); + } + } + + for (c = 0; c < NCOM; c++) { + uint8_t reg = coms[c].reg; + uint8_t bit = coms[c].bit; + + if (ao_lcd_stm_com_enabled(c)) { + stm_moder_set(gpios[reg], bit, STM_MODER_ALTERNATE); + stm_afr_set(gpios[reg], bit, STM_AFR_AF11); + } + } + + /* duty cycle 1/3, radio 352, frame rate about 33Hz */ + stm_lcd.fcr = ((STM_LCD_FCR_PS_1 << STM_LCD_FCR_PS) | + (STM_LCD_FCR_DIV_31 << STM_LCD_FCR_DIV) | + (4 << STM_LCD_FCR_CC) | + (4 << STM_LCD_FCR_PON) | + (0 << STM_LCD_FCR_UDDIE) | + (0 << STM_LCD_FCR_SOFIE) | + (0 << STM_LCD_FCR_HD)); + + ao_lcd_stm_fcr_sync(); + + /* Program desired DUTY in LCD_CR */ + /* Program desired BIAS in LCD_CR */ + /* Enable mux seg */ + /* Internal voltage source */ + stm_lcd.cr = ((STM_LCD_CR_DUTY_1_4 << STM_LCD_CR_DUTY) | + (STM_LCD_CR_BIAS_1_3 << STM_LCD_CR_BIAS) | + (0 << STM_LCD_CR_VSEL) | + (1 << STM_LCD_CR_MUX_SEG)); + + ao_lcd_stm_fcr_sync(); + + /* Enable the display (LCDEN bit in LCD_CR) */ + stm_lcd.cr |= (1 << STM_LCD_CR_LCDEN); + + while ((stm_lcd.sr & (1 << STM_LCD_SR_RDY)) == 0) + asm("nop"); + + /* Load initial data into LCD_RAM and set the + * UDR bit in the LCD_SR register */ + for (r = 0; r < NCOM; r++) { + stm_lcd.ram[r*2] = 0; + stm_lcd.ram[r*2 + 1] = 0; + } + + stm_lcd.sr = (1 << STM_LCD_SR_UDR); + + /* Program desired frame rate (PS and DIV bits in LCD_FCR) */ + + /* Program the contrast (CC bits in LCD_FCR) */ + + /* Program optional features (BLINK, BLINKF, PON, DEAD, HD) */ + + /* Program the required interrupts */ + + /* All done */ + ao_cmd_register(ao_lcd_stm_cmds); +} -- cgit v1.2.3 From d236a5c7cd6e9b1d7192e801d63b4bd348cc2f12 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 22 Mar 2012 20:02:30 -0700 Subject: Move LCD string output code to ao_lcd_font.c It's all very specific to the 14-segment display, so stick it there. Signed-off-by: Keith Packard --- src/stm-demo/ao_demo.c | 1 + src/stm/ao_arch.h | 2 ++ src/stm/ao_lcd_font.c | 27 +++++++++++++++++++++++++++ src/stm/ao_lcd_stm.c | 15 --------------- 4 files changed, 30 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 24566f9b..a672964b 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -49,6 +49,7 @@ main(void) ao_cmd_init(); // ao_led_init(LEDS_AVAILABLE); ao_lcd_stm_init(); + ao_lcd_font_init(); // ao_add_task(&demo_task, ao_demo, "demo"); ao_start_scheduler(); diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 96cbfe85..61e62f5d 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -157,6 +157,8 @@ struct ao_adc { void ao_lcd_stm_init(void); +void ao_lcd_font_init(void); + void ao_lcd_font_string(char *s); #endif /* _AO_ARCH_H_ */ diff --git a/src/stm/ao_lcd_font.c b/src/stm/ao_lcd_font.c index f6074587..2bd787ed 100644 --- a/src/stm/ao_lcd_font.c +++ b/src/stm/ao_lcd_font.c @@ -99,3 +99,30 @@ ao_lcd_font_string(char *s) { while (pos < 6) ao_lcd_font_char(pos++, ' ', 0); } + +static void +ao_lcd_font_text(void) +{ + char string[20]; + uint8_t c = 0; + ao_cmd_white(); + while (ao_cmd_lex_c != '\n' && c < sizeof (string) - 1) { + string[c++] = ao_cmd_lex_c; + ao_cmd_lex(); + } + string[c++] = '\0'; + ao_lcd_font_string(string); + stm_lcd.sr = (1 << STM_LCD_SR_UDR); +} + +const struct ao_cmds ao_lcd_font_cmds[] = { + { ao_lcd_font_text, "t \0Write to LCD" }, + { 0, NULL } +}; + +void +ao_lcd_font_init(void) +{ + ao_cmd_register(ao_lcd_font_cmds); +} + diff --git a/src/stm/ao_lcd_stm.c b/src/stm/ao_lcd_stm.c index 2d2fa9b3..f68cf165 100644 --- a/src/stm/ao_lcd_stm.c +++ b/src/stm/ao_lcd_stm.c @@ -268,25 +268,10 @@ ao_lcd_stm_clear(void) stm_lcd.sr = (1 << STM_LCD_SR_UDR); } -static void -ao_lcd_stm_text(void) -{ - char string[7]; - uint8_t c = 0; - ao_cmd_white(); - while (ao_cmd_lex_c != '\n' && c < sizeof (string)) { - string[c++] = ao_cmd_lex_c; - ao_cmd_lex(); - } - string[c++] = '\0'; - ao_lcd_font_string(string); - stm_lcd.sr = (1 << STM_LCD_SR_UDR); -} const struct ao_cmds ao_lcd_stm_cmds[] = { { ao_lcd_stm_seg_set, "s \0Set LCD segment" }, { ao_lcd_stm_clear, "C\0Clear LCD" }, - { ao_lcd_stm_text, "t \0Write to LCD" }, { 0, NULL }, }; -- cgit v1.2.3 From bf060b3e3ed655bbb8464f342d0a0b1745a06173 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:01:50 -0700 Subject: Allow for more than one serial port in core AltOS Signed-off-by: Keith Packard --- src/core/ao.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 86a943a8..b2f3305f 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -899,7 +899,7 @@ ao_dbg_init(void); #error Please define HAS_SERIAL_1 #endif -#if HAS_SERIAL_1 +#if HAS_SERIAL_1 | HAS_SERIAL_2 | HAS_SERIAL_3 #ifndef USE_SERIAL_STDIN #error Please define USE_SERIAL_STDIN #endif -- cgit v1.2.3 From c9e61a4f1f0ce5e5177a2252e8b7a02a578e77f1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:02:38 -0700 Subject: Allow any STM usart to be used for stdio This also adds the alternate pin configurations for the other two usarts Signed-off-by: Keith Packard --- src/stm/ao_arch.h | 2 + src/stm/ao_serial_stm.c | 170 ++++++++++++++++++++++++++++++++++++------------ 2 files changed, 131 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 61e62f5d..55976c89 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -161,5 +161,7 @@ void ao_lcd_font_init(void); void ao_lcd_font_string(char *s); +#define USE_SERIAL_STDIN (USE_SERIAL_1_STDIN + USE_SERIAL_2_STDIN + USE_SERIAL_3_STDIN) + #endif /* _AO_ARCH_H_ */ diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index bd3b1e61..95189f0c 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -184,35 +184,111 @@ ao_usart_init(struct ao_stm_usart *usart) } #if HAS_SERIAL_1 + struct ao_stm_usart ao_stm_usart1; -void stm_usart1_isr(void) { ao_usart_isr(&ao_stm_usart1, USE_SERIAL_STDIN); } -#endif + +void stm_usart1_isr(void) { ao_usart_isr(&ao_stm_usart1, USE_SERIAL_1_STDIN); } + +#if USE_SERIAL_1_STDIN +char +ao_serial1_getchar(void) +{ + return ao_usart_getchar(&ao_stm_usart1); +} + +void +ao_serial1_putchar(char c) +{ + ao_usart_putchar(&ao_stm_usart1, c); +} + +char +ao_serial1_pollchar(void) +{ + return ao_usart_pollchar(&ao_stm_usart1); +} +#endif /* USE_SERIAL_1_STDIN */ +#endif /* HAS_SERIAL_1 */ + #if HAS_SERIAL_2 + struct ao_stm_usart ao_stm_usart2; -void stm_usart2_isr(void) { ao_usart_isr(&ao_stm_usart2, 0); } -#endif + +void stm_usart2_isr(void) { ao_usart_isr(&ao_stm_usart2, USE_SERIAL_2_STDIN); } + +#if USE_SERIAL_2_STDIN +char +ao_serial2_getchar(void) +{ + return ao_usart_getchar(&ao_stm_usart2); +} + +void +ao_serial2_putchar(char c) +{ + ao_usart_putchar(&ao_stm_usart2, c); +} + +char +ao_serial2_pollchar(void) +{ + return ao_usart_pollchar(&ao_stm_usart2); +} +#endif /* USE_SERIAL_2_STDIN */ +#endif /* HAS_SERIAL_2 */ + #if HAS_SERIAL_3 + struct ao_stm_usart ao_stm_usart3; -void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, 0); } -#endif + +void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, USE_SERIAL_3_STDIN); } + +#if USE_SERIAL_3_STDIN +char +ao_serial3_getchar(void) +{ + return ao_usart_getchar(&ao_stm_usart3); +} + +void +ao_serial3_putchar(char c) +{ + ao_usart_putchar(&ao_stm_usart3, c); +} + +char +ao_serial3_pollchar(void) +{ + return ao_usart_pollchar(&ao_stm_usart2); +} +#endif /* USE_SERIAL_3_STDIN */ +#endif /* HAS_SERIAL_3 */ void ao_serial_init(void) { -#ifdef HAS_SERIAL_1 +#if HAS_SERIAL_1 /* * TX RX * PA9 PA10 * PB6 PB7 * */ +#if SERIAL_1_PA9_PA10 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + + stm_afr_set(&stm_gpioa, 9, STM_AFR_AF7); + stm_afr_set(&stm_gpioa, 10, STM_AFR_AF7); +#else +#if SERIAL_1_PB6_PB7 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); - stm_moder_set(&stm_gpiob, 6, STM_MODER_ALTERNATE); - stm_moder_set(&stm_gpiob, 7, STM_MODER_ALTERNATE); stm_afr_set(&stm_gpiob, 6, STM_AFR_AF7); stm_afr_set(&stm_gpiob, 7, STM_AFR_AF7); - +#else +#error "No SERIAL_1 port configuration specified" +#endif +#endif /* Enable USART */ stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN); ao_stm_usart1.reg = &stm_usart1; @@ -221,9 +297,9 @@ ao_serial_init(void) stm_nvic_set_enable(STM_ISR_USART1_POS); stm_nvic_set_priority(STM_ISR_USART1_POS, 4); -#if USE_SERIAL_STDIN - ao_add_stdio(ao_serial_pollchar, - ao_serial_putchar, +#if USE_SERIAL_1_STDIN + ao_add_stdio(ao_serial1_pollchar, + ao_serial1_putchar, NULL); #endif #endif @@ -235,21 +311,34 @@ ao_serial_init(void) * PD5 PD6 */ +#if SERIAL_2_PA2_PA3 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); - stm_moder_set(&stm_gpioa, 2, STM_MODER_ALTERNATE); - stm_moder_set(&stm_gpioa, 3, STM_MODER_ALTERNATE); stm_afr_set(&stm_gpioa, 2, STM_AFR_AF7); stm_afr_set(&stm_gpioa, 3, STM_AFR_AF7); - +#else +#if SERIAL_2_PD5_PD6 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN); + + stm_afr_set(&stm_gpiod, 5, STM_AFR_AF7); + stm_afr_set(&stm_gpiod, 6, STM_AFR_AF7); +#else +#error "No SERIAL_2 port configuration specified" +#endif +#endif /* Enable USART */ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART2EN); - ao_usart_init(&stm_usart1); ao_stm_usart2.reg = &stm_usart2; + ao_usart_init(&ao_stm_usart2); stm_nvic_set_enable(STM_ISR_USART2_POS); stm_nvic_set_priority(STM_ISR_USART2_POS, 4); +#if USE_SERIAL_2_STDIN + ao_add_stdio(ao_serial2_pollchar, + ao_serial2_putchar, + NULL); +#endif #endif #if HAS_SERIAL_3 @@ -259,44 +348,43 @@ ao_serial_init(void) * PC10 PC11 * PD8 PD9 */ +#if SERIAL_3_PB10_PB11 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); - stm_moder_set(&stm_gpiob, 10, STM_MODER_ALTERNATE); - stm_moder_set(&stm_gpiob, 11, STM_MODER_ALTERNATE); stm_afr_set(&stm_gpiob, 10, STM_AFR_AF7); stm_afr_set(&stm_gpiob, 11, STM_AFR_AF7); +#else +#if SERIAL_3_PC10_PC11 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN); + + stm_afr_set(&stm_gpioc, 10, STM_AFR_AF7); + stm_afr_set(&stm_gpioc, 11, STM_AFR_AF7); +#else +#if SERIAL_3_PD8_PD9 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN); + + stm_afr_set(&stm_gpiod, 8, STM_AFR_AF7); + stm_afr_set(&stm_gpiod, 9, STM_AFR_AF7); +#else +#error "No SERIAL_3 port configuration specified" +#endif +#endif +#endif /* Enable USART */ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART3EN); - ao_usart_init(&stm_usart1); ao_stm_usart3.reg = &stm_usart3; + ao_usart_init(&ao_stm_usart3); stm_nvic_set_enable(STM_ISR_USART3_POS); stm_nvic_set_priority(STM_ISR_USART3_POS, 4); +#if USE_SERIAL_3_STDIN + ao_add_stdio(ao_serial3_pollchar, + ao_serial3_putchar, + NULL); #endif -} - -#if HAS_SERIAL_1 -char -ao_serial_getchar(void) -{ - return ao_usart_getchar(&ao_stm_usart1); -} - -#if USE_SERIAL_STDIN -char -ao_serial_pollchar(void) -{ - return ao_usart_pollchar(&ao_stm_usart1); -} #endif - -void -ao_serial_putchar(char c) -{ - ao_usart_putchar(&ao_stm_usart1, c); } -#endif /* HAS_SERIAL_1 */ -- cgit v1.2.3 From 6337b5f522be11926a6490d7bb27a4f7795da569 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:03:29 -0700 Subject: Automatically set ALTERNATE pin mode when setting alternate function When selecting an alternate function, set the pin to alternate mode as well; there's no sense requiring two separate calls everywhere. Signed-off-by: Keith Packard --- src/stm/stm32l.h | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 50e5cc34..531a4fb9 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -133,6 +133,10 @@ stm_pupdr_get(struct stm_gpio *gpio, int pin) { static inline void stm_afr_set(struct stm_gpio *gpio, int pin, uint32_t value) { + /* + * Set alternate pin mode too + */ + stm_moder_set(gpio, pin, STM_MODER_ALTERNATE); if (pin < 8) gpio->afrl = ((gpio->afrl & ~(STM_AFR_MASK << STM_AFR_SHIFT(pin))) | -- cgit v1.2.3 From 9b5e98a3407b369803109bfc1409e4f8b6e848ba Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:04:21 -0700 Subject: Flush LCD changes each time the text is updated Rather than requiring the caller to do it. Signed-off-by: Keith Packard --- src/stm/ao_lcd_font.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/ao_lcd_font.c b/src/stm/ao_lcd_font.c index 2bd787ed..0d7d87c1 100644 --- a/src/stm/ao_lcd_font.c +++ b/src/stm/ao_lcd_font.c @@ -98,6 +98,7 @@ ao_lcd_font_string(char *s) { } while (pos < 6) ao_lcd_font_char(pos++, ' ', 0); + stm_lcd.sr = (1 << STM_LCD_SR_UDR); } static void @@ -112,7 +113,6 @@ ao_lcd_font_text(void) } string[c++] = '\0'; ao_lcd_font_string(string); - stm_lcd.sr = (1 << STM_LCD_SR_UDR); } const struct ao_cmds ao_lcd_font_cmds[] = { -- cgit v1.2.3 From 41a3fded116a3101789df44647d0eb06be07a25b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:04:47 -0700 Subject: Make stm-demo display a scrolling message Instead of trying to frob the LEDs, which are now owned by the serial port. Signed-off-by: Keith Packard --- src/stm-demo/ao_demo.c | 26 ++++++++++++++++++-------- src/stm-demo/ao_pins.h | 14 +++++++++++++- 2 files changed, 31 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index a672964b..544f261f 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -19,16 +19,27 @@ struct ao_task demo_task; +static inline int min(int a, int b) { return a < b ? a : b; } + void ao_demo(void) { + char message[] = "Hello, Mike & Bdale --- "; + char part[7]; + int i = 0; + int len = sizeof(message) - 1; + int first, second; + + part[6] = '\0'; for (;;) { - ao_led_on(AO_LED_BLUE); - ao_delay(AO_MS_TO_TICKS(500)); - ao_led_off(AO_LED_BLUE); - ao_led_on(AO_LED_GREEN); - ao_delay(AO_MS_TO_TICKS(500)); - ao_led_off(AO_LED_GREEN); + ao_delay(AO_MS_TO_TICKS(150)); + first = min(6, len - i); + second = 6 - first; + memcpy(part, message + i, first); + memcpy(part + first, message, second); + ao_lcd_font_string(part); + if (++i >= len) + i = 0; } } @@ -47,10 +58,9 @@ main(void) ao_serial_init(); ao_timer_init(); ao_cmd_init(); -// ao_led_init(LEDS_AVAILABLE); ao_lcd_stm_init(); ao_lcd_font_init(); -// ao_add_task(&demo_task, ao_demo, "demo"); + ao_add_task(&demo_task, ao_demo, "demo"); ao_start_scheduler(); return 0; diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 8d7ed76b..798a292e 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -19,9 +19,21 @@ #define _AO_PINS_H_ #define HAS_SERIAL_1 1 +#define USE_SERIAL_1_STDIN 1 +#define SERIAL_1_PB6_PB7 1 +#define SERIAL_1_PA9_PA10 0 + #define HAS_SERIAL_2 0 +#define USE_SERIAL_2_STDIN 1 +#define SERIAL_2_PA2_PA3 0 +#define SERIAL_2_PD5_PD6 1 + #define HAS_SERIAL_3 0 -#define USE_SERIAL_STDIN 1 +#define USE_SERIAL_3_STDIN 1 +#define SERIAL_3_PB10_PB11 0 +#define SERIAL_3_PC10_PC11 0 +#define SERIAL_3_PD8_PD9 1 + #define HAS_USB 0 #define HAS_BEEP 0 #define PACKET_HAS_SLAVE 0 -- cgit v1.2.3 From 87ca5c9c5f9cea1b9e14468e4694ce6acc21955a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:19:06 -0700 Subject: Clean up STM build by moving common defs to Makefile.defs Shortens default Makefile a bit Signed-off-by: Keith Packard --- src/stm/Makefile.defs | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/stm/Makefile.defs (limited to 'src') diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs new file mode 100644 index 00000000..c799231a --- /dev/null +++ b/src/stm/Makefile.defs @@ -0,0 +1,33 @@ +vpath % ../stm:../product:../drivers:../core:../util:../kalman:.. +vpath make-altitude ../util +vpath make-kalman ../util +vpath kalman.5c ../kalman +vpath kalman_filter.5c ../kalman +vpath load_csv.5c ../kalman +vpath matrix.5c ../kalman +vpath ao-make-product.5c ../util + +CC=arm-none-eabi-gcc +SAT=$(HOME)/sat +SAT_CLIB=$(SAT)/lib/pdclib.a +SAT_CFLAGS=-I$(SAT)/include + +ifndef VERSION +include ../Version +endif + +AO_CFLAGS=-I. -I../stm -I../core -I.. +STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) + +NICKLE=nickle + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +.c.o: + $(call quiet,CC) -c $(CFLAGS) -o $@ $< -- cgit v1.2.3 From 25184baa36c20e3d661f94e642a33e8aae179d60 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:40:09 -0700 Subject: Allow for more than 8 LEDs Provide hook for architecture-specific LED mask (AO_LED_TYPE) Signed-off-by: Keith Packard --- src/core/ao.h | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index b2f3305f..c9f17dc0 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -258,29 +258,33 @@ ao_beep_init(void); #define AO_LED_NONE 0 +#ifndef AO_LED_TYPE +#define AO_LED_TYPE uint8_t +#endif + /* Turn on the specified LEDs */ void -ao_led_on(uint8_t colors); +ao_led_on(AO_LED_TYPE colors); /* Turn off the specified LEDs */ void -ao_led_off(uint8_t colors); +ao_led_off(AO_LED_TYPE colors); /* Set all of the LEDs to the specified state */ void -ao_led_set(uint8_t colors); +ao_led_set(AO_LED_TYPE colors); /* Toggle the specified LEDs */ void -ao_led_toggle(uint8_t colors); +ao_led_toggle(AO_LED_TYPE colors); /* Turn on the specified LEDs for the indicated interval */ void -ao_led_for(uint8_t colors, uint16_t ticks) __reentrant; +ao_led_for(AO_LED_TYPE colors, uint16_t ticks) __reentrant; /* Initialize the LEDs */ void -ao_led_init(uint8_t enable); +ao_led_init(AO_LED_TYPE enable); /* * ao_usb.c -- cgit v1.2.3 From 606d866153cb639a2400cbedbc45046372ad1b30 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:40:48 -0700 Subject: Allow skytraq to be on non-default serial port Provide ao_gps_getchar, ao_gps_putchar and ao_gps_set_speed hooks to let product specify functions for serial access. Signed-off-by: Keith Packard --- src/drivers/ao_gps_skytraq.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index 050573e8..39e36cc8 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -19,6 +19,18 @@ #include "ao.h" #endif +#ifndef ao_gps_getchar +#define ao_gps_getchar ao_serial_getchar +#endif + +#ifndef ao_gps_putchar +#define ao_gps_putchar ao_serial_putchar +#endif + +#ifndef ao_gps_set_speed +#define ao_gps_set_speed ao_serial_set_speed +#endif + __xdata uint8_t ao_gps_mutex; static __data char ao_gps_char; static __data uint8_t ao_gps_cksum; @@ -68,7 +80,7 @@ ao_gps_lexchar(void) if (ao_gps_error) c = '\n'; else - c = ao_serial_getchar(); + c = ao_gps_getchar(); ao_gps_cksum ^= c; ao_gps_char = c; } @@ -402,7 +414,7 @@ ao_skytraq_sendbytes(__code uint8_t *b, uint8_t l) uint8_t c = *b++; if (c == 0xa0) ao_delay(AO_MS_TO_TICKS(500)); - ao_serial_putchar(c); + ao_gps_putchar(c); } } @@ -444,7 +456,7 @@ ao_gps_nmea_parse(void) void ao_gps(void) __reentrant { - ao_serial_set_speed(AO_SERIAL_SPEED_9600); + ao_gps_set_speed(AO_SERIAL_SPEED_9600); /* give skytraq time to boot in case of cold start */ ao_delay(AO_MS_TO_TICKS(2000)); @@ -453,7 +465,7 @@ ao_gps(void) __reentrant for (;;) { /* Locate the begining of the next record */ - if (ao_serial_getchar() == '$') { + if (ao_gps_getchar() == '$') { ao_gps_nmea_parse(); } } -- cgit v1.2.3 From d7ddfd4e6d75e50ca64a342181f5c52e9f4919af Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:42:13 -0700 Subject: Use 16-bits for STM32 LED mask. Export serial I/O functions Signed-off-by: Keith Packard --- src/stm/ao_arch.h | 38 ++++++++++++++++++++++++++++++++++++++ src/stm/ao_led.c | 14 +++++++------- src/stm/ao_serial_stm.c | 26 +++++++++++++++++++------- 3 files changed, 64 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 55976c89..fcc177ef 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -27,6 +27,8 @@ #define AO_STACK_SIZE 1024 +#define AO_LED_TYPE uint16_t + /* Various definitions to make GCC look more like SDCC */ #define ao_arch_naked_declare __attribute__((naked)) @@ -163,5 +165,41 @@ void ao_lcd_font_string(char *s); #define USE_SERIAL_STDIN (USE_SERIAL_1_STDIN + USE_SERIAL_2_STDIN + USE_SERIAL_3_STDIN) +char +ao_serial1_getchar(void); + +void +ao_serial1_putchar(char c); + +char +ao_serial1_pollchar(void); + +void +ao_serial1_set_speed(uint8_t speed); + +char +ao_serial2_getchar(void); + +void +ao_serial2_putchar(char c); + +char +ao_serial2_pollchar(void); + +void +ao_serial2_set_speed(uint8_t speed); + +char +ao_serial3_getchar(void); + +void +ao_serial3_putchar(char c); + +char +ao_serial3_pollchar(void); + +void +ao_serial3_set_speed(uint8_t speed); + #endif /* _AO_ARCH_H_ */ diff --git a/src/stm/ao_led.c b/src/stm/ao_led.c index 0574aa2a..d649f3d7 100644 --- a/src/stm/ao_led.c +++ b/src/stm/ao_led.c @@ -17,34 +17,34 @@ #include "ao.h" -__pdata uint8_t ao_led_enable; +__pdata uint16_t ao_led_enable; void -ao_led_on(uint8_t colors) +ao_led_on(uint16_t colors) { LED_PORT.odr |= (colors & ao_led_enable); } void -ao_led_off(uint8_t colors) +ao_led_off(uint16_t colors) { LED_PORT.odr &= ~(colors & ao_led_enable); } void -ao_led_set(uint8_t colors) +ao_led_set(uint16_t colors) { LED_PORT.odr = (LED_PORT.odr & ~(ao_led_enable)) | (colors & ao_led_enable); } void -ao_led_toggle(uint8_t colors) +ao_led_toggle(uint16_t colors) { LED_PORT.odr ^= (colors & ao_led_enable); } void -ao_led_for(uint8_t colors, uint16_t ticks) __reentrant +ao_led_for(uint16_t colors, uint16_t ticks) __reentrant { ao_led_on(colors); ao_delay(ticks); @@ -52,7 +52,7 @@ ao_led_for(uint8_t colors, uint16_t ticks) __reentrant } void -ao_led_init(uint8_t enable) +ao_led_init(uint16_t enable) { int bit; diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index 95189f0c..a8c10222 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -189,7 +189,6 @@ struct ao_stm_usart ao_stm_usart1; void stm_usart1_isr(void) { ao_usart_isr(&ao_stm_usart1, USE_SERIAL_1_STDIN); } -#if USE_SERIAL_1_STDIN char ao_serial1_getchar(void) { @@ -207,7 +206,12 @@ ao_serial1_pollchar(void) { return ao_usart_pollchar(&ao_stm_usart1); } -#endif /* USE_SERIAL_1_STDIN */ + +void +ao_serial1_set_speed(uint8_t speed) +{ + ao_usart_set_speed(&ao_stm_usart1, speed); +} #endif /* HAS_SERIAL_1 */ #if HAS_SERIAL_2 @@ -216,7 +220,6 @@ struct ao_stm_usart ao_stm_usart2; void stm_usart2_isr(void) { ao_usart_isr(&ao_stm_usart2, USE_SERIAL_2_STDIN); } -#if USE_SERIAL_2_STDIN char ao_serial2_getchar(void) { @@ -234,7 +237,12 @@ ao_serial2_pollchar(void) { return ao_usart_pollchar(&ao_stm_usart2); } -#endif /* USE_SERIAL_2_STDIN */ + +void +ao_serial2_set_speed(uint8_t speed) +{ + ao_usart_set_speed(&ao_stm_usart2, speed); +} #endif /* HAS_SERIAL_2 */ #if HAS_SERIAL_3 @@ -243,7 +251,6 @@ struct ao_stm_usart ao_stm_usart3; void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, USE_SERIAL_3_STDIN); } -#if USE_SERIAL_3_STDIN char ao_serial3_getchar(void) { @@ -259,9 +266,14 @@ ao_serial3_putchar(char c) char ao_serial3_pollchar(void) { - return ao_usart_pollchar(&ao_stm_usart2); + return ao_usart_pollchar(&ao_stm_usart3); +} + +void +ao_serial3_set_speed(uint8_t speed) +{ + ao_usart_set_speed(&ao_stm_usart3, speed); } -#endif /* USE_SERIAL_3_STDIN */ #endif /* HAS_SERIAL_3 */ void -- cgit v1.2.3 From c27e211796a64b6bbacfe6a1516e9872fdb0853e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:43:17 -0700 Subject: Use new Makefile.defs in stm-demo Signed-off-by: Keith Packard --- src/stm-demo/Makefile | 43 ++++++------------------------------------- 1 file changed, 6 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index ecdf6b7f..f2e6618e 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -2,32 +2,16 @@ # AltOS build # # -vpath % ..:../core:../product:../drivers:../stm -vpath make-altitude ../util -vpath make-kalman ../util -vpath kalman.5c ../kalman -vpath kalman_filter.5c ../kalman -vpath load_csv.5c ../kalman -vpath matrix.5c ../kalman -vpath ao-make-product.5c ../util - -#PROGRAMMER=stk500v2 -P usb -#PROGRAMMER=usbtiny -#LOADCMD=avrdude -#LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: -CC=arm-none-eabi-gcc -#OBJCOPY=avr-objcopy - -ifndef VERSION -include ../Version -endif + +include ../stm/Makefile.defs INC = \ ao.h \ ao_arch.h \ ao_pins.h \ altitude.h \ - ao_kalman.h + ao_kalman.h \ + ao_product.h # # Common AltOS sources @@ -49,33 +33,20 @@ ALTOS_SRC = \ PRODUCT=StmDemo-v0.0 PRODUCT_DEF=-DSTM_DEMO IDPRODUCT=0x000a -CPU=cortex-m3 -CFLAGS = $(PRODUCT_DEF) -I. -I../stm -I../core -I.. -CFLAGS += -g -std=gnu99 -O0 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib -I../stm $(CINC) -NICKLE=nickle +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) PROG=stm-demo SRC=$(ALTOS_SRC) ao_demo.c OBJ=$(SRC:.c=.o) -V=0 -# The user has explicitly enabled quiet compilation. -ifeq ($(V),0) -quiet = @printf " $1 $2 $@\n"; $($1) -endif -# Otherwise, print the full command line. -quiet ?= $($1) - all: $(PROG) -CLIB=/home/keithp/sat/lib/pdclib.a -CINC=-I/home/keithp/sat/include LDFLAGS=-L../stm -Wl,-Taltos.ld $(PROG): Makefile $(OBJ) - $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(CLIB) -lgcc + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc ../altitude.h: make-altitude nickle $< > $@ @@ -97,5 +68,3 @@ clean: install: uninstall: - -$(OBJ): ao.h ao_product.h \ No newline at end of file -- cgit v1.2.3 From 0bda768c2be5b81bec13f21d4d3bb6a11a8e88fa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:43:47 -0700 Subject: Add preliminary MegaMetrum v0.1 support This turns on an LED, enables the internal R/C clock, hooks USART3 to the GPS chip and USART1 to the console. Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 70 +++++++++++++++++++++++++++++++++++++ src/megametrum-v0.1/ao_megametrum.c | 33 +++++++++++++++++ src/megametrum-v0.1/ao_pins.h | 69 ++++++++++++++++++++++++++++++++++++ 3 files changed, 172 insertions(+) create mode 100644 src/megametrum-v0.1/Makefile create mode 100644 src/megametrum-v0.1/ao_megametrum.c create mode 100644 src/megametrum-v0.1/ao_pins.h (limited to 'src') diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile new file mode 100644 index 00000000..4f5e9244 --- /dev/null +++ b/src/megametrum-v0.1/Makefile @@ -0,0 +1,70 @@ +# +# AltOS build +# +# + +include ../stm/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_pins.h \ + altitude.h \ + ao_kalman.h \ + ao_product.h + +# +# Common AltOS sources +# +ALTOS_SRC = \ + ao_interrupt.c \ + ao_product.c \ + ao_romconfig.c \ + ao_cmd.c \ + ao_task.c \ + ao_led.c \ + ao_stdio.c \ + ao_panic.c \ + ao_timer.c \ + ao_mutex.c \ + ao_serial_stm.c \ + ao_gps_skytraq.c + +PRODUCT=MegaMetrum-v0.1 +PRODUCT_DEF=-DMEGAMETRUM +IDPRODUCT=0x000a + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) + +PROG=megametrum-v0.1 + +SRC=$(ALTOS_SRC) ao_megametrum.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) + +LDFLAGS=-L../stm -Wl,-Taltos.ld + +$(PROG): Makefile $(OBJ) + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + +../altitude.h: make-altitude + nickle $< > $@ + +$(OBJ): $(INC) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +ao_product.rel: ao_product.c ao_product.h + $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< + +distclean: clean + +clean: + rm -f $(OBJ) + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c new file mode 100644 index 00000000..14881eb8 --- /dev/null +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -0,0 +1,33 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +int +main(void) +{ + ao_clock_init(); + + ao_serial_init(); + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_GREEN); + ao_timer_init(); + ao_cmd_init(); + + ao_start_scheduler(); + return 0; +} diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h new file mode 100644 index 00000000..dadeb380 --- /dev/null +++ b/src/megametrum-v0.1/ao_pins.h @@ -0,0 +1,69 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_SERIAL_1 1 +#define USE_SERIAL_1_STDIN 1 +#define SERIAL_1_PB6_PB7 0 +#define SERIAL_1_PA9_PA10 1 + +#define HAS_SERIAL_2 0 +#define USE_SERIAL_2_STDIN 0 +#define SERIAL_2_PA2_PA3 0 +#define SERIAL_2_PD5_PD6 0 + +#define HAS_SERIAL_3 1 +#define USE_SERIAL_3_STDIN 0 +#define SERIAL_3_PB10_PB11 0 +#define SERIAL_3_PC10_PC11 1 +#define SERIAL_3_PD8_PD9 0 + +#define ao_gps_getchar ao_serial3_getchar +#define ao_gps_putchar ao_serial3_putchar +#define ao_gps_set_speed ao_serial3_set_speed + +#define HAS_USB 0 +#define HAS_BEEP 0 + +#define HAS_SPI_1 1 +#define SPI_1_PE13_PE14_PE15 1 + +#define HAS_SPI_2 1 +#define SPI_2_PB13_PB14_PB15 1 + +#define HAS_I2C_1 1 +#define I2C_1_PB8_PB9 1 + +#define HAS_I2C_2 1 +#define I2C_2_PB10_PB11 1 + +#define PACKET_HAS_SLAVE 1 + +#define LOW_LEVEL_DEBUG 1 + +#define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOCEN +#define LED_PORT stm_gpioc +#define LED_PIN_RED 8 +#define LED_PIN_GREEN 9 +#define AO_LED_RED (1 << LED_PIN_RED) +#define AO_LED_GREEN (1 << LED_PIN_GREEN) + +#define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN) + +#endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From f2c110fb4531144f18f62200e4127738c84e87f1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 00:55:53 -0700 Subject: Get config stuff hooked up for MegaMetrum This stubs out enough stuff to let ao_config link and work Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 4 +++- src/megametrum-v0.1/ao_megametrum.c | 2 ++ src/stm/ao_arch.h | 2 ++ 3 files changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 4f5e9244..ed91d04f 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -21,6 +21,7 @@ ALTOS_SRC = \ ao_product.c \ ao_romconfig.c \ ao_cmd.c \ + ao_config.c \ ao_task.c \ ao_led.c \ ao_stdio.c \ @@ -28,7 +29,8 @@ ALTOS_SRC = \ ao_timer.c \ ao_mutex.c \ ao_serial_stm.c \ - ao_gps_skytraq.c + ao_gps_skytraq.c \ + ao_cc1120.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 14881eb8..6bf43cb1 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -27,6 +27,8 @@ main(void) ao_led_on(AO_LED_GREEN); ao_timer_init(); ao_cmd_init(); + ao_gps_init(); + ao_config_init(); ao_start_scheduler(); return 0; diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index fcc177ef..188b8996 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -201,5 +201,7 @@ ao_serial3_pollchar(void); void ao_serial3_set_speed(uint8_t speed); +extern uint32_t ao_radio_cal; + #endif /* _AO_ARCH_H_ */ -- cgit v1.2.3 From c1531fb26461b9f4ec39672bbfaeb70e6f4d1056 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 23 Mar 2012 01:42:32 -0700 Subject: Use -Os for STM apps. Fix altos.ld to matchall .rodata* sections Without .rodata*, it would stick the flash copy of the data on top of any further .rodata* sections. Fortunately, the linker catches that and complains... Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 2 +- src/stm-demo/Makefile | 2 +- src/stm/Makefile.defs | 2 ++ src/stm/altos.ld | 4 ++-- 4 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index ed91d04f..510bee6a 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -36,7 +36,7 @@ PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM IDPRODUCT=0x000a -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -Os -g PROG=megametrum-v0.1 diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index f2e6618e..f1655d57 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -34,7 +34,7 @@ PRODUCT=StmDemo-v0.0 PRODUCT_DEF=-DSTM_DEMO IDPRODUCT=0x000a -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -g -Os PROG=stm-demo diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index c799231a..6191ec45 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -19,6 +19,8 @@ endif AO_CFLAGS=-I. -I../stm -I../core -I.. STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) +LDFLAGS=-L../stm -Wl,-Taltos.ld + NICKLE=nickle V=0 diff --git a/src/stm/altos.ld b/src/stm/altos.ld index 4e955666..7fede558 100644 --- a/src/stm/altos.ld +++ b/src/stm/altos.ld @@ -36,8 +36,8 @@ SECTIONS { .text : { *(.interrupt) /* Interrupt vectors */ - *(.text) /* Executable code */ - *(.rodata) /* Constants */ + *(.text*) /* Executable code */ + *(.rodata*) /* Constants */ } > rom .ARM.exidx : { -- cgit v1.2.3 From a157edbe1bf7fffd5a6041f7b1760674addd2229 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 25 Mar 2012 13:08:05 -0700 Subject: stm-demo does not use altitude.h --- src/megametrum-v0.1/Makefile | 2 -- src/stm-demo/Makefile | 10 +--------- 2 files changed, 1 insertion(+), 11 deletions(-) (limited to 'src') diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 510bee6a..b07d1e1d 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -45,8 +45,6 @@ OBJ=$(SRC:.c=.o) all: $(PROG) -LDFLAGS=-L../stm -Wl,-Taltos.ld - $(PROG): Makefile $(OBJ) $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index f1655d57..366291c6 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -9,8 +9,6 @@ INC = \ ao.h \ ao_arch.h \ ao_pins.h \ - altitude.h \ - ao_kalman.h \ ao_product.h # @@ -48,16 +46,10 @@ LDFLAGS=-L../stm -Wl,-Taltos.ld $(PROG): Makefile $(OBJ) $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc -../altitude.h: make-altitude - nickle $< > $@ - -$(OBJ): $(INC) - ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ -ao_product.rel: ao_product.c ao_product.h - $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< +$(OBJ): $(INC) distclean: clean -- cgit v1.2.3 From 0993595035a2813deba6991fa25bc0d475f2e6bb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Mar 2012 21:45:02 -0700 Subject: altos: Add ao_freq.c to megametrum build I think this will be needed to compute radio settings on the cc1120 Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index b07d1e1d..6347f8c3 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -30,7 +30,8 @@ ALTOS_SRC = \ ao_mutex.c \ ao_serial_stm.c \ ao_gps_skytraq.c \ - ao_cc1120.c + ao_cc1120.c \ + ao_freq.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM @@ -38,7 +39,7 @@ IDPRODUCT=0x000a CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -Os -g -PROG=megametrum-v0.1 +PROG=megametrum-v0.1-$(VERSION).ihx SRC=$(ALTOS_SRC) ao_megametrum.c OBJ=$(SRC:.c=.o) -- cgit v1.2.3 From 47a9925f16f6a13b173c49d3873d91fc7cf6d46e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Mar 2012 21:53:30 -0700 Subject: altos: Move cc1111 AES driver to cc1111 directory Signed-off-by: Keith Packard --- src/ao_aes.c | 142 ---------------------------------------------------- src/cc1111/ao_aes.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+), 142 deletions(-) delete mode 100644 src/ao_aes.c create mode 100644 src/cc1111/ao_aes.c (limited to 'src') diff --git a/src/ao_aes.c b/src/ao_aes.c deleted file mode 100644 index d50fecfb..00000000 --- a/src/ao_aes.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -#if !HAS_AES -#error Must define HAS_AES 1 -#endif - -__xdata uint8_t ao_aes_mutex; -__xdata uint8_t ao_aes_done; -__xdata uint8_t ao_aes_dma_in, ao_aes_dma_out; -__xdata uint8_t ao_aes_dma_in_done, ao_aes_dma_out_done; -__pdata enum ao_aes_mode ao_aes_current_mode; - -void -ao_aes_isr(void) __interrupt 4 -{ - S0CON = 0; - if (ENCCCS & ENCCCS_RDY) { - ao_aes_done = 1; - ao_wakeup(&ao_aes_done); - } -} - -void -ao_aes_set_mode(enum ao_aes_mode mode) -{ - ao_aes_current_mode = mode; -} - -void -ao_aes_set_key(__xdata uint8_t *in) -{ - ao_dma_set_transfer(ao_aes_dma_in, - in, - &ENCDIXADDR, - AO_AES_LEN, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_ENC_DW, - DMA_CFG1_SRCINC_1 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_LOW); - ao_dma_start(ao_aes_dma_in); - ao_aes_done = 0; - ENCCCS = ENCCCS_MODE_CBC_MAC | - ENCCCS_CMD_LOAD_KEY; - ENCCCS |= ENCCCS_START; - __critical while (!ao_aes_done) - ao_sleep(&ao_aes_done); -} - -void -ao_aes_zero_iv(void) -{ - uint8_t b; - - ENCCCS = ENCCCS_MODE_CBC_MAC | ENCCCS_CMD_LOAD_IV | ENCCCS_START; - for (b = 0; b < AO_AES_LEN; b++) - ENCDI = 0; -} - -void -ao_aes_run(__xdata uint8_t *in, - __xdata uint8_t *out) -{ - uint8_t b; - if (in) { - ao_dma_set_transfer(ao_aes_dma_in, - in, - &ENCDIXADDR, - AO_AES_LEN, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_ENC_DW, - DMA_CFG1_SRCINC_1 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_LOW); - } - if (out) { - ao_dma_set_transfer(ao_aes_dma_out, - &ENCDOXADDR, - out, - AO_AES_LEN, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_ENC_UP, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_1 | - DMA_CFG1_PRIORITY_LOW); - } - switch (ao_aes_current_mode) { - case ao_aes_mode_cbc_mac: - if (out) - b = (ENCCCS_MODE_CBC | - ENCCCS_CMD_ENCRYPT); - else - b = (ENCCCS_MODE_CBC_MAC | - ENCCCS_CMD_ENCRYPT); - break; - default: - return; - } - ao_aes_done = 0; - if (in) - ao_dma_start(ao_aes_dma_in); - if (out) - ao_dma_start(ao_aes_dma_out); - ENCCCS = b; - ENCCCS |= ENCCCS_START; - if (out) { - __critical while (!ao_aes_dma_out_done) - ao_sleep(&ao_aes_dma_out_done); - } else { - __critical while (!ao_aes_done) - ao_sleep(&ao_aes_done); - } -} - -void -ao_aes_init(void) -{ - ao_aes_dma_in = ao_dma_alloc(&ao_aes_dma_in_done); - ao_aes_dma_out = ao_dma_alloc(&ao_aes_dma_out_done); - S0CON = 0; - ENCIE = 1; -} diff --git a/src/cc1111/ao_aes.c b/src/cc1111/ao_aes.c new file mode 100644 index 00000000..d50fecfb --- /dev/null +++ b/src/cc1111/ao_aes.c @@ -0,0 +1,142 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +#if !HAS_AES +#error Must define HAS_AES 1 +#endif + +__xdata uint8_t ao_aes_mutex; +__xdata uint8_t ao_aes_done; +__xdata uint8_t ao_aes_dma_in, ao_aes_dma_out; +__xdata uint8_t ao_aes_dma_in_done, ao_aes_dma_out_done; +__pdata enum ao_aes_mode ao_aes_current_mode; + +void +ao_aes_isr(void) __interrupt 4 +{ + S0CON = 0; + if (ENCCCS & ENCCCS_RDY) { + ao_aes_done = 1; + ao_wakeup(&ao_aes_done); + } +} + +void +ao_aes_set_mode(enum ao_aes_mode mode) +{ + ao_aes_current_mode = mode; +} + +void +ao_aes_set_key(__xdata uint8_t *in) +{ + ao_dma_set_transfer(ao_aes_dma_in, + in, + &ENCDIXADDR, + AO_AES_LEN, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_ENC_DW, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_LOW); + ao_dma_start(ao_aes_dma_in); + ao_aes_done = 0; + ENCCCS = ENCCCS_MODE_CBC_MAC | + ENCCCS_CMD_LOAD_KEY; + ENCCCS |= ENCCCS_START; + __critical while (!ao_aes_done) + ao_sleep(&ao_aes_done); +} + +void +ao_aes_zero_iv(void) +{ + uint8_t b; + + ENCCCS = ENCCCS_MODE_CBC_MAC | ENCCCS_CMD_LOAD_IV | ENCCCS_START; + for (b = 0; b < AO_AES_LEN; b++) + ENCDI = 0; +} + +void +ao_aes_run(__xdata uint8_t *in, + __xdata uint8_t *out) +{ + uint8_t b; + if (in) { + ao_dma_set_transfer(ao_aes_dma_in, + in, + &ENCDIXADDR, + AO_AES_LEN, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_ENC_DW, + DMA_CFG1_SRCINC_1 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_LOW); + } + if (out) { + ao_dma_set_transfer(ao_aes_dma_out, + &ENCDOXADDR, + out, + AO_AES_LEN, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_ENC_UP, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_1 | + DMA_CFG1_PRIORITY_LOW); + } + switch (ao_aes_current_mode) { + case ao_aes_mode_cbc_mac: + if (out) + b = (ENCCCS_MODE_CBC | + ENCCCS_CMD_ENCRYPT); + else + b = (ENCCCS_MODE_CBC_MAC | + ENCCCS_CMD_ENCRYPT); + break; + default: + return; + } + ao_aes_done = 0; + if (in) + ao_dma_start(ao_aes_dma_in); + if (out) + ao_dma_start(ao_aes_dma_out); + ENCCCS = b; + ENCCCS |= ENCCCS_START; + if (out) { + __critical while (!ao_aes_dma_out_done) + ao_sleep(&ao_aes_dma_out_done); + } else { + __critical while (!ao_aes_done) + ao_sleep(&ao_aes_done); + } +} + +void +ao_aes_init(void) +{ + ao_aes_dma_in = ao_dma_alloc(&ao_aes_dma_in_done); + ao_aes_dma_out = ao_dma_alloc(&ao_aes_dma_out_done); + S0CON = 0; + ENCIE = 1; +} -- cgit v1.2.3 From 1f2b75518169c4f2da9762de46bf1d9a71a04d17 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 28 Mar 2012 21:54:32 -0700 Subject: altos: Move cc1111 DMA engine interface to cc1111/ao_arch.h from ao.h It's hardware specific Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 36 ++++++++++++++++++++++++++++++++++++ src/core/ao.h | 36 ------------------------------------ 2 files changed, 36 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 360b35c8..847ac1a6 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -258,4 +258,40 @@ struct ao_serial_speed { extern const __code struct ao_serial_speed ao_serial_speeds[]; +/* + * ao_dma.c + */ + +/* Allocate a DMA channel. the 'done' parameter will be set when the + * dma is finished and will be used to wakeup any waiters + */ + +uint8_t +ao_dma_alloc(__xdata uint8_t * done); + +/* Setup a DMA channel */ +void +ao_dma_set_transfer(uint8_t id, + void __xdata *srcaddr, + void __xdata *dstaddr, + uint16_t count, + uint8_t cfg0, + uint8_t cfg1); + +/* Start a DMA channel */ +void +ao_dma_start(uint8_t id); + +/* Manually trigger a DMA channel */ +void +ao_dma_trigger(uint8_t id); + +/* Abort a running DMA transfer */ +void +ao_dma_abort(uint8_t id); + +/* DMA interrupt routine */ +void +ao_dma_isr(void) ao_arch_interrupt(8); + #endif /* _AO_ARCH_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index c9f17dc0..8263a529 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -394,42 +394,6 @@ uint8_t ao_cmd_filter(void); #endif -/* - * ao_dma.c - */ - -/* Allocate a DMA channel. the 'done' parameter will be set when the - * dma is finished and will be used to wakeup any waiters - */ - -uint8_t -ao_dma_alloc(__xdata uint8_t * done); - -/* Setup a DMA channel */ -void -ao_dma_set_transfer(uint8_t id, - void __xdata *srcaddr, - void __xdata *dstaddr, - uint16_t count, - uint8_t cfg0, - uint8_t cfg1); - -/* Start a DMA channel */ -void -ao_dma_start(uint8_t id); - -/* Manually trigger a DMA channel */ -void -ao_dma_trigger(uint8_t id); - -/* Abort a running DMA transfer */ -void -ao_dma_abort(uint8_t id); - -/* DMA interrupt routine */ -void -ao_dma_isr(void) ao_arch_interrupt(8); - /* * ao_mutex.c */ -- cgit v1.2.3 From bbf31b8591f89e2a1fcc7dac5f42d730a81473d2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 31 Mar 2012 12:43:58 -0700 Subject: altos: Add stub cc1120 driver Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/drivers/ao_cc1120.c (limited to 'src') diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c new file mode 100644 index 00000000..9470fa87 --- /dev/null +++ b/src/drivers/ao_cc1120.c @@ -0,0 +1,25 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include + +uint32_t ao_radio_cal = 1186611; + +void +ao_radio_recv_abort(void) +{ +} -- cgit v1.2.3 From b89f11139fae7ae722ed78d342a169ed2bf5c948 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 31 Mar 2012 12:44:14 -0700 Subject: Build megametrum-v0.1 by default --- src/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 3603c277..db9bd508 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,6 +13,7 @@ vpath matrix.5c kalman include Version SUBDIRS=\ + megametrum-v0.1 \ stm-bringup stm-demo \ telemetrum-v1.2 telemetrum-v1.1 telemetrum-v1.0 \ teledongle-v0.2 teledongle-v0.1 \ -- cgit v1.2.3 From 4ca52908c8b3f98a79588981f6878025250f0924 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sat, 31 Mar 2012 16:43:39 -0600 Subject: use explicit path not $(HOME) to find ARM toolchain for now --- src/stm/Makefile.defs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index 6191ec45..76962a3e 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -8,7 +8,7 @@ vpath matrix.5c ../kalman vpath ao-make-product.5c ../util CC=arm-none-eabi-gcc -SAT=$(HOME)/sat +SAT=/home/keithp/sat SAT_CLIB=$(SAT)/lib/pdclib.a SAT_CFLAGS=-I$(SAT)/include -- cgit v1.2.3 From c09d155328bd446bb84ac1068d380cceb884df22 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Apr 2012 19:27:53 -0700 Subject: altos: Oops. Set per-USART STM baud rate register instead of usart1 Was accidentally always setting usart1 instead of the per-usart register. Didn't work too well for other usarts... Signed-off-by: Keith Packard --- src/stm/ao_serial_stm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index a8c10222..f8db6883 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -134,7 +134,7 @@ ao_usart_set_speed(struct ao_stm_usart *usart, uint8_t speed) { if (speed > AO_SERIAL_SPEED_57600) return; - stm_usart1.brr = ao_usart_speeds[speed].brr; + usart->reg->brr = ao_usart_speeds[speed].brr; } void @@ -303,8 +303,8 @@ ao_serial_init(void) #endif /* Enable USART */ stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_USART1EN); - ao_stm_usart1.reg = &stm_usart1; + ao_stm_usart1.reg = &stm_usart1; ao_usart_init(&ao_stm_usart1); stm_nvic_set_enable(STM_ISR_USART1_POS); @@ -382,7 +382,6 @@ ao_serial_init(void) #endif #endif #endif - /* Enable USART */ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USART3EN); -- cgit v1.2.3 From cf1e4d60e1fcd75fa734365a2666ea8930938128 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Apr 2012 22:58:54 -0700 Subject: altos: Move SPI functions to architecture-specific location Some architecture specific stuff needs to use core altos code, so create new ao_arch_funcs.h files per architecture that get pulled in at the end of ao.h Signed-off-by: Keith Packard --- src/avr/ao_arch_funcs.h | 58 ++++++++++++++++++++++++++++++++++++++++++++++ src/cc1111/ao_arch_funcs.h | 58 ++++++++++++++++++++++++++++++++++++++++++++++ src/core/ao.h | 43 ++-------------------------------- src/stm/ao_arch_funcs.h | 35 ++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+), 41 deletions(-) create mode 100644 src/avr/ao_arch_funcs.h create mode 100644 src/cc1111/ao_arch_funcs.h create mode 100644 src/stm/ao_arch_funcs.h (limited to 'src') diff --git a/src/avr/ao_arch_funcs.h b/src/avr/ao_arch_funcs.h new file mode 100644 index 00000000..9ad14fbb --- /dev/null +++ b/src/avr/ao_arch_funcs.h @@ -0,0 +1,58 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +/* + * ao_spi.c + */ + +extern __xdata uint8_t ao_spi_mutex; + +#define ao_spi_get_mask(reg,mask) do {\ + ao_mutex_get(&ao_spi_mutex); \ + (reg) &= ~(mask); \ + } while (0) + +#define ao_spi_put_mask(reg,mask) do { \ + (reg) |= (mask); \ + ao_mutex_put(&ao_spi_mutex); \ + } while (0) + +#define ao_spi_get_bit(bit) do {\ + ao_mutex_get(&ao_spi_mutex); \ + (bit) = 0; \ + } while (0) + +#define ao_spi_put_bit(bit) do { \ + (bit) = 1; \ + ao_mutex_put(&ao_spi_mutex); \ + } while (0) + +/* + * The SPI mutex must be held to call either of these + * functions -- this mutex covers the entire SPI operation, + * from chip select low to chip select high + */ + +void +ao_spi_send(void __xdata *block, uint16_t len) __reentrant; + +void +ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; + +void +ao_spi_init(void); + diff --git a/src/cc1111/ao_arch_funcs.h b/src/cc1111/ao_arch_funcs.h new file mode 100644 index 00000000..9ad14fbb --- /dev/null +++ b/src/cc1111/ao_arch_funcs.h @@ -0,0 +1,58 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +/* + * ao_spi.c + */ + +extern __xdata uint8_t ao_spi_mutex; + +#define ao_spi_get_mask(reg,mask) do {\ + ao_mutex_get(&ao_spi_mutex); \ + (reg) &= ~(mask); \ + } while (0) + +#define ao_spi_put_mask(reg,mask) do { \ + (reg) |= (mask); \ + ao_mutex_put(&ao_spi_mutex); \ + } while (0) + +#define ao_spi_get_bit(bit) do {\ + ao_mutex_get(&ao_spi_mutex); \ + (bit) = 0; \ + } while (0) + +#define ao_spi_put_bit(bit) do { \ + (bit) = 1; \ + ao_mutex_put(&ao_spi_mutex); \ + } while (0) + +/* + * The SPI mutex must be held to call either of these + * functions -- this mutex covers the entire SPI operation, + * from chip select low to chip select high + */ + +void +ao_spi_send(void __xdata *block, uint16_t len) __reentrant; + +void +ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; + +void +ao_spi_init(void); + diff --git a/src/core/ao.h b/src/core/ao.h index 8263a529..080cadb2 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -940,47 +940,6 @@ ao_serial0_init(void); #endif -/* - * ao_spi.c - */ - -extern __xdata uint8_t ao_spi_mutex; - -#define ao_spi_get_mask(reg,mask) do {\ - ao_mutex_get(&ao_spi_mutex); \ - (reg) &= ~(mask); \ - } while (0) - -#define ao_spi_put_mask(reg,mask) do { \ - (reg) |= (mask); \ - ao_mutex_put(&ao_spi_mutex); \ - } while (0) - -#define ao_spi_get_bit(bit) do {\ - ao_mutex_get(&ao_spi_mutex); \ - (bit) = 0; \ - } while (0) - -#define ao_spi_put_bit(bit) do { \ - (bit) = 1; \ - ao_mutex_put(&ao_spi_mutex); \ - } while (0) - -/* - * The SPI mutex must be held to call either of these - * functions -- this mutex covers the entire SPI operation, - * from chip select low to chip select high - */ - -void -ao_spi_send(void __xdata *block, uint16_t len) __reentrant; - -void -ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; - -void -ao_spi_init(void); - /* * ao_spi_slave.c */ @@ -1934,4 +1893,6 @@ ao_sqrt(uint32_t op); int32_t ao_freq_to_set(int32_t freq, int32_t cal); +#include + #endif /* _AO_H_ */ diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h new file mode 100644 index 00000000..9b68f19a --- /dev/null +++ b/src/stm/ao_arch_funcs.h @@ -0,0 +1,35 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_ARCH_FUNCS_H_ +#define _AO_ARCH_FUNCS_H_ + +extern uint8_t ao_spi_mutex[STM_NUM_SPI]; + +static inline void ao_spi_get(uint8_t spi_index) { ao_mutex_get(&ao_spi_mutex[spi_index]); } +static inline void ao_spi_put(uint8_t spi_index) { ao_mutex_put(&ao_spi_mutex[spi_index]); } + +void +ao_spi_send(void *block, uint16_t len, uint8_t spi_index); + +void +ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); + +void +ao_spi_init(uint8_t spi_index); + +#endif /* _AO_ARCH_FUNCS_H_ */ -- cgit v1.2.3 From 2a04ac8dff1bfc3efba8c7e4dc9c1a827496dbdf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Apr 2012 23:00:29 -0700 Subject: altos: megametrum builds an ELF file, not an IHX file Name it appropriately. Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 6347f8c3..23160d9b 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -39,7 +39,7 @@ IDPRODUCT=0x000a CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -Os -g -PROG=megametrum-v0.1-$(VERSION).ihx +PROG=megametrum-v0.1-$(VERSION).elf SRC=$(ALTOS_SRC) ao_megametrum.c OBJ=$(SRC:.c=.o) -- cgit v1.2.3 From 9b12bc445fe482306e4587ad60c6d2daf65a60f3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 Apr 2012 18:07:07 -0700 Subject: altos: Add DMA, SPI and MS5607 drivers Signed-off-by: Keith Packard --- src/core/ao.h | 7 ++ src/drivers/ao_ms5607.c | 164 ++++++++++++++++++++++++ src/drivers/ao_ms5607.h | 38 ++++++ src/megametrum-v0.1/Makefile | 7 +- src/megametrum-v0.1/ao_megametrum.c | 3 + src/megametrum-v0.1/ao_pins.h | 5 +- src/stm-demo/Makefile | 5 +- src/stm-demo/ao_demo.c | 79 +++++++++++- src/stm-demo/ao_pins.h | 5 + src/stm/ao_arch_funcs.h | 28 ++++- src/stm/ao_dma_stm.c | 99 +++++++++++++++ src/stm/ao_spi_stm.c | 240 ++++++++++++++++++++++++++++++++++++ src/stm/stm32l.h | 180 ++++++++++++++++++++++++++- 13 files changed, 847 insertions(+), 13 deletions(-) create mode 100644 src/drivers/ao_ms5607.c create mode 100644 src/drivers/ao_ms5607.h create mode 100644 src/stm/ao_dma_stm.c create mode 100644 src/stm/ao_spi_stm.c (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 080cadb2..67efa437 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -114,6 +114,7 @@ ao_start_scheduler(void); #define AO_PANIC_USB 10 /* Trying to send USB packet while busy */ #define AO_PANIC_BT 11 /* Communications with bluetooth device failed */ #define AO_PANIC_STACK 12 /* Stack overflow */ +#define AO_PANIC_SPI 13 /* SPI communication failure */ /* Stop the operating system, beeping and blinking the reason */ void @@ -1895,4 +1896,10 @@ int32_t ao_freq_to_set(int32_t freq, int32_t cal); #include +/* + * ao_ms5607.c + */ + +void ao_ms5607_init(void); + #endif /* _AO_H_ */ diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c new file mode 100644 index 00000000..970fea1e --- /dev/null +++ b/src/drivers/ao_ms5607.c @@ -0,0 +1,164 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include "ao_ms5607.h" + +#define AO_MS5607_CS_GPIO stm_gpioc +#define AO_MS5607_CS 4 +#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) +#define AO_MS5607_SPI_INDEX (STM_SPI_INDEX(1)) + +struct ms5607_prom { + uint16_t reserved; + uint16_t sens; + uint16_t off; + uint16_t tcs; + uint16_t tco; + uint16_t tref; + uint16_t tempsens; + uint16_t crc; +}; + +static struct ms5607_prom ms5607_prom; + +static void +ao_ms5607_start(void) { + ao_spi_get(AO_MS5607_SPI_INDEX); + stm_gpio_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, 0); +} + +static void +ao_ms5607_stop(void) { + stm_gpio_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, 1); + ao_spi_put(AO_MS5607_SPI_INDEX); +} + +static void +ao_ms5607_reset(void) { + uint8_t cmd; + + cmd = AO_MS5607_RESET; + ao_ms5607_start(); + ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); + ao_ms5607_stop(); +} + +static uint16_t +ao_ms5607_prom_read(uint8_t addr) +{ + uint8_t cmd = AO_MS5607_PROM_READ(addr); + uint8_t d[2]; + + ao_ms5607_start(); + ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); + ao_spi_recv(d, 2, AO_MS5607_SPI_INDEX); + ao_ms5607_stop(); + return ((uint16_t) d[0] << 8) | (uint16_t) d[1]; +} + +static void +ao_ms5607_init_chip(void) { + uint8_t addr; + uint16_t *prom; + ao_ms5607_reset(); + prom = &ms5607_prom.reserved; + + for (addr = 0; addr <= 7; addr++) + prom[addr] = ao_ms5607_prom_read(addr); +} + +static uint32_t +ao_ms5607_convert(uint8_t cmd) { + uint8_t reply[3]; + uint8_t read; + + ao_ms5607_start(); + ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); + ao_ms5607_stop(); + + ao_delay(AO_MS_TO_TICKS(200)); + + ao_ms5607_start(); + read = AO_MS5607_ADC_READ; + ao_spi_send(&read, 1, AO_MS5607_SPI_INDEX); + ao_spi_recv(&reply, 3, AO_MS5607_SPI_INDEX); + ao_ms5607_stop(); + + return ((uint32_t) reply[0] << 16) | ((uint32_t) reply[1] << 8) | (uint32_t) reply[2]; +} + +static void +ao_ms5607_dump(void) +{ + uint8_t addr; + uint32_t d1, d2; + int32_t dT; + int32_t TEMP; + int64_t OFF; + int64_t SENS; + int32_t P; + + ao_ms5607_init_chip(); + printf ("reserved: %d\n", ms5607_prom.reserved); + printf ("sens: %d\n", ms5607_prom.sens); + printf ("off: %d\n", ms5607_prom.off); + printf ("tcs: %d\n", ms5607_prom.tcs); + printf ("tco: %d\n", ms5607_prom.tco); + printf ("tref: %d\n", ms5607_prom.tref); + printf ("tempsens: %d\n", ms5607_prom.tempsens); + printf ("crc: %d\n", ms5607_prom.crc); + d1 = ao_ms5607_convert(AO_MS5607_CONVERT_D1_4096); + printf ("Conversion D1: %d\n", d1); + d2 = ao_ms5607_convert(AO_MS5607_CONVERT_D2_4096); + printf ("Conversion D2: %d\n", d2); + + dT = d2 - ((int32_t) ms5607_prom.tref << 8); + + TEMP = 2000 + (((int64_t) dT * ms5607_prom.tempsens) >> 23); + + OFF = ((int64_t) ms5607_prom.off << 17) + (((int64_t) ms5607_prom.tco * dT) >> 6); + + SENS = ((int64_t) ms5607_prom.sens << 16) + (((int64_t) ms5607_prom.tcs * dT) >> 7); + + if (TEMP < 2000) { + int32_t T2 = ((int64_t) dT * (int64_t) dT) >> 31; + int32_t TEMPM = TEMP - 2000; + int64_t OFF2 = (61 * (int64_t) TEMPM * (int64_t) TEMPM) >> 4; + int64_t SENS2 = 2 * (int64_t) TEMPM * (int64_t) TEMPM; + } + + P = ((((int64_t) d1 * SENS) >> 21) - OFF) >> 15; + + printf ("Temperature: %d", TEMP); + printf ("Pressure %d\n", P); +} + +__code struct ao_cmds ao_ms5607_cmds[] = { + { ao_ms5607_dump, "p\0Display MS5607 data" }, + { 0, NULL }, +}; + +void +ao_ms5607_init(void) +{ + ao_cmd_register(&ao_ms5607_cmds[0]); + + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN); + stm_gpio_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, 1); + stm_moder_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, STM_MODER_OUTPUT); +} diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h new file mode 100644 index 00000000..6c245368 --- /dev/null +++ b/src/drivers/ao_ms5607.h @@ -0,0 +1,38 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_MS5607_H_ +#define _AO_MS5607_H_ + +#define AO_MS5607_RESET 0x1e + +#define AO_MS5607_CONVERT_D1_256 0x40 +#define AO_MS5607_CONVERT_D1_512 0x42 +#define AO_MS5607_CONVERT_D1_1024 0x44 +#define AO_MS5607_CONVERT_D1_2048 0x46 +#define AO_MS5607_CONVERT_D1_4096 0x48 + +#define AO_MS5607_CONVERT_D2_256 0x50 +#define AO_MS5607_CONVERT_D2_512 0x52 +#define AO_MS5607_CONVERT_D2_1024 0x54 +#define AO_MS5607_CONVERT_D2_2048 0x56 +#define AO_MS5607_CONVERT_D2_4096 0x58 + +#define AO_MS5607_ADC_READ 0x00 +#define AO_MS5607_PROM_READ(ad) 0xA0 | ((ad) << 1) + +#endif /* _AO_MS5607_H_ */ diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 23160d9b..fbcb4a57 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -31,13 +31,16 @@ ALTOS_SRC = \ ao_serial_stm.c \ ao_gps_skytraq.c \ ao_cc1120.c \ - ao_freq.c + ao_freq.c \ + ao_dma_stm.c \ + ao_spi_stm.c \ + ao_ms5607.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM IDPRODUCT=0x000a -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -Os -g +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -O0 -g PROG=megametrum-v0.1-$(VERSION).elf diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 6bf43cb1..0d88f4c1 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -29,6 +29,9 @@ main(void) ao_cmd_init(); ao_gps_init(); ao_config_init(); + ao_dma_init(); + ao_spi_init(); + ao_ms5607_init(); ao_start_scheduler(); return 0; diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index dadeb380..ee4510e6 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -42,10 +42,13 @@ #define HAS_BEEP 0 #define HAS_SPI_1 1 -#define SPI_1_PE13_PE14_PE15 1 +#define SPI_1_PA5_PA6_PA7 1 +#define SPI_1_PB3_PB4_PB5 0 +#define SPI_1_PE13_PE14_PE15 0 #define HAS_SPI_2 1 #define SPI_2_PB13_PB14_PB15 1 +#define SPI_2_PD1_PD3_PD4 0 #define HAS_I2C_1 1 #define I2C_1_PB8_PB9 1 diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 366291c6..c1f49371 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -26,7 +26,10 @@ ALTOS_SRC = \ ao_timer.c \ ao_serial_stm.c \ ao_lcd_stm.c \ - ao_lcd_font.c + ao_lcd_font.c \ + ao_mutex.c \ + ao_dma_stm.c \ + ao_spi_stm.c PRODUCT=StmDemo-v0.0 PRODUCT_DEF=-DSTM_DEMO diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 544f261f..54f7c8f2 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -50,6 +50,71 @@ void _lseek() { } void _exit () { } void _read () { } void _fstat() { } + +static void +ao_dma_test(void) { + static char src[20] = "hello, world"; + static char dst[20]; + + dst[0] = '\0'; + ao_dma_set_transfer(STM_DMA_INDEX(1), dst, src, 13, + (1 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_LOW << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (1 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); + ao_dma_start(STM_DMA_INDEX(1)); + cli(); + while (!ao_dma_done[STM_DMA_INDEX(1)]) + ao_sleep(&ao_dma_done[STM_DMA_INDEX(1)]); + sei(); + printf ("copied %s\n", dst); +} + +static void +ao_spi_write(void) { + unsigned char data[] = { 0x55, 0xaa, 0xff, 0x00 }; + int i; + + for (i = 0; i < 10; i++) { + ao_spi_get(0); + stm_gpio_set(&stm_gpioc, 12, 0); + ao_spi_send(data, 1, 0); + stm_gpio_set(&stm_gpioc, 12, 1); + ao_spi_put(0); + printf("."); + flush(); + ao_delay(100); + } +} + +static void +ao_spi_read(void) { + unsigned char data[4]; + int i; + + for (i = 0; i < 10; i++) { + ao_spi_get(0); + stm_gpio_set(&stm_gpioc, 12, 0); + ao_spi_recv(data, 4, 0); + printf("."); + flush(); + stm_gpio_set(&stm_gpioc, 12, 1); + ao_spi_put(0); + ao_delay(100); + } +} + +__code struct ao_cmds ao_demo_cmds[] = { + { ao_dma_test, "D\0DMA test" }, + { ao_spi_write, "W\0SPI write" }, + { ao_spi_read, "R\0SPI read" }, + { 0, NULL } +}; + int main(void) { @@ -57,11 +122,19 @@ main(void) ao_serial_init(); ao_timer_init(); + ao_dma_init(); ao_cmd_init(); - ao_lcd_stm_init(); - ao_lcd_font_init(); - ao_add_task(&demo_task, ao_demo, "demo"); +// ao_lcd_stm_init(); +// ao_lcd_font_init(); + ao_spi_init(); + + ao_cmd_register(&ao_demo_cmds[0]); + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN); + stm_gpio_set(&stm_gpioc, 12, 1); + stm_moder_set(&stm_gpioc, 12, STM_MODER_OUTPUT); + stm_otyper_set(&stm_gpioc, 12, STM_OTYPER_PUSH_PULL); + ao_start_scheduler(); return 0; } diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 798a292e..09c88f90 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -34,6 +34,11 @@ #define SERIAL_3_PC10_PC11 0 #define SERIAL_3_PD8_PD9 1 +#define HAS_SPI_1 1 +#define SPI_1_PB3_PB4_PB5 1 + +#define HAS_SPI_2 0 + #define HAS_USB 0 #define HAS_BEEP 0 #define PACKET_HAS_SLAVE 0 diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 9b68f19a..29e3f42f 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -18,6 +18,8 @@ #ifndef _AO_ARCH_FUNCS_H_ #define _AO_ARCH_FUNCS_H_ +/* ao_spi_stm.c + */ extern uint8_t ao_spi_mutex[STM_NUM_SPI]; static inline void ao_spi_get(uint8_t spi_index) { ao_mutex_get(&ao_spi_mutex[spi_index]); } @@ -30,6 +32,30 @@ void ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); void -ao_spi_init(uint8_t spi_index); +ao_spi_init(void); + +/* ao_dma_stm.c + */ + +extern uint8_t ao_dma_done[STM_NUM_DMA]; + +void +ao_dma_set_transfer(uint8_t index, + volatile void *peripheral, + void *memory, + uint16_t count, + uint32_t ccr); + +void +ao_dma_start(uint8_t index); + +void +ao_dma_done_transfer(uint8_t index); + +void +ao_dma_abort(uint8_t index); + +void +ao_dma_init(void); #endif /* _AO_ARCH_FUNCS_H_ */ diff --git a/src/stm/ao_dma_stm.c b/src/stm/ao_dma_stm.c new file mode 100644 index 00000000..70b9e48a --- /dev/null +++ b/src/stm/ao_dma_stm.c @@ -0,0 +1,99 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +#define NUM_DMA 7 + +struct ao_dma_config { + uint32_t isr; +}; + +uint8_t ao_dma_done[NUM_DMA]; + +static struct ao_dma_config ao_dma_config[NUM_DMA]; +static uint8_t ao_dma_mutex[NUM_DMA]; + +static void +ao_dma_isr(uint8_t index) { + /* Get channel interrupt bits */ + uint32_t isr = stm_dma.isr & (STM_DMA_ISR_MASK << + STM_DMA_ISR(index)); + + /* Ack them */ + stm_dma.ifcr = isr; + isr >>= STM_DMA_ISR(index); + ao_dma_config[index].isr |= isr; + ao_dma_done[index] = 1; + ao_wakeup(&ao_dma_done[index]); +} + +void stm_dma1_channel1_isr(void) { ao_dma_isr(STM_DMA_INDEX(1)); } +void stm_dma1_channel2_isr(void) { ao_dma_isr(STM_DMA_INDEX(2)); } +void stm_dma1_channel3_isr(void) { ao_dma_isr(STM_DMA_INDEX(3)); } +void stm_dma1_channel4_isr(void) { ao_dma_isr(STM_DMA_INDEX(4)); } +void stm_dma1_channel5_isr(void) { ao_dma_isr(STM_DMA_INDEX(5)); } +void stm_dma1_channel6_isr(void) { ao_dma_isr(STM_DMA_INDEX(6)); } +void stm_dma1_channel7_isr(void) { ao_dma_isr(STM_DMA_INDEX(7)); } + +void +ao_dma_set_transfer(uint8_t index, + volatile void *peripheral, + void *memory, + uint16_t count, + uint32_t ccr) +{ + ao_mutex_get(&ao_dma_mutex[index]); + stm_dma.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE); + stm_dma.channel[index].cndtr = count; + stm_dma.channel[index].cpar = (uint32_t) peripheral; + stm_dma.channel[index].cmar = (uint32_t) memory; +} + +void +ao_dma_start(uint8_t index) +{ + ao_dma_done[index] = 0; + stm_dma.channel[index].ccr |= (1 << STM_DMA_CCR_EN); +} + +void +ao_dma_done_transfer(uint8_t index) +{ + stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN); + ao_mutex_put(&ao_dma_mutex[index]); +} + +void +ao_dma_abort(uint8_t index) +{ + stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN); +} + +void +ao_dma_init(void) +{ + int index; + + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN); + + for (index = 0; index < STM_NUM_DMA; index++) { + stm_nvic_set_enable(STM_ISR_DMA1_CHANNEL1_POS + index); + stm_nvic_set_priority(STM_ISR_DMA1_CHANNEL1_POS + index, 4); + } + +} diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c new file mode 100644 index 00000000..da04302b --- /dev/null +++ b/src/stm/ao_spi_stm.c @@ -0,0 +1,240 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include + +struct ao_spi_stm_info { + uint8_t miso_dma_index; + uint8_t mosi_dma_index; + struct stm_spi *stm_spi; +}; + +uint8_t ao_spi_mutex[STM_NUM_SPI]; + +static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = { + { + .miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_RX), + .mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI1_TX), + &stm_spi1 + }, + { + .miso_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_RX), + .mosi_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_SPI2_TX), + &stm_spi2 + } +}; + +static uint8_t spi_dev_null; + +void +ao_spi_send(void *block, uint16_t len, uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; + uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + + ao_dma_set_transfer(mosi_dma_index, + &stm_spi->dr, + block, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); + /* Clear any stale data */ + (void) stm_spi->dr; + ao_dma_set_transfer(miso_dma_index, + &stm_spi->dr, + &spi_dev_null, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (0 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (1 << STM_SPI_CR2_TXDMAEN) | + (1 << STM_SPI_CR2_RXDMAEN)); + ao_dma_start(miso_dma_index); + ao_dma_start(mosi_dma_index); + ao_arch_critical( + while (!ao_dma_done[miso_dma_index]) + ao_sleep(&ao_dma_done[miso_dma_index]); + ); + ao_dma_done_transfer(mosi_dma_index); + ao_dma_done_transfer(miso_dma_index); +} + +void +ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; +#if 0 + uint8_t *d = block; + + while (len--) { + stm_spi->dr = 0xff; + while (!(stm_spi->sr & (1 << STM_SPI_SR_RXNE))); + *d++ = stm_spi->dr; + } + while (stm_spi->sr & (1 << STM_SPI_SR_BSY)); +#else + uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + + ao_dma_set_transfer(mosi_dma_index, + &stm_spi->dr, + &spi_dev_null, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (0 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); + /* Clear any stale data */ + (void) stm_spi->dr; + ao_dma_set_transfer(miso_dma_index, + &stm_spi->dr, + block, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (1 << STM_SPI_CR2_TXDMAEN) | + (1 << STM_SPI_CR2_RXDMAEN)); + ao_dma_start(miso_dma_index); + ao_dma_start(mosi_dma_index); + ao_arch_critical( + while (!ao_dma_done[miso_dma_index]) + ao_sleep(&ao_dma_done[miso_dma_index]); + ); + ao_dma_done_transfer(mosi_dma_index); + ao_dma_done_transfer(miso_dma_index); +#endif +} + +static void +ao_spi_channel_init(uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; + + stm_spi->cr1 = 0; + (void) stm_spi->sr; + stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | + (0 << STM_SPI_CR1_BIDIOE) | + (0 << STM_SPI_CR1_CRCEN) | + (0 << STM_SPI_CR1_CRCNEXT) | + (0 << STM_SPI_CR1_DFF) | + (0 << STM_SPI_CR1_RXONLY) | + (1 << STM_SPI_CR1_SSM) | + (1 << STM_SPI_CR1_SSI) | + (0 << STM_SPI_CR1_LSBFIRST) | + (1 << STM_SPI_CR1_SPE) | + (STM_SPI_CR1_BR_PCLK_4 << STM_SPI_CR1_BR) | + (1 << STM_SPI_CR1_MSTR) | + (0 << STM_SPI_CR1_CPOL) | + (0 << STM_SPI_CR1_CPHA)); + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (0 << STM_SPI_CR2_TXDMAEN) | + (0 << STM_SPI_CR2_RXDMAEN)); +} + +void +ao_spi_init(void) +{ +#if HAS_SPI_1 +# if SPI_1_PA5_PA6_PA7 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + stm_afr_set(&stm_gpioa, 5, STM_AFR_AF5); + stm_afr_set(&stm_gpioa, 6, STM_AFR_AF5); + stm_afr_set(&stm_gpioa, 7, STM_AFR_AF5); +# else +# if SPI_1_PB3_PB4_PB5 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); + stm_afr_set(&stm_gpiob, 3, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 4, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 5, STM_AFR_AF5); +# else +# if SPI_1_PE13_PE14_PE15 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOEEN); + stm_afr_set(&stm_gpioe, 13, STM_AFR_AF5); + stm_afr_set(&stm_gpioe, 14, STM_AFR_AF5); + stm_afr_set(&stm_gpioe, 15, STM_AFR_AF5); +# else +# error "No SPI_1 port configuration specified" +# endif +# endif +# endif + + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN); + + ao_spi_channel_init(0); + + stm_nvic_set_enable(STM_ISR_SPI1_POS); + stm_nvic_set_priority(STM_ISR_SPI1_POS, 3); +#endif + +#if HAS_SPI_2 +# if SPI_2_PB13_PB14_PB15 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); + stm_afr_set(&stm_gpiob, 13, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 14, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 15, STM_AFR_AF5); +# else +# if SPI_2_PPD1_PD3_PD4 + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN); + stm_afr_set(&stm_gpiod, 1, STM_AFR_AF5); + stm_afr_set(&stm_gpiod, 3, STM_AFR_AF5); + stm_afr_set(&stm_gpiod, 4, STM_AFR_AF5); +# else +# error "No SPI_2 port configuration specified" +# endif +# endif + + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN); + + ao_spi_channel_init(1); + + stm_nvic_set_enable(STM_ISR_SPI2_POS); + stm_nvic_set_priority(STM_ISR_SPI2_POS, 3); +#endif +} diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 531a4fb9..b40ec0ee 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -159,6 +159,17 @@ stm_afr_get(struct stm_gpio *gpio, int pin) { } } +static inline void +stm_gpio_set(struct stm_gpio *gpio, int pin, uint8_t value) { + /* Use the bit set/reset register to do this atomically */ + gpio->bsrr = ((uint32_t) (value ^ 1) << (pin + 16)) | ((uint32_t) value << pin); +} + +static inline uint8_t +stm_gpio_isset(struct stm_gpio *gpio, int pin) { + return (gpio->idr >> pin) & 1; +} + extern struct stm_gpio stm_gpioa; extern struct stm_gpio stm_gpiob; extern struct stm_gpio stm_gpioc; @@ -238,11 +249,6 @@ extern struct stm_usart stm_usart3; #define STM_USART_CR3_IREN (1) /* IrDA mode enable */ #define STM_USART_CR3_EIE (0) /* Error interrupt enable */ -struct stm_spi { -}; - -extern struct stm_spi stm_spi1; - struct stm_tim { }; @@ -842,4 +848,168 @@ isr(tim7) #define STM_ISR_TIM6_POS 43 #define STM_ISR_TIM7_POS 44 +struct stm_dma_channel { + vuint32_t ccr; + vuint32_t cndtr; + vuint32_t cpar; + vuint32_t cmar; + vuint32_t reserved; +}; + +#define STM_NUM_DMA 7 + +struct stm_dma { + vuint32_t isr; + vuint32_t ifcr; + struct stm_dma_channel channel[STM_NUM_DMA]; +}; + +extern struct stm_dma stm_dma; + +/* DMA channels go from 1 to 7, instead of 0 to 6 (sigh) + */ + +#define STM_DMA_INDEX(channel) ((channel) - 1) + +#define STM_DMA_ISR(index) ((index) << 2) +#define STM_DMA_ISR_MASK 0xf +#define STM_DMA_ISR_TEIF 3 +#define STM_DMA_ISR_HTIF 2 +#define STM_DMA_ISR_TCIF 1 +#define STM_DMA_ISR_GIF 0 + +#define STM_DMA_IFCR(index) ((index) << 2) +#define STM_DMA_IFCR_MASK 0xf +#define STM_DMA_IFCR_CTEIF 3 +#define STM_DMA_IFCR_CHTIF 2 +#define STM_DMA_IFCR_CTCIF 1 +#define STM_DMA_IFCR_CGIF 0 + +#define STM_DMA_CCR_MEM2MEM (14) + +#define STM_DMA_CCR_PL (12) +#define STM_DMA_CCR_PL_LOW (0) +#define STM_DMA_CCR_PL_MEDIUM (1) +#define STM_DMA_CCR_PL_HIGH (2) +#define STM_DMA_CCR_PL_VERY_HIGH (3) +#define STM_DMA_CCR_PL_MASK (3) + +#define STM_DMA_CCR_MSIZE (10) +#define STM_DMA_CCR_MSIZE_8 (0) +#define STM_DMA_CCR_MSIZE_16 (1) +#define STM_DMA_CCR_MSIZE_32 (2) +#define STM_DMA_CCR_MSIZE_MASK (3) + +#define STM_DMA_CCR_PSIZE (8) +#define STM_DMA_CCR_PSIZE_8 (0) +#define STM_DMA_CCR_PSIZE_16 (1) +#define STM_DMA_CCR_PSIZE_32 (2) +#define STM_DMA_CCR_PSIZE_MASK (3) + +#define STM_DMA_CCR_MINC (7) +#define STM_DMA_CCR_PINC (6) +#define STM_DMA_CCR_CIRC (5) +#define STM_DMA_CCR_DIR (4) +#define STM_DMA_CCR_DIR_PER_TO_MEM 0 +#define STM_DMA_CCR_DIR_MEM_TO_PER 1 +#define STM_DMA_CCR_TEIE (3) +#define STM_DMA_CCR_HTIE (2) +#define STM_DMA_CCR_TCIE (1) +#define STM_DMA_CCR_EN (0) + +#define STM_DMA_CHANNEL_ADC1 1 +#define STM_DMA_CHANNEL_SPI1_RX 2 +#define STM_DMA_CHANNEL_SPI1_TX 3 +#define STM_DMA_CHANNEL_SPI2_RX 4 +#define STM_DMA_CHANNEL_SPI2_TX 5 +#define STM_DMA_CHANNEL_USART3_TX 2 +#define STM_DMA_CHANNEL_USART3_RX 3 +#define STM_DMA_CHANNEL_USART1_TX 4 +#define STM_DMA_CHANNEL_USART1_RX 5 +#define STM_DMA_CHANNEL_USART2_RX 6 +#define STM_DMA_CHANNEL_USART2_TX 7 +#define STM_DMA_CHANNEL_I2C2_TX 4 +#define STM_DMA_CHANNEL_I2C2_RX 5 +#define STM_DMA_CHANNEL_I2C1_RX 6 +#define STM_DMA_CHANNEL_I2C1_TX 7 +#define STM_DMA_CHANNEL_TIM2_CH3 1 +#define STM_DMA_CHANNEL_TIM2_UP 2 +#define STM_DMA_CHANNEL_TIM2_CH1 5 +#define STM_DMA_CHANNEL_TIM2_CH2 7 +#define STM_DMA_CHANNEL_TIM2_CH4 7 +#define STM_DMA_CHANNEL_TIM3_CH3 2 +#define STM_DMA_CHANNEL_TIM3_CH4 3 +#define STM_DMA_CHANNEL_TIM3_UP 3 +#define STM_DMA_CHANNEL_TIM3_CH1 6 +#define STM_DMA_CHANNEL_TIM3_TRIG 6 +#define STM_DMA_CHANNEL_TIM4_CH1 1 +#define STM_DMA_CHANNEL_TIM4_CH2 4 +#define STM_DMA_CHANNEL_TIM4_CH3 5 +#define STM_DMA_CHANNEL_TIM4_UP 7 +#define STM_DMA_CHANNEL_TIM6_UP_DA 2 +#define STM_DMA_CHANNEL_C_CHANNEL1 2 +#define STM_DMA_CHANNEL_TIM7_UP_DA 3 +#define STM_DMA_CHANNEL_C_CHANNEL2 3 + +/* + * Only spi channel 1 and 2 can use DMA + */ +#define STM_NUM_SPI 2 + +struct stm_spi { + vuint32_t cr1; + vuint32_t cr2; + vuint32_t sr; + vuint32_t dr; + vuint32_t crcpr; + vuint32_t rxcrcr; + vuint32_t txcrcr; +}; + +extern struct stm_spi stm_spi1, stm_spi2, stm_spi3; + +/* SPI channels go from 1 to 3, instead of 0 to 2 (sigh) + */ + +#define STM_SPI_INDEX(channel) ((channel) - 1) + +#define STM_SPI_CR1_BIDIMODE 15 +#define STM_SPI_CR1_BIDIOE 14 +#define STM_SPI_CR1_CRCEN 13 +#define STM_SPI_CR1_CRCNEXT 12 +#define STM_SPI_CR1_DFF 11 +#define STM_SPI_CR1_RXONLY 10 +#define STM_SPI_CR1_SSM 9 +#define STM_SPI_CR1_SSI 8 +#define STM_SPI_CR1_LSBFIRST 7 +#define STM_SPI_CR1_SPE 6 +#define STM_SPI_CR1_BR 3 +#define STM_SPI_CR1_BR_PCLK_2 0 +#define STM_SPI_CR1_BR_PCLK_4 1 +#define STM_SPI_CR1_BR_PCLK_8 2 +#define STM_SPI_CR1_BR_PCLK_16 3 +#define STM_SPI_CR1_BR_PCLK_32 4 +#define STM_SPI_CR1_BR_PCLK_64 5 +#define STM_SPI_CR1_BR_PCLK_128 6 +#define STM_SPI_CR1_BR_PCLK_256 7 +#define STM_SPI_CR1_BR_MASK 7 + +#define STM_SPI_CR1_MSTR 2 +#define STM_SPI_CR1_CPOL 1 +#define STM_SPI_CR1_CPHA 0 + +#define STM_SPI_CR2_TXEIE 7 +#define STM_SPI_CR2_RXNEIE 6 +#define STM_SPI_CR2_ERRIE 5 +#define STM_SPI_CR2_SSOE 2 +#define STM_SPI_CR2_TXDMAEN 1 +#define STM_SPI_CR2_RXDMAEN 0 + +#define STM_SPI_SR_BSY 7 +#define STM_SPI_SR_OVR 6 +#define STM_SPI_SR_MODF 5 +#define STM_SPI_SR_CRCERR 4 +#define STM_SPI_SR_TXE 1 +#define STM_SPI_SR_RXNE 0 + #endif /* _STM32L_H_ */ -- cgit v1.2.3 From 20926b62a87154a846cb950dc542c737cd54826d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 Apr 2012 22:39:12 -0700 Subject: altos: Disable STM SPI transceiver when idle Should save a bit of power. Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 7 +++-- src/stm/ao_spi_stm.c | 71 ++++++++++++++++++++++++++++++++----------------- 2 files changed, 51 insertions(+), 27 deletions(-) (limited to 'src') diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 29e3f42f..e0ecb0a5 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -22,8 +22,11 @@ */ extern uint8_t ao_spi_mutex[STM_NUM_SPI]; -static inline void ao_spi_get(uint8_t spi_index) { ao_mutex_get(&ao_spi_mutex[spi_index]); } -static inline void ao_spi_put(uint8_t spi_index) { ao_mutex_put(&ao_spi_mutex[spi_index]); } +void +ao_spi_get(uint8_t spi_index); + +void +ao_spi_put(uint8_t spi_index); void ao_spi_send(void *block, uint16_t len, uint8_t spi_index); diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index da04302b..92747d87 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -47,6 +47,7 @@ ao_spi_send(void *block, uint16_t len, uint8_t spi_index) uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + /* Set up the transmit DMA to deliver data */ ao_dma_set_transfer(mosi_dma_index, &stm_spi->dr, block, @@ -59,8 +60,14 @@ ao_spi_send(void *block, uint16_t len, uint8_t spi_index) (0 << STM_DMA_CCR_PINC) | (0 << STM_DMA_CCR_CIRC) | (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); - /* Clear any stale data */ + + /* Clear RXNE */ (void) stm_spi->dr; + + /* Set up the receive DMA -- when this is done, we know the SPI unit + * is idle. Without this, we'd have to poll waiting for the BSY bit to + * be cleared + */ ao_dma_set_transfer(miso_dma_index, &stm_spi->dr, &spi_dev_null, @@ -93,19 +100,10 @@ void ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) { struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; -#if 0 - uint8_t *d = block; - - while (len--) { - stm_spi->dr = 0xff; - while (!(stm_spi->sr & (1 << STM_SPI_SR_RXNE))); - *d++ = stm_spi->dr; - } - while (stm_spi->sr & (1 << STM_SPI_SR_BSY)); -#else uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + /* Set up transmit DMA to make the SPI hardware actually run */ ao_dma_set_transfer(mosi_dma_index, &stm_spi->dr, &spi_dev_null, @@ -118,8 +116,11 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) (0 << STM_DMA_CCR_PINC) | (0 << STM_DMA_CCR_CIRC) | (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); - /* Clear any stale data */ + + /* Clear RXNE */ (void) stm_spi->dr; + + /* Set up the receive DMA to capture data */ ao_dma_set_transfer(miso_dma_index, &stm_spi->dr, block, @@ -132,6 +133,7 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) (0 << STM_DMA_CCR_PINC) | (0 << STM_DMA_CCR_CIRC) | (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | (0 << STM_SPI_CR2_RXNEIE) | (0 << STM_SPI_CR2_ERRIE) | @@ -140,36 +142,55 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) (1 << STM_SPI_CR2_RXDMAEN)); ao_dma_start(miso_dma_index); ao_dma_start(mosi_dma_index); + + /* Wait until the SPI unit is done */ ao_arch_critical( while (!ao_dma_done[miso_dma_index]) ao_sleep(&ao_dma_done[miso_dma_index]); ); + ao_dma_done_transfer(mosi_dma_index); ao_dma_done_transfer(miso_dma_index); -#endif } -static void -ao_spi_channel_init(uint8_t spi_index) +void +ao_spi_get(uint8_t spi_index) { struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; - stm_spi->cr1 = 0; - (void) stm_spi->sr; - stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | + ao_mutex_get(&ao_spi_mutex[spi_index]); + stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | /* Three wire mode */ (0 << STM_SPI_CR1_BIDIOE) | - (0 << STM_SPI_CR1_CRCEN) | + (0 << STM_SPI_CR1_CRCEN) | /* CRC disabled */ (0 << STM_SPI_CR1_CRCNEXT) | (0 << STM_SPI_CR1_DFF) | (0 << STM_SPI_CR1_RXONLY) | - (1 << STM_SPI_CR1_SSM) | - (1 << STM_SPI_CR1_SSI) | - (0 << STM_SPI_CR1_LSBFIRST) | - (1 << STM_SPI_CR1_SPE) | - (STM_SPI_CR1_BR_PCLK_4 << STM_SPI_CR1_BR) | + (1 << STM_SPI_CR1_SSM) | /* Software SS handling */ + (1 << STM_SPI_CR1_SSI) | /* ... */ + (0 << STM_SPI_CR1_LSBFIRST) | /* Little endian */ + (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */ + (STM_SPI_CR1_BR_PCLK_4 << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ (1 << STM_SPI_CR1_MSTR) | - (0 << STM_SPI_CR1_CPOL) | + (0 << STM_SPI_CR1_CPOL) | /* Format 0 */ (0 << STM_SPI_CR1_CPHA)); +} + +void +ao_spi_put(uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; + + stm_spi->cr1 = 0; + ao_mutex_put(&ao_spi_mutex[spi_index]); +} + +static void +ao_spi_channel_init(uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; + + stm_spi->cr1 = 0; + (void) stm_spi->sr; stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | (0 << STM_SPI_CR2_RXNEIE) | (0 << STM_SPI_CR2_ERRIE) | -- cgit v1.2.3 From 0bcc23c3be1a20a362fea268901c600f9f0d287a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 Apr 2012 22:39:45 -0700 Subject: altos: Disable DMA unit when idle Should save a bit of power Signed-off-by: Keith Packard --- src/stm/ao_dma_stm.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/stm/ao_dma_stm.c b/src/stm/ao_dma_stm.c index 70b9e48a..f996e7cd 100644 --- a/src/stm/ao_dma_stm.c +++ b/src/stm/ao_dma_stm.c @@ -27,6 +27,7 @@ uint8_t ao_dma_done[NUM_DMA]; static struct ao_dma_config ao_dma_config[NUM_DMA]; static uint8_t ao_dma_mutex[NUM_DMA]; +static uint8_t ao_dma_active; static void ao_dma_isr(uint8_t index) { @@ -58,10 +59,12 @@ ao_dma_set_transfer(uint8_t index, uint32_t ccr) { ao_mutex_get(&ao_dma_mutex[index]); + if (ao_dma_active++ == 0) + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN); stm_dma.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE); stm_dma.channel[index].cndtr = count; - stm_dma.channel[index].cpar = (uint32_t) peripheral; - stm_dma.channel[index].cmar = (uint32_t) memory; + stm_dma.channel[index].cpar = peripheral; + stm_dma.channel[index].cmar = memory; } void @@ -75,6 +78,8 @@ void ao_dma_done_transfer(uint8_t index) { stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN); + if (--ao_dma_active == 0) + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMA1EN); ao_mutex_put(&ao_dma_mutex[index]); } @@ -89,8 +94,6 @@ ao_dma_init(void) { int index; - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN); - for (index = 0; index < STM_NUM_DMA; index++) { stm_nvic_set_enable(STM_ISR_DMA1_CHANNEL1_POS + index); stm_nvic_set_priority(STM_ISR_DMA1_CHANNEL1_POS + index, 4); -- cgit v1.2.3 From 89201cdf2062b7319a0da4e266e4d6edba1493f8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 Apr 2012 22:40:17 -0700 Subject: altos: Declare stm DMA address registers as volatile void * Eliminates a cast when assigning to them. Signed-off-by: Keith Packard --- src/stm/stm32l.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index b40ec0ee..e03556b0 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -21,6 +21,7 @@ #include typedef volatile uint32_t vuint32_t; +typedef volatile void * vvoid_t; struct stm_gpio { vuint32_t moder; @@ -851,8 +852,8 @@ isr(tim7) struct stm_dma_channel { vuint32_t ccr; vuint32_t cndtr; - vuint32_t cpar; - vuint32_t cmar; + vvoid_t cpar; + vvoid_t cmar; vuint32_t reserved; }; -- cgit v1.2.3 From 2db6b0f58811ffc44a468c8fbcacc08d37edd26c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 6 Apr 2012 22:40:49 -0700 Subject: altos: Shuffle stm-demo SPI test code around a bit Move a debug printf beyond the chip select boundary to allow for more accurate timing. Send four bytes instead of just one. Signed-off-by: Keith Packard --- src/stm-demo/ao_demo.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 54f7c8f2..5ff2b32a 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -82,7 +82,7 @@ ao_spi_write(void) { for (i = 0; i < 10; i++) { ao_spi_get(0); stm_gpio_set(&stm_gpioc, 12, 0); - ao_spi_send(data, 1, 0); + ao_spi_send(data, 4, 0); stm_gpio_set(&stm_gpioc, 12, 1); ao_spi_put(0); printf("."); @@ -100,10 +100,10 @@ ao_spi_read(void) { ao_spi_get(0); stm_gpio_set(&stm_gpioc, 12, 0); ao_spi_recv(data, 4, 0); - printf("."); - flush(); stm_gpio_set(&stm_gpioc, 12, 1); ao_spi_put(0); + printf("."); + flush(); ao_delay(100); } } -- cgit v1.2.3 From 5f63065a16b65618b39314880c72074f0a8b5550 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 00:22:02 -0700 Subject: altos: Add fake install/uninstall targets for stm-bringup Keep global 'make install' from failing. Signed-off-by: Keith Packard --- src/stm-bringup/Makefile | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/stm-bringup/Makefile b/src/stm-bringup/Makefile index 1ba480ba..01c80614 100644 --- a/src/stm-bringup/Makefile +++ b/src/stm-bringup/Makefile @@ -40,3 +40,7 @@ clean: rm -rf *.bin .PHONY: all clean + +install: + +uninstall: -- cgit v1.2.3 From 41a8383ccd29351f3a88a374f9456d6efb71b9a0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 00:22:41 -0700 Subject: altos: Save memory in ao_cmd.c Shrink a couple of help strings move a variable in ao_cmd from data to pdata. Signed-off-by: Keith Packard --- src/core/ao_cmd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index cde68b39..fdc70007 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -300,7 +300,7 @@ ao_cmd_register(__code struct ao_cmds *cmds) void ao_cmd(void) { - char c; + __pdata char c; uint8_t cmd, cmds; __code struct ao_cmds * __xdata cs; void (*__xdata func)(void); @@ -336,8 +336,8 @@ __xdata struct ao_task ao_cmd_task; __code struct ao_cmds ao_base_cmds[] = { { help, "?\0Help" }, - { ao_task_info, "T\0Show tasks" }, - { echo, "E <0 off, 1 on>\0Set echo mode" }, + { ao_task_info, "T\0Tasks" }, + { echo, "E <0 off, 1 on>\0Echo" }, { ao_reboot, "r eboot\0Reboot" }, { version, "v\0Version" }, { 0, NULL }, -- cgit v1.2.3 From 8405efb6ca68c8216413b94e7acbdf51af00554a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 00:23:55 -0700 Subject: altos: Save memory in ao_config.c Shorten help messages. Stop setting aes_key on products not using aes key. Signed-off-by: Keith Packard --- src/core/ao_config.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 08e6deea..1dafab8d 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -113,8 +113,10 @@ _ao_config_get(void) ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; if (ao_config.minor < 8) ao_config.radio_enable = TRUE; +#if HAS_AES if (ao_config.minor < 9) - memset(&ao_config.aes_key, 0, AO_AES_LEN); + ao_xmemset(&ao_config.aes_key, '\0', AO_AES_LEN); +#endif if (ao_config.minor < 10) { ao_config.frequency = 434550; #if HAS_RADIO_CHANNELS @@ -525,12 +527,12 @@ ao_config_write(void) __reentrant; __code struct ao_config_var ao_config_vars[] = { #if HAS_ADC - { "m \0Main deploy (in meters)", + { "m \0Main deploy (m)", ao_config_main_deploy_set, ao_config_main_deploy_show, }, - { "d \0Apogee delay (in seconds)", + { "d \0Apogee delay (s)", ao_config_apogee_delay_set, ao_config_apogee_delay_show }, #endif /* HAS_ADC */ - { "r \0Radio channel (freq = 434.550 + chan * .1)", + { "r \0Radio channel", ao_config_radio_channel_set, ao_config_radio_channel_show }, { "F \0Frequency (kHz)", ao_config_frequency_set, ao_config_frequency_show }, @@ -545,7 +547,7 @@ __code struct ao_config_var ao_config_vars[] = { { "f \0Radio calib (cal = rf/(xtal/2^16))", ao_config_radio_cal_set, ao_config_radio_cal_show }, #if HAS_LOG - { "l \0Flight log size in kB", + { "l \0Flight log size (kB)", ao_config_log_set, ao_config_log_show }, #endif #if HAS_IGNITE @@ -637,7 +639,7 @@ ao_config_write(void) __reentrant #endif __code struct ao_cmds ao_config_cmds[] = { - { ao_config_set, "c \0Set config variable (? for help, s to show)" }, + { ao_config_set, "c \0Set config (? for help, s to show)" }, { 0, NULL }, }; -- cgit v1.2.3 From d0d0d20c20e5eeacbc9a1ec1c93141a2044830fb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 00:24:59 -0700 Subject: altos: Shorten help strings Save a bit of code space Signed-off-by: Keith Packard --- src/core/ao_log.c | 2 +- src/core/ao_log_single.c | 6 +++--- src/core/ao_monitor.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/core/ao_log.c b/src/core/ao_log.c index 6d3ad535..db60707d 100644 --- a/src/core/ao_log.c +++ b/src/core/ao_log.c @@ -264,7 +264,7 @@ ao_log_delete(void) __reentrant } __code struct ao_cmds ao_log_cmds[] = { - { ao_log_list, "l\0List flight logs" }, + { ao_log_list, "l\0List logs" }, { ao_log_delete, "d \0Delete flight" }, { 0, NULL }, }; diff --git a/src/core/ao_log_single.c b/src/core/ao_log_single.c index 9e90bd82..3f6235a6 100644 --- a/src/core/ao_log_single.c +++ b/src/core/ao_log_single.c @@ -180,9 +180,9 @@ ao_log_single_query(void) } const struct ao_cmds ao_log_single_cmds[] = { - { ao_log_single_set, "L <0 off, 1 on>\0Set logging mode" }, - { ao_log_single_list, "l\0List stored flight logs" }, - { ao_log_single_delete, "d 1\0Delete all stored flights" }, + { ao_log_single_set, "L <0 off, 1 on>\0Set logging" }, + { ao_log_single_list, "l\0List stored logs" }, + { ao_log_single_delete, "d 1\0Delete all stored logs" }, { ao_log_single_query, "q\0Query log status" }, { 0, NULL }, }; diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 7960208e..830464d8 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -267,7 +267,7 @@ set_monitor(void) } __code struct ao_cmds ao_monitor_cmds[] = { - { set_monitor, "m <0 off, 1 old, 20 std>\0Enable/disable radio monitoring" }, + { set_monitor, "m <0 off, 1 old, 20 std>\0Set radio monitoring" }, { 0, NULL }, }; #endif -- cgit v1.2.3 From c7119405a3dd7128120374a2a001bc98ef523619 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 00:25:26 -0700 Subject: altos: Make ao_freq_to_set reentrant Save a bunch of data space this way. Signed-off-by: Keith Packard --- src/core/ao.h | 2 +- src/core/ao_freq.c | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 67efa437..150c0817 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1892,7 +1892,7 @@ ao_sqrt(uint32_t op); * ao_freq.c */ -int32_t ao_freq_to_set(int32_t freq, int32_t cal); +int32_t ao_freq_to_set(int32_t freq, int32_t cal) __reentrant; #include diff --git a/src/core/ao_freq.c b/src/core/ao_freq.c index 67b0b037..12496f6f 100644 --- a/src/core/ao_freq.c +++ b/src/core/ao_freq.c @@ -25,10 +25,15 @@ * frequency, and updating the radio setting along the way */ -int32_t ao_freq_to_set(int32_t freq, int32_t cal) { - __pdata int32_t set = 0; - uint8_t neg = 0; - __pdata int32_t error = -434550 / 2; +int32_t ao_freq_to_set(int32_t freq, int32_t cal) __reentrant +{ + static __pdata int32_t set; + static __pdata uint8_t neg; + static __pdata int32_t error; + + set = 0; + neg = 0; + error = -434550 / 2; if ((freq -= 434550) < 0) { neg = 1; -- cgit v1.2.3 From a0a650a2be007b0436bd527d6c18f36eef6fbe2b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 00:25:50 -0700 Subject: altos: Force radio channel to zero when setting frequency Otherwise, the actual radio frequency will include the channel offset, which is not useful. Signed-off-by: Keith Packard --- src/core/ao_config.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 1dafab8d..2d3d2870 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -218,6 +218,7 @@ ao_config_frequency_set(void) __reentrant return; _ao_config_edit_start(); ao_config.frequency = ao_cmd_lex_u32; + ao_config.radio_channel = 0; ao_config_set_radio(); _ao_config_edit_finish(); ao_radio_recv_abort(); -- cgit v1.2.3 From 4700f63937786e8f6e9b4882363234a33eb54c46 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 01:01:06 -0700 Subject: altos: Make ao_config_set_radio public Allows other bits of code to reset the radio parameters. Signed-off-by: Keith Packard --- src/core/ao.h | 3 +++ src/core/ao_config.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 150c0817..f7db3bf4 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1510,6 +1510,9 @@ ao_config_get(void); void ao_config_put(void); +void +ao_config_set_radio(void); + void ao_config_init(void); diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 2d3d2870..32798f75 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -64,7 +64,7 @@ ao_config_put(void) } #endif -static void +void ao_config_set_radio(void) { ao_config.radio_setting = ao_freq_to_set(ao_config.frequency, ao_config.radio_cal); -- cgit v1.2.3 From d35c4df12a3d8e2dab5d41f8d918ff4237f91e46 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 01:01:33 -0700 Subject: altos: Add ability to change radio frequency in TeleTerra Provide a way to set the frequency locally. Signed-off-by: Keith Packard --- src/product/ao_terraui.c | 83 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 62 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c index 9b40c42a..8875ff48 100644 --- a/src/product/ao_terraui.c +++ b/src/product/ao_terraui.c @@ -98,13 +98,19 @@ ao_terraui_startup(void) } static void -ao_terraui_info(void) +ao_terraui_info_firstline(void) { sprintf(ao_lcd_line, "S %4d %7.7s %c", ao_tel_sensor.serial, ao_tel_config.callsign, ao_terraui_state()); ao_terraui_line(AO_LCD_ADDR(0,0)); +} + +static void +ao_terraui_info(void) +{ + ao_terraui_info_firstline(); sprintf(ao_lcd_line, "F %4d RSSI%4d%c", ao_tel_config.flight, ao_tel_rssi, @@ -449,31 +455,57 @@ ao_terraui_local(void) __reentrant ao_terraui_line(AO_LCD_ADDR(1,0)); } +static __pdata uint8_t ao_set_freq; +static __pdata uint32_t ao_set_freq_orig; + static void -ao_terraui_config(void) __reentrant +ao_terraui_freq(void) __reentrant { - uint8_t chan; - uint32_t kHz; uint16_t MHz; uint16_t frac; - - for (chan = 0; chan < AO_NUM_CHANNELS; chan++) - if (ao_config.radio_channels[chan].kHz == ao_config.frequency) - break; - if (chan == AO_NUM_CHANNELS) - chan = 0; - kHz = ao_config.radio_channels[chan].kHz; - MHz = kHz / 1000; - frac = kHz % 1000; - sprintf(ao_lcd_line, "%2d: %-10.10s ", chan, ao_config.radio_channels[chan].name); - ao_terraui_line(AO_LCD_ADDR(0,0)); - sprintf(ao_lcd_line, "%-8.8s %3d.%03d", ao_config.callsign, MHz, frac); + MHz = ao_config.frequency / 1000; + frac = ao_config.frequency % 1000; + ao_terraui_info_firstline(); + sprintf(ao_lcd_line, "Freq: %3d.%03d MHz", MHz, frac); ao_terraui_line(AO_LCD_ADDR(1,0)); - ao_lcd_goto(AO_LCD_ADDR(0,1)); + ao_lcd_goto(AO_LCD_ADDR(1,11)); +} + +static void +ao_terraui_freq_start(void) +{ + ao_set_freq = 1; + ao_set_freq_orig = ao_config.frequency; ao_lcd_cursor_on(); } +static void +ao_terraui_freq_button(char b) { + + switch (b) { + case 0: + return; + case 1: + if (ao_config.frequency > 430000) + ao_config.frequency -= 100; + break; + case 2: + ao_set_freq = 0; + ao_lcd_cursor_off(); + if (ao_set_freq_orig != ao_config.frequency) + ao_config_put(); + return; + case 3: + if (ao_config.frequency < 438000) + ao_config.frequency += 100; + break; + + } + ao_config_set_radio(); + ao_radio_recv_abort(); +} + static __code void (*__code ao_terraui_page[])(void) = { ao_terraui_startup, ao_terraui_info, @@ -483,13 +515,12 @@ static __code void (*__code ao_terraui_page[])(void) = { ao_terraui_recover, ao_terraui_remote, ao_terraui_local, - ao_terraui_config, }; #define NUM_PAGE (sizeof (ao_terraui_page)/sizeof (ao_terraui_page[0])) -__pdata uint8_t ao_current_page = 0; -__pdata uint8_t ao_shown_about = 3; +static __pdata uint8_t ao_current_page = 0; +static __pdata uint8_t ao_shown_about = 3; static void ao_terraui(void) @@ -501,7 +532,12 @@ ao_terraui(void) for (;;) { char b; - ao_terraui_page[ao_current_page](); + + if (ao_set_freq) + ao_terraui_freq(); + else + ao_terraui_page[ao_current_page](); + ao_alarm(AO_SEC_TO_TICKS(1)); b = ao_button_get(); ao_clear_alarm(); @@ -511,6 +547,10 @@ ao_terraui(void) ao_shown_about = 0; } + if (ao_set_freq) { + ao_terraui_freq_button(b); + continue; + } switch (b) { case 0: if (ao_shown_about) { @@ -524,6 +564,7 @@ ao_terraui(void) ao_current_page = 0; break; case 2: + ao_terraui_freq_start(); break; case 3: if (ao_current_page == 0) -- cgit v1.2.3 From 5e41d1e03680af9806c599aad80b9b64dd719f9b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 18:53:12 -0700 Subject: altos: Add support for STM ADC DMA-based driver for the STM analog to digital converter. Signed-off-by: Keith Packard --- src/stm/ao_adc_stm.c | 225 ++++++++++++++++++++++++++++++++++++++++++++++++ src/stm/ao_arch.h | 10 +-- src/stm/ao_arch_funcs.h | 3 + src/stm/ao_dma_stm.c | 31 +++++-- src/stm/stm32l.h | 139 ++++++++++++++++++++++++++++++ 5 files changed, 392 insertions(+), 16 deletions(-) create mode 100644 src/stm/ao_adc_stm.c (limited to 'src') diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c new file mode 100644 index 00000000..1722a9ec --- /dev/null +++ b/src/stm/ao_adc_stm.c @@ -0,0 +1,225 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include + + +volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; +volatile __data uint8_t ao_adc_head; +static uint8_t ao_adc_ready; + +#define AO_ADC_CR2_VAL ((0 << STM_ADC_CR2_SWSTART) | \ + (STM_ADC_CR2_EXTEN_DISABLE << STM_ADC_CR2_EXTEN) | \ + (0 << STM_ADC_CR2_EXTSEL) | \ + (0 << STM_ADC_CR2_JWSTART) | \ + (STM_ADC_CR2_JEXTEN_DISABLE << STM_ADC_CR2_JEXTEN) | \ + (0 << STM_ADC_CR2_JEXTSEL) | \ + (1 << STM_ADC_CR2_ALIGN) | \ + (0 << STM_ADC_CR2_EOCS) | \ + (1 << STM_ADC_CR2_DDS) | \ + (1 << STM_ADC_CR2_DMA) | \ + (STM_ADC_CR2_DELS_NONE << STM_ADC_CR2_DELS) | \ + (0 << STM_ADC_CR2_CONT) | \ + (1 << STM_ADC_CR2_ADON)) + +/* + * Callback from DMA ISR + * + * Mark time in ring, shut down DMA engine + */ +static void ao_adc_done(void) +{ + ao_adc_ring[ao_adc_head].tick = ao_time(); + ao_adc_head = ao_adc_ring_next(ao_adc_head); + ao_wakeup((void *) &ao_adc_head); + ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1)); + ao_adc_ready = 1; +} + +/* + * Start the ADC sequence using the DMA engine + */ +void +ao_adc_poll(void) +{ + if (!ao_adc_ready) + return; + ao_adc_ready = 0; + stm_adc.sr = 0; + ao_dma_set_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1), + &stm_adc.dr, + (void *) (&ao_adc_ring[ao_adc_head].tick + 1), + AO_NUM_ADC, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_16 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_16 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + ao_dma_set_isr(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1), ao_adc_done); + ao_dma_start(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1)); + + stm_adc.cr2 = AO_ADC_CR2_VAL | (1 << STM_ADC_CR2_SWSTART); +} + +/* + * Fetch a copy of the most recent ADC data + */ +void +ao_adc_get(__xdata struct ao_adc *packet) +{ + uint8_t i = ao_adc_ring_prev(ao_adc_head); + memcpy(packet, (void *) &ao_adc_ring[i], sizeof (struct ao_adc)); +} + +static void +ao_adc_dump(void) __reentrant +{ + struct ao_adc packet; + int16_t *d; + uint8_t i; + + ao_adc_get(&packet); + printf("tick: %5u", packet.tick); + d = (int16_t *) (&packet.tick + 1); + for (i = 0; i < AO_NUM_ADC; i++) + printf (" %2d: %5d", i, d[i]); + printf("\n"); +} + +__code struct ao_cmds ao_adc_cmds[] = { + { ao_adc_dump, "a\0Display current ADC values" }, + { 0, NULL }, +}; + +void +ao_adc_init(void) +{ +#ifdef AO_ADC_PIN0_PORT + stm_rcc.ahbenr |= AO_ADC_RCC_AHBENR; +#endif + +#ifdef AO_ADC_PIN0_PORT + stm_moder_set(&AO_ADC_PIN0_PORT, AO_ADC_PIN0_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN1_PORT + stm_moder_set(&AO_ADC_PIN1_PORT, AO_ADC_PIN1_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN2_PORT + stm_moder_set(&AO_ADC_PIN2_PORT, AO_ADC_PIN2_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN3_PORT + stm_moder_set(&AO_ADC_PIN3_PORT, AO_ADC_PIN3_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN4_PORT + stm_moder_set(&AO_ADC_PIN4_PORT, AO_ADC_PIN4_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN5_PORT + stm_moder_set(&AO_ADC_PIN5_PORT, AO_ADC_PIN5_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN6_PORT + stm_moder_set(&AO_ADC_PIN6_PORT, AO_ADC_PIN6_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN7_PORT + stm_moder_set(&AO_ADC_PIN7_PORT, AO_ADC_PIN7_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN8_PORT + stm_moder_set(&AO_ADC_PIN8_PORT, AO_ADC_PIN8_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN9_PORT + stm_moder_set(&AO_ADC_PIN9_PORT, AO_ADC_PIN9_PIN, STM_MODER_ANALOG); +#endif + + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_ADC1EN); + + /* Turn off ADC during configuration */ + stm_adc.cr2 = 0; + + stm_adc.cr1 = ((0 << STM_ADC_CR1_OVRIE ) | + (STM_ADC_CR1_RES_12 << STM_ADC_CR1_RES ) | + (0 << STM_ADC_CR1_AWDEN ) | + (0 << STM_ADC_CR1_JAWDEN ) | + (0 << STM_ADC_CR1_PDI ) | + (0 << STM_ADC_CR1_PDD ) | + (0 << STM_ADC_CR1_DISCNUM ) | + (0 << STM_ADC_CR1_JDISCEN ) | + (0 << STM_ADC_CR1_DISCEN ) | + (0 << STM_ADC_CR1_JAUTO ) | + (0 << STM_ADC_CR1_AWDSGL ) | + (1 << STM_ADC_CR1_SCAN ) | + (0 << STM_ADC_CR1_JEOCIE ) | + (0 << STM_ADC_CR1_AWDIE ) | + (0 << STM_ADC_CR1_EOCIE ) | + (0 << STM_ADC_CR1_AWDCH )); + + /* 4 cycle sample time for everyone */ + stm_adc.smpr1 = 0; + stm_adc.smpr2 = 0; + stm_adc.smpr3 = 0; + + stm_adc.sqr1 = ((AO_NUM_ADC - 1) << 20); + stm_adc.sqr2 = 0; + stm_adc.sqr3 = 0; + stm_adc.sqr4 = 0; + stm_adc.sqr5 = 0; +#if AO_NUM_ADC > 0 + stm_adc.sqr5 |= (AO_ADC_SQ1 << 0); +#endif +#if AO_NUM_ADC > 1 + stm_adc.sqr5 |= (AO_ADC_SQ2 << 5); +#endif +#if AO_NUM_ADC > 2 + stm_adc.sqr5 |= (AO_ADC_SQ3 << 10); +#endif +#if AO_NUM_ADC > 3 + stm_adc.sqr5 |= (AO_ADC_SQ4 << 15); +#endif +#if AO_NUM_ADC > 4 + stm_adc.sqr5 |= (AO_ADC_SQ5 << 20); +#endif +#if AO_NUM_ADC > 5 + stm_adc.sqr5 |= (AO_ADC_SQ6 << 25); +#endif +#if AO_NUM_ADC > 6 + stm_adc.sqr4 |= (AO_ADC_SQ7 << 0); +#endif +#if AO_NUM_ADC > 7 + stm_adc.sqr4 |= (AO_ADC_SQ8 << 5); +#endif +#if AO_NUM_ADC > 8 + stm_adc.sqr4 |= (AO_ADC_SQ9 << 10); +#endif + + /* Turn ADC on */ + stm_adc.cr2 = AO_ADC_CR2_VAL; + + /* Wait for ADC to be ready */ + while (!(stm_adc.sr & (1 << STM_ADC_SR_ADONS))) + ; + +#if HAS_ADC_TEMP + stm_adc.ccr = ((1 << STM_ADC_CCR_TSVREFE)); +#else + stm_adc.ccr = 0; +#endif + /* Clear any stale status bits */ + stm_adc.sr = 0; + ao_adc_ready = 1; + ao_cmd_register(&ao_adc_cmds[0]); +} diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 188b8996..ce3a22e2 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -145,13 +145,6 @@ extern const uint16_t ao_serial_number; #define ao_arch_critical(b) do { cli(); do { b } while (0); sei(); } while (0) -#define AO_ARM_NUM_ADC 12 - -struct ao_adc { - uint16_t tick; /* tick when the sample was read */ - uint16_t adc[AO_ARM_NUM_ADC]; /* samples */ -}; - /* * For now, we're running at a weird frequency */ @@ -203,5 +196,8 @@ ao_serial3_set_speed(uint8_t speed); extern uint32_t ao_radio_cal; +void +ao_adc_init(); + #endif /* _AO_ARCH_H_ */ diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index e0ecb0a5..a42fe10f 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -49,6 +49,9 @@ ao_dma_set_transfer(uint8_t index, uint16_t count, uint32_t ccr); +void +ao_dma_set_isr(uint8_t index, void (*isr)(void)); + void ao_dma_start(uint8_t index); diff --git a/src/stm/ao_dma_stm.c b/src/stm/ao_dma_stm.c index f996e7cd..785235a8 100644 --- a/src/stm/ao_dma_stm.c +++ b/src/stm/ao_dma_stm.c @@ -20,7 +20,7 @@ #define NUM_DMA 7 struct ao_dma_config { - uint32_t isr; + void (*isr)(void); }; uint8_t ao_dma_done[NUM_DMA]; @@ -37,10 +37,12 @@ ao_dma_isr(uint8_t index) { /* Ack them */ stm_dma.ifcr = isr; - isr >>= STM_DMA_ISR(index); - ao_dma_config[index].isr |= isr; - ao_dma_done[index] = 1; - ao_wakeup(&ao_dma_done[index]); + if (ao_dma_config[index].isr) + (*ao_dma_config[index].isr)(); + else { + ao_dma_done[index] = 1; + ao_wakeup(&ao_dma_done[index]); + } } void stm_dma1_channel1_isr(void) { ao_dma_isr(STM_DMA_INDEX(1)); } @@ -59,12 +61,21 @@ ao_dma_set_transfer(uint8_t index, uint32_t ccr) { ao_mutex_get(&ao_dma_mutex[index]); - if (ao_dma_active++ == 0) - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN); + ao_arch_critical( + if (ao_dma_active++ == 0) + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN); + ); stm_dma.channel[index].ccr = ccr | (1 << STM_DMA_CCR_TCIE); stm_dma.channel[index].cndtr = count; stm_dma.channel[index].cpar = peripheral; stm_dma.channel[index].cmar = memory; + ao_dma_config[index].isr = NULL; +} + +void +ao_dma_set_isr(uint8_t index, void (*isr)(void)) +{ + ao_dma_config[index].isr = isr; } void @@ -78,8 +89,10 @@ void ao_dma_done_transfer(uint8_t index) { stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN); - if (--ao_dma_active == 0) - stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMA1EN); + ao_arch_critical( + if (--ao_dma_active == 0) + stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMA1EN); + ); ao_mutex_put(&ao_dma_mutex[index]); } diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index e03556b0..b9f45513 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -1013,4 +1013,143 @@ extern struct stm_spi stm_spi1, stm_spi2, stm_spi3; #define STM_SPI_SR_TXE 1 #define STM_SPI_SR_RXNE 0 +struct stm_adc { + vuint32_t sr; + vuint32_t cr1; + vuint32_t cr2; + vuint32_t smpr1; + vuint32_t smpr2; + vuint32_t smpr3; + vuint32_t jofr1; + vuint32_t jofr2; + vuint32_t jofr3; + vuint32_t jofr4; + vuint32_t htr; + vuint32_t ltr; + vuint32_t sqr1; + vuint32_t sqr2; + vuint32_t sqr3; + vuint32_t sqr4; + vuint32_t sqr5; + vuint32_t jsqr; + vuint32_t jdr1; + vuint32_t jdr2; + vuint32_t jdr3; + vuint32_t jdr4; + vuint32_t dr; + uint8_t reserved[0x300 - 0x5c]; + vuint32_t csr; + vuint32_t ccr; +}; + +extern struct stm_adc stm_adc; + +#define STM_ADC_SR_JCNR 9 +#define STM_ADC_SR_RCNR 8 +#define STM_ADC_SR_ADONS 6 +#define STM_ADC_SR_OVR 5 +#define STM_ADC_SR_STRT 4 +#define STM_ADC_SR_JSTRT 3 +#define STM_ADC_SR_JEOC 2 +#define STM_ADC_SR_EOC 1 +#define STM_ADC_SR_AWD 0 + +#define STM_ADC_CR1_OVRIE 26 +#define STM_ADC_CR1_RES 24 +#define STM_ADC_CR1_RES_12 0 +#define STM_ADC_CR1_RES_10 1 +#define STM_ADC_CR1_RES_8 2 +#define STM_ADC_CR1_RES_6 3 +#define STM_ADC_CR1_RES_MASK 3 +#define STM_ADC_CR1_AWDEN 23 +#define STM_ADC_CR1_JAWDEN 22 +#define STM_ADC_CR1_PDI 17 +#define STM_ADC_CR1_PDD 16 +#define STM_ADC_CR1_DISCNUM 13 +#define STM_ADC_CR1_DISCNUM_1 0 +#define STM_ADC_CR1_DISCNUM_2 1 +#define STM_ADC_CR1_DISCNUM_3 2 +#define STM_ADC_CR1_DISCNUM_4 3 +#define STM_ADC_CR1_DISCNUM_5 4 +#define STM_ADC_CR1_DISCNUM_6 5 +#define STM_ADC_CR1_DISCNUM_7 6 +#define STM_ADC_CR1_DISCNUM_8 7 +#define STM_ADC_CR1_DISCNUM_MASK 7 +#define STM_ADC_CR1_JDISCEN 12 +#define STM_ADC_CR1_DISCEN 11 +#define STM_ADC_CR1_JAUTO 10 +#define STM_ADC_CR1_AWDSGL 9 +#define STM_ADC_CR1_SCAN 8 +#define STM_ADC_CR1_JEOCIE 7 +#define STM_ADC_CR1_AWDIE 6 +#define STM_ADC_CR1_EOCIE 5 +#define STM_ADC_CR1_AWDCH 0 +#define STM_ADC_CR1_AWDCH_MASK 0x1f + +#define STM_ADC_CR2_SWSTART 30 +#define STM_ADC_CR2_EXTEN 28 +#define STM_ADC_CR2_EXTEN_DISABLE 0 +#define STM_ADC_CR2_EXTEN_RISING 1 +#define STM_ADC_CR2_EXTEN_FALLING 2 +#define STM_ADC_CR2_EXTEN_BOTH 3 +#define STM_ADC_CR2_EXTEN_MASK 3 +#define STM_ADC_CR2_EXTSEL 24 +#define STM_ADC_CR2_EXTSEL_TIM9_CC2 0 +#define STM_ADC_CR2_EXTSEL_TIM9_TRGO 1 +#define STM_ADC_CR2_EXTSEL_TIM2_CC3 2 +#define STM_ADC_CR2_EXTSEL_TIM2_CC2 3 +#define STM_ADC_CR2_EXTSEL_TIM3_TRGO 4 +#define STM_ADC_CR2_EXTSEL_TIM4_CC4 5 +#define STM_ADC_CR2_EXTSEL_TIM2_TRGO 6 +#define STM_ADC_CR2_EXTSEL_TIM3_CC1 7 +#define STM_ADC_CR2_EXTSEL_TIM3_CC3 8 +#define STM_ADC_CR2_EXTSEL_TIM4_TRGO 9 +#define STM_ADC_CR2_EXTSEL_TIM6_TRGO 10 +#define STM_ADC_CR2_EXTSEL_EXTI_11 15 +#define STM_ADC_CR2_EXTSEL_MASK 15 +#define STM_ADC_CR2_JWSTART 22 +#define STM_ADC_CR2_JEXTEN 20 +#define STM_ADC_CR2_JEXTEN_DISABLE 0 +#define STM_ADC_CR2_JEXTEN_RISING 1 +#define STM_ADC_CR2_JEXTEN_FALLING 2 +#define STM_ADC_CR2_JEXTEN_BOTH 3 +#define STM_ADC_CR2_JEXTEN_MASK 3 +#define STM_ADC_CR2_JEXTSEL 16 +#define STM_ADC_CR2_JEXTSEL_TIM9_CC1 0 +#define STM_ADC_CR2_JEXTSEL_TIM9_TRGO 1 +#define STM_ADC_CR2_JEXTSEL_TIM2_TRGO 2 +#define STM_ADC_CR2_JEXTSEL_TIM2_CC1 3 +#define STM_ADC_CR2_JEXTSEL_TIM3_CC4 4 +#define STM_ADC_CR2_JEXTSEL_TIM4_TRGO 5 +#define STM_ADC_CR2_JEXTSEL_TIM4_CC1 6 +#define STM_ADC_CR2_JEXTSEL_TIM4_CC2 7 +#define STM_ADC_CR2_JEXTSEL_TIM4_CC3 8 +#define STM_ADC_CR2_JEXTSEL_TIM10_CC1 9 +#define STM_ADC_CR2_JEXTSEL_TIM7_TRGO 10 +#define STM_ADC_CR2_JEXTSEL_EXTI_15 15 +#define STM_ADC_CR2_JEXTSEL_MASK 15 +#define STM_ADC_CR2_ALIGN 11 +#define STM_ADC_CR2_EOCS 10 +#define STM_ADC_CR2_DDS 9 +#define STM_ADC_CR2_DMA 8 +#define STM_ADC_CR2_DELS 4 +#define STM_ADC_CR2_DELS_NONE 0 +#define STM_ADC_CR2_DELS_UNTIL_READ 1 +#define STM_ADC_CR2_DELS_7 2 +#define STM_ADC_CR2_DELS_15 3 +#define STM_ADC_CR2_DELS_31 4 +#define STM_ADC_CR2_DELS_63 5 +#define STM_ADC_CR2_DELS_127 6 +#define STM_ADC_CR2_DELS_255 7 +#define STM_ADC_CR2_DELS_MASK 7 +#define STM_ADC_CR2_CONT 1 +#define STM_ADC_CR2_ADON 0 + +#define STM_ADC_CCR_TSVREFE 23 +#define STM_ADC_CCR_ADCPRE 16 +#define STM_ADC_CCR_ADCPRE_HSI_1 0 +#define STM_ADC_CCR_ADCPRE_HSI_2 1 +#define STM_ADC_CCR_ADCPRE_HSI_4 2 +#define STM_ADC_CCR_ADCPRE_MASK 3 + #endif /* _STM32L_H_ */ -- cgit v1.2.3 From b5e9d14b4e3e8f29ad8a7bb9b339890be4bcfa2f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 18:54:32 -0700 Subject: altos: STM SPI is not using interrupts itself All SPI transfers are done via DMA, so the DMA interrupts suffice. Signed-off-by: Keith Packard --- src/stm/ao_spi_stm.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'src') diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index 92747d87..ecf7934f 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -229,9 +229,6 @@ ao_spi_init(void) stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN); ao_spi_channel_init(0); - - stm_nvic_set_enable(STM_ISR_SPI1_POS); - stm_nvic_set_priority(STM_ISR_SPI1_POS, 3); #endif #if HAS_SPI_2 @@ -254,8 +251,5 @@ ao_spi_init(void) stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN); ao_spi_channel_init(1); - - stm_nvic_set_enable(STM_ISR_SPI2_POS); - stm_nvic_set_priority(STM_ISR_SPI2_POS, 3); #endif } -- cgit v1.2.3 From 9b9357f48597a034211affb3f18fc6089816456d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 18:55:20 -0700 Subject: altos: Add ADC tests to stm-demo Signed-off-by: Keith Packard --- src/stm-demo/Makefile | 5 +++-- src/stm-demo/ao_demo.c | 24 +++++++++++++----------- src/stm-demo/ao_pins.h | 25 +++++++++++++++++++++++++ 3 files changed, 41 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index c1f49371..26c81a82 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -29,13 +29,14 @@ ALTOS_SRC = \ ao_lcd_font.c \ ao_mutex.c \ ao_dma_stm.c \ - ao_spi_stm.c + ao_spi_stm.c \ + ao_adc_stm.c PRODUCT=StmDemo-v0.0 PRODUCT_DEF=-DSTM_DEMO IDPRODUCT=0x000a -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -g -Os +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -g -O0 PROG=stm-demo diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 5ff2b32a..63647aac 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -51,13 +51,15 @@ void _exit () { } void _read () { } void _fstat() { } +#define AO_DMA_TEST_INDEX STM_DMA_INDEX(4) + static void ao_dma_test(void) { static char src[20] = "hello, world"; static char dst[20]; dst[0] = '\0'; - ao_dma_set_transfer(STM_DMA_INDEX(1), dst, src, 13, + ao_dma_set_transfer(AO_DMA_TEST_INDEX, dst, src, 13, (1 << STM_DMA_CCR_MEM2MEM) | (STM_DMA_CCR_PL_LOW << STM_DMA_CCR_PL) | (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | @@ -66,11 +68,12 @@ ao_dma_test(void) { (1 << STM_DMA_CCR_PINC) | (0 << STM_DMA_CCR_CIRC) | (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); - ao_dma_start(STM_DMA_INDEX(1)); - cli(); - while (!ao_dma_done[STM_DMA_INDEX(1)]) - ao_sleep(&ao_dma_done[STM_DMA_INDEX(1)]); - sei(); + ao_dma_start(AO_DMA_TEST_INDEX); + ao_arch_critical( + while (!ao_dma_done[AO_DMA_TEST_INDEX]) + ao_sleep(&ao_dma_done[AO_DMA_TEST_INDEX]); + ); + ao_dma_done_transfer(AO_DMA_TEST_INDEX); printf ("copied %s\n", dst); } @@ -128,13 +131,12 @@ main(void) // ao_lcd_font_init(); ao_spi_init(); + ao_timer_set_adc_interval(100); + + ao_adc_init(); + ao_cmd_register(&ao_demo_cmds[0]); - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN); - stm_gpio_set(&stm_gpioc, 12, 1); - stm_moder_set(&stm_gpioc, 12, STM_MODER_OUTPUT); - stm_otyper_set(&stm_gpioc, 12, STM_OTYPER_PUSH_PULL); - ao_start_scheduler(); return 0; } diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 09c88f90..fecd8cda 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -111,4 +111,29 @@ #define AO_LCD_28_ON_C 1 +#define HAS_ADC 1 + +#define AO_ADC_RING 32 + +struct ao_adc { + uint16_t tick; + int16_t idd; + int16_t temp; +}; + +#define AO_ADC_IDD 4 +#define AO_ADC_PIN0_PORT stm_gpioa +#define AO_ADC_PIN0_PIN 4 + +#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN)) +#define AO_ADC_TEMP 16 + +#define HAS_ADC_TEMP 1 + +#define AO_NUM_ADC 2 + +#define AO_ADC_SQ1 AO_ADC_IDD +#define AO_ADC_SQ2 AO_ADC_TEMP + + #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From a41628c97e90770890cce1d6f580e92c1cad1a7f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 18:55:53 -0700 Subject: altos: Add ADC support to megametrum firmware Measures all MM igniter and battery voltages. Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 3 +- src/megametrum-v0.1/ao_megametrum.c | 1 + src/megametrum-v0.1/ao_pins.h | 82 +++++++++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index fbcb4a57..71f4adf7 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -34,7 +34,8 @@ ALTOS_SRC = \ ao_freq.c \ ao_dma_stm.c \ ao_spi_stm.c \ - ao_ms5607.c + ao_ms5607.c \ + ao_adc_stm.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 0d88f4c1..02fe91fe 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -32,6 +32,7 @@ main(void) ao_dma_init(); ao_spi_init(); ao_ms5607_init(); + ao_adc_init(); ao_start_scheduler(); return 0; diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index ee4510e6..803678b2 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -69,4 +69,86 @@ #define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN) +#define HAS_ADC 1 + +#define AO_ADC_RING 32 +#define AO_ADC_NUM_SENSE 6 + +struct ao_adc { + uint16_t tick; + int16_t sense[AO_ADC_NUM_SENSE]; + int16_t v_batt; + int16_t v_pbatt; + int16_t temp; +}; + +#define AO_ADC_SENSE_A 0 +#define AO_ADC_SENSE_A_PORT stm_gpioa +#define AO_ADC_SENSE_A_PIN 0 + +#define AO_ADC_SENSE_B 1 +#define AO_ADC_SENSE_B_PORT stm_gpioa +#define AO_ADC_SENSE_B_PIN 1 + +#define AO_ADC_SENSE_C 2 +#define AO_ADC_SENSE_C_PORT stm_gpioa +#define AO_ADC_SENSE_C_PIN 2 + +#define AO_ADC_SENSE_D 3 +#define AO_ADC_SENSE_D_PORT stm_gpioa +#define AO_ADC_SENSE_D_PIN 3 + +#define AO_ADC_SENSE_E 4 +#define AO_ADC_SENSE_E_PORT stm_gpioa +#define AO_ADC_SENSE_E_PIN 4 + +#define AO_ADC_SENSE_F 22 +#define AO_ADC_SENSE_F_PORT stm_gpioe +#define AO_ADC_SENSE_F_PIN 7 + +#define AO_ADC_V_BATT 8 +#define AO_ADC_V_BATT_PORT stm_gpiob +#define AO_ADC_V_BATT_PIN 0 + +#define AO_ADC_V_PBATT 9 +#define AO_ADC_V_PBATT_PORT stm_gpiob +#define AO_ADC_V_PBATT_PIN 1 + +#define AO_ADC_TEMP 16 + +#define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN) | \ + (1 << STM_RCC_AHBENR_GPIOEEN) | \ + (1 << STM_RCC_AHBENR_GPIOBEN)) + +#define AO_NUM_ADC_PIN (AO_ADC_NUM_SENSE + 2) + +#define AO_ADC_PIN0_PORT AO_ADC_SENSE_A_PORT +#define AO_ADC_PIN0_PIN AO_ADC_SENSE_A_PIN +#define AO_ADC_PIN1_PORT AO_ADC_SENSE_B_PORT +#define AO_ADC_PIN1_PIN AO_ADC_SENSE_B_PIN +#define AO_ADC_PIN2_PORT AO_ADC_SENSE_C_PORT +#define AO_ADC_PIN2_PIN AO_ADC_SENSE_C_PIN +#define AO_ADC_PIN3_PORT AO_ADC_SENSE_D_PORT +#define AO_ADC_PIN3_PIN AO_ADC_SENSE_D_PIN +#define AO_ADC_PIN4_PORT AO_ADC_SENSE_E_PORT +#define AO_ADC_PIN4_PIN AO_ADC_SENSE_E_PIN +#define AO_ADC_PIN5_PORT AO_ADC_SENSE_F_PORT +#define AO_ADC_PIN5_PIN AO_ADC_SENSE_F_PIN +#define AO_ADC_PIN6_PORT AO_ADC_V_BATT_PORT +#define AO_ADC_PIN6_PIN AO_ADC_V_BATT_PIN +#define AO_ADC_PIN7_PORT AO_ADC_V_PBATT_PORT +#define AO_ADC_PIN7_PIN AO_ADC_V_PBATT_PIN + +#define AO_NUM_ADC (AO_ADC_NUM_SENSE + 3) + +#define AO_ADC_SQ1 AO_ADC_SENSE_A +#define AO_ADC_SQ2 AO_ADC_SENSE_B +#define AO_ADC_SQ3 AO_ADC_SENSE_C +#define AO_ADC_SQ4 AO_ADC_SENSE_D +#define AO_ADC_SQ5 AO_ADC_SENSE_E +#define AO_ADC_SQ6 AO_ADC_SENSE_F +#define AO_ADC_SQ7 AO_ADC_V_BATT +#define AO_ADC_SQ8 AO_ADC_V_PBATT +#define AO_ADC_SQ9 AO_ADC_TEMP + #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 0bce68e6a0abc19f49c573331164d13643c9bee5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 20:31:58 -0700 Subject: altos: Add STM temperature sensor calibration data Each stm32l has two-point factory temperature calibration data. Provide access to that for displaying temperature data. Signed-off-by: Keith Packard --- src/stm/registers.ld | 5 ++++- src/stm/stm32l.h | 12 ++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/registers.ld b/src/stm/registers.ld index 51921444..fd61e486 100644 --- a/src/stm/registers.ld +++ b/src/stm/registers.ld @@ -44,4 +44,7 @@ stm_tim4 = 0x40000800; stm_tim3 = 0x40000400; stm_tim2 = 0x40000000; -stm_nvic = 0xe000e100; \ No newline at end of file +stm_nvic = 0xe000e100; + +/* calibration data in system memory */ +stm_temp_cal = 0x1ff80078; diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index b9f45513..338bc471 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -1152,4 +1152,16 @@ extern struct stm_adc stm_adc; #define STM_ADC_CCR_ADCPRE_HSI_4 2 #define STM_ADC_CCR_ADCPRE_MASK 3 +struct stm_temp_cal { + uint16_t vref; + uint16_t ts_cal_cold; + uint16_t reserved; + uint16_t ts_cal_hot; +}; + +extern struct stm_temp_cal stm_temp_cal; + +#define stm_temp_cal_cold 25 +#define stm_temp_cal_hot 110 + #endif /* _STM32L_H_ */ -- cgit v1.2.3 From 98aa481741b8fbc617545beda3d295b53de90716 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 20:33:27 -0700 Subject: altos: Use 384 cycle ADC sample time This is plenty fast, and provides nice stable readings. Signed-off-by: Keith Packard --- src/stm/ao_adc_stm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index 1722a9ec..d758e629 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -28,11 +28,11 @@ static uint8_t ao_adc_ready; (0 << STM_ADC_CR2_JWSTART) | \ (STM_ADC_CR2_JEXTEN_DISABLE << STM_ADC_CR2_JEXTEN) | \ (0 << STM_ADC_CR2_JEXTSEL) | \ - (1 << STM_ADC_CR2_ALIGN) | \ + (0 << STM_ADC_CR2_ALIGN) | \ (0 << STM_ADC_CR2_EOCS) | \ (1 << STM_ADC_CR2_DDS) | \ (1 << STM_ADC_CR2_DMA) | \ - (STM_ADC_CR2_DELS_NONE << STM_ADC_CR2_DELS) | \ + (STM_ADC_CR2_DELS_UNTIL_READ << STM_ADC_CR2_DELS) | \ (0 << STM_ADC_CR2_CONT) | \ (1 << STM_ADC_CR2_ADON)) @@ -168,10 +168,10 @@ ao_adc_init(void) (0 << STM_ADC_CR1_EOCIE ) | (0 << STM_ADC_CR1_AWDCH )); - /* 4 cycle sample time for everyone */ - stm_adc.smpr1 = 0; - stm_adc.smpr2 = 0; - stm_adc.smpr3 = 0; + /* 384 cycle sample time for everyone */ + stm_adc.smpr1 = 0x3ffff; + stm_adc.smpr2 = 0x3fffffff; + stm_adc.smpr3 = 0x3fffffff; stm_adc.sqr1 = ((AO_NUM_ADC - 1) << 20); stm_adc.sqr2 = 0; -- cgit v1.2.3 From f7cfbbce2b94b5ac0094a0e34e1766fe1ceb12c8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 7 Apr 2012 20:35:17 -0700 Subject: altos: Show temperature in stm-demo Use the ADC to show current temperature Signed-off-by: Keith Packard --- src/stm-demo/ao_demo.c | 19 +++++++++++++++++++ src/stm-demo/ao_pins.h | 5 ++++- 2 files changed, 23 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 63647aac..ea4dadfa 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -111,10 +111,29 @@ ao_spi_read(void) { } } + + +static void +ao_temp (void) +{ + struct ao_adc adc; + int temp; + + ao_adc_get(&adc); + + /* + * r = (110 - 25) / (ts_cal_hot - ts_cal_cold) + * 25 + (110 - 25) * (temp - ts_cal_cold) / (ts_cal_hot - ts_cal_cold) + */ + temp = 25 + (110 - 25) * (adc.temp - stm_temp_cal.ts_cal_cold) / (stm_temp_cal.ts_cal_hot - stm_temp_cal.ts_cal_cold); + printf ("temp: %d\n", temp); +} + __code struct ao_cmds ao_demo_cmds[] = { { ao_dma_test, "D\0DMA test" }, { ao_spi_write, "W\0SPI write" }, { ao_spi_read, "R\0SPI read" }, + { ao_temp, "t\0Show temp" }, { 0, NULL } }; diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index fecd8cda..42f4123d 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -119,6 +119,7 @@ struct ao_adc { uint16_t tick; int16_t idd; int16_t temp; + int16_t vref; }; #define AO_ADC_IDD 4 @@ -127,13 +128,15 @@ struct ao_adc { #define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN)) #define AO_ADC_TEMP 16 +#define AO_ADC_VREF 17 #define HAS_ADC_TEMP 1 -#define AO_NUM_ADC 2 +#define AO_NUM_ADC 3 #define AO_ADC_SQ1 AO_ADC_IDD #define AO_ADC_SQ2 AO_ADC_TEMP +#define AO_ADC_SQ3 AO_ADC_VREF #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 059f09dbca4703c25b42389b54c6510331c39485 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 00:05:18 -0700 Subject: altos: Allow STM DMA channels to be reserved for one use This allows a single user of a DMA channel to reserve it for use without needing to lock the mutex; this is required for DMA from the ADC to work on megametrum as it wants to start DMA from an interrupt handler, which cannot block on a mutex. Signed-off-by: Keith Packard --- src/stm/ao_adc_stm.c | 2 ++ src/stm/ao_arch_funcs.h | 3 +++ src/stm/ao_dma_stm.c | 23 +++++++++++++++++++++-- 3 files changed, 26 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index d758e629..729551c4 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -221,5 +221,7 @@ ao_adc_init(void) /* Clear any stale status bits */ stm_adc.sr = 0; ao_adc_ready = 1; + + ao_dma_alloc(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1)); ao_cmd_register(&ao_adc_cmds[0]); } diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index a42fe10f..7dc576d1 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -61,6 +61,9 @@ ao_dma_done_transfer(uint8_t index); void ao_dma_abort(uint8_t index); +void +ao_dma_alloc(uint8_t index); + void ao_dma_init(void); diff --git a/src/stm/ao_dma_stm.c b/src/stm/ao_dma_stm.c index 785235a8..21390748 100644 --- a/src/stm/ao_dma_stm.c +++ b/src/stm/ao_dma_stm.c @@ -26,6 +26,7 @@ struct ao_dma_config { uint8_t ao_dma_done[NUM_DMA]; static struct ao_dma_config ao_dma_config[NUM_DMA]; +static uint8_t ao_dma_allocated[NUM_DMA]; static uint8_t ao_dma_mutex[NUM_DMA]; static uint8_t ao_dma_active; @@ -60,7 +61,12 @@ ao_dma_set_transfer(uint8_t index, uint16_t count, uint32_t ccr) { - ao_mutex_get(&ao_dma_mutex[index]); + if (ao_dma_allocated[index]) { + if (ao_dma_mutex[index]) + ao_panic(AO_PANIC_DMA); + ao_dma_mutex[index] = 1; + } else + ao_mutex_get(&ao_dma_mutex[index]); ao_arch_critical( if (ao_dma_active++ == 0) stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_DMA1EN); @@ -93,7 +99,10 @@ ao_dma_done_transfer(uint8_t index) if (--ao_dma_active == 0) stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_DMA1EN); ); - ao_mutex_put(&ao_dma_mutex[index]); + if (ao_dma_allocated[index]) + ao_dma_mutex[index] = 0; + else + ao_mutex_put(&ao_dma_mutex[index]); } void @@ -102,6 +111,14 @@ ao_dma_abort(uint8_t index) stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN); } +void +ao_dma_alloc(uint8_t index) +{ + if (ao_dma_allocated[index]) + ao_panic(AO_PANIC_DMA); + ao_dma_allocated[index] = 1; +} + void ao_dma_init(void) { @@ -110,6 +127,8 @@ ao_dma_init(void) for (index = 0; index < STM_NUM_DMA; index++) { stm_nvic_set_enable(STM_ISR_DMA1_CHANNEL1_POS + index); stm_nvic_set_priority(STM_ISR_DMA1_CHANNEL1_POS + index, 4); + ao_dma_allocated[index] = 0; + ao_dma_mutex[index] = 0; } } -- cgit v1.2.3 From e027247a9ef82746c26bcb8d0a851a0fa06511de Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 00:06:35 -0700 Subject: altos: Slow STM SPI down a bit so the MS5607 returns values It's still not working right, but at least it returns something other than all zeros... Signed-off-by: Keith Packard --- src/stm/ao_spi_stm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index ecf7934f..d3e1ca4b 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -167,9 +167,9 @@ ao_spi_get(uint8_t spi_index) (0 << STM_SPI_CR1_RXONLY) | (1 << STM_SPI_CR1_SSM) | /* Software SS handling */ (1 << STM_SPI_CR1_SSI) | /* ... */ - (0 << STM_SPI_CR1_LSBFIRST) | /* Little endian */ + (0 << STM_SPI_CR1_LSBFIRST) | /* Big endian */ (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */ - (STM_SPI_CR1_BR_PCLK_4 << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ + (STM_SPI_CR1_BR_PCLK_16 << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ (1 << STM_SPI_CR1_MSTR) | (0 << STM_SPI_CR1_CPOL) | /* Format 0 */ (0 << STM_SPI_CR1_CPHA)); -- cgit v1.2.3 From e9362841b1075a2ae59eecc73137b20e700567a8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 00:08:20 -0700 Subject: altos: add STM I2C driver. Not well tested yet... Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 20 +++++ src/stm/ao_i2c_stm.c | 230 ++++++++++++++++++++++++++++++++++++++++++++++++ src/stm/stm32l.h | 76 ++++++++++++++++ 3 files changed, 326 insertions(+) create mode 100644 src/stm/ao_i2c_stm.c (limited to 'src') diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 7dc576d1..052abb65 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -67,4 +67,24 @@ ao_dma_alloc(uint8_t index); void ao_dma_init(void); +/* ao_i2c_stm.c */ + +void +ao_i2c_get(uint8_t i2c_index); + +uint8_t +ao_i2c_start(uint8_t i2c_index, uint16_t address); + +void +ao_i2c_put(uint8_t i2c_index); + +void +ao_i2c_send(void *block, uint16_t len, uint8_t i2c_index); + +void +ao_i2c_recv(void *block, uint16_t len, uint8_t i2c_index); + +void +ao_i2c_init(void); + #endif /* _AO_ARCH_FUNCS_H_ */ diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c new file mode 100644 index 00000000..1a0280d3 --- /dev/null +++ b/src/stm/ao_i2c_stm.c @@ -0,0 +1,230 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include + +struct ao_i2c_stm_info { + uint8_t tx_dma_index; + uint8_t rx_dma_index; + struct stm_i2c *stm_i2c; +}; + +#define I2C_IDLE 0 +#define I2C_RUNNING 1 +#define I2C_ERROR 2 + +static uint8_t ao_i2c_state[STM_NUM_I2C]; +static uint16_t ao_i2c_addr[STM_NUM_I2C]; +uint8_t ao_i2c_mutex[STM_NUM_I2C]; + +#define AO_STM_I2C_CR1 ((0 << STM_I2C_CR1_SWRST) | \ + (0 << STM_I2C_CR1_ALERT) | \ + (0 << STM_I2C_CR1_PEC) | \ + (0 << STM_I2C_CR1_POS) | \ + (0 << STM_I2C_CR1_ACK) | \ + (0 << STM_I2C_CR1_STOP) | \ + (0 << STM_I2C_CR1_START) | \ + (0 << STM_I2C_CR1_NOSTRETCH) | \ + (0 << STM_I2C_CR1_ENGC) | \ + (0 << STM_I2C_CR1_ENPEC) | \ + (0 << STM_I2C_CR1_ENARP) | \ + (0 << STM_I2C_CR1_SMBTYPE) | \ + (0 << STM_I2C_CR1_SMBUS) | \ + (1 << STM_I2C_CR1_PE)) + +#define AO_STM_I2C_CR2 ((0 << STM_I2C_CR2_LAST) | \ + (1 << STM_I2C_CR2_DMAEN) | \ + (0 << STM_I2C_CR2_ITBUFEN) | \ + (0 << STM_I2C_CR2_ITEVTEN) | \ + (0 << STM_I2C_CR2_ITERREN) | \ + (STM_I2C_CR2_FREQ_16_MHZ << STM_I2C_CR2_FREQ)) + +static const struct ao_i2c_stm_info ao_i2c_stm_info[STM_NUM_I2C] = { + { + .tx_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_I2C1_TX), + .rx_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_I2C1_RX), + .stm_i2c = &stm_i2c1 + }, + { + .tx_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_I2C2_TX), + .rx_dma_index = STM_DMA_INDEX(STM_DMA_CHANNEL_I2C2_RX), + .stm_i2c = &stm_i2c2 + }, +}; + +static void +ao_i2c_ev_isr(uint8_t index) +{ + struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + uint32_t sr1; + + sr1 = stm_i2c->sr1; + if (sr1 & (1 << STM_I2C_SR1_SB)) + stm_i2c->dr = ao_i2c_addr[index]; + if (sr1 & (1 << STM_I2C_SR1_ADDR)) { + (void) stm_i2c->sr2; + ao_i2c_state[index] = I2C_RUNNING; + ao_wakeup(&ao_i2c_state[index]); + } +} + +void stm_i2c1_ev_isr(void) { ao_i2c_ev_isr(0); } +void stm_i2c2_ev_isr(void) { ao_i2c_ev_isr(1); } + +static void +ao_i2c_er_isr(uint8_t index) +{ + struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + uint32_t sr1; + + sr1 = stm_i2c->sr1; + if (sr1 & (1 << STM_I2C_SR1_AF)) { + ao_i2c_state[index] = I2C_ERROR; + stm_i2c->sr1 = sr1 & ~(1 << STM_I2C_SR1_AF); + ao_wakeup(&ao_i2c_state[index]); + } +} + +void stm_i2c1_er_isr(void) { ao_i2c_er_isr(0); } +void stm_i2c2_er_isr(void) { ao_i2c_er_isr(1); } + +void +ao_i2c_get(uint8_t index) +{ + struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + ao_mutex_get(&ao_i2c_mutex[index]); + + stm_i2c->sr1 = 0; + stm_i2c->sr2 = 0; +} + +void +ao_i2c_put(uint8_t index) +{ + ao_mutex_put(&ao_i2c_mutex[index]); +} + +uint8_t +ao_i2c_start(uint8_t index, uint16_t addr) +{ + struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + + ao_i2c_state[index] = I2C_IDLE; + ao_i2c_addr[index] = addr; + stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN); + stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START); + ao_arch_critical( + while (ao_i2c_state[index] == I2C_IDLE) + ao_sleep(&ao_i2c_state[index]); + ); + return ao_i2c_state[index] == I2C_RUNNING; +} + +void +ao_i2c_send(void *block, uint16_t len, uint8_t index) +{ + struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + uint8_t tx_dma_index = ao_i2c_stm_info[index].tx_dma_index; + + ao_dma_set_transfer(tx_dma_index, + &stm_i2c->dr, + block, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); + + ao_dma_start(tx_dma_index); + ao_arch_critical( + while (!ao_dma_done[tx_dma_index]) + ao_sleep(&ao_dma_done[tx_dma_index]); + ); + ao_dma_done_transfer(tx_dma_index); +} + +void +ao_i2c_channel_init(uint8_t index) +{ + struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + + /* Turn I2C off while configuring */ + stm_i2c->cr1 = 0; + stm_i2c->cr2 = AO_STM_I2C_CR2; + + (void) stm_i2c->sr1; + (void) stm_i2c->sr2; + (void) stm_i2c->dr; + + stm_i2c->sr1 = 0; + stm_i2c->sr2 = 0; + + stm_i2c->ccr = ((1 << STM_I2C_CCR_FS) | + (0 << STM_I2C_CCR_DUTY) | + (20 << STM_I2C_CCR_CCR)); + + stm_i2c->cr1 = AO_STM_I2C_CR1; +} + +void +ao_i2c_init(void) +{ + /* All of the I2C configurations are on port B */ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); +#if HAS_I2C_1 +# if I2C_1_PB6_PB7 + stm_afr_set(&stm_gpiob, 6, STM_AFR_AF4); + stm_afr_set(&stm_gpiob, 7, STM_AFR_AF4); +# else +# if I2C_1_PB8_PB9 + stm_afr_set(&stm_gpiob, 8, STM_AFR_AF4); + stm_afr_set(&stm_gpiob, 9, STM_AFR_AF4); +# else +# error "No I2C_1 port configuration specified" +# endif +# endif + + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_I2C1EN); + ao_i2c_channel_init(0); + + stm_nvic_set_enable(STM_ISR_I2C1_EV_POS); + stm_nvic_set_priority(STM_ISR_I2C1_EV_POS, 3); + stm_nvic_set_enable(STM_ISR_I2C1_ER_POS); + stm_nvic_set_priority(STM_ISR_I2C1_ER_POS, 3); +#endif + +#if HAS_I2C_2 +# if I2C_2_PB10_PB11 + stm_afr_set(&stm_gpiob, 10, STM_AFR_AF4); + stm_afr_set(&stm_gpiob, 11, STM_AFR_AF4); +# else +# error "No I2C_2 port configuration specified" +# endif + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_I2C2EN); + ao_i2c_channel_init(1); + + stm_nvic_set_enable(STM_ISR_I2C2_EV_POS); + stm_nvic_set_priority(STM_ISR_I2C2_EV_POS, 3); + stm_nvic_set_enable(STM_ISR_I2C2_ER_POS); + stm_nvic_set_priority(STM_ISR_I2C2_ER_POS, 3); +#endif +} + diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 338bc471..54d95c9a 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -1164,4 +1164,80 @@ extern struct stm_temp_cal stm_temp_cal; #define stm_temp_cal_cold 25 #define stm_temp_cal_hot 110 +#define STM_NUM_I2C 2 + +#define STM_I2C_INDEX(channel) ((channel) - 1) + +struct stm_i2c { + vuint32_t cr1; + vuint32_t cr2; + vuint32_t oar1; + vuint32_t oar2; + vuint32_t dr; + vuint32_t sr1; + vuint32_t sr2; + vuint32_t ccr; + vuint32_t trise; +}; + +extern struct stm_i2c stm_i2c1, stm_i2c2; + +#define STM_I2C_CR1_SWRST 15 +#define STM_I2C_CR1_ALERT 13 +#define STM_I2C_CR1_PEC 12 +#define STM_I2C_CR1_POS 11 +#define STM_I2C_CR1_ACK 10 +#define STM_I2C_CR1_STOP 9 +#define STM_I2C_CR1_START 8 +#define STM_I2C_CR1_NOSTRETCH 7 +#define STM_I2C_CR1_ENGC 6 +#define STM_I2C_CR1_ENPEC 5 +#define STM_I2C_CR1_ENARP 4 +#define STM_I2C_CR1_SMBTYPE 3 +#define STM_I2C_CR1_SMBUS 1 +#define STM_I2C_CR1_PE 0 + +#define STM_I2C_CR2_LAST 12 +#define STM_I2C_CR2_DMAEN 11 +#define STM_I2C_CR2_ITBUFEN 10 +#define STM_I2C_CR2_ITEVTEN 9 +#define STM_I2C_CR2_ITERREN 8 +#define STM_I2C_CR2_FREQ 0 +#define STM_I2C_CR2_FREQ_2_MHZ 2 +#define STM_I2C_CR2_FREQ_4_MHZ 4 +#define STM_I2C_CR2_FREQ_8_MHZ 8 +#define STM_I2C_CR2_FREQ_16_MHZ 16 +#define STM_I2C_CR2_FREQ_32_MHZ 32 +#define STM_I2C_CR2_FREQ_MASK 0x3f; + +#define STM_I2C_SR1_SMBALERT 15 +#define STM_I2C_SR1_TIMEOUT 14 +#define STM_I2C_SR1_PECERR 12 +#define STM_I2C_SR1_OVR 11 +#define STM_I2C_SR1_AF 10 +#define STM_I2C_SR1_ARLO 9 +#define STM_I2C_SR1_BERR 8 +#define STM_I2C_SR1_TXE 7 +#define STM_I2C_SR1_RXNE 6 +#define STM_I2C_SR1_STOPF 4 +#define STM_I2C_SR1_ADD10 3 +#define STM_I2C_SR1_BTF 2 +#define STM_I2C_SR1_ADDR 1 +#define STM_I2C_SR1_SB 0 + +#define STM_I2C_SR2_PEC 8 +#define STM_I2C_SR2_PEC_MASK 0xff00 +#define STM_I2C_SR2_DUALF 7 +#define STM_I2C_SR2_SMBHOST 6 +#define STM_I2C_SR2_SMBDEFAULT 5 +#define STM_I2C_SR2_GENCALL 4 +#define STM_I2C_SR2_TRA 2 +#define STM_I2C_SR2_BUSY 1 +#define STM_I2C_SR2_MSL 0 + +#define STM_I2C_CCR_FS 15 +#define STM_I2C_CCR_DUTY 14 +#define STM_I2C_CCR_CCR 0 +#define STM_I2C_CCR_MASK 0x7ff + #endif /* _STM32L_H_ */ -- cgit v1.2.3 From 597c3df668ccf656d8c014f665c154a03166577c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 00:09:18 -0700 Subject: altos: Make ms5607 driver do something It's loading prom values and converting sensor data, but it's getting the wrong answer at present. Signed-off-by: Keith Packard --- src/drivers/ao_ms5607.c | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 970fea1e..51922dc7 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -55,6 +55,7 @@ ao_ms5607_reset(void) { cmd = AO_MS5607_RESET; ao_ms5607_start(); ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); + ao_delay(AO_MS_TO_TICKS(100)); ao_ms5607_stop(); } @@ -63,12 +64,15 @@ ao_ms5607_prom_read(uint8_t addr) { uint8_t cmd = AO_MS5607_PROM_READ(addr); uint8_t d[2]; + uint16_t v; ao_ms5607_start(); ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); ao_spi_recv(d, 2, AO_MS5607_SPI_INDEX); ao_ms5607_stop(); - return ((uint16_t) d[0] << 8) | (uint16_t) d[1]; + v = ((uint16_t) d[0] << 8) | (uint16_t) d[1]; +// printf ("ms5607_prom_read recv %02x %02x -> %04x\n", d[0], d[1], v); + return v; } static void @@ -80,6 +84,14 @@ ao_ms5607_init_chip(void) { for (addr = 0; addr <= 7; addr++) prom[addr] = ao_ms5607_prom_read(addr); + printf ("reserved: %d\n", ms5607_prom.reserved); + printf ("sens: %d\n", ms5607_prom.sens); + printf ("off: %d\n", ms5607_prom.off); + printf ("tcs: %d\n", ms5607_prom.tcs); + printf ("tco: %d\n", ms5607_prom.tco); + printf ("tref: %d\n", ms5607_prom.tref); + printf ("tempsens: %d\n", ms5607_prom.tempsens); + printf ("crc: %d\n", ms5607_prom.crc); } static uint32_t @@ -91,7 +103,7 @@ ao_ms5607_convert(uint8_t cmd) { ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); ao_ms5607_stop(); - ao_delay(AO_MS_TO_TICKS(200)); + ao_delay(AO_MS_TO_TICKS(10)); ao_ms5607_start(); read = AO_MS5607_ADC_READ; @@ -106,28 +118,19 @@ static void ao_ms5607_dump(void) { uint8_t addr; - uint32_t d1, d2; + uint32_t D1, D2; int32_t dT; int32_t TEMP; int64_t OFF; int64_t SENS; int32_t P; - ao_ms5607_init_chip(); - printf ("reserved: %d\n", ms5607_prom.reserved); - printf ("sens: %d\n", ms5607_prom.sens); - printf ("off: %d\n", ms5607_prom.off); - printf ("tcs: %d\n", ms5607_prom.tcs); - printf ("tco: %d\n", ms5607_prom.tco); - printf ("tref: %d\n", ms5607_prom.tref); - printf ("tempsens: %d\n", ms5607_prom.tempsens); - printf ("crc: %d\n", ms5607_prom.crc); - d1 = ao_ms5607_convert(AO_MS5607_CONVERT_D1_4096); - printf ("Conversion D1: %d\n", d1); - d2 = ao_ms5607_convert(AO_MS5607_CONVERT_D2_4096); - printf ("Conversion D2: %d\n", d2); + D2 = ao_ms5607_convert(AO_MS5607_CONVERT_D2_4096); + printf ("Conversion D2: %d\n", D2); + D1 = ao_ms5607_convert(AO_MS5607_CONVERT_D1_4096); + printf ("Conversion D1: %d\n", D1); - dT = d2 - ((int32_t) ms5607_prom.tref << 8); + dT = D2 - ((int32_t) ms5607_prom.tref << 8); TEMP = 2000 + (((int64_t) dT * ms5607_prom.tempsens) >> 23); @@ -142,13 +145,14 @@ ao_ms5607_dump(void) int64_t SENS2 = 2 * (int64_t) TEMPM * (int64_t) TEMPM; } - P = ((((int64_t) d1 * SENS) >> 21) - OFF) >> 15; + P = ((((int64_t) D1 * SENS) >> 21) - OFF) >> 15; - printf ("Temperature: %d", TEMP); + printf ("Temperature: %d\n", TEMP); printf ("Pressure %d\n", P); } __code struct ao_cmds ao_ms5607_cmds[] = { + { ao_ms5607_init_chip, "i\0Init MS5607" }, { ao_ms5607_dump, "p\0Display MS5607 data" }, { 0, NULL }, }; -- cgit v1.2.3 From 0a198dfcd1b0defe194feaf301f4586e5573d6e9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 00:10:01 -0700 Subject: altos: ARM -O0 flag appears to generate buggy code Use -Os always, which is annoying... Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 71f4adf7..297d136a 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -8,6 +8,7 @@ include ../stm/Makefile.defs INC = \ ao.h \ ao_arch.h \ + ao_arch_funcs.h \ ao_pins.h \ altitude.h \ ao_kalman.h \ @@ -41,7 +42,7 @@ PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM IDPRODUCT=0x000a -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -O0 -g +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -Os -g PROG=megametrum-v0.1-$(VERSION).elf -- cgit v1.2.3 From 67044cca5b463772491d0712d0ce07a8f897a476 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 00:10:43 -0700 Subject: altos: Test I2C code on discovery board. Signed-off-by: Keith Packard --- src/stm-demo/Makefile | 4 +++- src/stm-demo/ao_demo.c | 21 +++++++++++++++++++++ src/stm-demo/ao_pins.h | 6 ++++++ 3 files changed, 30 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 26c81a82..2f156ea4 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -8,6 +8,7 @@ include ../stm/Makefile.defs INC = \ ao.h \ ao_arch.h \ + ao_arch_funcs.h \ ao_pins.h \ ao_product.h @@ -30,7 +31,8 @@ ALTOS_SRC = \ ao_mutex.c \ ao_dma_stm.c \ ao_spi_stm.c \ - ao_adc_stm.c + ao_adc_stm.c \ + ao_i2c_stm.c PRODUCT=StmDemo-v0.0 PRODUCT_DEF=-DSTM_DEMO diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index ea4dadfa..879f7f75 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -111,7 +111,26 @@ ao_spi_read(void) { } } +static void +ao_i2c_write(void) { + unsigned char data[] = { 0x55, 0xaa, 0xff, 0x00 }; + int i; + for (i = 0; i < 10; i++) { + ao_i2c_get(0); + if (ao_i2c_start(0, 0x55)) + ao_i2c_send(data, 4, 0); + else { + printf ("i2c start failed\n"); + ao_i2c_put(0); + break; + } + ao_i2c_put(0); + printf("."); + flush(); + ao_delay(100); + } +} static void ao_temp (void) @@ -133,6 +152,7 @@ __code struct ao_cmds ao_demo_cmds[] = { { ao_dma_test, "D\0DMA test" }, { ao_spi_write, "W\0SPI write" }, { ao_spi_read, "R\0SPI read" }, + { ao_i2c_write, "i\0I2C write" }, { ao_temp, "t\0Show temp" }, { 0, NULL } }; @@ -149,6 +169,7 @@ main(void) // ao_lcd_stm_init(); // ao_lcd_font_init(); ao_spi_init(); + ao_i2c_init(); ao_timer_set_adc_interval(100); diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 42f4123d..9fd1175d 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -138,5 +138,11 @@ struct ao_adc { #define AO_ADC_SQ2 AO_ADC_TEMP #define AO_ADC_SQ3 AO_ADC_VREF +#define HAS_I2C_1 1 +#define I2C_1_PB6_PB7 0 +#define I2C_1_PB8_PB9 1 + +#define HAS_I2C_2 0 +#define I2C_2_PB10_PB11 0 #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 1dcfbb05531767e67df45c2799a2fe533834fb71 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 20:28:19 -0700 Subject: altos: Add beeper driver to STM arch Drives the MegaMetrum beeper Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 6 +- src/megametrum-v0.1/ao_megametrum.c | 13 +++ src/stm/ao_beep_stm.c | 130 ++++++++++++++++++++++ src/stm/stm32l.h | 215 ++++++++++++++++++++++++++++++++++++ 4 files changed, 362 insertions(+), 2 deletions(-) create mode 100644 src/stm/ao_beep_stm.c (limited to 'src') diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 297d136a..5b20a8a5 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -12,7 +12,8 @@ INC = \ ao_pins.h \ altitude.h \ ao_kalman.h \ - ao_product.h + ao_product.h \ + ao_ms5607.h # # Common AltOS sources @@ -36,7 +37,8 @@ ALTOS_SRC = \ ao_dma_stm.c \ ao_spi_stm.c \ ao_ms5607.c \ - ao_adc_stm.c + ao_adc_stm.c \ + ao_beep_stm.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 02fe91fe..4d9343e1 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -17,6 +17,17 @@ #include "ao.h" +void +beep(void) +{ + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(2000)); +} + +const struct ao_cmds ao_mm_cmds[] = { + { beep, "b\0Beep" }, + { 0, NULL }, +}; + int main(void) { @@ -32,8 +43,10 @@ main(void) ao_dma_init(); ao_spi_init(); ao_ms5607_init(); + ao_beep_init(); ao_adc_init(); + ao_cmd_register(&ao_mm_cmds[0]); ao_start_scheduler(); return 0; } diff --git a/src/stm/ao_beep_stm.c b/src/stm/ao_beep_stm.c new file mode 100644 index 00000000..8c0c0ee3 --- /dev/null +++ b/src/stm/ao_beep_stm.c @@ -0,0 +1,130 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +void +ao_beep(uint8_t beep) +{ + if (beep == 0) { + stm_tim3.cr1 = 0; + stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_TIM3EN); + } else { + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM3EN); + + stm_tim3.cr1 = ((STM_TIM234_CR1_CKD_1 << STM_TIM234_CR1_CKD) | + (0 << STM_TIM234_CR1_ARPE) | + (STM_TIM234_CR1_CMS_EDGE << STM_TIM234_CR1_CMS) | + (0 << STM_TIM234_CR1_DIR) | + (0 << STM_TIM234_CR1_OPM) | + (0 << STM_TIM234_CR1_URS) | + (0 << STM_TIM234_CR1_UDIS) | + (0 << STM_TIM234_CR1_CEN)); + + stm_tim3.cr2 = ((0 << STM_TIM234_CR2_TI1S) | + (STM_TIM234_CR2_MMS_RESET << STM_TIM234_CR2_MMS) | + (0 << STM_TIM234_CR2_CCDS)); + + /* Set prescaler to match cc1111 clocks + */ + stm_tim3.psc = STM_APB1 / 750000; + + /* 1. Select the counter clock (internal, external, prescaler). + * + * Setting SMCR to zero means use the internal clock + */ + + stm_tim3.smcr = 0; + + /* 2. Write the desired data in the TIMx_ARR and TIMx_CCRx registers. */ + stm_tim3.arr = beep; + stm_tim3.ccr1 = beep; + + /* 3. Set the CCxIE and/or CCxDE bits if an interrupt and/or a + * DMA request is to be generated. + */ + /* don't want this */ + + /* 4. Select the output mode. For example, you must write + * OCxM=011, OCxPE=0, CCxP=0 and CCxE=1 to toggle OCx output + * pin when CNT matches CCRx, CCRx preload is not used, OCx + * is enabled and active high. + */ + + stm_tim3.ccmr1 = ((0 << STM_TIM234_CCMR1_OC2CE) | + (STM_TIM234_CCMR1_OC2M_FROZEN << STM_TIM234_CCMR1_OC2M) | + (0 << STM_TIM234_CCMR1_OC2PE) | + (0 << STM_TIM234_CCMR1_OC2FE) | + (STM_TIM234_CCMR1_CC2S_OUTPUT << STM_TIM234_CCMR1_CC2S) | + + (0 << STM_TIM234_CCMR1_OC1CE) | + (STM_TIM234_CCMR1_OC1M_TOGGLE << STM_TIM234_CCMR1_OC1M) | + (0 << STM_TIM234_CCMR1_OC1PE) | + (0 << STM_TIM234_CCMR1_OC1FE) | + (STM_TIM234_CCMR1_CC1S_OUTPUT << STM_TIM234_CCMR1_CC1S)); + + + stm_tim3.ccer = ((0 << STM_TIM234_CCER_CC4NP) | + (0 << STM_TIM234_CCER_CC4P) | + (0 << STM_TIM234_CCER_CC4E) | + (0 << STM_TIM234_CCER_CC3NP) | + (0 << STM_TIM234_CCER_CC3P) | + (0 << STM_TIM234_CCER_CC3E) | + (0 << STM_TIM234_CCER_CC2NP) | + (0 << STM_TIM234_CCER_CC2P) | + (0 << STM_TIM234_CCER_CC2E) | + (0 << STM_TIM234_CCER_CC1NP) | + (0 << STM_TIM234_CCER_CC1P) | + (1 << STM_TIM234_CCER_CC1E)); + + + /* 5. Enable the counter by setting the CEN bit in the TIMx_CR1 register. */ + + stm_tim3.cr1 = ((STM_TIM234_CR1_CKD_1 << STM_TIM234_CR1_CKD) | + (0 << STM_TIM234_CR1_ARPE) | + (STM_TIM234_CR1_CMS_EDGE << STM_TIM234_CR1_CMS) | + (0 << STM_TIM234_CR1_DIR) | + (0 << STM_TIM234_CR1_OPM) | + (0 << STM_TIM234_CR1_URS) | + (0 << STM_TIM234_CR1_UDIS) | + (1 << STM_TIM234_CR1_CEN)); + } +} + +void +ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant +{ + ao_beep(beep); + ao_delay(ticks); + ao_beep(0); +} + +void +ao_beep_init(void) +{ + /* Our beeper is on PC6, which is hooked to TIM3_CH1, + * which is on PC6 + */ + + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN); + + stm_afr_set(&stm_gpioc, 6, STM_AFR_AF2); + + /* Leave the timer off until requested */ + + stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_TIM3EN); +} diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 54d95c9a..39dd710d 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -1240,4 +1240,219 @@ extern struct stm_i2c stm_i2c1, stm_i2c2; #define STM_I2C_CCR_CCR 0 #define STM_I2C_CCR_MASK 0x7ff +struct stm_tim234 { + vuint32_t cr1; + vuint32_t cr2; + vuint32_t smcr; + vuint32_t dier; + + vuint32_t sr; + vuint32_t egr; + vuint32_t ccmr1; + vuint32_t ccmr2; + + vuint32_t ccer; + vuint32_t cnt; + vuint32_t psc; + vuint32_t arr; + + uint32_t reserved_30; + vuint32_t ccr1; + vuint32_t ccr2; + vuint32_t ccr3; + + vuint32_t ccr4; + uint32_t reserved_44; + vuint32_t dcr; + vuint32_t dmar; + + uint32_t reserved_50; +}; + +extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4; + +#define STM_TIM234_CR1_CKD 8 +#define STM_TIM234_CR1_CKD_1 0 +#define STM_TIM234_CR1_CKD_2 1 +#define STM_TIM234_CR1_CKD_4 2 +#define STM_TIM234_CR1_CKD_MASK 3 +#define STM_TIM234_CR1_ARPE 7 +#define STM_TIM234_CR1_CMS 5 +#define STM_TIM234_CR1_CMS_EDGE 0 +#define STM_TIM234_CR1_CMS_CENTER_1 1 +#define STM_TIM234_CR1_CMS_CENTER_2 2 +#define STM_TIM234_CR1_CMS_CENTER_3 3 +#define STM_TIM234_CR1_CMS_MASK 3 +#define STM_TIM234_CR1_DIR 4 +#define STM_TIM234_CR1_OPM 3 +#define STM_TIM234_CR1_URS 2 +#define STM_TIM234_CR1_UDIS 1 +#define STM_TIM234_CR1_CEN 0 + +#define STM_TIM234_CR2_TI1S 7 +#define STM_TIM234_CR2_MMS 4 +#define STM_TIM234_CR2_MMS_RESET 0 +#define STM_TIM234_CR2_MMS_ENABLE 1 +#define STM_TIM234_CR2_MMS_UPDATE 2 +#define STM_TIM234_CR2_MMS_COMPARE_PULSE 3 +#define STM_TIM234_CR2_MMS_COMPARE_OC1REF 4 +#define STM_TIM234_CR2_MMS_COMPARE_OC2REF 5 +#define STM_TIM234_CR2_MMS_COMPARE_OC3REF 6 +#define STM_TIM234_CR2_MMS_COMPARE_OC4REF 7 +#define STM_TIM234_CR2_MMS_MASK 7 +#define STM_TIM234_CR2_CCDS 3 + +#define STM_TIM234_SMCR_ETP 15 +#define STM_TIM234_SMCR_ECE 14 +#define STM_TIM234_SMCR_ETPS 12 +#define STM_TIM234_SMCR_ETPS_OFF 0 +#define STM_TIM234_SMCR_ETPS_DIV_2 1 +#define STM_TIM234_SMCR_ETPS_DIV_4 2 +#define STM_TIM234_SMCR_ETPS_DIV_8 3 +#define STM_TIM234_SMCR_ETPS_MASK 3 +#define STM_TIM234_SMCR_ETF 8 +#define STM_TIM234_SMCR_ETF_NONE 0 +#define STM_TIM234_SMCR_ETF_INT_N_2 1 +#define STM_TIM234_SMCR_ETF_INT_N_4 2 +#define STM_TIM234_SMCR_ETF_INT_N_8 3 +#define STM_TIM234_SMCR_ETF_DTS_2_N_6 4 +#define STM_TIM234_SMCR_ETF_DTS_2_N_8 5 +#define STM_TIM234_SMCR_ETF_DTS_4_N_6 6 +#define STM_TIM234_SMCR_ETF_DTS_4_N_8 7 +#define STM_TIM234_SMCR_ETF_DTS_8_N_6 8 +#define STM_TIM234_SMCR_ETF_DTS_8_N_8 9 +#define STM_TIM234_SMCR_ETF_DTS_16_N_5 10 +#define STM_TIM234_SMCR_ETF_DTS_16_N_6 11 +#define STM_TIM234_SMCR_ETF_DTS_16_N_8 12 +#define STM_TIM234_SMCR_ETF_DTS_32_N_5 13 +#define STM_TIM234_SMCR_ETF_DTS_32_N_6 14 +#define STM_TIM234_SMCR_ETF_DTS_32_N_8 15 +#define STM_TIM234_SMCR_ETF_MASK 15 +#define STM_TIM234_SMCR_MSM 7 +#define STM_TIM234_SMCR_TS 4 +#define STM_TIM234_SMCR_TS_TR0 0 +#define STM_TIM234_SMCR_TS_TR1 1 +#define STM_TIM234_SMCR_TS_TR2 2 +#define STM_TIM234_SMCR_TS_TR3 3 +#define STM_TIM234_SMCR_TS_TI1F_ED 4 +#define STM_TIM234_SMCR_TS_TI1FP1 5 +#define STM_TIM234_SMCR_TS_TI2FP2 6 +#define STM_TIM234_SMCR_TS_ETRF 7 +#define STM_TIM234_SMCR_TS_MASK 7 +#define STM_TIM234_SMCR_OCCS 3 +#define STM_TIM234_SMCR_SMS 0 +#define STM_TIM234_SMCR_SMS_DISABLE 0 +#define STM_TIM234_SMCR_SMS_ENCODER_MODE_1 1 +#define STM_TIM234_SMCR_SMS_ENCODER_MODE_2 2 +#define STM_TIM234_SMCR_SMS_ENCODER_MODE_3 3 +#define STM_TIM234_SMCR_SMS_RESET_MODE 4 +#define STM_TIM234_SMCR_SMS_GATED_MODE 5 +#define STM_TIM234_SMCR_SMS_TRIGGER_MODE 6 +#define STM_TIM234_SMCR_SMS_EXTERNAL_CLOCK 7 +#define STM_TIM234_SMCR_SMS_MASK 7 + +#define STM_TIM234_SR_CC4OF 12 +#define STM_TIM234_SR_CC3OF 11 +#define STM_TIM234_SR_CC2OF 10 +#define STM_TIM234_SR_CC1OF 9 +#define STM_TIM234_SR_TIF 6 +#define STM_TIM234_SR_CC4IF 4 +#define STM_TIM234_SR_CC3IF 3 +#define STM_TIM234_SR_CC2IF 2 +#define STM_TIM234_SR_CC1IF 1 +#define STM_TIM234_SR_UIF 0 + +#define STM_TIM234_CCMR1_OC2CE 15 +#define STM_TIM234_CCMR1_OC2M 12 +#define STM_TIM234_CCMR1_OC2M_FROZEN 0 +#define STM_TIM234_CCMR1_OC2M_SET_HIGH_ON_MATCH 1 +#define STM_TIM234_CCMR1_OC2M_SET_LOW_ON_MATCH 2 +#define STM_TIM234_CCMR1_OC2M_TOGGLE 3 +#define STM_TIM234_CCMR1_OC2M_FORCE_LOW 4 +#define STM_TIM234_CCMR1_OC2M_FORCE_HIGH 5 +#define STM_TIM234_CCMR1_OC2M_PWM_MODE_1 6 +#define STM_TIM234_CCMR1_OC2M_PWM_MODE_2 7 +#define STM_TIM234_CCMR1_OC2M_MASK 7 +#define STM_TIM234_CCMR1_OC2PE 11 +#define STM_TIM234_CCMR1_OC2FE 10 +#define STM_TIM234_CCMR1_CC2S 8 +#define STM_TIM234_CCMR1_CC2S_OUTPUT 0 +#define STM_TIM234_CCMR1_CC2S_INPUT_TI2 1 +#define STM_TIM234_CCMR1_CC2S_INPUT_TI1 2 +#define STM_TIM234_CCMR1_CC2S_INPUT_TRC 3 +#define STM_TIM234_CCMR1_CC2S_MASK 3 + +#define STM_TIM234_CCMR1_OC1CE 7 +#define STM_TIM234_CCMR1_OC1M 4 +#define STM_TIM234_CCMR1_OC1M_FROZEN 0 +#define STM_TIM234_CCMR1_OC1M_SET_HIGH_ON_MATCH 1 +#define STM_TIM234_CCMR1_OC1M_SET_LOW_ON_MATCH 2 +#define STM_TIM234_CCMR1_OC1M_TOGGLE 3 +#define STM_TIM234_CCMR1_OC1M_FORCE_LOW 4 +#define STM_TIM234_CCMR1_OC1M_FORCE_HIGH 5 +#define STM_TIM234_CCMR1_OC1M_PWM_MODE_1 6 +#define STM_TIM234_CCMR1_OC1M_PWM_MODE_2 7 +#define STM_TIM234_CCMR1_OC1M_MASK 7 +#define STM_TIM234_CCMR1_OC1PE 11 +#define STM_TIM234_CCMR1_OC1FE 2 +#define STM_TIM234_CCMR1_CC1S 0 +#define STM_TIM234_CCMR1_CC1S_OUTPUT 0 +#define STM_TIM234_CCMR1_CC1S_INPUT_TI1 1 +#define STM_TIM234_CCMR1_CC1S_INPUT_TI2 2 +#define STM_TIM234_CCMR1_CC1S_INPUT_TRC 3 +#define STM_TIM234_CCMR1_CC1S_MASK 3 + +#define STM_TIM234_CCMR2_OC2CE 15 +#define STM_TIM234_CCMR2_OC4M 12 +#define STM_TIM234_CCMR2_OC4M_FROZEN 0 +#define STM_TIM234_CCMR2_OC4M_SET_HIGH_ON_MATCH 1 +#define STM_TIM234_CCMR2_OC4M_SET_LOW_ON_MATCH 2 +#define STM_TIM234_CCMR2_OC4M_TOGGLE 3 +#define STM_TIM234_CCMR2_OC4M_FORCE_LOW 4 +#define STM_TIM234_CCMR2_OC4M_FORCE_HIGH 5 +#define STM_TIM234_CCMR2_OC4M_PWM_MODE_1 6 +#define STM_TIM234_CCMR2_OC4M_PWM_MODE_2 7 +#define STM_TIM234_CCMR2_OC4M_MASK 7 +#define STM_TIM234_CCMR2_OC4PE 11 +#define STM_TIM234_CCMR2_OC4FE 10 +#define STM_TIM234_CCMR2_CC4S 8 +#define STM_TIM234_CCMR2_CC4S_OUTPUT 0 +#define STM_TIM234_CCMR2_CC4S_INPUT_TI4 1 +#define STM_TIM234_CCMR2_CC4S_INPUT_TI3 2 +#define STM_TIM234_CCMR2_CC4S_INPUT_TRC 3 +#define STM_TIM234_CCMR2_CC4S_MASK 3 + +#define STM_TIM234_CCMR2_OC3CE 7 +#define STM_TIM234_CCMR2_OC3M 4 +#define STM_TIM234_CCMR2_OC3M_FROZEN 0 +#define STM_TIM234_CCMR2_OC3M_SET_HIGH_ON_MATCH 1 +#define STM_TIM234_CCMR2_OC3M_SET_LOW_ON_MATCH 2 +#define STM_TIM234_CCMR2_OC3M_TOGGLE 3 +#define STM_TIM234_CCMR2_OC3M_FORCE_LOW 4 +#define STM_TIM234_CCMR2_OC3M_FORCE_HIGH 5 +#define STM_TIM234_CCMR2_OC3M_PWM_MODE_1 6 +#define STM_TIM234_CCMR2_OC3M_PWM_MODE_2 7 +#define STM_TIM234_CCMR2_OC3M_MASK 7 +#define STM_TIM234_CCMR2_OC3PE 11 +#define STM_TIM234_CCMR2_OC3FE 2 +#define STM_TIM234_CCMR2_CC3S 0 +#define STM_TIM234_CCMR2_CC3S_OUTPUT 0 +#define STM_TIM234_CCMR2_CC3S_INPUT_TI3 1 +#define STM_TIM234_CCMR2_CC3S_INPUT_TI4 2 +#define STM_TIM234_CCMR2_CC3S_INPUT_TRC 3 +#define STM_TIM234_CCMR2_CC3S_MASK 3 + +#define STM_TIM234_CCER_CC4NP 15 +#define STM_TIM234_CCER_CC4P 13 +#define STM_TIM234_CCER_CC4E 12 +#define STM_TIM234_CCER_CC3NP 11 +#define STM_TIM234_CCER_CC3P 9 +#define STM_TIM234_CCER_CC3E 8 +#define STM_TIM234_CCER_CC2NP 7 +#define STM_TIM234_CCER_CC2P 5 +#define STM_TIM234_CCER_CC2E 4 +#define STM_TIM234_CCER_CC1NP 3 +#define STM_TIM234_CCER_CC1P 1 +#define STM_TIM234_CCER_CC1E 0 + #endif /* _STM32L_H_ */ -- cgit v1.2.3 From 51aef5d4fc29986353ad887f4a67ed2fe35f8c8e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 22:17:33 -0700 Subject: altos: Make STM clock configuration per-product. Fix 32MHz CPU speed This moves all of the STM clock configuration into ao_pins.h so that each product can configure it separately. While doing this, I discovered that the flash memory mode (64-bit, prefetch, latency 1) wasn't actually getting set, which is why the CPU refused to work at 32MHz. Signed-off-by: Keith Packard --- src/megametrum-v0.1/ao_pins.h | 23 ++++++++++++++ src/stm-demo/ao_pins.h | 17 ++++++++++ src/stm/ao_arch.h | 25 ++++++++++++++- src/stm/ao_beep_stm.c | 2 +- src/stm/ao_serial_stm.c | 8 ++--- src/stm/ao_timer.c | 73 ++++++++++++++++++++++++------------------- src/stm/stm32l.h | 3 ++ 7 files changed, 113 insertions(+), 38 deletions(-) (limited to 'src') diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 803678b2..f5789cf9 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -18,6 +18,29 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ +/* 8MHz High speed external crystal */ +#define AO_HSE 8000000 + +/* PLLVCO = 96MHz (so that USB will work*/ +#define AO_PLLMUL 12 +#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12) + +/* SYSCLK = 32MHz (no need to go faster than CPU) */ +#define AO_PLLDIV 3 +#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHz (CPU clock) */ +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at 16MHz (HCLK/2) */ +#define AO_APB1_PRESCALER 2 +#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +/* Run APB2 at 16MHz (HCLK/2) */ +#define AO_APB2_PRESCALER 2 +#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2 + #define HAS_SERIAL_1 1 #define USE_SERIAL_1_STDIN 1 #define SERIAL_1_PB6_PB7 0 diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 9fd1175d..3192c2b7 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -18,6 +18,23 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ +/* No external crystal */ +#define AO_HSE 0 + +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +#define AO_APB1_PRESCALER 2 +#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +#define AO_APB2_PRESCALER 2 +#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +#define AO_PLLMUL 6 +#define AO_PLLDIV 4 +#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_6) +#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_4) + #define HAS_SERIAL_1 1 #define USE_SERIAL_1_STDIN 1 #define SERIAL_1_PB6_PB7 1 diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index ce3a22e2..dd9579f1 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -148,7 +148,30 @@ extern const uint16_t ao_serial_number; /* * For now, we're running at a weird frequency */ -#define STM_APB1 (16000000 * 6 / 4) + +#if AO_HSE +#define AO_PLLSRC AO_HSE +#else +#define AO_PLLSRC STM_HSI_FREQ +#endif + +#define AO_PLLVCO (AO_PLLSRC * AO_PLLMUL) +#define AO_SYSCLK (AO_PLLVCO / AO_PLLDIV) +#define AO_HCLK (AO_SYSCLK / AO_AHB_PRESCALER) +#define AO_PCLK1 (AO_HCLK / AO_APB1_PRESCALER) +#define AO_PCLK2 (AO_HCLK / AO_APB2_PRESCALER) + +#if AO_APB1_PRESCALER == 1 +#define AO_TIM23467_CLK AO_PCLK1 +#else +#define AO_TIM23467_CLK (2 * AO_PCLK1) +#endif + +#if AO_APB2_PRESCALER == 1 +#define AO_TIM91011_CLK AO_PCLK2 +#else +#define AO_TIM91011_CLK (2 * AO_PCLK2) +#endif void ao_lcd_stm_init(void); diff --git a/src/stm/ao_beep_stm.c b/src/stm/ao_beep_stm.c index 8c0c0ee3..37c30e25 100644 --- a/src/stm/ao_beep_stm.c +++ b/src/stm/ao_beep_stm.c @@ -41,7 +41,7 @@ ao_beep(uint8_t beep) /* Set prescaler to match cc1111 clocks */ - stm_tim3.psc = STM_APB1 / 750000; + stm_tim3.psc = AO_TIM23467_CLK / 750000; /* 1. Select the counter clock (internal, external, prescaler). * diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index f8db6883..3cebc094 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -116,16 +116,16 @@ static const struct { uint32_t brr; } ao_usart_speeds[] = { [AO_SERIAL_SPEED_4800] = { - STM_APB1 / 4800 + AO_PCLK1 / 4800 }, [AO_SERIAL_SPEED_9600] = { - STM_APB1 / 9600 + AO_PCLK1 / 9600 }, [AO_SERIAL_SPEED_19200] = { - STM_APB1 / 19200 + AO_PCLK1 / 19200 }, [AO_SERIAL_SPEED_57600] = { - STM_APB1 / 57600 + AO_PCLK1 / 57600 }, }; diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 387df184..e7f1ddfe 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -69,7 +69,7 @@ ao_timer_set_adc_interval(uint8_t interval) __critical } #endif -#define TIMER_10kHz (STM_APB1 / 10000) +#define TIMER_10kHz (AO_PCLK1 / 10000) void ao_timer_init(void) @@ -107,44 +107,41 @@ ao_clock_init(void) uint32_t cr; /* Set flash latency to tolerate 32MHz SYSCLK -> 1 wait state */ - uint32_t acr = stm_flash.acr; /* Enable 64-bit access and prefetch */ - acr |= (1 << STM_FLASH_ACR_ACC64) | (1 << STM_FLASH_ACR_PRFEN); - stm_flash.acr = acr; + stm_flash.acr |= (1 << STM_FLASH_ACR_ACC64); + stm_flash.acr |= (1 << STM_FLASH_ACR_PRFEN); /* Enable 1 wait state so the CPU can run at 32MHz */ /* (haven't managed to run the CPU at 32MHz yet, it's at 16MHz) */ - acr |= (1 << STM_FLASH_ACR_LATENCY); - stm_flash.acr = acr; + stm_flash.acr |= (1 << STM_FLASH_ACR_LATENCY); + /* HCLK to 16MHz -> AHB prescaler = /1 */ cfgr = stm_rcc.cfgr; cfgr &= ~(STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE); - cfgr |= (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE); + cfgr |= (AO_RCC_CFGR_HPRE_DIV << STM_RCC_CFGR_HPRE); stm_rcc.cfgr = cfgr; while ((stm_rcc.cfgr & (STM_RCC_CFGR_HPRE_MASK << STM_RCC_CFGR_HPRE)) != - (STM_RCC_CFGR_HPRE_DIV_1 << STM_RCC_CFGR_HPRE)) + (AO_RCC_CFGR_HPRE_DIV << STM_RCC_CFGR_HPRE)) asm ("nop"); -#define STM_AHB_PRESCALER 1 - /* PCLK1 to 16MHz -> APB1 Prescaler = 1 */ + /* APB1 Prescaler = AO_APB1_PRESCALER */ cfgr = stm_rcc.cfgr; cfgr &= ~(STM_RCC_CFGR_PPRE1_MASK << STM_RCC_CFGR_PPRE1); - cfgr |= (STM_RCC_CFGR_PPRE1_DIV_1 << STM_RCC_CFGR_PPRE1); + cfgr |= (AO_RCC_CFGR_PPRE1_DIV << STM_RCC_CFGR_PPRE1); stm_rcc.cfgr = cfgr; -#define STM_APB1_PRESCALER 1 - /* PCLK2 to 16MHz -> APB2 Prescaler = 1 */ + /* APB2 Prescaler = AO_APB2_PRESCALER */ cfgr = stm_rcc.cfgr; cfgr &= ~(STM_RCC_CFGR_PPRE2_MASK << STM_RCC_CFGR_PPRE2); - cfgr |= (STM_RCC_CFGR_PPRE2_DIV_1 << STM_RCC_CFGR_PPRE2); + cfgr |= (AO_RCC_CFGR_PPRE2_DIV << STM_RCC_CFGR_PPRE2); stm_rcc.cfgr = cfgr; -#define STM_APB2_PRESCALER 1 /* Enable power interface clock */ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); + /* Set voltage range to 1.8V */ /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ @@ -161,23 +158,42 @@ ao_clock_init(void) while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) asm("nop"); +#if AO_HSE + /* Enable HSE clock */ + if (!(stm_rcc.cr & (1 << STM_RCC_CR_HSERDY))) { + stm_rcc.cr |= (1 << STM_RCC_CR_HSEON); + while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSERDY))) + asm("nop"); + } +#define STM_RCC_CFGR_SWS_TARGET_CLOCK (STM_RCC_CFGR_SWS_HSE << STM_RCC_CFGR_SWS) +#define STM_RCC_CFGR_SW_TARGET_CLOCK (STM_RCC_CFGR_SW_HSE) +#define STM_PLLSRC AO_HSE +#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK (1 << STM_RCC_CFGR_PLLSRC) +#else +#define STM_HSI 16000000 +#define STM_RCC_CFGR_SWS_TARGET_CLOCK (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS) +#define STM_RCC_CFGR_SW_TARGET_CLOCK (STM_RCC_CFGR_SW_HSI) +#define STM_PLLSRC STM_HSI +#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK (0 << STM_RCC_CFGR_PLLSRC) +#endif + +#if !AO_HSE || HAS_ADC /* Enable HSI RC clock 16MHz */ if (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) { stm_rcc.cr |= (1 << STM_RCC_CR_HSION); while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) asm("nop"); } -#define STM_HSI 16000000 - - /* Switch to direct HSI for SYSCLK */ +#endif + /* Switch to direct high speed clock for SYSCLK */ if ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != - (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) { + STM_RCC_CFGR_SWS_TARGET_CLOCK) { cfgr = stm_rcc.cfgr; cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); - cfgr |= (STM_RCC_CFGR_SW_HSI << STM_RCC_CFGR_SW); + cfgr |= STM_RCC_CFGR_SW_TARGET_CLOCK; stm_rcc.cfgr = cfgr; while ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != - (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS)) + STM_RCC_CFGR_SWS_TARGET_CLOCK); asm("nop"); } @@ -191,19 +207,12 @@ ao_clock_init(void) cfgr &= ~(STM_RCC_CFGR_PLLMUL_MASK << STM_RCC_CFGR_PLLMUL); cfgr &= ~(STM_RCC_CFGR_PLLDIV_MASK << STM_RCC_CFGR_PLLDIV); -// cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); -// cfgr |= (STM_RCC_CFGR_PLLDIV_3 << STM_RCC_CFGR_PLLDIV); - - cfgr |= (STM_RCC_CFGR_PLLMUL_6 << STM_RCC_CFGR_PLLMUL); - cfgr |= (STM_RCC_CFGR_PLLDIV_4 << STM_RCC_CFGR_PLLDIV); + cfgr |= (AO_RCC_CFGR_PLLMUL << STM_RCC_CFGR_PLLMUL); + cfgr |= (AO_RCC_CFGR_PLLDIV << STM_RCC_CFGR_PLLDIV); -#define STM_PLLMUL 6 -#define STM_PLLDIV 4 - - /* PLL source to HSI */ + /* PLL source */ cfgr &= ~(1 << STM_RCC_CFGR_PLLSRC); - -#define STM_PLLSRC STM_HSI + cfgr |= STM_RCC_CFGR_PLLSRC_TARGET_CLOCK; stm_rcc.cfgr = cfgr; diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 39dd710d..b922b6bc 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -303,6 +303,9 @@ struct stm_rcc { extern struct stm_rcc stm_rcc; +/* Nominal high speed internal oscillator frequency is 16MHz */ +#define STM_HSI_FREQ 16000000 + #define STM_RCC_CR_RTCPRE (29) #define STM_RCC_CR_RTCPRE_HSE_DIV_2 0 #define STM_RCC_CR_RTCPRE_HSE_DIV_4 1 -- cgit v1.2.3 From c5bbfc7244faaae41c7b581644c3c253e9b7f462 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 22:21:46 -0700 Subject: altos: Reduce MS5607 reset delay, increase conversion delay Reset doesn't take very long, while doing a conversion seems to take more than 10ms. Signed-off-by: Keith Packard --- src/drivers/ao_ms5607.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 51922dc7..87748272 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -18,11 +18,6 @@ #include #include "ao_ms5607.h" -#define AO_MS5607_CS_GPIO stm_gpioc -#define AO_MS5607_CS 4 -#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) -#define AO_MS5607_SPI_INDEX (STM_SPI_INDEX(1)) - struct ms5607_prom { uint16_t reserved; uint16_t sens; @@ -55,7 +50,7 @@ ao_ms5607_reset(void) { cmd = AO_MS5607_RESET; ao_ms5607_start(); ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); - ao_delay(AO_MS_TO_TICKS(100)); + ao_delay(AO_MS_TO_TICKS(10)); ao_ms5607_stop(); } @@ -70,28 +65,27 @@ ao_ms5607_prom_read(uint8_t addr) ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); ao_spi_recv(d, 2, AO_MS5607_SPI_INDEX); ao_ms5607_stop(); - v = ((uint16_t) d[0] << 8) | (uint16_t) d[1]; -// printf ("ms5607_prom_read recv %02x %02x -> %04x\n", d[0], d[1], v); - return v; + return ((uint16_t) d[0] << 8) | (uint16_t) d[1]; } static void ao_ms5607_init_chip(void) { uint8_t addr; uint16_t *prom; + ao_ms5607_reset(); prom = &ms5607_prom.reserved; for (addr = 0; addr <= 7; addr++) prom[addr] = ao_ms5607_prom_read(addr); - printf ("reserved: %d\n", ms5607_prom.reserved); - printf ("sens: %d\n", ms5607_prom.sens); - printf ("off: %d\n", ms5607_prom.off); - printf ("tcs: %d\n", ms5607_prom.tcs); - printf ("tco: %d\n", ms5607_prom.tco); - printf ("tref: %d\n", ms5607_prom.tref); - printf ("tempsens: %d\n", ms5607_prom.tempsens); - printf ("crc: %d\n", ms5607_prom.crc); + printf ("reserved: 0x%x\n", ms5607_prom.reserved); + printf ("sens: 0x%x\n", ms5607_prom.sens); + printf ("off: 0x%x\n", ms5607_prom.off); + printf ("tcs: 0x%x\n", ms5607_prom.tcs); + printf ("tco: 0x%x\n", ms5607_prom.tco); + printf ("tref: 0x%x\n", ms5607_prom.tref); + printf ("tempsens: 0x%x\n", ms5607_prom.tempsens); + printf ("crc: 0x%x\n", ms5607_prom.crc); } static uint32_t @@ -103,7 +97,7 @@ ao_ms5607_convert(uint8_t cmd) { ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); ao_ms5607_stop(); - ao_delay(AO_MS_TO_TICKS(10)); + ao_delay(AO_MS_TO_TICKS(20)); ao_ms5607_start(); read = AO_MS5607_ADC_READ; -- cgit v1.2.3 From 3909fca0a3f918121888a415f9bf9bca99505366 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 22:22:58 -0700 Subject: altos: Add missing parens in ao_ms5607.h Signed-off-by: Keith Packard --- src/drivers/ao_ms5607.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h index 6c245368..489190a4 100644 --- a/src/drivers/ao_ms5607.h +++ b/src/drivers/ao_ms5607.h @@ -33,6 +33,6 @@ #define AO_MS5607_CONVERT_D2_4096 0x58 #define AO_MS5607_ADC_READ 0x00 -#define AO_MS5607_PROM_READ(ad) 0xA0 | ((ad) << 1) +#define AO_MS5607_PROM_READ(ad) (0xA0 | ((ad) << 1)) #endif /* _AO_MS5607_H_ */ -- cgit v1.2.3 From 0cd682ef0c8cdcf364b7e173ff3a9f84e485c113 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 22:23:52 -0700 Subject: altos: Move MS5607 configuration to ao_pins.h Which SPI port and where chip select is to be found are product specific. Signed-off-by: Keith Packard --- src/megametrum-v0.1/ao_pins.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index f5789cf9..e200a692 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -174,4 +174,12 @@ struct ao_adc { #define AO_ADC_SQ8 AO_ADC_V_PBATT #define AO_ADC_SQ9 AO_ADC_TEMP +/* + * Pressure sensor settings + */ +#define AO_MS5607_CS_GPIO stm_gpioc +#define AO_MS5607_CS 4 +#define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) +#define AO_MS5607_SPI_INDEX (STM_SPI_INDEX(1)) + #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From d15c4976ed9c23c861e620eb9c429d1cb7eedbee Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 22:24:36 -0700 Subject: altos: Increase STM SPI speed to PCLK/4 The pressure sensor seems happy at this speed. Signed-off-by: Keith Packard --- src/stm/ao_spi_stm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index d3e1ca4b..be24ebcf 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -169,7 +169,7 @@ ao_spi_get(uint8_t spi_index) (1 << STM_SPI_CR1_SSI) | /* ... */ (0 << STM_SPI_CR1_LSBFIRST) | /* Big endian */ (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */ - (STM_SPI_CR1_BR_PCLK_16 << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ + (STM_SPI_CR1_BR_PCLK_4 << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ (1 << STM_SPI_CR1_MSTR) | (0 << STM_SPI_CR1_CPOL) | /* Format 0 */ (0 << STM_SPI_CR1_CPHA)); -- cgit v1.2.3 From 9804528e249db256e020d4b5340ba6216d3474f0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 22:25:13 -0700 Subject: altos: Check for cc1111 flash overflow The linker is supposed to do this, but it ignores the static initializer data added after the code. Signed-off-by: Keith Packard --- src/util/check-stack | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src') diff --git a/src/util/check-stack b/src/util/check-stack index 3b639d70..7b62e460 100755 --- a/src/util/check-stack +++ b/src/util/check-stack @@ -5,6 +5,8 @@ MEM=$2 HEADER_STACK=`awk '/#define AO_STACK_START/ {print strtonum($3)}' $HEADER` MEM_STACK=`awk '/Stack starts at/ {print strtonum ($4)}' $MEM` XRAM_END=`awk '/EXTERNAL RAM/ { print strtonum ($4)}' $MEM` +FLASH_END=`awk '/ROM\/EPROM\/FLASH/ { print strtonum ($3)}' $MEM` +echo FLASH_END $FLASH_END if [ "$HEADER_STACK" -lt "$MEM_STACK" ]; then echo $MEM_STACK | awk '{ printf ("Set AO_STACK_START to at least 0x%x\n", $1); }' @@ -14,6 +16,10 @@ if [ "$XRAM_END" -ge 65024 ]; then echo $XRAM_END | awk '{ printf ("Uses too much XRAM, 0x%x >= 0x%x\n", $1, 65024); }' exit 1 fi +if [ "$FLASH_END" -ge 32768 ]; then + echo $FLASH_END | awk '{ printf ("Uses too much FLASH, 0x%x >= 0x%x\n", $1, 32768); }' + exit 1 +fi exit 0 -- cgit v1.2.3 From 35e3c47da895bdd868b9b66b98bca64bd82db862 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 22:25:59 -0700 Subject: altos: make megametrum beeper test keep beeping Used to measure the beep frequency. Signed-off-by: Keith Packard --- src/megametrum-v0.1/ao_megametrum.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 4d9343e1..eaab9b50 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -20,7 +20,11 @@ void beep(void) { - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(2000)); + ao_beep(AO_BEEP_MID); + printf ("Hit a character to stop..."); flush(); + getchar(); + putchar('\n'); + ao_beep(0); } const struct ao_cmds ao_mm_cmds[] = { -- cgit v1.2.3 From 0dd9e1dd62656a931f9559af6da9131f704f83f9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 9 Apr 2012 23:27:43 -0700 Subject: altos: Add support for multiple SPI busses and sharing device drivers The STM32L151 has several SPI busses, and we want to use more than one, so add a 'bus' parameter to the SPI interfaces. To avoid wasting time on AVR and CC1111 processors which only use one SPI bus, elide those parameters from the actual functions by wrapping them with macros. Configuring chip select is now all macroized so that each chip can have its own version, allowing the STM to share the various SPI device drivers with the cc1111 and avr processors. Note that only the M25 driver has been ported; porting the others is 'trivial', but not necessary at this point. Signed-off-by: Keith Packard --- src/avr/ao_arch_funcs.h | 35 +++++++++++++++----------- src/avr/ao_pins.h | 3 +++ src/avr/ao_spi_usart.c | 4 +-- src/cc1111/ao_arch_funcs.h | 21 +++++++++++----- src/cc1111/ao_pins.h | 8 +++--- src/cc1111/ao_spi.c | 4 +-- src/drivers/ao_25lc1024.c | 20 +++++++-------- src/drivers/ao_at45db161d.c | 18 +++++++------- src/drivers/ao_companion.c | 10 ++++---- src/drivers/ao_m25.c | 43 ++++++++++++++------------------ src/drivers/ao_ms5607.c | 5 +--- src/megametrum-v0.1/Makefile | 4 ++- src/megametrum-v0.1/ao_megametrum.c | 1 + src/megametrum-v0.1/ao_pins.h | 9 +++++++ src/stm/ao_arch_funcs.h | 49 +++++++++++++++++++++++++++++++++++++ src/teleterra-v0.2/ao_pins.h | 3 +++ 16 files changed, 157 insertions(+), 80 deletions(-) (limited to 'src') diff --git a/src/avr/ao_arch_funcs.h b/src/avr/ao_arch_funcs.h index 9ad14fbb..1eeca6cc 100644 --- a/src/avr/ao_arch_funcs.h +++ b/src/avr/ao_arch_funcs.h @@ -21,24 +21,24 @@ extern __xdata uint8_t ao_spi_mutex; -#define ao_spi_get_mask(reg,mask) do {\ - ao_mutex_get(&ao_spi_mutex); \ - (reg) &= ~(mask); \ +#define ao_spi_get_mask(reg,mask,bus) do { \ + ao_mutex_get(&ao_spi_mutex); \ + (reg) &= ~(mask); \ } while (0) -#define ao_spi_put_mask(reg,mask) do { \ - (reg) |= (mask); \ - ao_mutex_put(&ao_spi_mutex); \ +#define ao_spi_put_mask(reg,mask,bus) do { \ + (reg) |= (mask); \ + ao_mutex_put(&ao_spi_mutex); \ } while (0) -#define ao_spi_get_bit(bit) do {\ - ao_mutex_get(&ao_spi_mutex); \ - (bit) = 0; \ +#define ao_spi_get_bit(bit) do { \ + ao_mutex_get(&ao_spi_mutex); \ + (bit) = 0; \ } while (0) -#define ao_spi_put_bit(bit) do { \ - (bit) = 1; \ - ao_mutex_put(&ao_spi_mutex); \ +#define ao_spi_put_bit(bit) do { \ + (bit) = 1; \ + ao_mutex_put(&ao_spi_mutex); \ } while (0) /* @@ -48,11 +48,18 @@ extern __xdata uint8_t ao_spi_mutex; */ void -ao_spi_send(void __xdata *block, uint16_t len) __reentrant; +ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant; void -ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; +ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant; + +#define ao_spi_send(block, len, bus) ao_spi_send_bus(block, len) +#define ao_spi_recv(block, len, bus) ao_spi_recv_bus(block, len) void ao_spi_init(void); +#define ao_spi_init_cs(port, mask) do { \ + SPI_CS_PORT |= (mask); \ + SPI_CS_DIR |= (mask); \ + } while (0) diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index bf02db1b..6a63468f 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -85,4 +85,7 @@ #define SPI_SLAVE_PIN_2_5 0 #endif +#define AO_M25_SPI_CS_PORT SPI_CS_PORT +#define AO_M25_SPI_CS_MASK M25_CS_MASK + #endif /* _AO_PINS_H_ */ diff --git a/src/avr/ao_spi_usart.c b/src/avr/ao_spi_usart.c index 5ea11da6..7c41042a 100644 --- a/src/avr/ao_spi_usart.c +++ b/src/avr/ao_spi_usart.c @@ -29,7 +29,7 @@ __xdata uint8_t ao_spi_mutex; * so using interrupts would take way too long */ void -ao_spi_send(void __xdata *block, uint16_t len) __reentrant +ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant { uint8_t *d = block; @@ -46,7 +46,7 @@ ao_spi_send(void __xdata *block, uint16_t len) __reentrant * Poll, sending zeros and reading data back */ void -ao_spi_recv(void __xdata *block, uint16_t len) __reentrant +ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant { uint8_t *d = block; diff --git a/src/cc1111/ao_arch_funcs.h b/src/cc1111/ao_arch_funcs.h index 9ad14fbb..d9f5955a 100644 --- a/src/cc1111/ao_arch_funcs.h +++ b/src/cc1111/ao_arch_funcs.h @@ -21,26 +21,27 @@ extern __xdata uint8_t ao_spi_mutex; -#define ao_spi_get_mask(reg,mask) do {\ +#define ao_spi_get_mask(reg,mask,bus) do { \ ao_mutex_get(&ao_spi_mutex); \ (reg) &= ~(mask); \ } while (0) -#define ao_spi_put_mask(reg,mask) do { \ +#define ao_spi_put_mask(reg,mask,bus) do { \ (reg) |= (mask); \ ao_mutex_put(&ao_spi_mutex); \ } while (0) -#define ao_spi_get_bit(bit) do {\ +#define ao_spi_get_bit(bit,bus) do { \ ao_mutex_get(&ao_spi_mutex); \ (bit) = 0; \ } while (0) -#define ao_spi_put_bit(bit) do { \ +#define ao_spi_put_bit(bit,bus) do { \ (bit) = 1; \ ao_mutex_put(&ao_spi_mutex); \ } while (0) + /* * The SPI mutex must be held to call either of these * functions -- this mutex covers the entire SPI operation, @@ -48,11 +49,19 @@ extern __xdata uint8_t ao_spi_mutex; */ void -ao_spi_send(void __xdata *block, uint16_t len) __reentrant; +ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant; void -ao_spi_recv(void __xdata *block, uint16_t len) __reentrant; +ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant; + +#define ao_spi_send(block, len, bus) ao_spi_send_bus(block, len) +#define ao_spi_recv(block, len, bus) ao_spi_recv_bus(block, len) void ao_spi_init(void); +#define ao_spi_init_cs(port, mask) do { \ + SPI_CS_PORT |= mask; \ + SPI_CS_DIR |= mask; \ + SPI_CS_SEL &= ~mask; \ + } while (0) diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index a18c74c8..5c0cb7df 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -82,7 +82,7 @@ #define HAS_ACCEL_REF 1 #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 - #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ + #define AO_M25_SPI_CS_MASK 0x02 /* CS0 is P1_1 */ #define M25_MAX_CHIPS 1 #define HAS_ACCEL 1 #define HAS_IGNITE 1 @@ -119,7 +119,7 @@ #define HAS_ACCEL_REF 1 #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 - #define M25_CS_MASK 0x02 /* CS0 is P1_1 */ + #define AO_M25_SPI_CS_MASK 0x02 /* CS0 is P1_1 */ #define M25_MAX_CHIPS 1 #define HAS_ACCEL 1 #define HAS_IGNITE 1 @@ -358,7 +358,7 @@ #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define SPI_CS_ON_P1 1 #define SPI_CS_ON_P0 0 - #define M25_CS_MASK 0x04 /* CS0 is P1_2 */ + #define AO_M25_SPI_CS_MASK 0x04 /* CS0 is P1_2 */ #define M25_MAX_CHIPS 1 #define HAS_ACCEL 0 #define HAS_IGNITE 0 @@ -458,6 +458,8 @@ #define SPI_CS_DIR P0DIR #endif +#define AO_M25_SPI_CS_PORT SPI_CS_PORT + #ifndef IGNITE_ON_P2 #error Please define IGNITE_ON_P2 #endif diff --git a/src/cc1111/ao_spi.c b/src/cc1111/ao_spi.c index 1fa8e128..1bf5e155 100644 --- a/src/cc1111/ao_spi.c +++ b/src/cc1111/ao_spi.c @@ -38,7 +38,7 @@ static __xdata uint8_t ao_spi_const; * completion one byte before the transfer is actually complete */ void -ao_spi_send(void __xdata *block, uint16_t len) __reentrant +ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant { ao_dma_set_transfer(ao_spi_dma_in_id, &U0DBUFXADDR, @@ -76,7 +76,7 @@ ao_spi_send(void __xdata *block, uint16_t len) __reentrant * clocks the data coming in. */ void -ao_spi_recv(void __xdata *block, uint16_t len) __reentrant +ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant { ao_dma_set_transfer(ao_spi_dma_in_id, &U0DBUFXADDR, diff --git a/src/drivers/ao_25lc1024.c b/src/drivers/ao_25lc1024.c index 2d047a44..f0fb13c9 100644 --- a/src/drivers/ao_25lc1024.c +++ b/src/drivers/ao_25lc1024.c @@ -49,9 +49,9 @@ static __xdata uint8_t ao_ee_mutex; _asm nop _endasm; \ } while(0) -#define ao_ee_cs_low() ao_spi_get_bit(EE_CS) +#define ao_ee_cs_low() ao_spi_get_bit(EE_CS, AO_EE_SPI_BUS) -#define ao_ee_cs_high() ao_spi_put_bit(EE_CS) +#define ao_ee_cs_high() ao_spi_put_bit(EE_CS, AO_EE_SPI_BUS) struct ao_ee_instruction { uint8_t instruction; @@ -63,7 +63,7 @@ ao_ee_write_enable(void) { ao_ee_cs_low(); ao_ee_instruction.instruction = EE_WREN; - ao_spi_send(&ao_ee_instruction, 1); + ao_spi_send(&ao_ee_instruction, 1, AO_EE_SPI_BUS); ao_ee_cs_high(); } @@ -72,8 +72,8 @@ ao_ee_rdsr(void) { ao_ee_cs_low(); ao_ee_instruction.instruction = EE_RDSR; - ao_spi_send(&ao_ee_instruction, 1); - ao_spi_recv(&ao_ee_instruction, 1); + ao_spi_send(&ao_ee_instruction, 1, AO_EE_SPI_BUS); + ao_spi_recv(&ao_ee_instruction, 1, AO_EE_SPI_BUS); ao_ee_cs_high(); return ao_ee_instruction.instruction; } @@ -84,7 +84,7 @@ ao_ee_wrsr(uint8_t status) ao_ee_cs_low(); ao_ee_instruction.instruction = EE_WRSR; ao_ee_instruction.address[0] = status; - ao_spi_send(&ao_ee_instruction, 2); + ao_spi_send(&ao_ee_instruction, 2, AO_EE_SPI_BUS); ao_ee_cs_high(); } @@ -111,8 +111,8 @@ ao_ee_write_block(void) ao_ee_instruction.address[0] = ao_ee_block >> 8; ao_ee_instruction.address[1] = ao_ee_block; ao_ee_instruction.address[2] = 0; - ao_spi_send(&ao_ee_instruction, 4); - ao_spi_send(ao_ee_data, EE_BLOCK_SIZE); + ao_spi_send(&ao_ee_instruction, 4, AO_EE_SPI_BUS); + ao_spi_send(ao_ee_data, EE_BLOCK_SIZE, AO_EE_SPI_BUS); ao_ee_cs_high(); for (;;) { uint8_t status = ao_ee_rdsr(); @@ -130,8 +130,8 @@ ao_ee_read_block(void) ao_ee_instruction.address[0] = ao_ee_block >> 8; ao_ee_instruction.address[1] = ao_ee_block; ao_ee_instruction.address[2] = 0; - ao_spi_send(&ao_ee_instruction, 4); - ao_spi_recv(ao_ee_data, EE_BLOCK_SIZE); + ao_spi_send(&ao_ee_instruction, 4, AO_EE_SPI_BUS); + ao_spi_recv(ao_ee_data, EE_BLOCK_SIZE, AO_EE_SPI_BUS); ao_ee_cs_high(); } diff --git a/src/drivers/ao_at45db161d.c b/src/drivers/ao_at45db161d.c index 6cd689e5..afe0080b 100644 --- a/src/drivers/ao_at45db161d.c +++ b/src/drivers/ao_at45db161d.c @@ -43,9 +43,9 @@ __xdata uint8_t ao_flash_mutex; _asm nop _endasm; \ } while(0) -#define ao_flash_cs_low() ao_spi_get_bit(FLASH_CS) +#define ao_flash_cs_low() ao_spi_get_bit(FLASH_CS, AO_FLASH_SPI_BUS) -#define ao_flash_cs_high() ao_spi_put_bit(FLASH_CS) +#define ao_flash_cs_high() ao_spi_put_bit(FLASH_CS, AO_FLASH_SPI_BUS) struct ao_flash_instruction { uint8_t instruction; @@ -60,7 +60,7 @@ ao_flash_set_pagesize_512(void) ao_flash_instruction.address[0] = FLASH_SET_512_BYTE_0; ao_flash_instruction.address[1] = FLASH_SET_512_BYTE_1; ao_flash_instruction.address[2] = FLASH_SET_512_BYTE_2; - ao_spi_send(&ao_flash_instruction, 4); + ao_spi_send(&ao_flash_instruction, 4, AO_FLASH_SPI_BUS); ao_flash_cs_high(); } @@ -70,8 +70,8 @@ ao_flash_read_status(void) { ao_flash_cs_low(); ao_flash_instruction.instruction = FLASH_READ_STATUS; - ao_spi_send(&ao_flash_instruction, 1); - ao_spi_recv(&ao_flash_instruction, 1); + ao_spi_send(&ao_flash_instruction, 1, AO_FLASH_SPI_BUS); + ao_spi_recv(&ao_flash_instruction, 1, AO_FLASH_SPI_BUS); ao_flash_cs_high(); return ao_flash_instruction.instruction; } @@ -190,8 +190,8 @@ ao_flash_write_block(void) ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift); ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); ao_flash_instruction.address[2] = 0; - ao_spi_send(&ao_flash_instruction, 4); - ao_spi_send(ao_flash_data, ao_storage_block); + ao_spi_send(&ao_flash_instruction, 4, AO_FLASH_SPI_BUS); + ao_spi_send(ao_flash_data, ao_storage_block, AO_FLASH_SPI_BUS); ao_flash_cs_high(); ao_flash_write_pending = 1; } @@ -208,8 +208,8 @@ ao_flash_read_block(void) ao_flash_instruction.address[0] = ao_flash_block >> (16 - ao_flash_block_shift); ao_flash_instruction.address[1] = ao_flash_block << (ao_flash_block_shift - 8); ao_flash_instruction.address[2] = 0; - ao_spi_send(&ao_flash_instruction, 4); - ao_spi_recv(ao_flash_data, ao_flash_block_size); + ao_spi_send(&ao_flash_instruction, 4, AO_FLASH_SPI_BUS); + ao_spi_recv(ao_flash_data, ao_flash_block_size, AO_FLASH_SPI_BUS); ao_flash_cs_high(); } diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index 2e587f8e..fe88e998 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -27,8 +27,8 @@ UxGCR_ORDER_MSB | \ (17 << UxGCR_BAUD_E_SHIFT))) -#define COMPANION_SELECT() do { ao_spi_get_bit(COMPANION_CS); ao_spi_slow(); } while (0) -#define COMPANION_DESELECT() do { ao_spi_fast(); ao_spi_put_bit(COMPANION_CS); } while (0) +#define COMPANION_SELECT() do { ao_spi_get_bit(COMPANION_CS, AO_COMPANION_BUS); ao_spi_slow(); } while (0) +#define COMPANION_DESELECT() do { ao_spi_fast(); ao_spi_put_bit(COMPANION_CS, AO_COMPANION_BUS); } while (0) __xdata struct ao_companion_command ao_companion_command; __xdata struct ao_companion_setup ao_companion_setup; @@ -45,7 +45,7 @@ ao_companion_send_command(uint8_t command) ao_companion_command.tick = ao_time(); ao_companion_command.serial = ao_serial_number; ao_companion_command.flight = ao_flight_number; - ao_spi_send(&ao_companion_command, sizeof (ao_companion_command)); + ao_spi_send(&ao_companion_command, sizeof (ao_companion_command), AO_COMPANION_SPI_BUS); } static uint8_t @@ -53,7 +53,7 @@ ao_companion_get_setup(void) { COMPANION_SELECT(); ao_companion_send_command(AO_COMPANION_SETUP); - ao_spi_recv(&ao_companion_setup, sizeof (ao_companion_setup)); + ao_spi_recv(&ao_companion_setup, sizeof (ao_companion_setup), AO_COMPANION_SPI_BUS); COMPANION_DESELECT(); return (ao_companion_setup.board_id == ~ao_companion_setup.board_id_inverse); @@ -65,7 +65,7 @@ ao_companion_get_data(void) COMPANION_SELECT(); ao_companion_send_command(AO_COMPANION_FETCH); ao_mutex_get(&ao_companion_mutex); - ao_spi_recv(&ao_companion_data, ao_companion_setup.channels * 2); + ao_spi_recv(&ao_companion_data, ao_companion_setup.channels * 2, AO_COMPANION_SPI_BUS); ao_mutex_put(&ao_companion_mutex); COMPANION_DESELECT(); } diff --git a/src/drivers/ao_m25.c b/src/drivers/ao_m25.c index 28cb1dd7..c807cd68 100644 --- a/src/drivers/ao_m25.c +++ b/src/drivers/ao_m25.c @@ -99,8 +99,8 @@ static __xdata uint8_t ao_m25_mutex; static __xdata uint8_t ao_m25_instruction[4]; -#define M25_SELECT(cs) ao_spi_get_mask(SPI_CS_PORT,cs) -#define M25_DESELECT(cs) ao_spi_put_mask(SPI_CS_PORT,cs) +#define M25_SELECT(cs) ao_spi_get_mask(AO_M25_SPI_CS_PORT,cs,AO_M25_SPI_BUS) +#define M25_DESELECT(cs) ao_spi_put_mask(AO_M25_SPI_CS_PORT,cs,AO_M25_SPI_BUS) #define M25_BLOCK_SHIFT 16 #define M25_BLOCK 65536L @@ -116,9 +116,9 @@ ao_m25_wait_wip(uint8_t cs) if (ao_m25_wip & cs) { M25_SELECT(cs); ao_m25_instruction[0] = M25_RDSR; - ao_spi_send(ao_m25_instruction, 1); + ao_spi_send(ao_m25_instruction, 1, AO_M25_SPI_BUS); do { - ao_spi_recv(ao_m25_instruction, 1); + ao_spi_recv(ao_m25_instruction, 1, AO_M25_SPI_BUS); } while (ao_m25_instruction[0] & M25_STATUS_WIP); M25_DESELECT(cs); ao_m25_wip &= ~cs; @@ -135,7 +135,7 @@ ao_m25_write_enable(uint8_t cs) { M25_SELECT(cs); ao_m25_instruction[0] = M25_WREN; - ao_spi_send(&ao_m25_instruction, 1); + ao_spi_send(&ao_m25_instruction, 1, AO_M25_SPI_BUS); M25_DESELECT(cs); ao_m25_wip |= cs; } @@ -150,8 +150,8 @@ ao_m25_read_capacity(uint8_t cs) uint8_t capacity; M25_SELECT(cs); ao_m25_instruction[0] = M25_RDID; - ao_spi_send(ao_m25_instruction, 1); - ao_spi_recv(ao_m25_instruction, M25_RDID_LEN); + ao_spi_send(ao_m25_instruction, 1, AO_M25_SPI_BUS); + ao_spi_recv(ao_m25_instruction, M25_RDID_LEN, AO_M25_SPI_BUS); M25_DESELECT(cs); /* Check to see if the chip is present */ @@ -183,7 +183,7 @@ ao_m25_set_address(uint32_t pos) chip = ao_m25_pin[chip]; #else - chip = M25_CS_MASK; + chip = AO_M25_SPI_CS_MASK; #endif ao_m25_wait_wip(chip); @@ -210,7 +210,7 @@ ao_m25_scan(void) #if M25_MAX_CHIPS > 1 ao_m25_numchips = 0; for (pin = 1; pin != 0; pin <<= 1) { - if (M25_CS_MASK & pin) { + if (AO_M25_SPI_CS_MASK & pin) { size = ao_m25_read_capacity(pin); if (size != 0) { ao_m25_size[ao_m25_numchips] = size; @@ -221,7 +221,7 @@ ao_m25_scan(void) } } #else - ao_m25_total = ao_m25_read_capacity(M25_CS_MASK); + ao_m25_total = ao_m25_read_capacity(AO_M25_SPI_CS_MASK); #endif if (!ao_m25_total) return 0; @@ -253,7 +253,7 @@ ao_storage_erase(uint32_t pos) __reentrant ao_m25_instruction[0] = M25_SE; M25_SELECT(cs); - ao_spi_send(ao_m25_instruction, 4); + ao_spi_send(ao_m25_instruction, 4, AO_M25_SPI_BUS); M25_DESELECT(cs); ao_m25_wip |= cs; @@ -280,8 +280,8 @@ ao_storage_device_write(uint32_t pos, __xdata void *d, uint16_t len) __reentrant ao_m25_instruction[0] = M25_PP; M25_SELECT(cs); - ao_spi_send(ao_m25_instruction, 4); - ao_spi_send(d, len); + ao_spi_send(ao_m25_instruction, 4, AO_M25_SPI_BUS); + ao_spi_send(d, len, AO_M25_SPI_BUS); M25_DESELECT(cs); ao_mutex_put(&ao_m25_mutex); @@ -306,8 +306,8 @@ ao_storage_device_read(uint32_t pos, __xdata void *d, uint16_t len) __reentrant /* No need to use the FAST_READ as we're running at only 8MHz */ ao_m25_instruction[0] = M25_READ; M25_SELECT(cs); - ao_spi_send(ao_m25_instruction, 4); - ao_spi_recv(d, len); + ao_spi_send(ao_m25_instruction, 4, AO_M25_SPI_BUS); + ao_spi_recv(d, len, AO_M25_SPI_BUS); M25_DESELECT(cs); ao_mutex_put(&ao_m25_mutex); @@ -350,14 +350,14 @@ ao_storage_device_info(void) __reentrant printf ("Available chips:\n"); for (cs = 1; cs != 0; cs <<= 1) { - if ((M25_CS_MASK & cs) == 0) + if ((AO_M25_SPI_CS_MASK & cs) == 0) continue; ao_mutex_get(&ao_m25_mutex); M25_SELECT(cs); ao_m25_instruction[0] = M25_RDID; - ao_spi_send(ao_m25_instruction, 1); - ao_spi_recv(ao_m25_instruction, M25_RDID_LEN); + ao_spi_send(ao_m25_instruction, 1, AO_M25_SPI_BUS); + ao_spi_recv(ao_m25_instruction, M25_RDID_LEN, AO_M25_SPI_BUS); M25_DESELECT(cs); printf ("Select %02x manf %02x type %02x cap %02x uid %02x\n", @@ -373,10 +373,5 @@ ao_storage_device_info(void) __reentrant void ao_storage_device_init(void) { - /* Set up chip select wires */ - SPI_CS_PORT |= M25_CS_MASK; /* raise all CS pins */ - SPI_CS_DIR |= M25_CS_MASK; /* set CS pins as outputs */ -#ifdef SPI_CS_SEL - SPI_CS_SEL &= ~M25_CS_MASK; /* set CS pins as GPIO */ -#endif + ao_spi_init_cs (AO_M25_SPI_CS_PORT, AO_M25_SPI_CS_MASK); } diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 87748272..3c0a310d 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -155,8 +155,5 @@ void ao_ms5607_init(void) { ao_cmd_register(&ao_ms5607_cmds[0]); - - stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN); - stm_gpio_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, 1); - stm_moder_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, STM_MODER_OUTPUT); + ao_spi_init_cs(AO_MS5607_CS_GPIO, (1 << AO_MS5607_CS)); } diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 5b20a8a5..b0f2a612 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -38,7 +38,9 @@ ALTOS_SRC = \ ao_spi_stm.c \ ao_ms5607.c \ ao_adc_stm.c \ - ao_beep_stm.c + ao_beep_stm.c \ + ao_storage.c \ + ao_m25.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index eaab9b50..77a2bf0a 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -49,6 +49,7 @@ main(void) ao_ms5607_init(); ao_beep_init(); ao_adc_init(); + ao_storage_init(); ao_cmd_register(&ao_mm_cmds[0]); ao_start_scheduler(); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index e200a692..46098d34 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -182,4 +182,13 @@ struct ao_adc { #define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) #define AO_MS5607_SPI_INDEX (STM_SPI_INDEX(1)) +/* + * SPI Flash memory + */ + +#define M25_MAX_CHIPS 1 +#define AO_M25_SPI_CS_PORT stm_gpiod +#define AO_M25_SPI_CS_MASK (1 << 3) +#define AO_M25_SPI_BUS STM_SPI_INDEX(2) + #endif /* _AO_PINS_H_ */ diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 052abb65..309937d5 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -37,6 +37,55 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); void ao_spi_init(void); +#define ao_spi_get_mask(reg,mask,bus) do { \ + ao_spi_get(bus); \ + (reg).bsrr = ((uint32_t) mask) << 16; \ + } while (0) + +#define ao_spi_put_mask(reg,mask,bus) do { \ + (reg).bsrr = mask; \ + ao_spi_put(bus); \ + } while (0) + +#define ao_stm_enable_port(port) do { \ + if (&(port) == &stm_gpioa) \ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); \ + else if (&(port) == &stm_gpiob) \ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); \ + else if (&(port) == &stm_gpioc) \ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN); \ + else if (&(port) == &stm_gpiod) \ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN); \ + else if (&(port) == &stm_gpioe) \ + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOEEN); \ + } while (0) + + +#define ao_stm_enable_cs(port,bit) do { \ + stm_gpio_set(&(port), bit, 1); \ + stm_moder_set(&(port), bit, STM_MODER_OUTPUT); \ + } while (0) + +#define ao_spi_init_cs(port, mask) do { \ + ao_stm_enable_port(port); \ + if (mask & 0x0001) ao_stm_enable_cs(port, 0); \ + if (mask & 0x0002) ao_stm_enable_cs(port, 1); \ + if (mask & 0x0004) ao_stm_enable_cs(port, 2); \ + if (mask & 0x0008) ao_stm_enable_cs(port, 3); \ + if (mask & 0x0010) ao_stm_enable_cs(port, 4); \ + if (mask & 0x0020) ao_stm_enable_cs(port, 5); \ + if (mask & 0x0040) ao_stm_enable_cs(port, 6); \ + if (mask & 0x0080) ao_stm_enable_cs(port, 7); \ + if (mask & 0x0100) ao_stm_enable_cs(port, 8); \ + if (mask & 0x0200) ao_stm_enable_cs(port, 9); \ + if (mask & 0x0400) ao_stm_enable_cs(port, 10); \ + if (mask & 0x0800) ao_stm_enable_cs(port, 11); \ + if (mask & 0x1000) ao_stm_enable_cs(port, 12); \ + if (mask & 0x2000) ao_stm_enable_cs(port, 13); \ + if (mask & 0x4000) ao_stm_enable_cs(port, 14); \ + if (mask & 0x8000) ao_stm_enable_cs(port, 15); \ + } while (0) + /* ao_dma_stm.c */ diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 44a372cc..29b97385 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -229,4 +229,7 @@ #define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) #define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) +#define AO_M25_SPI_CS_PORT SPI_CS_PORT +#define AO_M25_SPI_CS_MASK M25_CS_MASK + #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 150881f86f8d90b5867507889441990d18223e62 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Apr 2012 23:25:36 -0700 Subject: altos: Add register definitions for STM syscfg and usb Signed-off-by: Keith Packard --- src/stm/stm32l.h | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 132 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index b922b6bc..e884ef04 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -289,7 +289,7 @@ struct stm_rcc { vuint32_t ahbrstr; vuint32_t apb2rstr; - vuint32_t abp1rstr; + vuint32_t apb1rstr; vuint32_t ahbenr; vuint32_t apb2enr; @@ -852,6 +852,25 @@ isr(tim7) #define STM_ISR_TIM6_POS 43 #define STM_ISR_TIM7_POS 44 +struct stm_syscfg { + vuint32_t memrmp; + vuint32_t pmc; + vuint32_t exticr1; + vuint32_t exticr2; + vuint32_t exticr3; + vuint32_t exticr4; +}; + +extern struct stm_syscfg stm_syscfg; + +#define STM_SYSCFG_MEMRMP_MEM_MODE 0 +#define STM_SYSCFG_MEMRMP_MEM_MODE_MAIN_FLASH 0 +#define STM_SYSCFG_MEMRMP_MEM_MODE_SYSTEM_FLASH 1 +#define STM_SYSCFG_MEMRMP_MEM_MODE_SRAM 3 +#define STM_SYSCFG_MEMRMP_MEM_MODE_MASK 3 + +#define STM_SYSCFG_PMC_USB_PU 0 + struct stm_dma_channel { vuint32_t ccr; vuint32_t cndtr; @@ -1458,4 +1477,116 @@ extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4; #define STM_TIM234_CCER_CC1P 1 #define STM_TIM234_CCER_CC1E 0 +struct stm_usb { + vuint32_t epr[8]; + uint8_t reserved_20[0x40 - 0x20]; + vuint32_t cntr; + vuint32_t istr; + vuint32_t fnr; + vuint32_t daddr; + vuint32_t btable; +}; + +#define STM_USB_EPR_CTR_RX 15 +#define STM_USB_EPR_CTR_RX_WRITE_INVARIANT 1 +#define STM_USB_EPR_DTOG_RX 14 +#define STM_USB_EPR_DTOG_RX_WRITE_INVARIANT 0 +#define STM_USB_EPR_STAT_RX 12 +#define STM_USB_EPR_STAT_RX_DISABLED 0 +#define STM_USB_EPR_STAT_RX_STALL 1 +#define STM_USB_EPR_STAT_RX_NAK 2 +#define STM_USB_EPR_STAT_RX_VALID 3 +#define STM_USB_EPR_STAT_RX_MASK 3 +#define STM_USB_EPR_STAT_RX_WRITE_INVARIANT 0 +#define STM_USB_EPR_SETUP 11 +#define STM_USB_EPR_EP_TYPE 9 +#define STM_USB_EPR_EP_TYPE_BULK 0 +#define STM_USB_EPR_EP_TYPE_CONTROL 1 +#define STM_USB_EPR_EP_TYPE_ISO 2 +#define STM_USB_EPR_EP_TYPE_INTERRUPT 3 +#define STM_USB_EPR_EP_TYPE_MASK 3 +#define STM_USB_EPR_EP_KIND 8 +#define STM_USB_EPR_EP_KIND_DBL_BUF 1 /* Bulk */ +#define STM_USB_EPR_EP_KIND_STATUS_OUT 1 /* Control */ +#define STM_USB_EPR_CTR_TX 7 +#define STM_USB_CTR_TX_WRITE_INVARIANT 1 +#define STM_USB_EPR_DTOG_TX 6 +#define STM_USB_EPR_DTOG_TX_WRITE_INVARIANT 0 +#define STM_USB_EPR_STAT_TX 4 +#define STM_USB_EPR_STAT_TX_DISABLED 0 +#define STM_USB_EPR_STAT_TX_STALL 1 +#define STM_USB_EPR_STAT_TX_NAK 2 +#define STM_USB_EPR_STAT_TX_VALID 3 +#define STM_USB_EPR_STAT_TX_WRITE_INVARIANT 0 +#define STM_USB_EPR_STAT_TX_MASK 3 +#define STM_USB_EPR_EA 0 +#define STM_USB_EPR_EA_MASK 0xf + +#define STM_USB_CNTR_CTRM 15 +#define STM_USB_CNTR_PMAOVRM 14 +#define STM_USB_CNTR_ERRM 13 +#define STM_USB_CNTR_WKUPM 12 +#define STM_USB_CNTR_SUSPM 11 +#define STM_USB_CNTR_RESETM 10 +#define STM_USB_CNTR_SOFM 9 +#define STM_USB_CNTR_ESOFM 8 +#define STM_USB_CNTR_RESUME 4 +#define STM_USB_CNTR_FSUSP 3 +#define STM_USB_CNTR_LP_MODE 2 +#define STM_USB_CNTR_PDWN 1 +#define STM_USB_CNTR_FRES 0 + +#define STM_USB_ISTR_CTR 15 +#define STM_USB_ISTR_PMAOVR 14 +#define STM_USB_ISTR_ERR 13 +#define STM_USB_ISTR_WKUP 12 +#define STM_USB_ISTR_SUSP 11 +#define STM_USB_ISTR_RESET 10 +#define STM_USB_ISTR_SOF 9 +#define STM_USB_ISTR_ESOF 8 +#define STM_USB_ISTR_DIR 4 +#define STM_USB_ISTR_EP_ID 0 +#define STM_USB_ISTR_EP_ID_MASK 0xf + +#define STM_USB_FNR_RXDP 15 +#define STM_USB_FNR_RXDM 14 +#define STM_USB_FNR_LCK 13 +#define STM_USB_FNR_LSOF 11 +#define STM_USB_FNR_LSOF_MASK 0x3 +#define STM_USB_FNR_FN 0 +#define STM_USB_FNR_FN_MASK 0x7ff + +#define STM_USB_DADDR_EF 7 +#define STM_USB_DADDR_ADD 0 +#define STM_USB_DADDR_ADD_MASK 0x7f + +extern struct stm_usb stm_usb; + +union stm_usb_bdt { + struct { + vuint32_t addr_tx; + vuint32_t count_tx; + vuint32_t addr_rx; + vuint32_t count_rx; + } single; + struct { + vuint32_t addr; + vuint32_t count; + } double_tx[2]; + struct { + vuint32_t addr; + vuint32_t count; + } double_rx[2]; +}; + +#define STM_USB_BDT_COUNT_RX_BL_SIZE 15 +#define STM_USB_BDT_COUNT_RX_NUM_BLOCK 10 +#define STM_USB_BDT_COUNT_RX_NUM_BLOCK_MASK 0x1f +#define STM_USB_BDT_COUNT_RX_COUNT_RX 0 +#define STM_USB_BDT_COUNT_RX_COUNT_RX_MASK 0x1ff + +#define STM_USB_BDT_SIZE 8 + +extern uint8_t stm_usb_sram[]; + #endif /* _STM32L_H_ */ -- cgit v1.2.3 From afd52a8b54fe31577d939a161ea9cf5ad48e3a43 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Apr 2012 23:26:30 -0700 Subject: altos: Add STM ao_arch_reboot implementation Uses the AIRCR register to force a reset Signed-off-by: Keith Packard --- src/stm/ao_arch.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index dd9579f1..adb6eb94 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -42,7 +42,9 @@ #define __interrupt(n) #define __at(n) -#define ao_arch_reboot() /* XXX */ +#define CORTEX_M3_AIRCR ((uint32_t *) 0xe000ed0c) + +#define ao_arch_reboot() (*((uint32_t *) 0xe000ed0c) = 0x05fa0004) #define ao_arch_nop() asm("nop") -- cgit v1.2.3 From d432307a3c2709634350eaa1262b935028d073d3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Apr 2012 23:28:45 -0700 Subject: altos: Add STM USB driver Emulates the usual CDC-ACM device Signed-off-by: Keith Packard --- src/stm/ao_usb.h | 101 +++++ src/stm/ao_usb_stm.c | 1027 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1128 insertions(+) create mode 100644 src/stm/ao_usb.h create mode 100644 src/stm/ao_usb_stm.c (limited to 'src') diff --git a/src/stm/ao_usb.h b/src/stm/ao_usb.h new file mode 100644 index 00000000..d3129d34 --- /dev/null +++ b/src/stm/ao_usb.h @@ -0,0 +1,101 @@ +/* + * 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. + */ + +#ifndef _AO_USB_H_ +#define _AO_USB_H_ + +#define AO_USB_SETUP_DIR_MASK (0x01 << 7) +#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) +#define AO_USB_SETUP_RECIP_MASK (0x1f) + +#define AO_USB_DIR_OUT 0 +#define AO_USB_DIR_IN (1 << 7) + +#define AO_USB_TYPE_STANDARD 0 +#define AO_USB_TYPE_CLASS (1 << 5) +#define AO_USB_TYPE_VENDOR (2 << 5) +#define AO_USB_TYPE_RESERVED (3 << 5) + +#define AO_USB_RECIP_DEVICE 0 +#define AO_USB_RECIP_INTERFACE 1 +#define AO_USB_RECIP_ENDPOINT 2 +#define AO_USB_RECIP_OTHER 3 + +/* standard requests */ +#define AO_USB_REQ_GET_STATUS 0x00 +#define AO_USB_REQ_CLEAR_FEATURE 0x01 +#define AO_USB_REQ_SET_FEATURE 0x03 +#define AO_USB_REQ_SET_ADDRESS 0x05 +#define AO_USB_REQ_GET_DESCRIPTOR 0x06 +#define AO_USB_REQ_SET_DESCRIPTOR 0x07 +#define AO_USB_REQ_GET_CONFIGURATION 0x08 +#define AO_USB_REQ_SET_CONFIGURATION 0x09 +#define AO_USB_REQ_GET_INTERFACE 0x0A +#define AO_USB_REQ_SET_INTERFACE 0x0B +#define AO_USB_REQ_SYNCH_FRAME 0x0C + +#define AO_USB_DESC_DEVICE 1 +#define AO_USB_DESC_CONFIGURATION 2 +#define AO_USB_DESC_STRING 3 +#define AO_USB_DESC_INTERFACE 4 +#define AO_USB_DESC_ENDPOINT 5 +#define AO_USB_DESC_DEVICE_QUALIFIER 6 +#define AO_USB_DESC_OTHER_SPEED 7 +#define AO_USB_DESC_INTERFACE_POWER 8 + +#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) +#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) + +#define AO_USB_CONTROL_EP 0 +#define AO_USB_INT_EP 1 +#define AO_USB_OUT_EP 4 +#define AO_USB_IN_EP 5 +#define AO_USB_CONTROL_SIZE 32 +/* + * Double buffer IN and OUT EPs, so each + * gets half of the available space + * + * Ah, but USB bulk packets can only come in 8, 16, 32 and 64 + * byte sizes, so we'll use 64 for everything + */ +#define AO_USB_INT_SIZE 8 +#define AO_USB_IN_SIZE 64 +#define AO_USB_OUT_SIZE 64 + +#define AO_USB_EP0_IDLE 0 +#define AO_USB_EP0_DATA_IN 1 +#define AO_USB_EP0_DATA_OUT 2 + +#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) + +/* CDC definitions */ +#define CS_INTERFACE 0x24 +#define CS_ENDPOINT 0x25 + +#define SET_LINE_CODING 0x20 +#define GET_LINE_CODING 0x21 +#define SET_CONTROL_LINE_STATE 0x22 + +/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ +struct ao_usb_line_coding { + uint32_t rate; + uint8_t char_format; + uint8_t parity; + uint8_t data_bits; +} ; + +#endif /* _AO_USB_H_ */ diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c new file mode 100644 index 00000000..5a447d43 --- /dev/null +++ b/src/stm/ao_usb_stm.c @@ -0,0 +1,1027 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_usb.h" +#include "ao_product.h" + +#define USB_DEBUG 0 +#define USB_DEBUG_DATA 0 + +#if USB_DEBUG +#define debug(format, args...) printf(format, ## args); +#else +#define debug(format, args...) +#endif + +#if USB_DEBUG_DATA +#define debug_data(format, args...) printf(format, ## args); +#else +#define debug_data(format, args...) +#endif + +struct ao_task ao_usb_task; + +struct ao_usb_setup { + uint8_t dir_type_recip; + uint8_t request; + uint16_t value; + uint16_t index; + uint16_t length; +} ao_usb_setup; + +static uint8_t ao_usb_ep0_state; +static const uint8_t * ao_usb_ep0_in_data; +static uint8_t ao_usb_ep0_in_len; +static uint8_t ao_usb_ep0_in_pending; +static uint8_t ao_usb_ep0_in_buf[2]; +static uint8_t ao_usb_ep0_out_len; +static uint8_t *ao_usb_ep0_out_data; +static union stm_usb_bdt *ao_usb_bdt; +static uint16_t ao_usb_sram_addr; +static uint8_t ao_usb_tx_buffer[AO_USB_IN_SIZE]; +static uint8_t ao_usb_tx_count; +static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE]; +static uint8_t ao_usb_rx_count, ao_usb_rx_pos; + +#define AO_USB_INT_EPR 1 +#define AO_USB_OUT_EPR 2 +#define AO_USB_IN_EPR 3 + +/* + * Pointers into the USB packet buffer area + */ +static uint32_t *ao_usb_ep0_tx_buffer; +static uint32_t *ao_usb_ep0_rx_buffer; + +static uint32_t *ao_usb_in_tx_buffer; +static uint32_t *ao_usb_out_rx_buffer; + +static uint8_t ao_usb_in_flushed; +static uint8_t ao_usb_in_pending; +static uint8_t ao_usb_out_avail; +static uint8_t ao_usb_running; +static uint8_t ao_usb_configuration; +static uint8_t ueienx_0; + +#define AO_USB_EP0_GOT_RESET 1 +#define AO_USB_EP0_GOT_SETUP 2 +#define AO_USB_EP0_GOT_RX_DATA 4 +#define AO_USB_EP0_GOT_TX_ACK 8 + +static uint8_t ao_usb_ep0_receive; +static uint8_t ao_usb_address; +static uint8_t ao_usb_address_pending; + +static inline uint32_t set_toggle(uint32_t current_value, + uint32_t mask, + uint32_t desired_value) +{ + return (current_value ^ desired_value) & mask; +} + +static inline uint32_t *ao_usb_packet_buffer_addr(uint16_t sram_addr) +{ + return (uint32_t *) (stm_usb_sram + 2 * sram_addr); +} + +static inline uint32_t ao_usb_epr_stat_rx(uint32_t epr) { + return (epr >> STM_USB_EPR_STAT_RX) & STM_USB_EPR_STAT_RX_MASK; +} + +static inline uint32_t ao_usb_epr_stat_tx(uint32_t epr) { + return (epr >> STM_USB_EPR_STAT_TX) & STM_USB_EPR_STAT_TX_MASK; +} + +static inline uint32_t ao_usb_epr_ctr_rx(uint32_t epr) { + return (epr >> STM_USB_EPR_CTR_RX) & 1; +} + +static inline uint32_t ao_usb_epr_ctr_tx(uint32_t epr) { + return (epr >> STM_USB_EPR_CTR_TX) & 1; +} + +static inline uint32_t ao_usb_epr_setup(uint32_t epr) { + return (epr >> STM_USB_EPR_SETUP) & 1; +} + +static inline uint32_t ao_usb_epr_dtog_rx(uint32_t epr) { + return (epr >> STM_USB_EPR_DTOG_RX) & 1; +} + +static inline uint32_t ao_usb_epr_dtog_tx(uint32_t epr) { + return (epr >> STM_USB_EPR_DTOG_TX) & 1; +} + +/* + * Set current device address and mark the + * interface as active + */ +void +ao_usb_set_address(uint8_t address) +{ + debug("ao_usb_set_address %02x\n", address); + stm_usb.daddr = (1 << STM_USB_DADDR_EF) | address; + ao_usb_address_pending = 0; +} + +/* + * Set just endpoint 0, for use during startup + */ + +static void +ao_usb_set_ep0(void) +{ + uint32_t epr; + int e; + + ao_usb_sram_addr = 0; + + /* buffer table is at the start of USB memory */ + stm_usb.btable = 0; + ao_usb_bdt = (void *) stm_usb_sram; + + ao_usb_sram_addr += 8 * STM_USB_BDT_SIZE; + + /* Set up EP 0 - a Control end point with 32 bytes of in and out buffers */ + + ao_usb_bdt[0].single.addr_tx = ao_usb_sram_addr; + ao_usb_bdt[0].single.count_tx = 0; + ao_usb_ep0_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_CONTROL_SIZE; + + ao_usb_bdt[0].single.addr_rx = ao_usb_sram_addr; + ao_usb_bdt[0].single.count_rx = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) | + (((AO_USB_CONTROL_SIZE / 32) - 1) << STM_USB_BDT_COUNT_RX_NUM_BLOCK)); + ao_usb_ep0_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_CONTROL_SIZE; + + cli(); + epr = stm_usb.epr[0]; + epr = ((STM_USB_EPR_CTR_RX_WRITE_INVARIANT << STM_USB_EPR_CTR_RX) | + (STM_USB_EPR_DTOG_RX_WRITE_INVARIANT << STM_USB_EPR_DTOG_RX) | + set_toggle(epr, + (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), + (STM_USB_EPR_STAT_RX_VALID << STM_USB_EPR_STAT_RX)) | + (STM_USB_EPR_EP_TYPE_CONTROL << STM_USB_EPR_EP_TYPE) | + (0 << STM_USB_EPR_EP_KIND) | + (STM_USB_CTR_TX_WRITE_INVARIANT << STM_USB_EPR_CTR_TX) | + (STM_USB_EPR_DTOG_TX_WRITE_INVARIANT << STM_USB_EPR_DTOG_TX) | + set_toggle(epr, + (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), + (STM_USB_EPR_STAT_TX_NAK << STM_USB_EPR_STAT_TX)) | + (AO_USB_CONTROL_EP << STM_USB_EPR_EA)); + stm_usb.epr[0] = epr; + sei(); + debug ("epr 0 now %x\n", stm_usb.epr[0]); + + /* Clear all of the other endpoints */ + for (e = 1; e < 8; e++) { + cli(); + epr = stm_usb.epr[e]; + epr = ((STM_USB_EPR_CTR_RX_WRITE_INVARIANT << STM_USB_EPR_CTR_RX) | + (STM_USB_EPR_DTOG_RX_WRITE_INVARIANT << STM_USB_EPR_DTOG_RX) | + set_toggle(epr, + (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), + (STM_USB_EPR_STAT_RX_DISABLED << STM_USB_EPR_STAT_RX)) | + (STM_USB_EPR_EP_TYPE_CONTROL << STM_USB_EPR_EP_TYPE) | + (0 << STM_USB_EPR_EP_KIND) | + (STM_USB_CTR_TX_WRITE_INVARIANT << STM_USB_EPR_CTR_TX) | + (STM_USB_EPR_DTOG_TX_WRITE_INVARIANT << STM_USB_EPR_DTOG_TX) | + set_toggle(epr, + (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), + (STM_USB_EPR_STAT_TX_DISABLED << STM_USB_EPR_STAT_TX)) | + (0 << STM_USB_EPR_EA)); + stm_usb.epr[e] = epr; + sei(); + } + + ao_usb_set_address(0); +} + +static void +ao_usb_set_configuration(void) +{ + uint32_t epr; + + debug ("ao_usb_set_configuration\n"); + + /* Set up the INT end point */ + ao_usb_bdt[AO_USB_INT_EPR].single.addr_tx = ao_usb_sram_addr; + ao_usb_bdt[AO_USB_INT_EPR].single.count_tx = 0; + ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_INT_SIZE; + + cli(); + epr = stm_usb.epr[AO_USB_INT_EPR]; + epr = ((0 << STM_USB_EPR_CTR_RX) | + (epr & (1 << STM_USB_EPR_DTOG_RX)) | + set_toggle(epr, + (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), + (STM_USB_EPR_STAT_RX_DISABLED << STM_USB_EPR_STAT_RX)) | + (STM_USB_EPR_EP_TYPE_CONTROL << STM_USB_EPR_EP_TYPE) | + (0 << STM_USB_EPR_EP_KIND) | + (0 << STM_USB_EPR_CTR_TX) | + (epr & (1 << STM_USB_EPR_DTOG_TX)) | + set_toggle(epr, + (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), + (STM_USB_EPR_STAT_TX_NAK << STM_USB_EPR_STAT_TX)) | + (AO_USB_INT_EP << STM_USB_EPR_EA)); + stm_usb.epr[AO_USB_INT_EPR] = epr; + sei(); + debug ("writing epr[%d] 0x%08x wrote 0x%08x\n", + AO_USB_INT_EPR, epr, stm_usb.epr[AO_USB_INT_EPR]); + + /* Set up the OUT end point */ + ao_usb_bdt[AO_USB_OUT_EPR].single.addr_rx = ao_usb_sram_addr; + ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) | + (((AO_USB_OUT_SIZE / 32) - 1) << STM_USB_BDT_COUNT_RX_NUM_BLOCK)); + ao_usb_out_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_OUT_SIZE; + + cli(); + epr = stm_usb.epr[AO_USB_OUT_EPR]; + epr = ((0 << STM_USB_EPR_CTR_RX) | + (epr & (1 << STM_USB_EPR_DTOG_RX)) | + set_toggle(epr, + (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), + (STM_USB_EPR_STAT_RX_VALID << STM_USB_EPR_STAT_RX)) | + (STM_USB_EPR_EP_TYPE_CONTROL << STM_USB_EPR_EP_TYPE) | + (0 << STM_USB_EPR_EP_KIND) | + (0 << STM_USB_EPR_CTR_TX) | + (epr & (1 << STM_USB_EPR_DTOG_TX)) | + set_toggle(epr, + (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), + (STM_USB_EPR_STAT_TX_DISABLED << STM_USB_EPR_STAT_TX)) | + (AO_USB_OUT_EP << STM_USB_EPR_EA)); + stm_usb.epr[AO_USB_OUT_EPR] = epr; + sei(); + debug ("writing epr[%d] 0x%08x wrote 0x%08x\n", + AO_USB_OUT_EPR, epr, stm_usb.epr[AO_USB_OUT_EPR]); + + /* Set up the IN end point */ + ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_sram_addr; + ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = 0; + ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); + ao_usb_sram_addr += AO_USB_IN_SIZE; + + cli(); + epr = stm_usb.epr[AO_USB_IN_EPR]; + epr = ((0 << STM_USB_EPR_CTR_RX) | + (epr & (1 << STM_USB_EPR_DTOG_RX)) | + set_toggle(epr, + (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), + (STM_USB_EPR_STAT_RX_DISABLED << STM_USB_EPR_STAT_RX)) | + (STM_USB_EPR_EP_TYPE_CONTROL << STM_USB_EPR_EP_TYPE) | + (0 << STM_USB_EPR_EP_KIND) | + (0 << STM_USB_EPR_CTR_TX) | + (epr & (1 << STM_USB_EPR_DTOG_TX)) | + set_toggle(epr, + (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), + (STM_USB_EPR_STAT_TX_NAK << STM_USB_EPR_STAT_TX)) | + (AO_USB_IN_EP << STM_USB_EPR_EA)); + stm_usb.epr[AO_USB_IN_EPR] = epr; + sei(); + debug ("writing epr[%d] 0x%08x wrote 0x%08x\n", + AO_USB_IN_EPR, epr, stm_usb.epr[AO_USB_IN_EPR]); + ao_usb_running = 1; +} + +static uint16_t control_count; +static uint16_t in_count; +static uint16_t out_count; +static uint16_t reset_count; + +/* + * Write these values to preserve register contents under HW changes + */ + +#define STM_USB_EPR_INVARIANT ((1 << STM_USB_EPR_CTR_RX) | \ + (STM_USB_EPR_DTOG_RX_WRITE_INVARIANT << STM_USB_EPR_DTOG_RX) | \ + (STM_USB_EPR_STAT_RX_WRITE_INVARIANT << STM_USB_EPR_STAT_RX) | \ + (1 << STM_USB_EPR_CTR_TX) | \ + (STM_USB_EPR_DTOG_TX_WRITE_INVARIANT << STM_USB_EPR_DTOG_TX) | \ + (STM_USB_EPR_STAT_TX_WRITE_INVARIANT << STM_USB_EPR_STAT_TX)) + +#define STM_USB_EPR_INVARIANT_MASK ((1 << STM_USB_EPR_CTR_RX) | \ + (STM_USB_EPR_DTOG_RX_MASK << STM_USB_EPR_DTOG_RX) | \ + (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX) | \ + (1 << STM_USB_EPR_CTR_TX) | \ + (STM_USB_EPR_DTOG_TX_MASK << STM_USB_EPR_DTOG_TX) | \ + (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX)) + +/* + * These bits are purely under sw control, so preserve them in the + * register by re-writing what was read + */ +#define STM_USB_EPR_PRESERVE_MASK ((STM_USB_EPR_EP_TYPE_MASK << STM_USB_EPR_EP_TYPE) | \ + (1 << STM_USB_EPR_EP_KIND) | \ + (STM_USB_EPR_EA_MASK << STM_USB_EPR_EA)) + +void +stm_usb_lp_isr(void) +{ + uint32_t istr = stm_usb.istr; + + if (istr & (1 << STM_USB_ISTR_CTR)) { + uint8_t ep = istr & STM_USB_ISTR_EP_ID_MASK; + uint32_t epr, epr_write; + + /* Preserve the SW write bits, don't mess with most HW writable bits, + * clear the CTR_RX and CTR_TX bits + */ + epr = stm_usb.epr[ep]; + epr_write = epr; + epr_write &= STM_USB_EPR_PRESERVE_MASK; + epr_write |= STM_USB_EPR_INVARIANT; + epr_write &= ~(1 << STM_USB_EPR_CTR_RX); + epr_write &= ~(1 << STM_USB_EPR_CTR_TX); + stm_usb.epr[ep] = epr_write; + + switch (ep) { + case 0: + ++control_count; + if (ao_usb_epr_ctr_rx(epr)) { + if (ao_usb_epr_setup(epr)) + ao_usb_ep0_receive |= AO_USB_EP0_GOT_SETUP; + else + ao_usb_ep0_receive |= AO_USB_EP0_GOT_RX_DATA; + } + if (ao_usb_epr_ctr_tx(epr)) + ao_usb_ep0_receive |= AO_USB_EP0_GOT_TX_ACK; + ao_wakeup(&ao_usb_ep0_receive); + break; + case AO_USB_OUT_EPR: + ++out_count; + if (ao_usb_epr_ctr_rx(epr)) { + ao_usb_out_avail = 1; + ao_wakeup(&ao_stdin_ready); + } + break; + case AO_USB_IN_EPR: + ++in_count; + if (ao_usb_epr_ctr_tx(epr)) { + ao_usb_in_pending = 0; + ao_wakeup(&ao_usb_in_pending); + } + break; + } + return; + } + + if (istr & (1 << STM_USB_ISTR_RESET)) { + ++reset_count; + stm_usb.istr &= ~(1 << STM_USB_ISTR_RESET); + ao_usb_ep0_receive |= AO_USB_EP0_GOT_RESET; + ao_wakeup(&ao_usb_ep0_receive); + } +} + +void +stm_usb_hp_isr(void) +{ + stm_usb_lp_isr(); +} + +void +stm_usb_fs_wkup(void) +{ + /* USB wakeup, just clear the bit for now */ + stm_usb.istr &= ~(1 << STM_USB_ISTR_WKUP); +} + +static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; + +/* Walk through the list of descriptors and find a match + */ +static void +ao_usb_get_descriptor(uint16_t value) +{ + const uint8_t *descriptor; + uint8_t type = value >> 8; + uint8_t index = value; + + descriptor = ao_usb_descriptors; + while (descriptor[0] != 0) { + if (descriptor[1] == type && index-- == 0) { + if (type == AO_USB_DESC_CONFIGURATION) + ao_usb_ep0_in_len = descriptor[2]; + else + ao_usb_ep0_in_len = descriptor[0]; + ao_usb_ep0_in_data = descriptor; + break; + } + descriptor += descriptor[0]; + } +} + +static void +ao_usb_ep0_set_in_pending(uint8_t in_pending) +{ + ao_usb_ep0_in_pending = in_pending; + +#if 0 + if (in_pending) + ueienx_0 = ((1 << RXSTPE) | (1 << RXOUTE) | (1 << TXINE)); /* Enable IN interrupt */ +#endif +} + +/* The USB memory holds 16 bit values on 32 bit boundaries + * and must be accessed only in 32 bit units. Sigh. + */ + +static inline void +ao_usb_write_byte(uint8_t byte, uint32_t *base, uint16_t offset) +{ + base += offset >> 1; + if (offset & 1) { + *base = (*base & 0xff) | ((uint32_t) byte << 8); + } else { + *base = (*base & 0xff00) | byte; + } +} + +static inline void +ao_usb_write_short(uint16_t data, uint32_t *base, uint16_t offset) +{ + base[offset>>1] = data; +} + +static void +ao_usb_write(const uint8_t *src, uint32_t *base, uint16_t offset, uint16_t bytes) +{ + if (!bytes) + return; + if (offset & 1) { + debug_data (" %02x", src[0]); + ao_usb_write_byte(*src++, base, offset++); + bytes--; + } + while (bytes >= 2) { + debug_data (" %02x %02x", src[0], src[1]); + ao_usb_write_short((src[1] << 8) | src[0], base, offset); + offset += 2; + src += 2; + bytes -= 2; + } + if (bytes) { + debug_data (" %02x", src[0]); + ao_usb_write_byte(*src, base, offset); + } +} + +static inline uint8_t +ao_usb_read_byte(uint32_t *base, uint16_t offset) +{ + base += offset >> 1; + if (offset & 1) + return (*base >> 8) & 0xff; + else + return *base & 0xff; +} + +static inline uint16_t +ao_usb_read_short(uint32_t *base, uint16_t offset) +{ + return base[offset>>1]; +} + +static void +ao_usb_read(uint8_t *dst, uint32_t *base, uint16_t offset, uint16_t bytes) +{ + if (!bytes) + return; + if (offset & 1) { + *dst++ = ao_usb_read_byte(base, offset++); + debug_data (" %02x", dst[-1]); + bytes--; + } + while (bytes >= 2) { + uint16_t s = ao_usb_read_short(base, offset); + dst[0] = s; + dst[1] = s >> 8; + debug_data (" %02x %02x", dst[0], dst[1]); + offset += 2; + dst += 2; + bytes -= 2; + } + if (bytes) { + *dst = ao_usb_read_byte(base, offset); + debug_data (" %02x", dst[0]); + } +} + +static inline void +ao_usb_set_stat_tx(int ep, uint32_t stat_tx) { + uint32_t epr_write, epr_old, epr_new, epr_want; + + cli(); + epr_write = epr_old = stm_usb.epr[ep]; + epr_write &= STM_USB_EPR_PRESERVE_MASK; + epr_write |= STM_USB_EPR_INVARIANT; + epr_write |= set_toggle(epr_old, + STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX, + stat_tx << STM_USB_EPR_STAT_TX); + stm_usb.epr[ep] = epr_write; + epr_new = stm_usb.epr[ep]; + sei(); + epr_want = (epr_old & ~(STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX)) | + (stat_tx << STM_USB_EPR_STAT_TX); + if (epr_new != epr_want) { + debug ("**** set_stat_tx to %x. old %08x want %08x write %08x new %08x\n", + stat_tx, epr_old, epr_want, epr_write, epr_new); + } +} + +/* Send an IN data packet */ +static void +ao_usb_ep0_flush(void) +{ + uint8_t this_len; + + /* Check to see if the endpoint is still busy */ + if (ao_usb_epr_stat_tx(stm_usb.epr[0]) == STM_USB_EPR_STAT_TX_VALID) { + debug("EP0 not accepting IN data\n"); + ao_usb_ep0_set_in_pending(1); + } else { + this_len = ao_usb_ep0_in_len; + if (this_len > AO_USB_CONTROL_SIZE) + this_len = AO_USB_CONTROL_SIZE; + + ao_usb_ep0_in_len -= this_len; + + /* Set IN interrupt enable */ + if (ao_usb_ep0_in_len == 0 && this_len != AO_USB_CONTROL_SIZE) + ao_usb_ep0_set_in_pending(0); + else + ao_usb_ep0_set_in_pending(1); + + debug_data ("Flush EP0 len %d:", this_len); + ao_usb_write(ao_usb_ep0_in_data, ao_usb_ep0_tx_buffer, 0, this_len); + debug_data ("\n"); + ao_usb_ep0_in_data += this_len; + + /* Mark the endpoint as TX valid to send the packet */ + ao_usb_bdt[0].single.count_tx = this_len; + ao_usb_set_stat_tx(0, STM_USB_EPR_STAT_TX_VALID); + debug ("queue tx. epr 0 now %08x\n", stm_usb.epr[0]); + } +} + +static inline void +ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { + uint32_t epr_write, epr_old, epr_new, epr_want; + + cli(); + epr_write = epr_old = stm_usb.epr[ep]; + epr_write &= STM_USB_EPR_PRESERVE_MASK; + epr_write |= STM_USB_EPR_INVARIANT; + epr_write |= set_toggle(epr_old, + STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX, + stat_rx << STM_USB_EPR_STAT_RX); + stm_usb.epr[ep] = epr_write; + epr_new = stm_usb.epr[ep]; + sei(); + epr_want = (epr_old & ~(STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX)) | + (stat_rx << STM_USB_EPR_STAT_RX); + if (epr_new != epr_want) { + debug ("**** set_stat_rx to %x. old %08x want %08x write %08x new %08x\n", + stat_rx, epr_old, epr_want, epr_write, epr_new); + } +} + +/* Read data from the ep0 OUT fifo */ +static void +ao_usb_ep0_fill(void) +{ + uint16_t len = ao_usb_bdt[0].single.count_rx & STM_USB_BDT_COUNT_RX_COUNT_RX_MASK; + + if (len > ao_usb_ep0_out_len) + len = ao_usb_ep0_out_len; + ao_usb_ep0_out_len -= len; + + /* Pull all of the data out of the packet */ + debug_data ("Fill EP0 len %d:", len); + ao_usb_read(ao_usb_ep0_out_data, ao_usb_ep0_rx_buffer, 0, len); + debug_data ("\n"); + ao_usb_ep0_out_data += len; + + /* ACK the packet */ + ao_usb_set_stat_rx(0, STM_USB_EPR_STAT_RX_VALID); +} + +void +ao_usb_ep0_queue_byte(uint8_t a) +{ + ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a; +} + +static void +ao_usb_ep0_setup(void) +{ + /* Pull the setup packet out of the fifo */ + ao_usb_ep0_out_data = (uint8_t *) &ao_usb_setup; + ao_usb_ep0_out_len = 8; + ao_usb_ep0_fill(); + if (ao_usb_ep0_out_len != 0) { + debug ("invalid setup packet length\n"); + return; + } + + /* Figure out how to ACK the setup packet */ + if (ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) { + if (ao_usb_setup.length) + ao_usb_ep0_state = AO_USB_EP0_DATA_IN; + else + ao_usb_ep0_state = AO_USB_EP0_IDLE; + } else { + if (ao_usb_setup.length) + ao_usb_ep0_state = AO_USB_EP0_DATA_OUT; + else + ao_usb_ep0_state = AO_USB_EP0_IDLE; + } + + ao_usb_ep0_in_data = ao_usb_ep0_in_buf; + ao_usb_ep0_in_len = 0; + switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_TYPE_MASK) { + case AO_USB_TYPE_STANDARD: + debug ("Standard setup packet\n"); + switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_RECIP_MASK) { + case AO_USB_RECIP_DEVICE: + debug ("Device setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + debug ("get status\n"); + ao_usb_ep0_queue_byte(0); + ao_usb_ep0_queue_byte(0); + break; + case AO_USB_REQ_SET_ADDRESS: + debug ("set address %d\n", ao_usb_setup.value); + ao_usb_address = ao_usb_setup.value; + ao_usb_address_pending = 1; + break; + case AO_USB_REQ_GET_DESCRIPTOR: + debug ("get descriptor %d\n", ao_usb_setup.value); + ao_usb_get_descriptor(ao_usb_setup.value); + break; + case AO_USB_REQ_GET_CONFIGURATION: + debug ("get configuration %d\n", ao_usb_configuration); + ao_usb_ep0_queue_byte(ao_usb_configuration); + break; + case AO_USB_REQ_SET_CONFIGURATION: + ao_usb_configuration = ao_usb_setup.value; + debug ("set configuration %d\n", ao_usb_configuration); + ao_usb_set_configuration(); + break; + } + break; + case AO_USB_RECIP_INTERFACE: + debug ("Interface setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + ao_usb_ep0_queue_byte(0); + ao_usb_ep0_queue_byte(0); + break; + case AO_USB_REQ_GET_INTERFACE: + ao_usb_ep0_queue_byte(0); + break; + case AO_USB_REQ_SET_INTERFACE: + break; + } + break; + case AO_USB_RECIP_ENDPOINT: + debug ("Endpoint setup packet\n"); + switch(ao_usb_setup.request) { + case AO_USB_REQ_GET_STATUS: + ao_usb_ep0_queue_byte(0); + ao_usb_ep0_queue_byte(0); + break; + } + break; + } + break; + case AO_USB_TYPE_CLASS: + debug ("Class setup packet\n"); + switch (ao_usb_setup.request) { + case SET_LINE_CODING: + debug ("set line coding\n"); + ao_usb_ep0_out_len = 7; + ao_usb_ep0_out_data = (uint8_t *) &ao_usb_line_coding; + break; + case GET_LINE_CODING: + debug ("get line coding\n"); + ao_usb_ep0_in_len = 7; + ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding; + break; + case SET_CONTROL_LINE_STATE: + break; + } + break; + } + if (ao_usb_ep0_state != AO_USB_EP0_DATA_OUT) { + if (ao_usb_setup.length < ao_usb_ep0_in_len) + ao_usb_ep0_in_len = ao_usb_setup.length; + ao_usb_ep0_flush(); + } +} + +/* End point 0 receives all of the control messages. */ +static void +ao_usb_ep0(void) +{ + uint8_t intx, udint; + + debug ("usb task started\n"); + ao_usb_ep0_state = AO_USB_EP0_IDLE; + for (;;) { + uint8_t receive; + ao_arch_critical( + while (!(receive = ao_usb_ep0_receive)) + ao_sleep(&ao_usb_ep0_receive); + ao_usb_ep0_receive = 0; + ); + + if (receive & AO_USB_EP0_GOT_RESET) { + debug ("\treset\n"); + ao_usb_set_ep0(); + continue; + } + if (receive & AO_USB_EP0_GOT_SETUP) { + debug ("\tsetup\n"); + ao_usb_ep0_setup(); + } + if (receive & AO_USB_EP0_GOT_RX_DATA) { + debug ("\tgot rx data\n"); + ao_usb_ep0_fill(); + ao_usb_ep0_set_in_pending(1); + } + if (receive & AO_USB_EP0_GOT_TX_ACK) { + debug ("\tgot tx ack\n"); + ao_usb_ep0_flush(); + if (ao_usb_address_pending) { + ao_usb_set_address(ao_usb_address); + ao_usb_set_configuration(); + } + } + } +} + +/* Queue the current IN buffer for transmission */ +static void +ao_usb_in_send(void) +{ + debug ("send %d\n", ao_usb_tx_count); + ao_usb_write(ao_usb_tx_buffer, ao_usb_in_tx_buffer, 0, ao_usb_tx_count); + ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = ao_usb_tx_count; + ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID); + ao_usb_in_pending = 1; + ao_usb_tx_count = 0; +} + +/* Wait for a free IN buffer */ +static void +ao_usb_in_wait(void) +{ + for (;;) { + /* Check if the current buffer is writable */ + if (ao_usb_tx_count < AO_USB_IN_SIZE) + break; + + cli(); + /* Wait for an IN buffer to be ready */ + while (ao_usb_in_pending) + ao_sleep(&ao_usb_in_pending); + sei(); + } +} + +void +ao_usb_flush(void) __critical +{ + if (!ao_usb_running) + return; + + /* Anytime we've sent a character since + * the last time we flushed, we'll need + * to send a packet -- the only other time + * we would send a packet is when that + * packet was full, in which case we now + * want to send an empty packet + */ + if (!ao_usb_in_flushed) { + ao_usb_in_flushed = 1; + cli(); + /* Wait for an IN buffer to be ready */ + while (ao_usb_in_pending) + ao_sleep(&ao_usb_in_pending); + sei(); + ao_usb_in_send(); + } +} + +void +ao_usb_putchar(char c) __critical __reentrant +{ + if (!ao_usb_running) + return; + + ao_usb_in_wait(); + + ao_usb_tx_buffer[ao_usb_tx_count++] = (uint8_t) c; + + /* Send the packet when full */ + if (ao_usb_tx_count == AO_USB_IN_SIZE) + ao_usb_in_send(); + ao_usb_in_flushed = 0; +} + +static void +ao_usb_out_recv(void) +{ + ao_usb_out_avail = 0; + + ao_usb_rx_count = ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx & STM_USB_BDT_COUNT_RX_COUNT_RX_MASK; + + debug ("recv %d\n", ao_usb_rx_count); + debug_data("Fill OUT len %d:", ao_usb_rx_count); + ao_usb_read(ao_usb_rx_buffer, ao_usb_out_rx_buffer, 0, ao_usb_rx_count); + debug_data("\n"); + ao_usb_rx_pos = 0; + + /* ACK the packet */ + ao_usb_set_stat_rx(AO_USB_OUT_EPR, STM_USB_EPR_STAT_RX_VALID); +} + +static char +_ao_usb_pollchar(void) +{ + char c; + + if (!ao_usb_running) + return AO_READ_AGAIN; + + for (;;) { + if (ao_usb_rx_pos != ao_usb_rx_count) + break; + + /* Check to see if a packet has arrived */ + if (!ao_usb_out_avail) + return AO_READ_AGAIN; + ao_usb_out_recv(); + } + + /* Pull a character out of the fifo */ + c = ao_usb_rx_buffer[ao_usb_rx_pos++]; + return c; +} + +char +ao_usb_pollchar(void) +{ + char c; + cli(); + c = _ao_usb_pollchar(); + sei(); + return c; +} + +char +ao_usb_getchar(void) __critical +{ + char c; + + cli(); + while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN) + ao_sleep(&ao_stdin_ready); + sei(); + return c; +} + +void +ao_usb_disable(void) +{ + stm_usb.cntr = (1 << STM_USB_CNTR_FRES); + stm_usb.istr = 0; + + /* Disable USB pull-up */ + stm_syscfg.pmc &= ~(1 << STM_SYSCFG_PMC_USB_PU); + + /* Switch off the device */ + stm_usb.cntr = (1 << STM_USB_CNTR_PDWN) | (1 << STM_USB_CNTR_FRES); + + /* Disable the interface */ + stm_rcc.apb1enr &+ ~(1 << STM_RCC_APB1ENR_USBEN); +} + +void +ao_usb_enable(void) +{ + uint16_t tick; + + /* Enable SYSCFG */ + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGEN); + + /* Disable USB pull-up */ + stm_syscfg.pmc &= ~(1 << STM_SYSCFG_PMC_USB_PU); + + /* Enable USB device */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_USBEN); + + /* Do not touch the GPIOA configuration; USB takes priority + * over GPIO on pins A11 and A12, but if you select alternate + * input 10 (the documented correct selection), then USB is + * pulled low and doesn't work at all + */ + + /* Route interrupts */ + stm_nvic_set_priority(STM_ISR_USB_LP_POS, 3); + stm_nvic_set_enable(STM_ISR_USB_LP_POS); + + ao_usb_configuration = 0; + + stm_usb.cntr = (1 << STM_USB_CNTR_FRES); + + /* Clear the power down bit */ + stm_usb.cntr = 0; + + /* Clear any spurious interrupts */ + stm_usb.istr = 0; + + debug ("ao_usb_enable\n"); + + /* Enable interrupts */ + stm_usb.cntr = ((1 << STM_USB_CNTR_CTRM) | + (0 << STM_USB_CNTR_PMAOVRM) | + (0 << STM_USB_CNTR_ERRM) | + (0 << STM_USB_CNTR_WKUPM) | + (0 << STM_USB_CNTR_SUSPM) | + (1 << STM_USB_CNTR_RESETM) | + (0 << STM_USB_CNTR_SOFM) | + (0 << STM_USB_CNTR_ESOFM) | + (0 << STM_USB_CNTR_RESUME) | + (0 << STM_USB_CNTR_FSUSP) | + (0 << STM_USB_CNTR_LP_MODE) | + (0 << STM_USB_CNTR_PDWN) | + (0 << STM_USB_CNTR_FRES)); + + /* Enable USB pull-up */ + stm_syscfg.pmc |= (1 << STM_SYSCFG_PMC_USB_PU); +} + +#if USB_DEBUG +struct ao_task ao_usb_echo_task; + +static void +ao_usb_echo(void) +{ + char c; + + for (;;) { + c = ao_usb_getchar(); + ao_usb_putchar(c); + ao_usb_flush(); + } +} +#endif + +static void +ao_usb_irq(void) +{ + printf ("control: %d out: %d in: %d reset: %d\n", + control_count, out_count, in_count, reset_count); +} + +__code struct ao_cmds ao_usb_cmds[] = { + { ao_usb_irq, "I\0Show USB interrupt counts" }, + { 0, NULL } +}; + +void +ao_usb_init(void) +{ + ao_usb_enable(); + + debug ("ao_usb_init\n"); + ao_add_task(&ao_usb_task, ao_usb_ep0, "usb"); +#if USB_DEBUG + ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo"); +#endif + ao_cmd_register(&ao_usb_cmds[0]); +#if !USB_DEBUG + ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); +#endif +} -- cgit v1.2.3 From 93ef7e4a23d13540615f1a9782e1d58ddb7f258e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Apr 2012 23:29:38 -0700 Subject: altos: Use new USB driver in megametrum-v0.1 product Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 6 ++---- src/megametrum-v0.1/ao_megametrum.c | 1 + src/megametrum-v0.1/ao_pins.h | 6 +++--- 3 files changed, 6 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index b0f2a612..3c3d7173 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -40,7 +40,8 @@ ALTOS_SRC = \ ao_adc_stm.c \ ao_beep_stm.c \ ao_storage.c \ - ao_m25.c + ao_m25.c \ + ao_usb_stm.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM @@ -66,9 +67,6 @@ $(OBJ): $(INC) ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ -ao_product.rel: ao_product.c ao_product.h - $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< - distclean: clean clean: diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 77a2bf0a..9efde598 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -50,6 +50,7 @@ main(void) ao_beep_init(); ao_adc_init(); ao_storage_init(); + ao_usb_init(); ao_cmd_register(&ao_mm_cmds[0]); ao_start_scheduler(); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 46098d34..e4e5def6 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -21,7 +21,7 @@ /* 8MHz High speed external crystal */ #define AO_HSE 8000000 -/* PLLVCO = 96MHz (so that USB will work*/ +/* PLLVCO = 96MHz (so that USB will work) */ #define AO_PLLMUL 12 #define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12) @@ -61,8 +61,8 @@ #define ao_gps_putchar ao_serial3_putchar #define ao_gps_set_speed ao_serial3_set_speed -#define HAS_USB 0 -#define HAS_BEEP 0 +#define HAS_USB 1 +#define HAS_BEEP 1 #define HAS_SPI_1 1 #define SPI_1_PA5_PA6_PA7 1 -- cgit v1.2.3 From 49ac2828510e8b5fcba7e31631dac0580a455011 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Apr 2012 23:30:13 -0700 Subject: altos: Rework how STM clocks are initialized. Clean all of the RCC configuration up after turning on the clocks. Use the MSI clock during initialization to avoid messing around with the HSI clock temporarily. Allow for an external clock on the HSE line. Signed-off-by: Keith Packard --- src/stm/ao_timer.c | 151 ++++++++++++++++++++++++++++++++--------------------- 1 file changed, 92 insertions(+), 59 deletions(-) (limited to 'src') diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index e7f1ddfe..099a0ece 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -106,6 +106,53 @@ ao_clock_init(void) uint32_t cfgr; uint32_t cr; + /* Switch to MSI while messing about */ + stm_rcc.cr |= (1 << STM_RCC_CR_MSION); + while (!(stm_rcc.cr & (1 << STM_RCC_CR_MSIRDY))) + asm("nop"); + + /* reset SW, HPRE, PPRE1, PPRE2, MCOSEL and MCOPRE */ + stm_rcc.cfgr &= (uint32_t)0x88FFC00C; + + /* reset HSION, HSEON, CSSON and PLLON bits */ + stm_rcc.cr &= 0xeefefffe; + + /* reset PLLSRC, PLLMUL and PLLDIV bits */ + stm_rcc.cfgr &= 0xff02ffff; + + /* Disable all interrupts */ + stm_rcc.cir = 0; + +#if AO_HSE +#if AO_HSE_BYPASS + stm_rcc.cr |= (1 << STM_RCC_CR_HSEBYP); +#else + stm_rcc.cr &= ~(1 << STM_RCC_CR_HSEBYP); +#endif + /* Enable HSE clock */ + stm_rcc.cr |= (1 << STM_RCC_CR_HSEON); + while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSERDY))) + asm("nop"); + +#define STM_RCC_CFGR_SWS_TARGET_CLOCK (STM_RCC_CFGR_SWS_HSE << STM_RCC_CFGR_SWS) +#define STM_RCC_CFGR_SW_TARGET_CLOCK (STM_RCC_CFGR_SW_HSE) +#define STM_PLLSRC AO_HSE +#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK (1 << STM_RCC_CFGR_PLLSRC) +#else +#define STM_HSI 16000000 +#define STM_RCC_CFGR_SWS_TARGET_CLOCK (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS) +#define STM_RCC_CFGR_SW_TARGET_CLOCK (STM_RCC_CFGR_SW_HSI) +#define STM_PLLSRC STM_HSI +#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK (0 << STM_RCC_CFGR_PLLSRC) +#endif + +#if !AO_HSE || HAS_ADC + /* Enable HSI RC clock 16MHz */ + stm_rcc.cr |= (1 << STM_RCC_CR_HSION); + while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) + asm("nop"); +#endif + /* Set flash latency to tolerate 32MHz SYSCLK -> 1 wait state */ /* Enable 64-bit access and prefetch */ @@ -116,6 +163,24 @@ ao_clock_init(void) /* (haven't managed to run the CPU at 32MHz yet, it's at 16MHz) */ stm_flash.acr |= (1 << STM_FLASH_ACR_LATENCY); + /* Enable power interface clock */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); + + /* Set voltage range to 1.8V */ + + /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ + while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) + asm("nop"); + + /* Configure voltage scaling range */ + cr = stm_pwr.cr; + cr &= ~(STM_PWR_CR_VOS_MASK << STM_PWR_CR_VOS); + cr |= (STM_PWR_CR_VOS_1_8 << STM_PWR_CR_VOS); + stm_pwr.cr = cr; + + /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ + while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) + asm("nop"); /* HCLK to 16MHz -> AHB prescaler = /1 */ cfgr = stm_rcc.cfgr; @@ -138,65 +203,6 @@ ao_clock_init(void) cfgr |= (AO_RCC_CFGR_PPRE2_DIV << STM_RCC_CFGR_PPRE2); stm_rcc.cfgr = cfgr; - /* Enable power interface clock */ - stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN); - - - /* Set voltage range to 1.8V */ - - /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ - while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) - asm("nop"); - - /* Configure voltage scaling range */ - cr = stm_pwr.cr; - cr &= ~(STM_PWR_CR_VOS_MASK << STM_PWR_CR_VOS); - cr |= (STM_PWR_CR_VOS_1_8 << STM_PWR_CR_VOS); - stm_pwr.cr = cr; - - /* poll VOSF bit in PWR_CSR. Wait until it is reset to 0 */ - while ((stm_pwr.csr & (1 << STM_PWR_CSR_VOSF)) != 0) - asm("nop"); - -#if AO_HSE - /* Enable HSE clock */ - if (!(stm_rcc.cr & (1 << STM_RCC_CR_HSERDY))) { - stm_rcc.cr |= (1 << STM_RCC_CR_HSEON); - while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSERDY))) - asm("nop"); - } -#define STM_RCC_CFGR_SWS_TARGET_CLOCK (STM_RCC_CFGR_SWS_HSE << STM_RCC_CFGR_SWS) -#define STM_RCC_CFGR_SW_TARGET_CLOCK (STM_RCC_CFGR_SW_HSE) -#define STM_PLLSRC AO_HSE -#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK (1 << STM_RCC_CFGR_PLLSRC) -#else -#define STM_HSI 16000000 -#define STM_RCC_CFGR_SWS_TARGET_CLOCK (STM_RCC_CFGR_SWS_HSI << STM_RCC_CFGR_SWS) -#define STM_RCC_CFGR_SW_TARGET_CLOCK (STM_RCC_CFGR_SW_HSI) -#define STM_PLLSRC STM_HSI -#define STM_RCC_CFGR_PLLSRC_TARGET_CLOCK (0 << STM_RCC_CFGR_PLLSRC) -#endif - -#if !AO_HSE || HAS_ADC - /* Enable HSI RC clock 16MHz */ - if (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) { - stm_rcc.cr |= (1 << STM_RCC_CR_HSION); - while (!(stm_rcc.cr & (1 << STM_RCC_CR_HSIRDY))) - asm("nop"); - } -#endif - /* Switch to direct high speed clock for SYSCLK */ - if ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != - STM_RCC_CFGR_SWS_TARGET_CLOCK) { - cfgr = stm_rcc.cfgr; - cfgr &= ~(STM_RCC_CFGR_SW_MASK << STM_RCC_CFGR_SW); - cfgr |= STM_RCC_CFGR_SW_TARGET_CLOCK; - stm_rcc.cfgr = cfgr; - while ((stm_rcc.cfgr & (STM_RCC_CFGR_SWS_MASK << STM_RCC_CFGR_SWS)) != - STM_RCC_CFGR_SWS_TARGET_CLOCK); - asm("nop"); - } - /* Disable the PLL */ stm_rcc.cr &= ~(1 << STM_RCC_CR_PLLON); while (stm_rcc.cr & (1 << STM_RCC_CR_PLLRDY)) @@ -237,4 +243,31 @@ ao_clock_init(void) if (part == val) break; } + +#if 0 + stm_rcc.apb2rstr = 0xffff; + stm_rcc.apb1rstr = 0xffff; + stm_rcc.ahbrstr = 0x3f; + stm_rcc.ahbenr = (1 << STM_RCC_AHBENR_FLITFEN); + stm_rcc.apb2enr = 0; + stm_rcc.apb1enr = 0; + stm_rcc.ahbrstr = 0; + stm_rcc.apb1rstr = 0; + stm_rcc.apb2rstr = 0; +#endif + + /* Clear reset flags */ + stm_rcc.csr |= (1 << STM_RCC_CSR_RMVF); + + + /* Output SYSCLK on PA8 for measurments */ + + stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); + + stm_afr_set(&stm_gpioa, 8, STM_AFR_AF0); + stm_moder_set(&stm_gpioa, 8, STM_MODER_ALTERNATE); + stm_ospeedr_set(&stm_gpioa, 8, STM_OSPEEDR_40MHz); + + stm_rcc.cfgr |= (STM_RCC_CFGR_MCOPRE_DIV_1 << STM_RCC_CFGR_MCOPRE); + stm_rcc.cfgr |= (STM_RCC_CFGR_MCOSEL_HSE << STM_RCC_CFGR_MCOSEL); } -- cgit v1.2.3 From 6d1606895f70c6bca20c25084107f90bd0b613ec Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Apr 2012 23:31:28 -0700 Subject: altos: Switch stm-demo to HSE clock, add USB Requires that SB17 be soldered shut so that the MCO from the STlink CPU is available the target for HSE input. Signed-off-by: Keith Packard --- src/stm-demo/Makefile | 3 ++- src/stm-demo/ao_demo.c | 1 + src/stm-demo/ao_pins.h | 31 +++++++++++++++++++------------ 3 files changed, 22 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 2f156ea4..dd7e6e02 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -32,7 +32,8 @@ ALTOS_SRC = \ ao_dma_stm.c \ ao_spi_stm.c \ ao_adc_stm.c \ - ao_i2c_stm.c + ao_i2c_stm.c \ + ao_usb_stm.c PRODUCT=StmDemo-v0.0 PRODUCT_DEF=-DSTM_DEMO diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 879f7f75..7bb53047 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -174,6 +174,7 @@ main(void) ao_timer_set_adc_interval(100); ao_adc_init(); + ao_usb_init(); ao_cmd_register(&ao_demo_cmds[0]); diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 3192c2b7..1daab351 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -18,22 +18,29 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ -/* No external crystal */ -#define AO_HSE 0 +/* Bridge SB17 on the board and use the MCO from the other chip */ +#define AO_HSE 8000000 +#define AO_HSE_BYPASS 1 +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL 12 +#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12) + +/* SYSCLK = 32MHz */ +#define AO_PLLDIV 3 +#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHZ (CPU clock) */ #define AO_AHB_PRESCALER 1 #define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 -#define AO_APB1_PRESCALER 2 -#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2 - -#define AO_APB2_PRESCALER 2 -#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2 +/* Run APB1 at HCLK/1 */ +#define AO_APB1_PRESCALER 1 +#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_1 -#define AO_PLLMUL 6 -#define AO_PLLDIV 4 -#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_6) -#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_4) +/* Run APB2 at HCLK/1 */ +#define AO_APB2_PRESCALER 1 +#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_1 #define HAS_SERIAL_1 1 #define USE_SERIAL_1_STDIN 1 @@ -56,7 +63,7 @@ #define HAS_SPI_2 0 -#define HAS_USB 0 +#define HAS_USB 1 #define HAS_BEEP 0 #define PACKET_HAS_SLAVE 0 -- cgit v1.2.3 From f952f9c285e2718a433c8c720c9b5d9c369e7036 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 12 Apr 2012 14:50:12 -0700 Subject: altos: Start adding apogee lockout support Remove radio channel support too. Signed-off-by: Keith Packard --- src/cc1111/ao_radio.c | 2 +- src/core/ao.h | 20 ++------- src/core/ao_config.c | 112 ++++++++++++-------------------------------------- 3 files changed, 32 insertions(+), 102 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index ee506f89..51ed369b 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -286,7 +286,7 @@ ao_radio_get(uint8_t len) ao_config_get(); ao_mutex_get(&ao_radio_mutex); ao_radio_idle(); - RF_CHANNR = ao_config.radio_channel; + RF_CHANNR = 0; RF_FREQ2 = (uint8_t) (ao_config.radio_setting >> 16); RF_FREQ1 = (uint8_t) (ao_config.radio_setting >> 8); RF_FREQ0 = (uint8_t) (ao_config.radio_setting); diff --git a/src/core/ao.h b/src/core/ao.h index f7db3bf4..9a3b5829 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -1457,26 +1457,16 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 10 -#define AO_AES_LEN 16 - -#if HAS_RADIO_CHANNELS -#define AO_CHANNEL_NAME_LEN 10 +#define AO_CONFIG_MINOR 11 -#define AO_NUM_CHANNELS 10 - -struct ao_radio_channel { - char name[AO_CHANNEL_NAME_LEN]; - uint32_t kHz; -}; -#endif +#define AO_AES_LEN 16 struct ao_config { uint8_t major; uint8_t minor; uint16_t main_deploy; int16_t accel_plus_g; /* changed for minor version 2 */ - uint8_t radio_channel; + uint8_t _legacy_radio_channel; char callsign[AO_MAX_CALLSIGN + 1]; uint8_t apogee_delay; /* minor version 1 */ int16_t accel_minus_g; /* minor version 2 */ @@ -1488,9 +1478,7 @@ struct ao_config { uint8_t radio_enable; /* minor version 8 */ uint8_t aes_key[AO_AES_LEN]; /* minor version 9 */ uint32_t frequency; /* minor version 10 */ -#if HAS_RADIO_CHANNELS - struct ao_radio_channel radio_channels[AO_NUM_CHANNELS]; /* minor version 10 */ -#endif + uint16_t apogee_lockout; /* minor version 11 */ }; #define AO_IGNITE_MODE_DUAL 0 diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 32798f75..55fb8590 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -85,7 +85,6 @@ _ao_config_get(void) /* Version 0 stuff */ ao_config.main_deploy = AO_CONFIG_DEFAULT_MAIN_DEPLOY; - ao_config.radio_channel = AO_CONFIG_DEFAULT_RADIO_CHANNEL; ao_xmemset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); ao_xmemcpy(&ao_config.callsign, CODE_TO_XDATA(AO_CONFIG_DEFAULT_CALLSIGN), sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); @@ -113,19 +112,12 @@ _ao_config_get(void) ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; if (ao_config.minor < 8) ao_config.radio_enable = TRUE; -#if HAS_AES if (ao_config.minor < 9) ao_xmemset(&ao_config.aes_key, '\0', AO_AES_LEN); -#endif - if (ao_config.minor < 10) { + if (ao_config.minor < 10) ao_config.frequency = 434550; -#if HAS_RADIO_CHANNELS - ao_xmemset(&ao_config.radio_channels, '\0', sizeof (ao_config.radio_channels)); - ao_xmemcpy(&ao_config.radio_channels[0].name[0], - CODE_TO_XDATA("Channel 0"), sizeof("Channel 0")); - ao_config.radio_channels[0].kHz = 434550; -#endif - } + if (ao_config.minor < 11) + ao_config.apogee_lockout = 0; ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -184,25 +176,6 @@ ao_config_callsign_set(void) __reentrant _ao_config_edit_finish(); } -void -ao_config_radio_channel_show(void) __reentrant -{ - printf("Radio channel: %d\n", - ao_config.radio_channel); -} - -void -ao_config_radio_channel_set(void) __reentrant -{ - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - _ao_config_edit_start(); - ao_config.radio_channel = ao_cmd_lex_i; - _ao_config_edit_finish(); - ao_radio_recv_abort(); -} - void ao_config_frequency_show(void) __reentrant { @@ -218,13 +191,12 @@ ao_config_frequency_set(void) __reentrant return; _ao_config_edit_start(); ao_config.frequency = ao_cmd_lex_u32; - ao_config.radio_channel = 0; ao_config_set_radio(); _ao_config_edit_finish(); ao_radio_recv_abort(); } -#if HAS_ADC +#if HAS_FLIGHT void ao_config_main_deploy_show(void) __reentrant @@ -328,7 +300,25 @@ ao_config_apogee_delay_set(void) __reentrant _ao_config_edit_finish(); } -#endif /* HAS_ADC */ +void +ao_config_apogee_lockout_show(void) __reentrant +{ + printf ("Apogee lockout: %d seconds\n", + ao_config.apogee_lockout); +} + +void +ao_config_apogee_lockout_set(void) __reentrant +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.apogee_lockout = ao_cmd_lex_i; + _ao_config_edit_finish(); +} + +#endif /* HAS_FLIGHT */ void ao_config_radio_cal_show(void) __reentrant @@ -467,50 +457,6 @@ ao_config_key_set(void) __reentrant } #endif -#if HAS_RADIO_CHANNELS -void -ao_config_radio_config_show(void) __reentrant -{ - uint8_t i; - for (i = 0; i < AO_NUM_CHANNELS; i++) - if (ao_config.radio_channels[i].name[0]) { - printf("%2d %-16.16s %ld\n", - i, - ao_config.radio_channels[i].name, - ao_config.radio_channels[i].kHz); - } -} - -void -ao_config_radio_config_set(void) __reentrant -{ - __xdata struct ao_radio_channel * ch; - uint8_t i; - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - if ((uint8_t) ao_cmd_lex_i >= AO_NUM_CHANNELS) { - ao_cmd_status = ao_cmd_syntax_error; - return; - } - ch = &ao_config.radio_channels[(uint8_t) ao_cmd_lex_i]; - _ao_config_edit_start(); - ao_cmd_white(); - i = 0; - while (ao_cmd_lex_c != '/' && ao_cmd_lex_c != '\n' && i < AO_CHANNEL_NAME_LEN) { - ch->name[i++] = ao_cmd_lex_c; - ao_cmd_lex(); - } - if (i < AO_CHANNEL_NAME_LEN) { - ch->name[i] = '\0'; - ao_cmd_lex(); - } - ao_cmd_decimal(); - ch->kHz = ao_cmd_lex_u32; - _ao_config_edit_finish(); -} -#endif - struct ao_config_var { __code char *str; void (*set)(void) __reentrant; @@ -527,14 +473,14 @@ static void ao_config_write(void) __reentrant; __code struct ao_config_var ao_config_vars[] = { -#if HAS_ADC +#if HAS_FLIGHT { "m \0Main deploy (m)", ao_config_main_deploy_set, ao_config_main_deploy_show, }, { "d \0Apogee delay (s)", ao_config_apogee_delay_set, ao_config_apogee_delay_show }, -#endif /* HAS_ADC */ - { "r \0Radio channel", - ao_config_radio_channel_set, ao_config_radio_channel_show }, + { "L \0Apogee detect lockout (s)", + ao_config_apogee_lockout_set, ao_config_apogee_lockout_show, }, +#endif /* HAS_FLIGHT */ { "F \0Frequency (kHz)", ao_config_frequency_set, ao_config_frequency_show }, { "c \0Callsign (8 char max)", @@ -562,10 +508,6 @@ __code struct ao_config_var ao_config_vars[] = { #if HAS_AES { "k <32 hex digits>\0Set AES encryption key", ao_config_key_set, ao_config_key_show }, -#endif -#if HAS_RADIO_CHANNELS - { "C / \0Set radio chan config", - ao_config_radio_config_set,ao_config_radio_config_show }, #endif { "s\0Show", ao_config_show, 0 }, -- cgit v1.2.3 From 040a6eb119451026e1ec7c3a6a8e76b439c632d5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 12 Apr 2012 14:51:07 -0700 Subject: altos: Massive product config cleanup Support multiple serial ports more cleanly Split out parts of ao.h into separate feature header files Signed-off-by: Keith Packard --- src/avr/ao_arch.h | 7 - src/avr/ao_pins.h | 15 +- src/avr/ao_serial_avr.c | 62 +-- src/avr/ao_usb.h | 100 ----- src/avr/ao_usb_avr.c | 6 +- src/cc1111/ao_arch.h | 30 ++ src/cc1111/ao_pins.h | 24 +- src/cc1111/ao_serial.c | 227 +++++++++-- src/cc1111/ao_serial0.c | 152 -------- src/cc1111/ao_usb.c | 6 +- src/cc1111/ao_usb.h | 100 ----- src/core/ao.h | 704 ++--------------------------------- src/core/ao_adc.h | 62 +++ src/core/ao_beep.h | 74 ++++ src/core/ao_dbg.h | 62 +++ src/core/ao_flight.h | 59 +++ src/core/ao_led.h | 55 +++ src/core/ao_log.h | 196 ++++++++++ src/core/ao_log_telem.c | 4 +- src/core/ao_product.c | 8 +- src/core/ao_report.c | 2 + src/core/ao_sample.h | 137 +++++++ src/core/ao_serial.h | 86 +++++ src/core/ao_stdio.c | 6 + src/core/ao_storage.c | 2 +- src/core/ao_storage.h | 84 +++++ src/core/ao_usb.h | 136 +++++++ src/drivers/ao_btm.c | 30 +- src/drivers/ao_gps_sirf.c | 36 +- src/drivers/ao_gps_skytraq.c | 6 +- src/drivers/ao_science_slave.c | 1 + src/megametrum-v0.1/ao_pins.h | 2 + src/product/ao_telebt.c | 2 + src/product/ao_terraui.c | 1 + src/stm/ao_arch.h | 2 - src/stm/ao_serial_stm.c | 2 +- src/stm/ao_usb.h | 101 ----- src/stm/ao_usb_stm.c | 6 +- src/teleballoon-v1.1/ao_pins.h | 5 - src/telepyro-v0.1/Makefile | 6 +- src/telescience-v0.1/Makefile | 9 +- src/teleshield-v0.1/Makefile | 1 - src/teleshield-v0.1/ao_ardu_serial.c | 3 +- src/teleshield-v0.1/ao_pins.h | 8 +- src/teleshield-v0.1/ao_teleshield.c | 3 + src/teleterra-v0.1/ao_pins.h | 5 - src/teleterra-v0.2/ao_pins.h | 5 - src/test/ao_gps_test.c | 6 +- src/test/ao_gps_test_skytraq.c | 6 +- 49 files changed, 1342 insertions(+), 1310 deletions(-) delete mode 100644 src/avr/ao_usb.h delete mode 100644 src/cc1111/ao_serial0.c delete mode 100644 src/cc1111/ao_usb.h create mode 100644 src/core/ao_adc.h create mode 100644 src/core/ao_beep.h create mode 100644 src/core/ao_dbg.h create mode 100644 src/core/ao_flight.h create mode 100644 src/core/ao_led.h create mode 100644 src/core/ao_log.h create mode 100644 src/core/ao_sample.h create mode 100644 src/core/ao_serial.h create mode 100644 src/core/ao_storage.h create mode 100644 src/core/ao_usb.h delete mode 100644 src/stm/ao_usb.h (limited to 'src') diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index b816279e..c775dab6 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -146,12 +146,5 @@ extern uint8_t ao_cpu_sleep_disable; #define AO_TELESCIENCE_NUM_ADC 12 -struct ao_adc { - uint16_t tick; /* tick when the sample was read */ - uint16_t adc[AO_TELESCIENCE_NUM_ADC]; /* samples */ -}; - -#define AO_ADC_RING 16 - #endif /* _AO_ARCH_H_ */ diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index 6a63468f..f2b40fb4 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -21,7 +21,7 @@ #ifdef AVR_DEMO #define AO_LED_RED (1<<7) #define LEDS_AVAILABLE (AO_LED_RED) - #define USE_SERIAL_STDIN 1 + #define USE_SERIAL_1_STDIN 1 #define HAS_USB 1 #define PACKET_HAS_SLAVE 0 #define HAS_SERIAL_1 1 @@ -37,11 +37,11 @@ #define HAS_USB 1 #define HAS_LOG 1 #define TEENSY 0 - #define USE_SERIAL_STDIN 0 #define HAS_SERIAL_1 0 #define HAS_ADC 1 #define PACKET_HAS_SLAVE 0 #define HAS_BEEP 0 + #define HAS_EEPROM 1 #define HAS_STORAGE_DEBUG 0 #define AVR_VCC_5V 0 @@ -66,7 +66,7 @@ #define HAS_USB 1 #define HAS_LOG 0 #define TEENSY 0 - #define USE_SERIAL_STDIN 1 + #define USE_SERIAL_1_STDIN 1 #define HAS_SERIAL_1 1 #define HAS_USB 1 #define HAS_ADC 1 @@ -88,4 +88,13 @@ #define AO_M25_SPI_CS_PORT SPI_CS_PORT #define AO_M25_SPI_CS_MASK M25_CS_MASK +#define AO_TELESCIENCE_NUM_ADC 12 + +struct ao_adc { + uint16_t tick; /* tick when the sample was read */ + uint16_t adc[AO_TELESCIENCE_NUM_ADC]; /* samples */ +}; + +#define AO_ADC_RING 16 + #endif /* _AO_PINS_H_ */ diff --git a/src/avr/ao_serial_avr.c b/src/avr/ao_serial_avr.c index 6885c339..dcee246c 100644 --- a/src/avr/ao_serial_avr.c +++ b/src/avr/ao_serial_avr.c @@ -17,8 +17,8 @@ #include "ao.h" -__xdata struct ao_fifo ao_usart1_rx_fifo; -__xdata struct ao_fifo ao_usart1_tx_fifo; +__xdata struct ao_fifo ao_serial1_rx_fifo; +__xdata struct ao_fifo ao_serial1_tx_fifo; void ao_debug_out(char c) @@ -31,10 +31,10 @@ ao_debug_out(char c) ISR(USART1_RX_vect) { - if (!ao_fifo_full(ao_usart1_rx_fifo)) - ao_fifo_insert(ao_usart1_rx_fifo, UDR1); - ao_wakeup(&ao_usart1_rx_fifo); -#if USE_SERIAL_STDIN + if (!ao_fifo_full(ao_serial1_rx_fifo)) + ao_fifo_insert(ao_serial1_rx_fifo, UDR1); + ao_wakeup(&ao_serial1_rx_fifo); +#if USE_SERIAL_1_STDIN ao_wakeup(&ao_stdin_ready); #endif } @@ -42,68 +42,68 @@ ISR(USART1_RX_vect) static __xdata uint8_t ao_serial_tx1_started; static void -ao_serial_tx1_start(void) +ao_serial1_tx_start(void) { - if (!ao_fifo_empty(ao_usart1_tx_fifo) && + if (!ao_fifo_empty(ao_serial1_tx_fifo) && !ao_serial_tx1_started) { ao_serial_tx1_started = 1; - ao_fifo_remove(ao_usart1_tx_fifo, UDR1); + ao_fifo_remove(ao_serial1_tx_fifo, UDR1); } } ISR(USART1_UDRE_vect) { - ao_serial_tx1_started = 0; - ao_serial_tx1_start(); - ao_wakeup(&ao_usart1_tx_fifo); + ao_serial1_tx_started = 0; + ao_serial1_tx_start(); + ao_wakeup(&ao_serial1_tx_fifo); } char -ao_serial_getchar(void) __critical +ao_serial1_getchar(void) __critical { char c; cli(); - while (ao_fifo_empty(ao_usart1_rx_fifo)) - ao_sleep(&ao_usart1_rx_fifo); - ao_fifo_remove(ao_usart1_rx_fifo, c); + while (ao_fifo_empty(ao_serial1_rx_fifo)) + ao_sleep(&ao_serial1_rx_fifo); + ao_fifo_remove(ao_serial1_rx_fifo, c); sei(); return c; } -#if USE_SERIAL_STDIN +#if USE_SERIAL_1_STDIN char -ao_serial_pollchar(void) __critical +ao_serial1_pollchar(void) __critical { char c; cli(); - if (ao_fifo_empty(ao_usart1_rx_fifo)) { + if (ao_fifo_empty(ao_serial1_rx_fifo)) { sei(); return AO_READ_AGAIN; } - ao_fifo_remove(ao_usart1_rx_fifo,c); + ao_fifo_remove(ao_serial1_rx_fifo,c); sei(); return c; } #endif void -ao_serial_putchar(char c) __critical +ao_serial1_putchar(char c) __critical { cli(); - while (ao_fifo_full(ao_usart1_tx_fifo)) - ao_sleep(&ao_usart1_tx_fifo); - ao_fifo_insert(ao_usart1_tx_fifo, c); + while (ao_fifo_full(ao_serial1_tx_fifo)) + ao_sleep(&ao_serial1_tx_fifo); + ao_fifo_insert(ao_serial1_tx_fifo, c); ao_serial_tx1_start(); sei(); } void -ao_serial_drain(void) __critical +ao_serial1_drain(void) __critical { cli(); - while (!ao_fifo_empty(ao_usart1_tx_fifo)) - ao_sleep(&ao_usart1_tx_fifo); + while (!ao_fifo_empty(ao_serial1_tx_fifo)) + ao_sleep(&ao_serial1_tx_fifo); sei(); } @@ -125,7 +125,7 @@ static const struct { }; void -ao_serial_set_speed(uint8_t speed) +ao_serial1_set_speed(uint8_t speed) { ao_serial_drain(); if (speed > AO_SERIAL_SPEED_57600) @@ -154,9 +154,9 @@ ao_serial_init(void) (1 << TXEN1) | /* Enable transmitter */ (1 << RXCIE1) | /* Enable receive interrupts */ (1 << UDRIE1)); /* Enable transmit empty interrupts */ -#if USE_SERIAL_STDIN - ao_add_stdio(ao_serial_pollchar, - ao_serial_putchar, +#if USE_SERIAL_1_STDIN + ao_add_stdio(ao_serial1_pollchar, + ao_serial1_putchar, NULL); #endif } diff --git a/src/avr/ao_usb.h b/src/avr/ao_usb.h deleted file mode 100644 index 6633dafc..00000000 --- a/src/avr/ao_usb.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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. - */ - -#ifndef _AO_USB_H_ -#define _AO_USB_H_ - -#define AO_USB_SETUP_DIR_MASK (0x01 << 7) -#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) -#define AO_USB_SETUP_RECIP_MASK (0x1f) - -#define AO_USB_DIR_OUT 0 -#define AO_USB_DIR_IN (1 << 7) - -#define AO_USB_TYPE_STANDARD 0 -#define AO_USB_TYPE_CLASS (1 << 5) -#define AO_USB_TYPE_VENDOR (2 << 5) -#define AO_USB_TYPE_RESERVED (3 << 5) - -#define AO_USB_RECIP_DEVICE 0 -#define AO_USB_RECIP_INTERFACE 1 -#define AO_USB_RECIP_ENDPOINT 2 -#define AO_USB_RECIP_OTHER 3 - -/* standard requests */ -#define AO_USB_REQ_GET_STATUS 0x00 -#define AO_USB_REQ_CLEAR_FEATURE 0x01 -#define AO_USB_REQ_SET_FEATURE 0x03 -#define AO_USB_REQ_SET_ADDRESS 0x05 -#define AO_USB_REQ_GET_DESCRIPTOR 0x06 -#define AO_USB_REQ_SET_DESCRIPTOR 0x07 -#define AO_USB_REQ_GET_CONFIGURATION 0x08 -#define AO_USB_REQ_SET_CONFIGURATION 0x09 -#define AO_USB_REQ_GET_INTERFACE 0x0A -#define AO_USB_REQ_SET_INTERFACE 0x0B -#define AO_USB_REQ_SYNCH_FRAME 0x0C - -#define AO_USB_DESC_DEVICE 1 -#define AO_USB_DESC_CONFIGURATION 2 -#define AO_USB_DESC_STRING 3 -#define AO_USB_DESC_INTERFACE 4 -#define AO_USB_DESC_ENDPOINT 5 -#define AO_USB_DESC_DEVICE_QUALIFIER 6 -#define AO_USB_DESC_OTHER_SPEED 7 -#define AO_USB_DESC_INTERFACE_POWER 8 - -#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) -#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) - -#define AO_USB_CONTROL_EP 0 -#define AO_USB_INT_EP 1 -#define AO_USB_OUT_EP 4 -#define AO_USB_IN_EP 5 -#define AO_USB_CONTROL_SIZE 32 -/* - * Double buffer IN and OUT EPs, so each - * gets half of the available space - * - * Ah, but USB bulk packets can only come in 8, 16, 32 and 64 - * byte sizes, so we'll use 64 for everything - */ -#define AO_USB_IN_SIZE 64 -#define AO_USB_OUT_SIZE 64 - -#define AO_USB_EP0_IDLE 0 -#define AO_USB_EP0_DATA_IN 1 -#define AO_USB_EP0_DATA_OUT 2 - -#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) - -/* CDC definitions */ -#define CS_INTERFACE 0x24 -#define CS_ENDPOINT 0x25 - -#define SET_LINE_CODING 0x20 -#define GET_LINE_CODING 0x21 -#define SET_CONTROL_LINE_STATE 0x22 - -/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ -struct ao_usb_line_coding { - uint32_t rate; - uint8_t char_format; - uint8_t parity; - uint8_t data_bits; -} ; - -#endif /* _AO_USB_H_ */ diff --git a/src/avr/ao_usb_avr.c b/src/avr/ao_usb_avr.c index fc8899d8..23a27c73 100644 --- a/src/avr/ao_usb_avr.c +++ b/src/avr/ao_usb_avr.c @@ -330,17 +330,17 @@ ao_usb_ep0_setup(void) case AO_USB_TYPE_CLASS: debug ("Class setup packet\n"); switch (ao_usb_setup.request) { - case SET_LINE_CODING: + case AO_USB_SET_LINE_CODING: debug ("set line coding\n"); ao_usb_ep0_out_len = 7; ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_line_coding; break; - case GET_LINE_CODING: + case AO_USB_GET_LINE_CODING: debug ("get line coding\n"); ao_usb_ep0_in_len = 7; ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding; break; - case SET_CONTROL_LINE_STATE: + case AO_USB_SET_CONTROL_LINE_STATE: break; } break; diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 847ac1a6..9d0643b4 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -294,4 +294,34 @@ ao_dma_abort(uint8_t id); void ao_dma_isr(void) ao_arch_interrupt(8); +/* ao_adc.c */ + +#if HAS_ADC +/* The A/D interrupt handler */ +void +ao_adc_isr(void) ao_arch_interrupt(1); +#endif + +#if HAS_USB +/* USB interrupt handler */ +void +ao_usb_isr(void) ao_arch_interrupt(6); +#endif + +#if HAS_SERIAL_0 +void +ao_serial0_rx_isr(void) ao_arch_interrupt(2); + +void +ao_serial0_tx_isr(void) ao_arch_interrupt(7); +#endif + +#if HAS_SERIAL_1 +void +ao_serial1_rx_isr(void) ao_arch_interrupt(3); + +void +ao_serial1_tx_isr(void) ao_arch_interrupt(14); +#endif + #endif /* _AO_ARCH_H_ */ diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 5c0cb7df..4f6edd37 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -25,7 +25,6 @@ #define HAS_GPS 1 #define HAS_SERIAL_1 1 #define HAS_ADC 1 - #define USE_SERIAL_STDIN 0 #define HAS_EEPROM 1 #define HAS_LOG 1 #define USE_INTERNAL_FLASH 0 @@ -58,7 +57,6 @@ #define HAS_BEEP 1 #define HAS_GPS 1 #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_LOG 1 @@ -95,7 +93,6 @@ #define HAS_BEEP 1 #define HAS_GPS 1 #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_LOG 1 @@ -131,7 +128,6 @@ #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 @@ -161,7 +157,6 @@ #define HAS_BEEP 0 #define HAS_GPS 0 #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_LOG 1 @@ -188,7 +183,6 @@ #define HAS_BEEP 0 #define HAS_GPS 0 #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_LOG 1 @@ -214,7 +208,6 @@ #define HAS_BEEP 1 #define HAS_GPS 1 #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_DBG 0 #define HAS_EEPROM 1 @@ -244,7 +237,6 @@ #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 0 #define HAS_DBG 0 #define HAS_EEPROM 0 @@ -273,7 +265,6 @@ #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 0 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 @@ -301,7 +292,8 @@ #define HAS_USB 1 #define HAS_BEEP 0 #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 1 + #define USE_SERIAL_1_STDIN 1 + #define DELAY_SERIAL_1_STDIN 1 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 0 @@ -339,7 +331,8 @@ #define HAS_SERIAL_1_ALT_1 1 #define HAS_SERIAL_1_ALT_2 0 #define HAS_SERIAL_1_HW_FLOW 1 - #define USE_SERIAL_STDIN 1 + #define USE_SERIAL_1_STDIN 1 + #define DELAY_SERIAL_1_STDIN 1 #define HAS_ADC 0 #define HAS_DBG 1 #define HAS_EEPROM 1 @@ -379,7 +372,6 @@ #define HAS_BEEP 1 #define HAS_GPS 0 #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_DBG 0 #define HAS_EEPROM 1 @@ -468,14 +460,6 @@ #error Please define IGNITE_ON_P0 #endif -#ifndef HAS_SERIAL_1 -#error Please define HAS_SERIAL_1 -#endif - -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - #ifndef HAS_ADC #error Please define HAS_ADC #endif diff --git a/src/cc1111/ao_serial.c b/src/cc1111/ao_serial.c index 4d5b9abd..00c85ff3 100644 --- a/src/cc1111/ao_serial.c +++ b/src/cc1111/ao_serial.c @@ -17,78 +17,168 @@ #include "ao.h" -volatile __xdata struct ao_fifo ao_usart1_rx_fifo; -volatile __xdata struct ao_fifo ao_usart1_tx_fifo; +#if HAS_SERIAL_0 + +volatile __xdata struct ao_fifo ao_serial0_rx_fifo; +volatile __xdata struct ao_fifo ao_serial0_tx_fifo; + +void +ao_serial0_rx_isr(void) __interrupt 2 +{ + if (!ao_fifo_full(ao_serial0_rx_fifo)) + ao_fifo_insert(ao_serial0_rx_fifo, U0DBUF); + ao_wakeup(&ao_serial0_rx_fifo); +#if USE_SERIAL_0_STDIN + ao_wakeup(&ao_stdin_ready); +#endif +} + +static __xdata uint8_t ao_serial0_tx_started; + +static void +ao_serial0_tx_start(void) +{ + if (!ao_fifo_empty(ao_serial0_tx_fifo) && + !ao_serial0_tx_started) + { + ao_serial0_tx_started = 1; + ao_fifo_remove(ao_serial0_tx_fifo, U0DBUF); + } +} + +void +ao_serial0_tx_isr(void) __interrupt 7 +{ + UTX0IF = 0; + ao_serial0_tx_started = 0; + ao_serial0_tx_start(); + ao_wakeup(&ao_serial0_tx_fifo); +} + +char +ao_serial0_getchar(void) __critical +{ + char c; + while (ao_fifo_empty(ao_serial0_rx_fifo)) + ao_sleep(&ao_serial0_rx_fifo); + ao_fifo_remove(ao_serial0_rx_fifo, c); + return c; +} + +#if USE_SERIAL_0_STDIN +char +ao_serial0_pollchar(void) __critical +{ + char c; + if (ao_fifo_empty(ao_serial0_rx_fifo)) + return AO_READ_AGAIN; + ao_fifo_remove(ao_serial0_rx_fifo,c); + return c; +} +#endif + +void +ao_serial0_putchar(char c) __critical +{ + while (ao_fifo_full(ao_serial0_tx_fifo)) + ao_sleep(&ao_serial0_tx_fifo); + ao_fifo_insert(ao_serial0_tx_fifo, c); + ao_serial0_tx_start(); +} + +void +ao_serial0_drain(void) __critical +{ + while (!ao_fifo_empty(ao_serial0_tx_fifo)) + ao_sleep(&ao_serial0_tx_fifo); +} + +void +ao_serial0_set_speed(uint8_t speed) +{ + ao_serial0_drain(); + if (speed > AO_SERIAL_SPEED_57600) + return; + U0UCR |= UxUCR_FLUSH; + U0BAUD = ao_serial_speeds[speed].baud; + U0GCR = ao_serial_speeds[speed].gcr; +} +#endif /* HAS_SERIAL_0 */ + +#if HAS_SERIAL_1 + +volatile __xdata struct ao_fifo ao_serial1_rx_fifo; +volatile __xdata struct ao_fifo ao_serial1_tx_fifo; void -ao_serial_rx1_isr(void) __interrupt 3 +ao_serial1_rx_isr(void) __interrupt 3 { - if (!ao_fifo_full(ao_usart1_rx_fifo)) - ao_fifo_insert(ao_usart1_rx_fifo, U1DBUF); - ao_wakeup(&ao_usart1_rx_fifo); -#if USE_SERIAL_STDIN + if (!ao_fifo_full(ao_serial1_rx_fifo)) + ao_fifo_insert(ao_serial1_rx_fifo, U1DBUF); + ao_wakeup(&ao_serial1_rx_fifo); +#if USE_SERIAL1_STDIN ao_wakeup(&ao_stdin_ready); #endif } -static __xdata uint8_t ao_serial_tx1_started; +static __xdata uint8_t ao_serial1_tx_started; static void -ao_serial_tx1_start(void) +ao_serial1_tx_start(void) { - if (!ao_fifo_empty(ao_usart1_tx_fifo) && - !ao_serial_tx1_started) + if (!ao_fifo_empty(ao_serial1_tx_fifo) && + !ao_serial1_tx_started) { - ao_serial_tx1_started = 1; - ao_fifo_remove(ao_usart1_tx_fifo, U1DBUF); + ao_serial1_tx_started = 1; + ao_fifo_remove(ao_serial1_tx_fifo, U1DBUF); } } void -ao_serial_tx1_isr(void) __interrupt 14 +ao_serial1_tx_isr(void) __interrupt 14 { UTX1IF = 0; - ao_serial_tx1_started = 0; - ao_serial_tx1_start(); - ao_wakeup(&ao_usart1_tx_fifo); + ao_serial1_tx_started = 0; + ao_serial1_tx_start(); + ao_wakeup(&ao_serial1_tx_fifo); } char -ao_serial_getchar(void) __critical +ao_serial1_getchar(void) __critical { char c; - while (ao_fifo_empty(ao_usart1_rx_fifo)) - ao_sleep(&ao_usart1_rx_fifo); - ao_fifo_remove(ao_usart1_rx_fifo, c); + while (ao_fifo_empty(ao_serial1_rx_fifo)) + ao_sleep(&ao_serial1_rx_fifo); + ao_fifo_remove(ao_serial1_rx_fifo, c); return c; } -#if USE_SERIAL_STDIN +#if USE_SERIAL_1_STDIN char -ao_serial_pollchar(void) __critical +ao_serial1_pollchar(void) __critical { char c; - if (ao_fifo_empty(ao_usart1_rx_fifo)) + if (ao_fifo_empty(ao_serial1_rx_fifo)) return AO_READ_AGAIN; - ao_fifo_remove(ao_usart1_rx_fifo,c); + ao_fifo_remove(ao_serial1_rx_fifo,c); return c; } #endif void -ao_serial_putchar(char c) __critical +ao_serial1_putchar(char c) __critical { - while (ao_fifo_full(ao_usart1_tx_fifo)) - ao_sleep(&ao_usart1_tx_fifo); - ao_fifo_insert(ao_usart1_tx_fifo, c); - ao_serial_tx1_start(); + while (ao_fifo_full(ao_serial1_tx_fifo)) + ao_sleep(&ao_serial1_tx_fifo); + ao_fifo_insert(ao_serial1_tx_fifo, c); + ao_serial1_tx_start(); } void -ao_serial_drain(void) __critical +ao_serial1_drain(void) __critical { - while (!ao_fifo_empty(ao_usart1_tx_fifo)) - ao_sleep(&ao_usart1_tx_fifo); + while (!ao_fifo_empty(ao_serial1_tx_fifo)) + ao_sleep(&ao_serial1_tx_fifo); } const __code struct ao_serial_speed ao_serial_speeds[] = { @@ -111,9 +201,9 @@ const __code struct ao_serial_speed ao_serial_speeds[] = { }; void -ao_serial_set_speed(uint8_t speed) +ao_serial1_set_speed(uint8_t speed) { - ao_serial_drain(); + ao_serial1_drain(); if (speed > AO_SERIAL_SPEED_57600) return; U1UCR |= UxUCR_FLUSH; @@ -121,9 +211,67 @@ ao_serial_set_speed(uint8_t speed) U1GCR = ao_serial_speeds[speed].gcr; } +#endif /* HAS_SERIAL_1 */ + void ao_serial_init(void) { +#if HAS_SERIAL_0 +#if HAS_SERIAL_0_ALT_1 + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_1; + + P2DIR = (P2DIR & ~P2DIR_PRIP0_MASK) | P2DIR_PRIP0_USART0_USART1; + + /* Make the USART pins be controlled by the USART */ + P0SEL |= (1 << 2) | (1 << 3); +#if HAS_SERIAL_0_HW_FLOW + P0SEL |= (1 << 4) | (1 << 5); +#endif +#else + /* Set up the USART pin assignment */ + PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2; + + P2SEL = (P2SEL & ~(P2SEL_PRI3P1_MASK | P2SEL_PRI0P1_MASK)) | + (P2SEL_PRI3P1_USART0 | P2SEL_PRI0P1_USART0); + + /* Make the USART pins be controlled by the USART */ + P1SEL |= (1 << 2) | (1 << 3); +#if HAS_SERIAL_0_HW_FLOW + P1SEL |= (1 << 5) | (1 << 4); +#endif +#endif + + /* UART mode with receiver enabled */ + U0CSR = (UxCSR_MODE_UART | UxCSR_RE); + + /* Pick a 9600 baud rate */ + ao_serial0_set_speed(AO_SERIAL_SPEED_9600); + + /* Reasonable serial parameters */ + U0UCR = (UxUCR_FLUSH | +#if HAS_SERIAL_0_HW_FLOW + UxUCR_FLOW_ENABLE | +#else + UxUCR_FLOW_DISABLE | +#endif + UxUCR_D9_EVEN_PARITY | + UxUCR_BIT9_8_BITS | + UxUCR_PARITY_DISABLE | + UxUCR_SPB_1_STOP_BIT | + UxUCR_STOP_HIGH | + UxUCR_START_LOW); + + IEN0 |= IEN0_URX0IE; + IEN2 |= IEN2_UTX0IE; +#if USE_SERIAL_0_STDIN && !DELAY_SERIAL_0_STDIN + ao_add_stdio(ao_serial0_pollchar, + ao_serial0_putchar, + NULL); +#endif +#endif /* HAS_SERIAL_0 */ + +#if HAS_SERIAL_1 #if HAS_SERIAL_1_ALT_1 /* Set up the USART pin assignment */ PERCFG = (PERCFG & ~PERCFG_U1CFG_ALT_MASK) | PERCFG_U1CFG_ALT_1; @@ -151,7 +299,7 @@ ao_serial_init(void) U1CSR = (UxCSR_MODE_UART | UxCSR_RE); /* Pick a 4800 baud rate */ - ao_serial_set_speed(AO_SERIAL_SPEED_4800); + ao_serial1_set_speed(AO_SERIAL_SPEED_4800); /* Reasonable serial parameters */ U1UCR = (UxUCR_FLUSH | @@ -169,4 +317,11 @@ ao_serial_init(void) IEN0 |= IEN0_URX1IE; IEN2 |= IEN2_UTX1IE; + +#if USE_SERIAL_1_STDIN && !DELAY_SERIAL_1_STDIN + ao_add_stdio(ao_serial1_pollchar, + ao_serial1_putchar, + NULL); +#endif +#endif /* HAS_SERIAL_1 */ } diff --git a/src/cc1111/ao_serial0.c b/src/cc1111/ao_serial0.c deleted file mode 100644 index e8c1eb35..00000000 --- a/src/cc1111/ao_serial0.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * 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" - -volatile __xdata struct ao_fifo ao_usart0_rx_fifo; -volatile __xdata struct ao_fifo ao_usart0_tx_fifo; - -void -ao_serial0_rx0_isr(void) __interrupt 2 -{ - if (!ao_fifo_full(ao_usart0_rx_fifo)) - ao_fifo_insert(ao_usart0_rx_fifo, U0DBUF); - ao_wakeup(&ao_usart0_rx_fifo); -} - -static __xdata uint8_t ao_serial0_tx0_started; - -static void -ao_serial0_tx0_start(void) -{ - if (!ao_fifo_empty(ao_usart0_tx_fifo) && - !ao_serial0_tx0_started) - { - ao_serial0_tx0_started = 1; - ao_fifo_remove(ao_usart0_tx_fifo, U0DBUF); - } -} - -void -ao_serial0_tx0_isr(void) __interrupt 7 -{ - UTX0IF = 0; - ao_serial0_tx0_started = 0; - ao_serial0_tx0_start(); - ao_wakeup(&ao_usart0_tx_fifo); -} - -char -ao_serial0_getchar(void) __critical -{ - char c; - while (ao_fifo_empty(ao_usart0_rx_fifo)) - ao_sleep(&ao_usart0_rx_fifo); - ao_fifo_remove(ao_usart0_rx_fifo, c); - return c; -} - -#if USE_SERIAL_STDIN -char -ao_serial0_pollchar(void) __critical -{ - char c; - if (ao_fifo_empty(ao_usart0_rx_fifo)) - return AO_READ_AGAIN; - ao_fifo_remove(ao_usart0_rx_fifo,c); - return c; -} -#endif - -void -ao_serial0_putchar(char c) __critical -{ - while (ao_fifo_full(ao_usart0_tx_fifo)) - ao_sleep(&ao_usart0_tx_fifo); - ao_fifo_insert(ao_usart0_tx_fifo, c); - ao_serial0_tx0_start(); -} - -void -ao_serial0_drain(void) __critical -{ - while (!ao_fifo_empty(ao_usart0_tx_fifo)) - ao_sleep(&ao_usart0_tx_fifo); -} - -void -ao_serial0_set_speed(uint8_t speed) -{ - ao_serial0_drain(); - if (speed > AO_SERIAL_SPEED_57600) - return; - U0UCR |= UxUCR_FLUSH; - U0BAUD = ao_serial_speeds[speed].baud; - U0GCR = ao_serial_speeds[speed].gcr; -} - -void -ao_serial0_init(void) -{ -#if HAS_SERIAL_0_ALT_1 - /* Set up the USART pin assignment */ - PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_1; - - P2DIR = (P2DIR & ~P2DIR_PRIP0_MASK) | P2DIR_PRIP0_USART0_USART1; - - /* Make the USART pins be controlled by the USART */ - P0SEL |= (1 << 2) | (1 << 3); -#if HAS_SERIAL_0_HW_FLOW - P0SEL |= (1 << 4) | (1 << 5); -#endif -#else - /* Set up the USART pin assignment */ - PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2; - - P2SEL = (P2SEL & ~(P2SEL_PRI3P1_MASK | P2SEL_PRI0P1_MASK)) | - (P2SEL_PRI3P1_USART0 | P2SEL_PRI0P1_USART0); - - /* Make the USART pins be controlled by the USART */ - P1SEL |= (1 << 2) | (1 << 3); -#if HAS_SERIAL_0_HW_FLOW - P1SEL |= (1 << 5) | (1 << 4); -#endif -#endif - - /* UART mode with receiver enabled */ - U0CSR = (UxCSR_MODE_UART | UxCSR_RE); - - /* Pick a 9600 baud rate */ - ao_serial0_set_speed(AO_SERIAL_SPEED_9600); - - /* Reasonable serial parameters */ - U0UCR = (UxUCR_FLUSH | -#if HAS_SERIAL_0_HW_FLOW - UxUCR_FLOW_ENABLE | -#else - UxUCR_FLOW_DISABLE | -#endif - UxUCR_D9_EVEN_PARITY | - UxUCR_BIT9_8_BITS | - UxUCR_PARITY_DISABLE | - UxUCR_SPB_1_STOP_BIT | - UxUCR_STOP_HIGH | - UxUCR_START_LOW); - - IEN0 |= IEN0_URX0IE; - IEN2 |= IEN2_UTX0IE; -} diff --git a/src/cc1111/ao_usb.c b/src/cc1111/ao_usb.c index 35c9ac20..ce26e808 100644 --- a/src/cc1111/ao_usb.c +++ b/src/cc1111/ao_usb.c @@ -261,15 +261,15 @@ ao_usb_ep0_setup(void) break; case AO_USB_TYPE_CLASS: switch (ao_usb_setup.request) { - case SET_LINE_CODING: + case AO_USB_SET_LINE_CODING: ao_usb_ep0_out_len = 7; ao_usb_ep0_out_data = (__xdata uint8_t *) &ao_usb_line_coding; break; - case GET_LINE_CODING: + case AO_USB_GET_LINE_CODING: ao_usb_ep0_in_len = 7; ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding; break; - case SET_CONTROL_LINE_STATE: + case AO_USB_SET_CONTROL_LINE_STATE: break; } break; diff --git a/src/cc1111/ao_usb.h b/src/cc1111/ao_usb.h deleted file mode 100644 index 6633dafc..00000000 --- a/src/cc1111/ao_usb.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * 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. - */ - -#ifndef _AO_USB_H_ -#define _AO_USB_H_ - -#define AO_USB_SETUP_DIR_MASK (0x01 << 7) -#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) -#define AO_USB_SETUP_RECIP_MASK (0x1f) - -#define AO_USB_DIR_OUT 0 -#define AO_USB_DIR_IN (1 << 7) - -#define AO_USB_TYPE_STANDARD 0 -#define AO_USB_TYPE_CLASS (1 << 5) -#define AO_USB_TYPE_VENDOR (2 << 5) -#define AO_USB_TYPE_RESERVED (3 << 5) - -#define AO_USB_RECIP_DEVICE 0 -#define AO_USB_RECIP_INTERFACE 1 -#define AO_USB_RECIP_ENDPOINT 2 -#define AO_USB_RECIP_OTHER 3 - -/* standard requests */ -#define AO_USB_REQ_GET_STATUS 0x00 -#define AO_USB_REQ_CLEAR_FEATURE 0x01 -#define AO_USB_REQ_SET_FEATURE 0x03 -#define AO_USB_REQ_SET_ADDRESS 0x05 -#define AO_USB_REQ_GET_DESCRIPTOR 0x06 -#define AO_USB_REQ_SET_DESCRIPTOR 0x07 -#define AO_USB_REQ_GET_CONFIGURATION 0x08 -#define AO_USB_REQ_SET_CONFIGURATION 0x09 -#define AO_USB_REQ_GET_INTERFACE 0x0A -#define AO_USB_REQ_SET_INTERFACE 0x0B -#define AO_USB_REQ_SYNCH_FRAME 0x0C - -#define AO_USB_DESC_DEVICE 1 -#define AO_USB_DESC_CONFIGURATION 2 -#define AO_USB_DESC_STRING 3 -#define AO_USB_DESC_INTERFACE 4 -#define AO_USB_DESC_ENDPOINT 5 -#define AO_USB_DESC_DEVICE_QUALIFIER 6 -#define AO_USB_DESC_OTHER_SPEED 7 -#define AO_USB_DESC_INTERFACE_POWER 8 - -#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) -#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) - -#define AO_USB_CONTROL_EP 0 -#define AO_USB_INT_EP 1 -#define AO_USB_OUT_EP 4 -#define AO_USB_IN_EP 5 -#define AO_USB_CONTROL_SIZE 32 -/* - * Double buffer IN and OUT EPs, so each - * gets half of the available space - * - * Ah, but USB bulk packets can only come in 8, 16, 32 and 64 - * byte sizes, so we'll use 64 for everything - */ -#define AO_USB_IN_SIZE 64 -#define AO_USB_OUT_SIZE 64 - -#define AO_USB_EP0_IDLE 0 -#define AO_USB_EP0_DATA_IN 1 -#define AO_USB_EP0_DATA_OUT 2 - -#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) - -/* CDC definitions */ -#define CS_INTERFACE 0x24 -#define CS_ENDPOINT 0x25 - -#define SET_LINE_CODING 0x20 -#define GET_LINE_CODING 0x21 -#define SET_CONTROL_LINE_STATE 0x22 - -/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ -struct ao_usb_line_coding { - uint32_t rate; - uint8_t char_format; - uint8_t parity; - uint8_t data_bits; -} ; - -#endif /* _AO_USB_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index 9a3b5829..28d0ba87 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -154,182 +154,14 @@ void ao_clock_init(void); /* - * One set of samples read from the A/D converter or telemetry - */ - -#if HAS_ADC - -/* - * ao_adc.c - */ - -#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) -#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) - - -/* - * A/D data is stored in a ring, with the next sample to be written - * at ao_adc_head - */ -extern volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; -extern volatile __data uint8_t ao_adc_head; -#if HAS_ACCEL_REF -extern volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; -#endif - -/* Trigger a conversion sequence (called from the timer interrupt) */ -void -ao_adc_poll(void); - -/* Suspend the current task until another A/D sample is converted */ -void -ao_adc_sleep(void); - -/* Get a copy of the last complete A/D sample set */ -void -ao_adc_get(__xdata struct ao_adc *packet); - -/* The A/D interrupt handler */ - -void -ao_adc_isr(void) ao_arch_interrupt(1); - -/* Initialize the A/D converter */ -void -ao_adc_init(void); - -#endif /* HAS_ADC */ - -/* - * ao_beep.c - */ - -/* - * Various pre-defined beep frequencies - * - * frequency = 1/2 (24e6/32) / beep - */ - -#define AO_BEEP_LOW 150 /* 2500Hz */ -#define AO_BEEP_MID 94 /* 3989Hz */ -#define AO_BEEP_HIGH 75 /* 5000Hz */ -#define AO_BEEP_OFF 0 /* off */ - -#define AO_BEEP_g 240 /* 1562.5Hz */ -#define AO_BEEP_gs 227 /* 1652Hz (1655Hz) */ -#define AO_BEEP_aa 214 /* 1752Hz (1754Hz) */ -#define AO_BEEP_bbf 202 /* 1856Hz (1858Hz) */ -#define AO_BEEP_bb 190 /* 1974Hz (1969Hz) */ -#define AO_BEEP_cc 180 /* 2083Hz (2086Hz) */ -#define AO_BEEP_ccs 170 /* 2205Hz (2210Hz) */ -#define AO_BEEP_dd 160 /* 2344Hz (2341Hz) */ -#define AO_BEEP_eef 151 /* 2483Hz (2480Hz) */ -#define AO_BEEP_ee 143 /* 2622Hz (2628Hz) */ -#define AO_BEEP_ff 135 /* 2778Hz (2784Hz) */ -#define AO_BEEP_ffs 127 /* 2953Hz (2950Hz) */ -#define AO_BEEP_gg 120 /* 3125Hz */ -#define AO_BEEP_ggs 113 /* 3319Hz (3311Hz) */ -#define AO_BEEP_aaa 107 /* 3504Hz (3508Hz) */ -#define AO_BEEP_bbbf 101 /* 3713Hz (3716Hz) */ -#define AO_BEEP_bbb 95 /* 3947Hz (3937Hz) */ -#define AO_BEEP_ccc 90 /* 4167Hz (4171Hz) */ -#define AO_BEEP_cccs 85 /* 4412Hz (4419Hz) */ -#define AO_BEEP_ddd 80 /* 4688Hz (4682Hz) */ -#define AO_BEEP_eeef 76 /* 4934Hz (4961Hz) */ -#define AO_BEEP_eee 71 /* 5282Hz (5256Hz) */ -#define AO_BEEP_fff 67 /* 5597Hz (5568Hz) */ -#define AO_BEEP_fffs 64 /* 5859Hz (5899Hz) */ -#define AO_BEEP_ggg 60 /* 6250Hz */ - -/* Set the beeper to the specified tone */ -void -ao_beep(uint8_t beep); - -/* Turn on the beeper for the specified time */ -void -ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant; - -/* Initialize the beeper */ -void -ao_beep_init(void); - -/* - * ao_led.c - */ - -#define AO_LED_NONE 0 - -#ifndef AO_LED_TYPE -#define AO_LED_TYPE uint8_t -#endif - -/* Turn on the specified LEDs */ -void -ao_led_on(AO_LED_TYPE colors); - -/* Turn off the specified LEDs */ -void -ao_led_off(AO_LED_TYPE colors); - -/* Set all of the LEDs to the specified state */ -void -ao_led_set(AO_LED_TYPE colors); - -/* Toggle the specified LEDs */ -void -ao_led_toggle(AO_LED_TYPE colors); - -/* Turn on the specified LEDs for the indicated interval */ -void -ao_led_for(AO_LED_TYPE colors, uint16_t ticks) __reentrant; - -/* Initialize the LEDs */ -void -ao_led_init(AO_LED_TYPE enable); - -/* - * ao_usb.c - */ - -/* Put one character to the USB output queue */ -void -ao_usb_putchar(char c); - -/* Get one character from the USB input queue */ -char -ao_usb_getchar(void); - -/* Poll for a charcter on the USB input queue. - * returns AO_READ_AGAIN if none are available + * ao_mutex.c */ -char -ao_usb_pollchar(void); - -/* Flush the USB output queue */ -void -ao_usb_flush(void); - -#if HAS_USB -/* USB interrupt handler */ -void -ao_usb_isr(void) ao_arch_interrupt(6); -#endif -/* Enable the USB controller */ void -ao_usb_enable(void); - -/* Disable the USB controller */ -void -ao_usb_disable(void); +ao_mutex_get(__xdata uint8_t *ao_mutex) __reentrant; -/* Initialize the USB system */ void -ao_usb_init(void); - -#if HAS_USB -extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; -#endif +ao_mutex_put(__xdata uint8_t *ao_mutex) __reentrant; /* * ao_cmd.c @@ -396,405 +228,36 @@ ao_cmd_filter(void); #endif /* - * ao_mutex.c - */ - -void -ao_mutex_get(__xdata uint8_t *ao_mutex) __reentrant; - -void -ao_mutex_put(__xdata uint8_t *ao_mutex) __reentrant; - -/* - * Storage interface, provided by one of the eeprom or flash - * drivers - */ - -/* Total bytes of available storage */ -extern __pdata uint32_t ao_storage_total; - -/* Block size - device is erased in these units. At least 256 bytes */ -extern __pdata uint32_t ao_storage_block; - -/* Byte offset of config block. Will be ao_storage_block bytes long */ -extern __pdata uint32_t ao_storage_config; - -/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ -extern __pdata uint16_t ao_storage_unit; - -#define AO_STORAGE_ERASE_LOG (ao_storage_config + AO_CONFIG_MAX_SIZE) - -/* Initialize above values. Can only be called once the OS is running */ -void -ao_storage_setup(void) __reentrant; - -/* Write data. Returns 0 on failure, 1 on success */ -uint8_t -ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; - -/* Read data. Returns 0 on failure, 1 on success */ -uint8_t -ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; - -/* Erase a block of storage. This always clears ao_storage_block bytes */ -uint8_t -ao_storage_erase(uint32_t pos) __reentrant; - -/* Flush any pending writes to stable storage */ -void -ao_storage_flush(void) __reentrant; - -/* Initialize the storage code */ -void -ao_storage_init(void); - -/* - * Low-level functions wrapped by ao_storage.c - */ - -/* Read data within a storage unit */ -uint8_t -ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; - -/* Write data within a storage unit */ -uint8_t -ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; - -/* Initialize low-level device bits */ -void -ao_storage_device_init(void); - -/* Print out information about flash chips */ -void -ao_storage_device_info(void) __reentrant; - -/* - * ao_log.c - */ - -/* We record flight numbers in the first record of - * the log. Tasks may wait for this to be initialized - * by sleeping on this variable. - */ -extern __xdata uint16_t ao_flight_number; - -extern __pdata uint32_t ao_log_current_pos; -extern __pdata uint32_t ao_log_end_pos; -extern __pdata uint32_t ao_log_start_pos; -extern __xdata uint8_t ao_log_running; -extern __pdata enum flight_state ao_log_state; - -/* required functions from the underlying log system */ - -#define AO_LOG_FORMAT_UNKNOWN 0 /* unknown; altosui will have to guess */ -#define AO_LOG_FORMAT_FULL 1 /* 8 byte typed log records */ -#define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */ -#define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */ -#define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ -#define AO_LOG_FORMAT_NONE 127 /* No log at all */ - -extern __code uint8_t ao_log_format; - -/* Return the flight number from the given log slot, 0 if none */ -uint16_t -ao_log_flight(uint8_t slot); - -/* Flush the log */ -void -ao_log_flush(void); - -/* Logging thread main routine */ -void -ao_log(void); - -/* functions provided in ao_log.c */ - -/* Figure out the current flight number */ -void -ao_log_scan(void) __reentrant; - -/* Return the position of the start of the given log slot */ -uint32_t -ao_log_pos(uint8_t slot); - -/* Start logging to eeprom */ -void -ao_log_start(void); - -/* Stop logging */ -void -ao_log_stop(void); - -/* Initialize the logging system */ -void -ao_log_init(void); - -/* Write out the current flight number to the erase log */ -void -ao_log_write_erase(uint8_t pos); - -/* Returns true if there are any logs stored in eeprom */ -uint8_t -ao_log_present(void); - -/* Returns true if there is no more storage space available */ -uint8_t -ao_log_full(void); - -/* - * ao_log_big.c + * Various drivers */ - -/* - * The data log is recorded in the eeprom as a sequence - * of data packets. - * - * Each packet starts with a 4-byte header that has the - * packet type, the packet checksum and the tick count. Then - * they all contain 2 16 bit values which hold packet-specific - * data. - * - * For each flight, the first packet - * is FLIGHT packet, indicating the serial number of the - * device and a unique number marking the number of flights - * recorded by this device. - * - * During flight, data from the accelerometer and barometer - * are recorded in SENSOR packets, using the raw 16-bit values - * read from the A/D converter. - * - * Also during flight, but at a lower rate, the deployment - * sensors are recorded in DEPLOY packets. The goal here is to - * detect failure in the deployment circuits. - * - * STATE packets hold state transitions as the flight computer - * transitions through different stages of the flight. - */ -#define AO_LOG_FLIGHT 'F' -#define AO_LOG_SENSOR 'A' -#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_GPS_SAT 'V' -#define AO_LOG_GPS_DATE 'Y' - -#define AO_LOG_POS_NONE (~0UL) - -struct ao_log_record { - char type; - uint8_t csum; - uint16_t tick; - union { - struct { - int16_t ground_accel; - uint16_t flight; - } flight; - struct { - int16_t accel; - int16_t pres; - } sensor; - struct { - int16_t temp; - int16_t v_batt; - } temp_volt; - struct { - int16_t drogue; - int16_t main; - } deploy; - struct { - uint16_t state; - uint16_t reason; - } state; - struct { - uint8_t hour; - uint8_t minute; - uint8_t second; - uint8_t flags; - } gps_time; - int32_t gps_latitude; - int32_t gps_longitude; - struct { - int16_t altitude; - uint16_t unused; - } gps_altitude; - struct { - uint16_t svid; - uint8_t unused; - uint8_t c_n; - } gps_sat; - struct { - uint8_t year; - uint8_t month; - uint8_t day; - uint8_t extra; - } gps_date; - struct { - uint16_t d0; - uint16_t d1; - } anon; - } u; -}; - -/* Write a record to the eeprom log */ -uint8_t -ao_log_data(__xdata struct ao_log_record *log) __reentrant; - -/* - * ao_flight.c - */ - -enum ao_flight_state { - ao_flight_startup = 0, - ao_flight_idle = 1, - ao_flight_pad = 2, - ao_flight_boost = 3, - ao_flight_fast = 4, - ao_flight_coast = 5, - ao_flight_drogue = 6, - ao_flight_main = 7, - ao_flight_landed = 8, - ao_flight_invalid = 9 -}; - -extern __pdata enum ao_flight_state ao_flight_state; - -extern __pdata uint16_t ao_launch_time; -extern __pdata uint8_t ao_flight_force_idle; - -/* Flight thread */ -void -ao_flight(void); - -/* Initialize flight thread */ -void -ao_flight_init(void); - -/* - * ao_flight_nano.c - */ - -void -ao_flight_nano_init(void); - -/* - * ao_sample.c - */ - -/* - * Barometer calibration - * - * We directly sample the barometer. The specs say: - * - * Pressure range: 15-115 kPa - * Voltage at 115kPa: 2.82 - * Output scale: 27mV/kPa - * - * If we want to detect launch with the barometer, we need - * a large enough bump to not be fooled by noise. At typical - * launch elevations (0-2000m), a 200Pa pressure change cooresponds - * to about a 20m elevation change. This is 5.4mV, or about 3LSB. - * As all of our calculations are done in 16 bits, we'll actually see a change - * of 16 times this though - * - * 27 mV/kPa * 32767 / 3300 counts/mV = 268.1 counts/kPa - */ - -/* Accelerometer calibration - * - * We're sampling the accelerometer through a resistor divider which - * consists of 5k and 10k resistors. This multiplies the values by 2/3. - * That goes into the cc1111 A/D converter, which is running at 11 bits - * of precision with the bits in the MSB of the 16 bit value. Only positive - * values are used, so values should range from 0-32752 for 0-3.3V. The - * specs say we should see 40mV/g (uncalibrated), multiply by 2/3 for what - * the A/D converter sees (26.67 mV/g). We should see 32752/3300 counts/mV, - * for a final computation of: - * - * 26.67 mV/g * 32767/3300 counts/mV = 264.8 counts/g - * - * Zero g was measured at 16000 (we would expect 16384). - * Note that this value is only require to tell if the - * rocket is standing upright. Once that is determined, - * the value of the accelerometer is averaged for 100 samples - * to find the resting accelerometer value, which is used - * for all further flight computations - */ - -#define GRAVITY 9.80665 - -/* - * Above this height, the baro sensor doesn't work - */ -#define AO_MAX_BARO_HEIGHT 12000 - -/* - * Above this speed, baro measurements are unreliable - */ -#define AO_MAX_BARO_SPEED 200 - -#define ACCEL_NOSE_UP (ao_accel_2g >> 2) - -/* - * Speed and acceleration are scaled by 16 to provide a bit more - * resolution while still having reasonable range. Note that this - * limits speed to 2047m/s (around mach 6) and acceleration to - * 2047m/s² (over 200g) - */ - -#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) -#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) -#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) - -extern __pdata uint16_t ao_sample_tick; /* time of last data */ -extern __pdata int16_t ao_sample_pres; /* most recent pressure sensor reading */ -extern __pdata int16_t ao_sample_alt; /* MSL of ao_sample_pres */ -extern __pdata int16_t ao_sample_height; /* AGL of ao_sample_pres */ -extern __data uint8_t ao_sample_adc; /* Ring position of last processed sample */ - -#if HAS_ACCEL -extern __pdata int16_t ao_sample_accel; /* most recent accel sensor reading */ +#if HAS_ADC +#include #endif -extern __pdata int16_t ao_ground_pres; /* startup pressure */ -extern __pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ - -#if HAS_ACCEL -extern __pdata int16_t ao_ground_accel; /* startup acceleration */ -extern __pdata int16_t ao_accel_2g; /* factory accel calibration */ -extern __pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +#if HAS_BEEP +#include #endif -void ao_sample_init(void); - -/* returns FALSE in preflight mode, TRUE in flight mode */ -uint8_t ao_sample(void); - -/* - * ao_kalman.c - */ - -#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) -#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) -#define from_fix(x) ((x) >> 16) +#if LEDS_AVAILABLE +#include +#endif -extern __pdata int16_t ao_height; /* meters */ -extern __pdata int16_t ao_speed; /* m/s * 16 */ -extern __pdata int16_t ao_accel; /* m/s² * 16 */ -extern __pdata int16_t ao_max_height; /* max of ao_height */ -extern __pdata int16_t ao_avg_height; /* running average of height */ +#if HAS_USB +#include +#endif -extern __pdata int16_t ao_error_h; -extern __pdata int16_t ao_error_h_sq_avg; +#if HAS_EEPROM +#include +#endif -#if HAS_ACCEL -extern __pdata int16_t ao_error_a; +#if HAS_LOG +#include #endif -void ao_kalman(void); +#if HAS_FLIGHT +#include +#include +#endif /* * ao_report.c @@ -819,125 +282,12 @@ ao_altitude_to_pres(int16_t alt) __reentrant; int16_t ao_temp_to_dC(int16_t temp) __reentrant; -/* - * ao_dbg.c - * - * debug another telemetrum board - */ - -/* Send a byte to the dbg target */ -void -ao_dbg_send_byte(uint8_t byte); - -/* Receive a byte from the dbg target */ -uint8_t -ao_dbg_recv_byte(void); - -/* Start a bulk transfer to/from dbg target memory */ -void -ao_dbg_start_transfer(uint16_t addr); - -/* End a bulk transfer to/from dbg target memory */ -void -ao_dbg_end_transfer(void); - -/* Write a byte to dbg target memory */ -void -ao_dbg_write_byte(uint8_t byte); - -/* Read a byte from dbg target memory */ -uint8_t -ao_dbg_read_byte(void); - -/* Enable dbg mode, switching use of the pins */ -void -ao_dbg_debug_mode(void); - -/* Reset the dbg target */ -void -ao_dbg_reset(void); - -void -ao_dbg_init(void); - -/* - * ao_serial.c - */ - -#ifndef HAS_SERIAL_1 -#error Please define HAS_SERIAL_1 +#if HAS_DBG +#include #endif -#if HAS_SERIAL_1 | HAS_SERIAL_2 | HAS_SERIAL_3 -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - -void -ao_serial_rx1_isr(void) ao_arch_interrupt(3); - -void -ao_serial_tx1_isr(void) ao_arch_interrupt(14); - -char -ao_serial_getchar(void) __critical; - -#if USE_SERIAL_STDIN -char -ao_serial_pollchar(void) __critical; - -void -ao_serial_set_stdin(uint8_t in); -#endif - -void -ao_serial_putchar(char c) __critical; - -void -ao_serial_drain(void) __critical; - -#define AO_SERIAL_SPEED_4800 0 -#define AO_SERIAL_SPEED_9600 1 -#define AO_SERIAL_SPEED_19200 2 -#define AO_SERIAL_SPEED_57600 3 - -void -ao_serial_set_speed(uint8_t speed); - -void -ao_serial_init(void); -#endif - -#ifndef HAS_SERIAL_0 -#define HAS_SERIAL_0 0 -#endif - -#if HAS_SERIAL_0 - -extern volatile __xdata struct ao_fifo ao_usart0_rx_fifo; -extern volatile __xdata struct ao_fifo ao_usart0_tx_fifo; - -void -ao_serial0_rx0_isr(void) ao_arch_interrupt(2); - -void -ao_serial0_tx0_isr(void) ao_arch_interrupt(7); - -char -ao_serial0_getchar(void) __critical; - -void -ao_serial0_putchar(char c) __critical; - -void -ao_serial0_drain(void) __critical; - -void -ao_serial0_set_speed(uint8_t speed); - -void -ao_serial0_init(void); - +#if HAS_SERIAL_0 || HAS_SERIAL_1 || HAS_SERIAL_2 || HAS_SERIAL_3 +#include #endif diff --git a/src/core/ao_adc.h b/src/core/ao_adc.h new file mode 100644 index 00000000..db5bfab3 --- /dev/null +++ b/src/core/ao_adc.h @@ -0,0 +1,62 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_ADC_H_ +#define _AO_ADC_H_ + + + +/* + * One set of samples read from the A/D converter or telemetry + */ + + +/* + * ao_adc.c + */ + +#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) +#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) + + +/* + * A/D data is stored in a ring, with the next sample to be written + * at ao_adc_head + */ +extern volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; +extern volatile __data uint8_t ao_adc_head; +#if HAS_ACCEL_REF +extern volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; +#endif + +/* Trigger a conversion sequence (called from the timer interrupt) */ +void +ao_adc_poll(void); + +/* Suspend the current task until another A/D sample is converted */ +void +ao_adc_sleep(void); + +/* Get a copy of the last complete A/D sample set */ +void +ao_adc_get(__xdata struct ao_adc *packet); + +/* Initialize the A/D converter */ +void +ao_adc_init(void); + +#endif /* _AO_ADC_H_ */ diff --git a/src/core/ao_beep.h b/src/core/ao_beep.h new file mode 100644 index 00000000..55f61171 --- /dev/null +++ b/src/core/ao_beep.h @@ -0,0 +1,74 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_BEEP_H_ +#define _AO_BEEP_H_ + +/* + * ao_beep.c + */ + +/* + * Various pre-defined beep frequencies + * + * frequency = 1/2 (24e6/32) / beep + */ + +#define AO_BEEP_LOW 150 /* 2500Hz */ +#define AO_BEEP_MID 94 /* 3989Hz */ +#define AO_BEEP_HIGH 75 /* 5000Hz */ +#define AO_BEEP_OFF 0 /* off */ + +#define AO_BEEP_g 240 /* 1562.5Hz */ +#define AO_BEEP_gs 227 /* 1652Hz (1655Hz) */ +#define AO_BEEP_aa 214 /* 1752Hz (1754Hz) */ +#define AO_BEEP_bbf 202 /* 1856Hz (1858Hz) */ +#define AO_BEEP_bb 190 /* 1974Hz (1969Hz) */ +#define AO_BEEP_cc 180 /* 2083Hz (2086Hz) */ +#define AO_BEEP_ccs 170 /* 2205Hz (2210Hz) */ +#define AO_BEEP_dd 160 /* 2344Hz (2341Hz) */ +#define AO_BEEP_eef 151 /* 2483Hz (2480Hz) */ +#define AO_BEEP_ee 143 /* 2622Hz (2628Hz) */ +#define AO_BEEP_ff 135 /* 2778Hz (2784Hz) */ +#define AO_BEEP_ffs 127 /* 2953Hz (2950Hz) */ +#define AO_BEEP_gg 120 /* 3125Hz */ +#define AO_BEEP_ggs 113 /* 3319Hz (3311Hz) */ +#define AO_BEEP_aaa 107 /* 3504Hz (3508Hz) */ +#define AO_BEEP_bbbf 101 /* 3713Hz (3716Hz) */ +#define AO_BEEP_bbb 95 /* 3947Hz (3937Hz) */ +#define AO_BEEP_ccc 90 /* 4167Hz (4171Hz) */ +#define AO_BEEP_cccs 85 /* 4412Hz (4419Hz) */ +#define AO_BEEP_ddd 80 /* 4688Hz (4682Hz) */ +#define AO_BEEP_eeef 76 /* 4934Hz (4961Hz) */ +#define AO_BEEP_eee 71 /* 5282Hz (5256Hz) */ +#define AO_BEEP_fff 67 /* 5597Hz (5568Hz) */ +#define AO_BEEP_fffs 64 /* 5859Hz (5899Hz) */ +#define AO_BEEP_ggg 60 /* 6250Hz */ + +/* Set the beeper to the specified tone */ +void +ao_beep(uint8_t beep); + +/* Turn on the beeper for the specified time */ +void +ao_beep_for(uint8_t beep, uint16_t ticks) __reentrant; + +/* Initialize the beeper */ +void +ao_beep_init(void); + +#endif /* _AO_BEEP_H_ */ diff --git a/src/core/ao_dbg.h b/src/core/ao_dbg.h new file mode 100644 index 00000000..181e6ec2 --- /dev/null +++ b/src/core/ao_dbg.h @@ -0,0 +1,62 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_DBG_H_ +#define _AO_DBG_H_ + +/* + * ao_dbg.c + * + * debug another telemetrum board + */ + +/* Send a byte to the dbg target */ +void +ao_dbg_send_byte(uint8_t byte); + +/* Receive a byte from the dbg target */ +uint8_t +ao_dbg_recv_byte(void); + +/* Start a bulk transfer to/from dbg target memory */ +void +ao_dbg_start_transfer(uint16_t addr); + +/* End a bulk transfer to/from dbg target memory */ +void +ao_dbg_end_transfer(void); + +/* Write a byte to dbg target memory */ +void +ao_dbg_write_byte(uint8_t byte); + +/* Read a byte from dbg target memory */ +uint8_t +ao_dbg_read_byte(void); + +/* Enable dbg mode, switching use of the pins */ +void +ao_dbg_debug_mode(void); + +/* Reset the dbg target */ +void +ao_dbg_reset(void); + +void +ao_dbg_init(void); + +#endif /* _AO_DBG_H_ */ diff --git a/src/core/ao_flight.h b/src/core/ao_flight.h new file mode 100644 index 00000000..aa5ab60d --- /dev/null +++ b/src/core/ao_flight.h @@ -0,0 +1,59 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_FLIGHT_H_ +#define _AO_FLIGHT_H_ + + +/* + * ao_flight.c + */ + +enum ao_flight_state { + ao_flight_startup = 0, + ao_flight_idle = 1, + ao_flight_pad = 2, + ao_flight_boost = 3, + ao_flight_fast = 4, + ao_flight_coast = 5, + ao_flight_drogue = 6, + ao_flight_main = 7, + ao_flight_landed = 8, + ao_flight_invalid = 9 +}; + +extern __pdata enum ao_flight_state ao_flight_state; + +extern __pdata uint16_t ao_launch_time; +extern __pdata uint8_t ao_flight_force_idle; + +/* Flight thread */ +void +ao_flight(void); + +/* Initialize flight thread */ +void +ao_flight_init(void); + +/* + * ao_flight_nano.c + */ + +void +ao_flight_nano_init(void); + +#endif /* _AO_FLIGHT_H_ */ diff --git a/src/core/ao_led.h b/src/core/ao_led.h new file mode 100644 index 00000000..edc5fd1f --- /dev/null +++ b/src/core/ao_led.h @@ -0,0 +1,55 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_LED_H_ +#define _AO_LED_H_ + +/* + * ao_led.c + */ + +#define AO_LED_NONE 0 + +#ifndef AO_LED_TYPE +#define AO_LED_TYPE uint8_t +#endif + +/* Turn on the specified LEDs */ +void +ao_led_on(AO_LED_TYPE colors); + +/* Turn off the specified LEDs */ +void +ao_led_off(AO_LED_TYPE colors); + +/* Set all of the LEDs to the specified state */ +void +ao_led_set(AO_LED_TYPE colors); + +/* Toggle the specified LEDs */ +void +ao_led_toggle(AO_LED_TYPE colors); + +/* Turn on the specified LEDs for the indicated interval */ +void +ao_led_for(AO_LED_TYPE colors, uint16_t ticks) __reentrant; + +/* Initialize the LEDs */ +void +ao_led_init(AO_LED_TYPE enable); + +#endif /* _AO_LED_H_ */ diff --git a/src/core/ao_log.h b/src/core/ao_log.h new file mode 100644 index 00000000..611c00d5 --- /dev/null +++ b/src/core/ao_log.h @@ -0,0 +1,196 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_LOG_H_ +#define _AO_LOG_H_ + +/* + * ao_log.c + */ + +/* We record flight numbers in the first record of + * the log. Tasks may wait for this to be initialized + * by sleeping on this variable. + */ +extern __xdata uint16_t ao_flight_number; + +extern __pdata uint32_t ao_log_current_pos; +extern __pdata uint32_t ao_log_end_pos; +extern __pdata uint32_t ao_log_start_pos; +extern __xdata uint8_t ao_log_running; +extern __pdata enum flight_state ao_log_state; + +/* required functions from the underlying log system */ + +#define AO_LOG_FORMAT_UNKNOWN 0 /* unknown; altosui will have to guess */ +#define AO_LOG_FORMAT_FULL 1 /* 8 byte typed log records */ +#define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */ +#define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */ +#define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ +#define AO_LOG_FORMAT_NONE 127 /* No log at all */ + +extern __code uint8_t ao_log_format; + +/* Return the flight number from the given log slot, 0 if none */ +uint16_t +ao_log_flight(uint8_t slot); + +/* Flush the log */ +void +ao_log_flush(void); + +/* Logging thread main routine */ +void +ao_log(void); + +/* functions provided in ao_log.c */ + +/* Figure out the current flight number */ +void +ao_log_scan(void) __reentrant; + +/* Return the position of the start of the given log slot */ +uint32_t +ao_log_pos(uint8_t slot); + +/* Start logging to eeprom */ +void +ao_log_start(void); + +/* Stop logging */ +void +ao_log_stop(void); + +/* Initialize the logging system */ +void +ao_log_init(void); + +/* Write out the current flight number to the erase log */ +void +ao_log_write_erase(uint8_t pos); + +/* Returns true if there are any logs stored in eeprom */ +uint8_t +ao_log_present(void); + +/* Returns true if there is no more storage space available */ +uint8_t +ao_log_full(void); + +/* + * ao_log_big.c + */ + +/* + * The data log is recorded in the eeprom as a sequence + * of data packets. + * + * Each packet starts with a 4-byte header that has the + * packet type, the packet checksum and the tick count. Then + * they all contain 2 16 bit values which hold packet-specific + * data. + * + * For each flight, the first packet + * is FLIGHT packet, indicating the serial number of the + * device and a unique number marking the number of flights + * recorded by this device. + * + * During flight, data from the accelerometer and barometer + * are recorded in SENSOR packets, using the raw 16-bit values + * read from the A/D converter. + * + * Also during flight, but at a lower rate, the deployment + * sensors are recorded in DEPLOY packets. The goal here is to + * detect failure in the deployment circuits. + * + * STATE packets hold state transitions as the flight computer + * transitions through different stages of the flight. + */ +#define AO_LOG_FLIGHT 'F' +#define AO_LOG_SENSOR 'A' +#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_GPS_SAT 'V' +#define AO_LOG_GPS_DATE 'Y' + +#define AO_LOG_POS_NONE (~0UL) + +struct ao_log_record { + char type; + uint8_t csum; + uint16_t tick; + union { + struct { + int16_t ground_accel; + uint16_t flight; + } flight; + struct { + int16_t accel; + int16_t pres; + } sensor; + struct { + int16_t temp; + int16_t v_batt; + } temp_volt; + struct { + int16_t drogue; + int16_t main; + } deploy; + struct { + uint16_t state; + uint16_t reason; + } state; + struct { + uint8_t hour; + uint8_t minute; + uint8_t second; + uint8_t flags; + } gps_time; + int32_t gps_latitude; + int32_t gps_longitude; + struct { + int16_t altitude; + uint16_t unused; + } gps_altitude; + struct { + uint16_t svid; + uint8_t unused; + uint8_t c_n; + } gps_sat; + struct { + uint8_t year; + uint8_t month; + uint8_t day; + uint8_t extra; + } gps_date; + struct { + uint16_t d0; + uint16_t d1; + } anon; + } u; +}; + +/* Write a record to the eeprom log */ +uint8_t +ao_log_data(__xdata struct ao_log_record *log) __reentrant; + +#endif /* _AO_LOG_H_ */ diff --git a/src/core/ao_log_telem.c b/src/core/ao_log_telem.c index 9e1b06d3..18ab85dd 100644 --- a/src/core/ao_log_telem.c +++ b/src/core/ao_log_telem.c @@ -15,7 +15,9 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" +#include +#include +#include __code uint8_t ao_log_format = AO_LOG_FORMAT_TELEMETRY; diff --git a/src/core/ao_product.c b/src/core/ao_product.c index fb59580b..f79922f5 100644 --- a/src/core/ao_product.c +++ b/src/core/ao_product.c @@ -70,26 +70,26 @@ __code __at(0x00aa) uint8_t ao_usb_descriptors [] = /* Header functional descriptor */ 0x05, - CS_INTERFACE, + AO_USB_CS_INTERFACE, 0x00, /* bDescriptor SubType Header */ LE_WORD(0x0110), /* CDC version 1.1 */ /* Call management functional descriptor */ 0x05, - CS_INTERFACE, + AO_USB_CS_INTERFACE, 0x01, /* bDescriptor SubType Call Management */ 0x01, /* bmCapabilities = device handles call management */ 0x01, /* bDataInterface call management interface number */ /* ACM functional descriptor */ 0x04, - CS_INTERFACE, + AO_USB_CS_INTERFACE, 0x02, /* bDescriptor SubType Abstract Control Management */ 0x02, /* bmCapabilities = D1 (Set_line_Coding, Set_Control_Line_State, Get_Line_Coding and Serial_State) */ /* Union functional descriptor */ 0x05, - CS_INTERFACE, + AO_USB_CS_INTERFACE, 0x06, /* bDescriptor SubType Union Functional descriptor */ 0x00, /* bMasterInterface */ 0x01, /* bSlaveInterface0 */ diff --git a/src/core/ao_report.c b/src/core/ao_report.c index 7c928792..eb90a4f8 100644 --- a/src/core/ao_report.c +++ b/src/core/ao_report.c @@ -16,6 +16,8 @@ */ #include "ao.h" +#include +#include #define BIT(i,x) ((x) ? (1 << (i)) : 0) #define MORSE1(a) (1 | BIT(3,a)) diff --git a/src/core/ao_sample.h b/src/core/ao_sample.h new file mode 100644 index 00000000..fb0e69e8 --- /dev/null +++ b/src/core/ao_sample.h @@ -0,0 +1,137 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_SAMPLE_H_ +#define _AO_SAMPLE_H_ + +/* + * ao_sample.c + */ + +/* + * Barometer calibration + * + * We directly sample the barometer. The specs say: + * + * Pressure range: 15-115 kPa + * Voltage at 115kPa: 2.82 + * Output scale: 27mV/kPa + * + * If we want to detect launch with the barometer, we need + * a large enough bump to not be fooled by noise. At typical + * launch elevations (0-2000m), a 200Pa pressure change cooresponds + * to about a 20m elevation change. This is 5.4mV, or about 3LSB. + * As all of our calculations are done in 16 bits, we'll actually see a change + * of 16 times this though + * + * 27 mV/kPa * 32767 / 3300 counts/mV = 268.1 counts/kPa + */ + +/* Accelerometer calibration + * + * We're sampling the accelerometer through a resistor divider which + * consists of 5k and 10k resistors. This multiplies the values by 2/3. + * That goes into the cc1111 A/D converter, which is running at 11 bits + * of precision with the bits in the MSB of the 16 bit value. Only positive + * values are used, so values should range from 0-32752 for 0-3.3V. The + * specs say we should see 40mV/g (uncalibrated), multiply by 2/3 for what + * the A/D converter sees (26.67 mV/g). We should see 32752/3300 counts/mV, + * for a final computation of: + * + * 26.67 mV/g * 32767/3300 counts/mV = 264.8 counts/g + * + * Zero g was measured at 16000 (we would expect 16384). + * Note that this value is only require to tell if the + * rocket is standing upright. Once that is determined, + * the value of the accelerometer is averaged for 100 samples + * to find the resting accelerometer value, which is used + * for all further flight computations + */ + +#define GRAVITY 9.80665 + +/* + * Above this height, the baro sensor doesn't work + */ +#define AO_MAX_BARO_HEIGHT 12000 + +/* + * Above this speed, baro measurements are unreliable + */ +#define AO_MAX_BARO_SPEED 200 + +#define ACCEL_NOSE_UP (ao_accel_2g >> 2) + +/* + * Speed and acceleration are scaled by 16 to provide a bit more + * resolution while still having reasonable range. Note that this + * limits speed to 2047m/s (around mach 6) and acceleration to + * 2047m/s² (over 200g) + */ + +#define AO_M_TO_HEIGHT(m) ((int16_t) (m)) +#define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) +#define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) + +extern __pdata uint16_t ao_sample_tick; /* time of last data */ +extern __pdata int16_t ao_sample_pres; /* most recent pressure sensor reading */ +extern __pdata int16_t ao_sample_alt; /* MSL of ao_sample_pres */ +extern __pdata int16_t ao_sample_height; /* AGL of ao_sample_pres */ +extern __data uint8_t ao_sample_adc; /* Ring position of last processed sample */ + +#if HAS_ACCEL +extern __pdata int16_t ao_sample_accel; /* most recent accel sensor reading */ +#endif + +extern __pdata int16_t ao_ground_pres; /* startup pressure */ +extern __pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ + +#if HAS_ACCEL +extern __pdata int16_t ao_ground_accel; /* startup acceleration */ +extern __pdata int16_t ao_accel_2g; /* factory accel calibration */ +extern __pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +#endif + +void ao_sample_init(void); + +/* returns FALSE in preflight mode, TRUE in flight mode */ +uint8_t ao_sample(void); + +/* + * ao_kalman.c + */ + +#define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) +#define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) +#define from_fix(x) ((x) >> 16) + +extern __pdata int16_t ao_height; /* meters */ +extern __pdata int16_t ao_speed; /* m/s * 16 */ +extern __pdata int16_t ao_accel; /* m/s² * 16 */ +extern __pdata int16_t ao_max_height; /* max of ao_height */ +extern __pdata int16_t ao_avg_height; /* running average of height */ + +extern __pdata int16_t ao_error_h; +extern __pdata int16_t ao_error_h_sq_avg; + +#if HAS_ACCEL +extern __pdata int16_t ao_error_a; +#endif + +void ao_kalman(void); + +#endif /* _AO_SAMPLE_H_ */ diff --git a/src/core/ao_serial.h b/src/core/ao_serial.h new file mode 100644 index 00000000..53aa8a89 --- /dev/null +++ b/src/core/ao_serial.h @@ -0,0 +1,86 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_SERIAL_H_ +#define _AO_SERIAL_H_ + +#define AO_SERIAL_SPEED_4800 0 +#define AO_SERIAL_SPEED_9600 1 +#define AO_SERIAL_SPEED_19200 2 +#define AO_SERIAL_SPEED_57600 3 + +#if HAS_SERIAL_0 +extern volatile __xdata struct ao_fifo ao_serial0_rx_fifo; +extern volatile __xdata struct ao_fifo ao_serial0_tx_fifo; + +char +ao_serial0_getchar(void); + +void +ao_serial0_putchar(char c); + +void +ao_serial0_drain(void); + +void +ao_serial0_set_speed(uint8_t speed); +#endif + +#if HAS_SERIAL_1 +extern volatile __xdata struct ao_fifo ao_serial1_rx_fifo; +extern volatile __xdata struct ao_fifo ao_serial1_tx_fifo; + +char +ao_serial1_getchar(void); + +char +ao_serial1_pollchar(void); + +void +ao_serial1_putchar(char c); + +void +ao_serial1_drain(void); + +void +ao_serial1_set_speed(uint8_t speed); +#endif + +#if HAS_SERIAL_2 +extern volatile __xdata struct ao_fifo ao_serial2_rx_fifo; +extern volatile __xdata struct ao_fifo ao_serial2_tx_fifo; + +char +ao_serial2_getchar(void); + +char +ao_serial2_pollchar(void); + +void +ao_serial2_putchar(char c); + +void +ao_serial2_drain(void); + +void +ao_serial2_set_speed(uint8_t speed); +#endif + +void +ao_serial_init(void); + +#endif /* _AO_SERIAL_H_ */ diff --git a/src/core/ao_stdio.c b/src/core/ao_stdio.c index 2967e705..18fa913e 100644 --- a/src/core/ao_stdio.c +++ b/src/core/ao_stdio.c @@ -21,6 +21,12 @@ * Basic I/O functions to support SDCC stdio package */ +#ifdef SERIAL_STDIN_PORT +#define USE_SERIAL_STDIN 1 +#else +#define USE_SERIAL_STDIN 0 +#endif + #define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) __xdata struct ao_stdio ao_stdios[AO_NUM_STDIOS]; diff --git a/src/core/ao_storage.c b/src/core/ao_storage.c index ff4747d0..66394e01 100644 --- a/src/core/ao_storage.c +++ b/src/core/ao_storage.c @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" +#include uint8_t ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant diff --git a/src/core/ao_storage.h b/src/core/ao_storage.h new file mode 100644 index 00000000..873fe097 --- /dev/null +++ b/src/core/ao_storage.h @@ -0,0 +1,84 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_STORAGE_H_ +#define _AO_STORAGE_H_ + +/* + * Storage interface, provided by one of the eeprom or flash + * drivers + */ + +/* Total bytes of available storage */ +extern __pdata uint32_t ao_storage_total; + +/* Block size - device is erased in these units. At least 256 bytes */ +extern __pdata uint32_t ao_storage_block; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +extern __pdata uint32_t ao_storage_config; + +/* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ +extern __pdata uint16_t ao_storage_unit; + +#define AO_STORAGE_ERASE_LOG (ao_storage_config + AO_CONFIG_MAX_SIZE) + +/* Initialize above values. Can only be called once the OS is running */ +void +ao_storage_setup(void) __reentrant; + +/* Write data. Returns 0 on failure, 1 on success */ +uint8_t +ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Read data. Returns 0 on failure, 1 on success */ +uint8_t +ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Erase a block of storage. This always clears ao_storage_block bytes */ +uint8_t +ao_storage_erase(uint32_t pos) __reentrant; + +/* Flush any pending writes to stable storage */ +void +ao_storage_flush(void) __reentrant; + +/* Initialize the storage code */ +void +ao_storage_init(void); + +/* + * Low-level functions wrapped by ao_storage.c + */ + +/* Read data within a storage unit */ +uint8_t +ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Write data within a storage unit */ +uint8_t +ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; + +/* Initialize low-level device bits */ +void +ao_storage_device_init(void); + +/* Print out information about flash chips */ +void +ao_storage_device_info(void) __reentrant; + +#endif /* _AO_STORAGE_H_ */ diff --git a/src/core/ao_usb.h b/src/core/ao_usb.h new file mode 100644 index 00000000..e051db93 --- /dev/null +++ b/src/core/ao_usb.h @@ -0,0 +1,136 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_USB_H_ +#define _AO_USB_H_ + +/* + * ao_usb.c + */ + +/* Put one character to the USB output queue */ +void +ao_usb_putchar(char c); + +/* Get one character from the USB input queue */ +char +ao_usb_getchar(void); + +/* Poll for a charcter on the USB input queue. + * returns AO_READ_AGAIN if none are available + */ +char +ao_usb_pollchar(void); + +/* Flush the USB output queue */ +void +ao_usb_flush(void); + +/* Enable the USB controller */ +void +ao_usb_enable(void); + +/* Disable the USB controller */ +void +ao_usb_disable(void); + +/* Initialize the USB system */ +void +ao_usb_init(void); + +extern __code __at (0x00aa) uint8_t ao_usb_descriptors []; + +#define AO_USB_SETUP_DIR_MASK (0x01 << 7) +#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) +#define AO_USB_SETUP_RECIP_MASK (0x1f) + +#define AO_USB_DIR_OUT 0 +#define AO_USB_DIR_IN (1 << 7) + +#define AO_USB_TYPE_STANDARD 0 +#define AO_USB_TYPE_CLASS (1 << 5) +#define AO_USB_TYPE_VENDOR (2 << 5) +#define AO_USB_TYPE_RESERVED (3 << 5) + +#define AO_USB_RECIP_DEVICE 0 +#define AO_USB_RECIP_INTERFACE 1 +#define AO_USB_RECIP_ENDPOINT 2 +#define AO_USB_RECIP_OTHER 3 + +/* standard requests */ +#define AO_USB_REQ_GET_STATUS 0x00 +#define AO_USB_REQ_CLEAR_FEATURE 0x01 +#define AO_USB_REQ_SET_FEATURE 0x03 +#define AO_USB_REQ_SET_ADDRESS 0x05 +#define AO_USB_REQ_GET_DESCRIPTOR 0x06 +#define AO_USB_REQ_SET_DESCRIPTOR 0x07 +#define AO_USB_REQ_GET_CONFIGURATION 0x08 +#define AO_USB_REQ_SET_CONFIGURATION 0x09 +#define AO_USB_REQ_GET_INTERFACE 0x0A +#define AO_USB_REQ_SET_INTERFACE 0x0B +#define AO_USB_REQ_SYNCH_FRAME 0x0C + +#define AO_USB_DESC_DEVICE 1 +#define AO_USB_DESC_CONFIGURATION 2 +#define AO_USB_DESC_STRING 3 +#define AO_USB_DESC_INTERFACE 4 +#define AO_USB_DESC_ENDPOINT 5 +#define AO_USB_DESC_DEVICE_QUALIFIER 6 +#define AO_USB_DESC_OTHER_SPEED 7 +#define AO_USB_DESC_INTERFACE_POWER 8 + +#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) +#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) + +#define AO_USB_CONTROL_EP 0 +#define AO_USB_CONTROL_SIZE 32 + +#define AO_USB_INT_EP 1 +#define AO_USB_INT_SIZE 8 + +#define AO_USB_OUT_EP 4 +#define AO_USB_IN_EP 5 +/* + * USB bulk packets can only come in 8, 16, 32 and 64 + * byte sizes, so we'll use 64 for everything + */ +#define AO_USB_IN_SIZE 64 +#define AO_USB_OUT_SIZE 64 + +#define AO_USB_EP0_IDLE 0 +#define AO_USB_EP0_DATA_IN 1 +#define AO_USB_EP0_DATA_OUT 2 + +#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) + +/* CDC definitions */ +#define AO_USB_CS_INTERFACE 0x24 +#define AO_USB_CS_ENDPOINT 0x25 + +#define AO_USB_SET_LINE_CODING 0x20 +#define AO_USB_GET_LINE_CODING 0x21 +#define AO_USB_SET_CONTROL_LINE_STATE 0x22 + +/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ +struct ao_usb_line_coding { + uint32_t rate; + uint8_t char_format; + uint8_t parity; + uint8_t data_bits; +} ; + +#endif /* _AO_USB_H_ */ diff --git a/src/drivers/ao_btm.c b/src/drivers/ao_btm.c index 5eb78815..f193ac8e 100644 --- a/src/drivers/ao_btm.c +++ b/src/drivers/ao_btm.c @@ -17,6 +17,13 @@ #include "ao.h" +#ifndef ao_serial_btm_getchar +#define ao_serial_btm_putchar ao_serial1_putchar +#define ao_serial_btm_pollchar ao_serial1_pollchar +#define ao_serial_btm_set_speed ao_serial1_set_speed +#define ao_serial_btm_drain ao_serial1_drain +#endif + int8_t ao_btm_stdio; __xdata uint8_t ao_btm_connected; @@ -80,9 +87,9 @@ ao_btm_speed(void) { ao_cmd_decimal(); if (ao_cmd_lex_u32 == 57600) - ao_serial_set_speed(AO_SERIAL_SPEED_57600); + ao_serial_btm_set_speed(AO_SERIAL_SPEED_57600); else if (ao_cmd_lex_u32 == 19200) - ao_serial_set_speed(AO_SERIAL_SPEED_19200); + ao_serial_btm_set_speed(AO_SERIAL_SPEED_19200); else ao_cmd_status = ao_cmd_syntax_error; } @@ -104,8 +111,6 @@ __code struct ao_cmds ao_btm_cmds[] = { #define AO_BTM_MAX_REPLY 16 __xdata char ao_btm_reply[AO_BTM_MAX_REPLY]; -extern volatile __xdata struct ao_fifo ao_usart1_rx_fifo; - /* * Read a line of data from the serial port, truncating * it after a few characters. @@ -119,7 +124,7 @@ ao_btm_get_line(void) for (;;) { - while ((c = ao_serial_pollchar()) != AO_READ_AGAIN) { + while ((c = ao_serial_btm_pollchar()) != AO_READ_AGAIN) { ao_btm_log_in_char(c); if (ao_btm_reply_len < sizeof (ao_btm_reply)) ao_btm_reply[ao_btm_reply_len++] = c; @@ -128,7 +133,7 @@ ao_btm_get_line(void) } for (c = 0; c < 10; c++) { ao_delay(AO_MS_TO_TICKS(10)); - if (!ao_fifo_empty(ao_usart1_rx_fifo)) + if (!ao_fifo_empty(ao_serial1_rx_fifo)) break; } if (c == 10) @@ -168,7 +173,7 @@ void ao_btm_putchar(char c) { ao_btm_log_out_char(c); - ao_serial_putchar(c); + ao_serial_btm_putchar(c); ao_delay(1); } @@ -229,8 +234,8 @@ ao_btm_set_name(void) uint8_t ao_btm_try_speed(uint8_t speed) { - ao_serial_set_speed(speed); - ao_btm_drain(); + ao_serial_btm_set_speed(speed); + ao_serial_btm_drain(); (void) ao_btm_cmd("\rATE0\rATQ0\r"); if (ao_btm_cmd("AT\r") == 1) return 1; @@ -274,8 +279,8 @@ ao_btm(void) /* Turn off status reporting */ ao_btm_cmd("ATQ1\r"); - ao_btm_stdio = ao_add_stdio(ao_serial_pollchar, - ao_serial_putchar, + ao_btm_stdio = ao_add_stdio(ao_serial_btm_pollchar, + ao_serial_btm_putchar, NULL); ao_btm_echo(0); @@ -341,7 +346,8 @@ void ao_btm_init (void) { ao_serial_init(); - ao_serial_set_speed(AO_SERIAL_SPEED_19200); + + ao_serial_btm_set_speed(AO_SERIAL_SPEED_19200); #if BT_LINK_ON_P1 /* diff --git a/src/drivers/ao_gps_sirf.c b/src/drivers/ao_gps_sirf.c index f2abbf84..91fc948b 100644 --- a/src/drivers/ao_gps_sirf.c +++ b/src/drivers/ao_gps_sirf.c @@ -124,7 +124,13 @@ static __xdata struct sirf_measured_tracker_data ao_sirf_tracker_data; static __pdata uint16_t ao_sirf_cksum; static __pdata uint16_t ao_sirf_len; -#define ao_sirf_byte() ((uint8_t) ao_serial_getchar()) +#ifndef ao_sirf_getchar +#define ao_sirf_getchar ao_serial1_getchar +#define ao_sirf_putchar ao_serial1_putchar +#define ao_sirf_set_speed ao_serial1_set_speed +#endif + +#define ao_sirf_byte() ((uint8_t) ao_sirf_getchar()) static uint8_t data_byte(void) { @@ -283,15 +289,15 @@ static void ao_gps_setup(void) __reentrant { uint8_t i, k; - ao_serial_set_speed(AO_SERIAL_SPEED_4800); + ao_sirf_set_speed(AO_SERIAL_SPEED_4800); for (i = 0; i < 64; i++) - ao_serial_putchar(0x00); + ao_sirf_putchar(0x00); for (k = 0; k < 3; k++) for (i = 0; i < sizeof (ao_gps_set_nmea); i++) - ao_serial_putchar(ao_gps_set_nmea[i]); - ao_serial_set_speed(AO_SERIAL_SPEED_57600); + ao_sirf_putchar(ao_gps_set_nmea[i]); + ao_sirf_set_speed(AO_SERIAL_SPEED_57600); for (i = 0; i < 64; i++) - ao_serial_putchar(0x00); + ao_sirf_putchar(0x00); } static const char ao_gps_set_message_rate[] = { @@ -307,16 +313,16 @@ ao_sirf_set_message_rate(uint8_t msg, uint8_t rate) __reentrant uint8_t i; for (i = 0; i < sizeof (ao_gps_set_message_rate); i++) - ao_serial_putchar(ao_gps_set_message_rate[i]); - ao_serial_putchar(msg); - ao_serial_putchar(rate); + ao_sirf_putchar(ao_gps_set_message_rate[i]); + ao_sirf_putchar(msg); + ao_sirf_putchar(rate); cksum = 0xa6 + msg + rate; for (i = 0; i < 4; i++) - ao_serial_putchar(0); - ao_serial_putchar((cksum >> 8) & 0x7f); - ao_serial_putchar(cksum & 0xff); - ao_serial_putchar(0xb0); - ao_serial_putchar(0xb3); + ao_sirf_putchar(0); + ao_sirf_putchar((cksum >> 8) & 0x7f); + ao_sirf_putchar(cksum & 0xff); + ao_sirf_putchar(0xb0); + ao_sirf_putchar(0xb3); } static const uint8_t sirf_disable[] = { @@ -338,7 +344,7 @@ ao_gps(void) __reentrant for (k = 0; k < 5; k++) { for (i = 0; i < sizeof (ao_gps_config); i++) - ao_serial_putchar(ao_gps_config[i]); + ao_sirf_putchar(ao_gps_config[i]); for (i = 0; i < sizeof (sirf_disable); i++) ao_sirf_set_message_rate(sirf_disable[i], 0); ao_sirf_set_message_rate(41, 1); diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index 39e36cc8..84616a05 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -20,15 +20,15 @@ #endif #ifndef ao_gps_getchar -#define ao_gps_getchar ao_serial_getchar +#define ao_gps_getchar ao_serial1_getchar #endif #ifndef ao_gps_putchar -#define ao_gps_putchar ao_serial_putchar +#define ao_gps_putchar ao_serial1_putchar #endif #ifndef ao_gps_set_speed -#define ao_gps_set_speed ao_serial_set_speed +#define ao_gps_set_speed ao_serial1_set_speed #endif __xdata uint8_t ao_gps_mutex; diff --git a/src/drivers/ao_science_slave.c b/src/drivers/ao_science_slave.c index 1ebb1480..fa9db98b 100644 --- a/src/drivers/ao_science_slave.c +++ b/src/drivers/ao_science_slave.c @@ -17,6 +17,7 @@ #include "ao.h" #include "ao_product.h" +#include "ao_flight.h" struct ao_companion_command ao_companion_command; diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index e4e5def6..f761e5c3 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -61,6 +61,8 @@ #define ao_gps_putchar ao_serial3_putchar #define ao_gps_set_speed ao_serial3_set_speed +#define HAS_EEPROM 1 +#define USE_INTERNAL_FLASH 0 #define HAS_USB 1 #define HAS_BEEP 1 diff --git a/src/product/ao_telebt.c b/src/product/ao_telebt.c index 97c9d792..46c63418 100644 --- a/src/product/ao_telebt.c +++ b/src/product/ao_telebt.c @@ -17,7 +17,9 @@ #include "ao.h" +#if HAS_LOG __code uint8_t ao_log_format = AO_LOG_FORMAT_NONE; /* until we actually log stuff */ +#endif void main(void) diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c index 8875ff48..963c7be4 100644 --- a/src/product/ao_terraui.c +++ b/src/product/ao_terraui.c @@ -16,6 +16,7 @@ */ #include "ao.h" +#include #include static __xdata struct ao_telemetry_sensor ao_tel_sensor; diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index adb6eb94..62af86f7 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -181,8 +181,6 @@ void ao_lcd_font_init(void); void ao_lcd_font_string(char *s); -#define USE_SERIAL_STDIN (USE_SERIAL_1_STDIN + USE_SERIAL_2_STDIN + USE_SERIAL_3_STDIN) - char ao_serial1_getchar(void); diff --git a/src/stm/ao_serial_stm.c b/src/stm/ao_serial_stm.c index 3cebc094..406da9fb 100644 --- a/src/stm/ao_serial_stm.c +++ b/src/stm/ao_serial_stm.c @@ -249,7 +249,7 @@ ao_serial2_set_speed(uint8_t speed) struct ao_stm_usart ao_stm_usart3; -void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, USE_SERIAL_3_STDIN); } +void stm_usart3_isr(void) { ao_usart_isr(&ao_stm_usart3, USE_SERIAL_2_STDIN); } char ao_serial3_getchar(void) diff --git a/src/stm/ao_usb.h b/src/stm/ao_usb.h deleted file mode 100644 index d3129d34..00000000 --- a/src/stm/ao_usb.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * 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. - */ - -#ifndef _AO_USB_H_ -#define _AO_USB_H_ - -#define AO_USB_SETUP_DIR_MASK (0x01 << 7) -#define AO_USB_SETUP_TYPE_MASK (0x03 << 5) -#define AO_USB_SETUP_RECIP_MASK (0x1f) - -#define AO_USB_DIR_OUT 0 -#define AO_USB_DIR_IN (1 << 7) - -#define AO_USB_TYPE_STANDARD 0 -#define AO_USB_TYPE_CLASS (1 << 5) -#define AO_USB_TYPE_VENDOR (2 << 5) -#define AO_USB_TYPE_RESERVED (3 << 5) - -#define AO_USB_RECIP_DEVICE 0 -#define AO_USB_RECIP_INTERFACE 1 -#define AO_USB_RECIP_ENDPOINT 2 -#define AO_USB_RECIP_OTHER 3 - -/* standard requests */ -#define AO_USB_REQ_GET_STATUS 0x00 -#define AO_USB_REQ_CLEAR_FEATURE 0x01 -#define AO_USB_REQ_SET_FEATURE 0x03 -#define AO_USB_REQ_SET_ADDRESS 0x05 -#define AO_USB_REQ_GET_DESCRIPTOR 0x06 -#define AO_USB_REQ_SET_DESCRIPTOR 0x07 -#define AO_USB_REQ_GET_CONFIGURATION 0x08 -#define AO_USB_REQ_SET_CONFIGURATION 0x09 -#define AO_USB_REQ_GET_INTERFACE 0x0A -#define AO_USB_REQ_SET_INTERFACE 0x0B -#define AO_USB_REQ_SYNCH_FRAME 0x0C - -#define AO_USB_DESC_DEVICE 1 -#define AO_USB_DESC_CONFIGURATION 2 -#define AO_USB_DESC_STRING 3 -#define AO_USB_DESC_INTERFACE 4 -#define AO_USB_DESC_ENDPOINT 5 -#define AO_USB_DESC_DEVICE_QUALIFIER 6 -#define AO_USB_DESC_OTHER_SPEED 7 -#define AO_USB_DESC_INTERFACE_POWER 8 - -#define AO_USB_GET_DESC_TYPE(x) (((x)>>8)&0xFF) -#define AO_USB_GET_DESC_INDEX(x) ((x)&0xFF) - -#define AO_USB_CONTROL_EP 0 -#define AO_USB_INT_EP 1 -#define AO_USB_OUT_EP 4 -#define AO_USB_IN_EP 5 -#define AO_USB_CONTROL_SIZE 32 -/* - * Double buffer IN and OUT EPs, so each - * gets half of the available space - * - * Ah, but USB bulk packets can only come in 8, 16, 32 and 64 - * byte sizes, so we'll use 64 for everything - */ -#define AO_USB_INT_SIZE 8 -#define AO_USB_IN_SIZE 64 -#define AO_USB_OUT_SIZE 64 - -#define AO_USB_EP0_IDLE 0 -#define AO_USB_EP0_DATA_IN 1 -#define AO_USB_EP0_DATA_OUT 2 - -#define LE_WORD(x) ((x)&0xFF),((uint8_t) (((uint16_t) (x))>>8)) - -/* CDC definitions */ -#define CS_INTERFACE 0x24 -#define CS_ENDPOINT 0x25 - -#define SET_LINE_CODING 0x20 -#define GET_LINE_CODING 0x21 -#define SET_CONTROL_LINE_STATE 0x22 - -/* Data structure for GET_LINE_CODING / SET_LINE_CODING class requests */ -struct ao_usb_line_coding { - uint32_t rate; - uint8_t char_format; - uint8_t parity; - uint8_t data_bits; -} ; - -#endif /* _AO_USB_H_ */ diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index 5a447d43..586f1e33 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -717,17 +717,17 @@ ao_usb_ep0_setup(void) case AO_USB_TYPE_CLASS: debug ("Class setup packet\n"); switch (ao_usb_setup.request) { - case SET_LINE_CODING: + case AO_USB_SET_LINE_CODING: debug ("set line coding\n"); ao_usb_ep0_out_len = 7; ao_usb_ep0_out_data = (uint8_t *) &ao_usb_line_coding; break; - case GET_LINE_CODING: + case AO_USB_GET_LINE_CODING: debug ("get line coding\n"); ao_usb_ep0_in_len = 7; ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding; break; - case SET_CONTROL_LINE_STATE: + case AO_USB_SET_CONTROL_LINE_STATE: break; } break; diff --git a/src/teleballoon-v1.1/ao_pins.h b/src/teleballoon-v1.1/ao_pins.h index a96c6f2b..3305719a 100644 --- a/src/teleballoon-v1.1/ao_pins.h +++ b/src/teleballoon-v1.1/ao_pins.h @@ -30,7 +30,6 @@ #define HAS_BEEP 1 #define HAS_GPS 1 #define HAS_SERIAL_1 1 - #define USE_SERIAL_STDIN 0 #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_LOG 1 @@ -127,10 +126,6 @@ #error Please define HAS_SERIAL_1 #endif -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - #ifndef HAS_ADC #error Please define HAS_ADC #endif diff --git a/src/telepyro-v0.1/Makefile b/src/telepyro-v0.1/Makefile index 2f664fcb..2ac7e747 100644 --- a/src/telepyro-v0.1/Makefile +++ b/src/telepyro-v0.1/Makefile @@ -85,8 +85,10 @@ load: $(PROG).hex ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ -ao_product.rel: ao_product.c ao_product.h - $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< +ao_product.o: ao_product.c ao_product.h + +%.o : %.c + $(call quiet,CC) -c $(CFLAGS) $< distclean: clean diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index be99f10d..10e4a2a3 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -22,7 +22,8 @@ INC = \ ao.h \ ao_arch.h \ ao_usb.h \ - ao_pins.h + ao_pins.h \ + ao_product.h # # Common AltOS sources @@ -96,8 +97,10 @@ load: $(PROG).hex ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ -ao_product.rel: ao_product.c ao_product.h - $(call quiet,CC) -c $(CFLAGS) -D PRODUCT_DEFS='\"ao_product.h\"' -o$@ $< +ao_product.o: ao_product.c ao_product.h + +%.o : %.c $(INC) + $(call quiet,CC) -c $(CFLAGS) $< distclean: clean diff --git a/src/teleshield-v0.1/Makefile b/src/teleshield-v0.1/Makefile index 44780476..c1f45f37 100644 --- a/src/teleshield-v0.1/Makefile +++ b/src/teleshield-v0.1/Makefile @@ -54,7 +54,6 @@ CC1111_SRC = \ ao_radio.c \ ao_romconfig.c \ ao_serial.c \ - ao_serial0.c \ ao_string.c \ ao_timer.c \ ao_usb.c \ diff --git a/src/teleshield-v0.1/ao_ardu_serial.c b/src/teleshield-v0.1/ao_ardu_serial.c index 7ff859af..e6e19f67 100644 --- a/src/teleshield-v0.1/ao_ardu_serial.c +++ b/src/teleshield-v0.1/ao_ardu_serial.c @@ -23,7 +23,7 @@ ao_ardu_serial_recv(void) char c; for (;;) { - if (ao_fifo_empty(ao_usart0_rx_fifo)) + if (ao_fifo_empty(ao_serial0_rx_fifo)) flush(); c = ao_serial0_getchar(); putchar (c); @@ -35,6 +35,5 @@ static __xdata struct ao_task ao_ardu_serial_recv_task; void ao_ardu_serial_init (void) { - ao_serial0_init(); ao_add_task(&ao_ardu_serial_recv_task, ao_ardu_serial_recv, "recv"); } diff --git a/src/teleshield-v0.1/ao_pins.h b/src/teleshield-v0.1/ao_pins.h index a907e2a5..701e25fc 100644 --- a/src/teleshield-v0.1/ao_pins.h +++ b/src/teleshield-v0.1/ao_pins.h @@ -26,14 +26,14 @@ #define HAS_SERIAL_1_ALT_1 1 #define HAS_SERIAL_1_ALT_2 0 #define HAS_SERIAL_1_HW_FLOW 1 - #define USE_SERIAL_STDIN 1 + #define USE_SERIAL_1_STDIN 1 #define HAS_SERIAL_0 1 #define HAS_SERIAL_0_ALT_1 0 #define HAS_SERIAL_0_ALT_2 1 #define HAS_SERIAL_0_HW_FLOW 0 #define HAS_ADC 0 #define HAS_DBG 1 - #define HAS_EEPROM 0 + #define HAS_EEPROM 1 #define HAS_LOG 0 #define USE_INTERNAL_FLASH 1 #define HAS_BTM 1 @@ -128,10 +128,6 @@ #error Please define HAS_SERIAL_1 #endif -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - #ifndef HAS_ADC #error Please define HAS_ADC #endif diff --git a/src/teleshield-v0.1/ao_teleshield.c b/src/teleshield-v0.1/ao_teleshield.c index fd12ce7a..4c32817a 100644 --- a/src/teleshield-v0.1/ao_teleshield.c +++ b/src/teleshield-v0.1/ao_teleshield.c @@ -17,7 +17,9 @@ #include "ao.h" +#if 0 __code uint8_t ao_log_format = AO_LOG_FORMAT_NONE; /* until we actually log stuff */ +#endif void main(void) @@ -43,6 +45,7 @@ main(void) ao_aes_init(); ao_radio_cmac_init(); #endif + ao_serial_init(); ao_ardu_serial_init(); ao_config_init(); ao_start_scheduler(); diff --git a/src/teleterra-v0.1/ao_pins.h b/src/teleterra-v0.1/ao_pins.h index 33de055e..ba7177af 100644 --- a/src/teleterra-v0.1/ao_pins.h +++ b/src/teleterra-v0.1/ao_pins.h @@ -25,7 +25,6 @@ #define HAS_GPS 0 #define HAS_SERIAL_1 0 #define HAS_ADC 0 - #define USE_SERIAL_STDIN 0 #define HAS_EEPROM 1 #define HAS_LOG 1 #define USE_INTERNAL_FLASH 0 @@ -124,10 +123,6 @@ #error Please define HAS_SERIAL_1 #endif -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - #ifndef HAS_ADC #error Please define HAS_ADC #endif diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 29b97385..2bea4e04 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -25,7 +25,6 @@ #define HAS_GPS 1 #define HAS_SERIAL_1 1 #define HAS_ADC 0 - #define USE_SERIAL_STDIN 0 #define HAS_EEPROM 1 #define HAS_LOG 1 #define USE_INTERNAL_FLASH 0 @@ -139,10 +138,6 @@ #error Please define HAS_SERIAL_1 #endif -#ifndef USE_SERIAL_STDIN -#error Please define USE_SERIAL_STDIN -#endif - #ifndef HAS_ADC #error Please define HAS_ADC #endif diff --git a/src/test/ao_gps_test.c b/src/test/ao_gps_test.c index 93d7a9ab..4d4012df 100644 --- a/src/test/ao_gps_test.c +++ b/src/test/ao_gps_test.c @@ -317,7 +317,7 @@ static uint8_t sirf_in_message[4096]; static int sirf_in_len; char -ao_serial_getchar(void) +ao_serial1_getchar(void) { char c; uint8_t uc; @@ -351,7 +351,7 @@ ao_serial_getchar(void) void -ao_serial_putchar(char c) +ao_serial1_putchar(char c) { int i; uint8_t uc = (uint8_t) c; @@ -388,7 +388,7 @@ ao_serial_putchar(char c) #define AO_SERIAL_SPEED_57600 1 static void -ao_serial_set_speed(uint8_t speed) +ao_serial1_set_speed(uint8_t speed) { int fd = ao_gps_fd; struct termios termios; diff --git a/src/test/ao_gps_test_skytraq.c b/src/test/ao_gps_test_skytraq.c index a78fae0f..88bed305 100644 --- a/src/test/ao_gps_test_skytraq.c +++ b/src/test/ao_gps_test_skytraq.c @@ -319,7 +319,7 @@ static uint8_t skytraq_in_message[4096]; static int skytraq_in_len; char -ao_serial_getchar(void) +ao_serial1_getchar(void) { char c; uint8_t uc; @@ -354,7 +354,7 @@ ao_serial_getchar(void) void -ao_serial_putchar(char c) +ao_serial1_putchar(char c) { int i; uint8_t uc = (uint8_t) c; @@ -392,7 +392,7 @@ ao_serial_putchar(char c) #define AO_SERIAL_SPEED_57600 2 static void -ao_serial_set_speed(uint8_t speed) +ao_serial1_set_speed(uint8_t speed) { int fd = ao_gps_fd; struct termios termios; -- cgit v1.2.3 From 2b4a53342980618b193cbee5b803e56f7c937893 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Apr 2012 09:36:00 -0700 Subject: altos: ao_telelaunch.c got left in src directory Should live in product/ao_telelaunch.c Signed-off-by: Keith Packard --- src/ao_telelaunch.c | 46 --------------------------------------------- src/product/ao_telelaunch.c | 46 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 46 deletions(-) delete mode 100644 src/ao_telelaunch.c create mode 100644 src/product/ao_telelaunch.c (limited to 'src') diff --git a/src/ao_telelaunch.c b/src/ao_telelaunch.c deleted file mode 100644 index 506431de..00000000 --- a/src/ao_telelaunch.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "ao_pins.h" - -void -main(void) -{ - ao_clock_init(); - - /* Turn on the red LED until the system is stable */ - ao_led_init(LEDS_AVAILABLE); - ao_led_on(AO_LED_RED); - - ao_timer_init(); - ao_adc_init(); - ao_beep_init(); - ao_cmd_init(); - ao_spi_init(); - ao_storage_init(); - ao_usb_init(); - ao_radio_init(); -#if HAS_DBG - ao_dbg_init(); -#endif - ao_aes_init(); - ao_radio_cmac_init(); - ao_launch_init(); - ao_config_init(); - ao_start_scheduler(); -} diff --git a/src/product/ao_telelaunch.c b/src/product/ao_telelaunch.c new file mode 100644 index 00000000..506431de --- /dev/null +++ b/src/product/ao_telelaunch.c @@ -0,0 +1,46 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +void +main(void) +{ + ao_clock_init(); + + /* Turn on the red LED until the system is stable */ + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_RED); + + ao_timer_init(); + ao_adc_init(); + ao_beep_init(); + ao_cmd_init(); + ao_spi_init(); + ao_storage_init(); + ao_usb_init(); + ao_radio_init(); +#if HAS_DBG + ao_dbg_init(); +#endif + ao_aes_init(); + ao_radio_cmac_init(); + ao_launch_init(); + ao_config_init(); + ao_start_scheduler(); +} -- cgit v1.2.3 From 0667261e03b3fd403e97d02ea6204b007bb13f58 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Apr 2012 09:39:20 -0700 Subject: altos: Pull more interfaces out of ao.h and move to separate files This moves the aes, btm, companion, lcd and packet interfaces out of ao.h Signed-off-by: Keith Packard --- src/core/ao.h | 199 +++------------------------------------- src/core/ao_aes.h | 69 ++++++++++++++ src/core/ao_btm.h | 36 ++++++++ src/core/ao_companion.h | 51 ++++++++++ src/core/ao_lcd.h | 60 ++++++++++++ src/core/ao_log_telescience.c | 2 + src/core/ao_packet.h | 88 ++++++++++++++++++ src/drivers/ao_pyro_slave.c | 5 +- src/drivers/ao_science_slave.c | 1 + src/product/Makefile.telelaunch | 2 - src/teleterra-v0.2/ao_pins.h | 1 + 11 files changed, 323 insertions(+), 191 deletions(-) create mode 100644 src/core/ao_aes.h create mode 100644 src/core/ao_btm.h create mode 100644 src/core/ao_companion.h create mode 100644 src/core/ao_lcd.h create mode 100644 src/core/ao_packet.h (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 28d0ba87..27b9c5c4 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -900,201 +900,26 @@ struct ao_fifo { #define ao_fifo_full(f) ((((f).insert + 1) & (AO_FIFO_SIZE-1)) == (f).remove) #define ao_fifo_empty(f) ((f).insert == (f).remove) -/* - * ao_packet.c - * - * Packet-based command interface - */ - -#define AO_PACKET_MAX 64 -#define AO_PACKET_SYN (uint8_t) 0xff - -struct ao_packet { - uint8_t addr; - uint8_t len; - uint8_t seq; - uint8_t ack; - uint8_t d[AO_PACKET_MAX]; - uint8_t callsign[AO_MAX_CALLSIGN]; -}; - -struct ao_packet_recv { - struct ao_packet packet; - int8_t rssi; - uint8_t status; -}; - -extern __xdata struct ao_packet_recv ao_rx_packet; -extern __xdata struct ao_packet ao_tx_packet; -extern __xdata struct ao_task ao_packet_task; -extern __xdata uint8_t ao_packet_enable; -extern __xdata uint8_t ao_packet_master_sleeping; -extern __pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; - -void -ao_packet_send(void); - -uint8_t -ao_packet_recv(void); - -void -ao_packet_flush(void); - -void -ao_packet_putchar(char c) __reentrant; - -char -ao_packet_pollchar(void) __critical; - -/* ao_packet_master.c */ - -void -ao_packet_master_init(void); - -/* ao_packet_slave.c */ - -void -ao_packet_slave_start(void); - -void -ao_packet_slave_stop(void); - -void -ao_packet_slave_init(uint8_t enable); - -/* ao_btm.c */ - -/* If bt_link is on P2, this interrupt is shared by USB, so the USB - * code calls this function. Otherwise, it's a regular ISR. - */ - -void -ao_btm_isr(void) -#if BT_LINK_ON_P1 - __interrupt 15 +#if PACKET_HAS_MASTER || PACKET_HAS_SLAVE +#include #endif - ; - -void -ao_btm_init(void); - -/* ao_companion.c */ - -#define AO_COMPANION_SETUP 1 -#define AO_COMPANION_FETCH 2 -#define AO_COMPANION_NOTIFY 3 - -struct ao_companion_command { - uint8_t command; - uint8_t flight_state; - uint16_t tick; - uint16_t serial; - uint16_t flight; -}; - -struct ao_companion_setup { - uint16_t board_id; - uint16_t board_id_inverse; - uint8_t update_period; - uint8_t channels; -}; - -extern __pdata uint8_t ao_companion_running; -extern __xdata uint8_t ao_companion_mutex; -extern __xdata struct ao_companion_command ao_companion_command; -extern __xdata struct ao_companion_setup ao_companion_setup; -extern __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; - -void -ao_companion_init(void); - -/* ao_lcd.c */ - -void -ao_lcd_putchar(uint8_t d); - -void -ao_lcd_putstring(char *string); - -void -ao_lcd_contrast_set(uint8_t contrast); - -void -ao_lcd_clear(void); - -void -ao_lcd_cursor_on(void); - -void -ao_lcd_cursor_off(void); - -#define AO_LCD_ADDR(row,col) ((row << 6) | (col)) - -void -ao_lcd_goto(uint8_t addr); - -void -ao_lcd_start(void); - -void -ao_lcd_init(void); - -/* ao_lcd_port.c */ - -void -ao_lcd_port_put_nibble(uint8_t rs, uint8_t d); - -void -ao_lcd_port_init(void); - -/* ao_aes.c */ -extern __xdata uint8_t ao_aes_mutex; +#if HAS_BTM +#include +#endif -/* AES keys and blocks are 128 bits */ +#if HAS_COMPANION +#include +#endif -enum ao_aes_mode { - ao_aes_mode_cbc_mac -}; +#if HAS_LCD +#include +#endif #if HAS_AES -void -ao_aes_isr(void) __interrupt 4; +#include #endif -void -ao_aes_set_mode(enum ao_aes_mode mode); - -void -ao_aes_set_key(__xdata uint8_t *in); - -void -ao_aes_zero_iv(void); - -void -ao_aes_run(__xdata uint8_t *in, - __xdata uint8_t *out); - -void -ao_aes_init(void); - -/* ao_radio_cmac.c */ - -int8_t -ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant; - -#define AO_RADIO_CMAC_OK 0 -#define AO_RADIO_CMAC_LEN_ERROR -1 -#define AO_RADIO_CMAC_CRC_ERROR -2 -#define AO_RADIO_CMAC_MAC_ERROR -3 -#define AO_RADIO_CMAC_TIMEOUT -4 - -int8_t -ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant; - -void -ao_radio_cmac_init(void); - /* ao_launch.c */ struct ao_launch_command { diff --git a/src/core/ao_aes.h b/src/core/ao_aes.h new file mode 100644 index 00000000..7f67374d --- /dev/null +++ b/src/core/ao_aes.h @@ -0,0 +1,69 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_AES_H_ +#define _AO_AES_H_ + +/* ao_aes.c */ + +extern __xdata uint8_t ao_aes_mutex; + +/* AES keys and blocks are 128 bits */ + +enum ao_aes_mode { + ao_aes_mode_cbc_mac +}; + +#if HAS_AES +void +ao_aes_isr(void) __interrupt 4; +#endif + +void +ao_aes_set_mode(enum ao_aes_mode mode); + +void +ao_aes_set_key(__xdata uint8_t *in); + +void +ao_aes_zero_iv(void); + +void +ao_aes_run(__xdata uint8_t *in, + __xdata uint8_t *out); + +void +ao_aes_init(void); + +/* ao_radio_cmac.c */ + +int8_t +ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant; + +#define AO_RADIO_CMAC_OK 0 +#define AO_RADIO_CMAC_LEN_ERROR -1 +#define AO_RADIO_CMAC_CRC_ERROR -2 +#define AO_RADIO_CMAC_MAC_ERROR -3 +#define AO_RADIO_CMAC_TIMEOUT -4 + +int8_t +ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant; + +void +ao_radio_cmac_init(void); + +#endif /* _AO_AES_H_ */ diff --git a/src/core/ao_btm.h b/src/core/ao_btm.h new file mode 100644 index 00000000..484e5d7f --- /dev/null +++ b/src/core/ao_btm.h @@ -0,0 +1,36 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_BTM_H_ +#define _AO_BTM_H_ + +/* ao_btm.c */ + +/* If bt_link is on P2, this interrupt is shared by USB, so the USB + * code calls this function. Otherwise, it's a regular ISR. + */ + +void +ao_btm_isr(void) +#if BT_LINK_ON_P1 + __interrupt 15 +#endif + ; +void +ao_btm_init(void); + +#endif /* _AO_BTM_H_ */ diff --git a/src/core/ao_companion.h b/src/core/ao_companion.h new file mode 100644 index 00000000..47e0acf5 --- /dev/null +++ b/src/core/ao_companion.h @@ -0,0 +1,51 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_COMPANION_H_ +#define _AO_COMPANION_H_ + +/* ao_companion.c */ + +#define AO_COMPANION_SETUP 1 +#define AO_COMPANION_FETCH 2 +#define AO_COMPANION_NOTIFY 3 + +struct ao_companion_command { + uint8_t command; + uint8_t flight_state; + uint16_t tick; + uint16_t serial; + uint16_t flight; +}; + +struct ao_companion_setup { + uint16_t board_id; + uint16_t board_id_inverse; + uint8_t update_period; + uint8_t channels; +}; + +extern __pdata uint8_t ao_companion_running; +extern __xdata uint8_t ao_companion_mutex; +extern __xdata struct ao_companion_command ao_companion_command; +extern __xdata struct ao_companion_setup ao_companion_setup; +extern __xdata uint16_t ao_companion_data[AO_COMPANION_MAX_CHANNELS]; + +void +ao_companion_init(void); + +#endif /* _AO_COMPANION_H_ */ diff --git a/src/core/ao_lcd.h b/src/core/ao_lcd.h new file mode 100644 index 00000000..f7e1391a --- /dev/null +++ b/src/core/ao_lcd.h @@ -0,0 +1,60 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_LCD_H_ +#define _AO_LCD_H_ + +/* ao_lcd.c */ + +void +ao_lcd_putchar(uint8_t d); + +void +ao_lcd_putstring(char *string); + +void +ao_lcd_contrast_set(uint8_t contrast); + +void +ao_lcd_clear(void); + +void +ao_lcd_cursor_on(void); + +void +ao_lcd_cursor_off(void); + +#define AO_LCD_ADDR(row,col) ((row << 6) | (col)) + +void +ao_lcd_goto(uint8_t addr); + +void +ao_lcd_start(void); + +void +ao_lcd_init(void); + +/* ao_lcd_port.c */ + +void +ao_lcd_port_put_nibble(uint8_t rs, uint8_t d); + +void +ao_lcd_port_init(void); + +#endif /* _AO_LCD_H_ */ diff --git a/src/core/ao_log_telescience.c b/src/core/ao_log_telescience.c index 31eda381..ae045281 100644 --- a/src/core/ao_log_telescience.c +++ b/src/core/ao_log_telescience.c @@ -17,6 +17,8 @@ #include "ao.h" #include "ao_product.h" +#include "ao_log.h" +#include "ao_companion.h" static uint8_t ao_log_adc_pos; diff --git a/src/core/ao_packet.h b/src/core/ao_packet.h new file mode 100644 index 00000000..618ccda4 --- /dev/null +++ b/src/core/ao_packet.h @@ -0,0 +1,88 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PACKET_H_ +#define _AO_PACKET_H_ + +/* + * ao_packet.c + * + * Packet-based command interface + */ + +#define AO_PACKET_MAX 64 +#define AO_PACKET_SYN (uint8_t) 0xff + +struct ao_packet { + uint8_t addr; + uint8_t len; + uint8_t seq; + uint8_t ack; + uint8_t d[AO_PACKET_MAX]; + uint8_t callsign[AO_MAX_CALLSIGN]; +}; + +struct ao_packet_recv { + struct ao_packet packet; + int8_t rssi; + uint8_t status; +}; + +extern __xdata struct ao_packet_recv ao_rx_packet; +extern __xdata struct ao_packet ao_tx_packet; +extern __xdata struct ao_task ao_packet_task; +extern __xdata uint8_t ao_packet_enable; +extern __xdata uint8_t ao_packet_master_sleeping; +extern __pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; + +void +ao_packet_send(void); + +uint8_t +ao_packet_recv(void); + +void +ao_packet_flush(void); + +void +ao_packet_putchar(char c) __reentrant; + +char +ao_packet_pollchar(void) __critical; + +#if PACKET_HAS_MASTER +/* ao_packet_master.c */ + +void +ao_packet_master_init(void); +#endif + +#if PACKET_HAS_SLAVE +/* ao_packet_slave.c */ + +void +ao_packet_slave_start(void); + +void +ao_packet_slave_stop(void); + +void +ao_packet_slave_init(uint8_t enable); + +#endif + +#endif /* _AO_PACKET_H_ */ diff --git a/src/drivers/ao_pyro_slave.c b/src/drivers/ao_pyro_slave.c index 5ef42b5a..5a8ab922 100644 --- a/src/drivers/ao_pyro_slave.c +++ b/src/drivers/ao_pyro_slave.c @@ -15,8 +15,9 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" -#include "ao_product.h" +#include +#include +#include struct ao_companion_command ao_companion_command; diff --git a/src/drivers/ao_science_slave.c b/src/drivers/ao_science_slave.c index fa9db98b..a86b5151 100644 --- a/src/drivers/ao_science_slave.c +++ b/src/drivers/ao_science_slave.c @@ -18,6 +18,7 @@ #include "ao.h" #include "ao_product.h" #include "ao_flight.h" +#include "ao_companion.h" struct ao_companion_command ao_companion_command; diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch index 8aab50e0..688ac5f3 100644 --- a/src/product/Makefile.telelaunch +++ b/src/product/Makefile.telelaunch @@ -39,8 +39,6 @@ CC1111_SRC = \ ao_ignite.c \ ao_intflash.c \ ao_led.c \ - ao_packet.c \ - ao_packet_slave.c \ ao_radio.c \ ao_radio_cmac.c \ ao_romconfig.c \ diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index 2bea4e04..bcabdfee 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -25,6 +25,7 @@ #define HAS_GPS 1 #define HAS_SERIAL_1 1 #define HAS_ADC 0 + #define HAS_LCD 1 #define HAS_EEPROM 1 #define HAS_LOG 1 #define USE_INTERNAL_FLASH 0 -- cgit v1.2.3 From 3c67543f3e5fddc6a8850f33ac519ccd55b607f0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Apr 2012 18:34:52 -0700 Subject: altos: Set USB Interrupt endpoint interval to maximum allowed We don't ever send anything over this channel, so there's no sense asking the host to poll it very often. Signed-off-by: Keith Packard --- src/core/ao_product.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_product.c b/src/core/ao_product.c index f79922f5..67ec6793 100644 --- a/src/core/ao_product.c +++ b/src/core/ao_product.c @@ -100,7 +100,7 @@ __code __at(0x00aa) uint8_t ao_usb_descriptors [] = AO_USB_INT_EP|0x80, /* bEndpointAddress */ 0x03, /* bmAttributes = intr */ LE_WORD(8), /* wMaxPacketSize */ - 0x0A, /* bInterval */ + 0xff, /* bInterval */ /* Data class interface descriptor */ 0x09, -- cgit v1.2.3 From 1a84d34fa08f43a5f79b1a5f8d8de7674d04647d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Apr 2012 18:35:46 -0700 Subject: altos: Check all USE_SERIAL_*_STDIO when computing AO_NUM_STDIOS AO_NUM_STDIOS is allocated based on the total number of possible stdio values. Now that multiple serial stdio are possible, make sure to check all of them. Signed-off-by: Keith Packard --- src/core/ao_stdio.c | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/core/ao_stdio.c b/src/core/ao_stdio.c index 18fa913e..9b4ea473 100644 --- a/src/core/ao_stdio.c +++ b/src/core/ao_stdio.c @@ -21,11 +21,47 @@ * Basic I/O functions to support SDCC stdio package */ -#ifdef SERIAL_STDIN_PORT -#define USE_SERIAL_STDIN 1 -#else -#define USE_SERIAL_STDIN 0 +#ifndef USE_SERIAL_0_STDIN +#define USE_SERIAL_0_STDIN 0 #endif +#ifndef USE_SERIAL_1_STDIN +#define USE_SERIAL_1_STDIN 0 +#endif +#ifndef USE_SERIAL_2_STDIN +#define USE_SERIAL_2_STDIN 0 +#endif +#ifndef USE_SERIAL_3_STDIN +#define USE_SERIAL_3_STDIN 0 +#endif +#ifndef USE_SERIAL_4_STDIN +#define USE_SERIAL_4_STDIN 0 +#endif +#ifndef USE_SERIAL_5_STDIN +#define USE_SERIAL_5_STDIN 0 +#endif +#ifndef USE_SERIAL_6_STDIN +#define USE_SERIAL_6_STDIN 0 +#endif +#ifndef USE_SERIAL_7_STDIN +#define USE_SERIAL_7_STDIN 0 +#endif +#ifndef USE_SERIAL_8_STDIN +#define USE_SERIAL_8_STDIN 0 +#endif +#ifndef USE_SERIAL_9_STDIN +#define USE_SERIAL_9_STDIN 0 +#endif + +#define USE_SERIAL_STDIN (USE_SERIAL_0_STDIN + \ + USE_SERIAL_1_STDIN | \ + USE_SERIAL_2_STDIN | \ + USE_SERIAL_3_STDIN | \ + USE_SERIAL_4_STDIN | \ + USE_SERIAL_5_STDIN | \ + USE_SERIAL_6_STDIN | \ + USE_SERIAL_7_STDIN | \ + USE_SERIAL_8_STDIN | \ + USE_SERIAL_9_STDIN) #define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) -- cgit v1.2.3 From e9f6fca7cfe796cbd86ae9d8f1ebe31bba7251db Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Apr 2012 18:38:29 -0700 Subject: altos: Correct STM USB driver Configure endpoint registers correctly now. Restructure code to make sure we send the right IN packets. Signed-off-by: Keith Packard --- src/stm/ao_usb_stm.c | 579 ++++++++++++++++++++++++++------------------------- 1 file changed, 293 insertions(+), 286 deletions(-) (limited to 'src') diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index 586f1e33..223fdeaa 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -21,6 +21,7 @@ #define USB_DEBUG 0 #define USB_DEBUG_DATA 0 +#define USB_ECHO 0 #if USB_DEBUG #define debug(format, args...) printf(format, ## args); @@ -45,34 +46,68 @@ struct ao_usb_setup { } ao_usb_setup; static uint8_t ao_usb_ep0_state; -static const uint8_t * ao_usb_ep0_in_data; -static uint8_t ao_usb_ep0_in_len; -static uint8_t ao_usb_ep0_in_pending; + +/* Pending EP0 IN data */ +static const uint8_t *ao_usb_ep0_in_data; /* Remaining data */ +static uint8_t ao_usb_ep0_in_len; /* Remaining amount */ + +/* Temp buffer for smaller EP0 in data */ static uint8_t ao_usb_ep0_in_buf[2]; -static uint8_t ao_usb_ep0_out_len; + +/* Pending EP0 OUT data */ static uint8_t *ao_usb_ep0_out_data; +static uint8_t ao_usb_ep0_out_len; + +/* + * Objects allocated in special USB memory + */ + +/* Buffer description tables */ static union stm_usb_bdt *ao_usb_bdt; +/* USB address of end of allocated storage */ static uint16_t ao_usb_sram_addr; + +/* Pointer to ep0 tx/rx buffers in USB memory */ +static uint32_t *ao_usb_ep0_tx_buffer; +static uint32_t *ao_usb_ep0_rx_buffer; + +/* Pointer to bulk data tx/rx buffers in USB memory */ +static uint32_t *ao_usb_in_tx_buffer; +static uint32_t *ao_usb_out_rx_buffer; + +/* System ram shadow of USB buffer; writing individual bytes is + * too much of a pain (sigh) */ static uint8_t ao_usb_tx_buffer[AO_USB_IN_SIZE]; static uint8_t ao_usb_tx_count; + static uint8_t ao_usb_rx_buffer[AO_USB_OUT_SIZE]; static uint8_t ao_usb_rx_count, ao_usb_rx_pos; -#define AO_USB_INT_EPR 1 -#define AO_USB_OUT_EPR 2 -#define AO_USB_IN_EPR 3 - /* - * Pointers into the USB packet buffer area + * End point register indices */ -static uint32_t *ao_usb_ep0_tx_buffer; -static uint32_t *ao_usb_ep0_rx_buffer; -static uint32_t *ao_usb_in_tx_buffer; -static uint32_t *ao_usb_out_rx_buffer; +#define AO_USB_CONTROL_EPR 0 +#define AO_USB_INT_EPR 1 +#define AO_USB_OUT_EPR 2 +#define AO_USB_IN_EPR 3 +/* Marks when we don't need to send an IN packet. + * This happens only when the last IN packet is not full, + * otherwise the host will expect to keep seeing packets. + * Send a zero-length packet as required + */ static uint8_t ao_usb_in_flushed; + +/* Marks when we have delivered an IN packet to the hardware + * and it has not been received yet. ao_sleep on this address + * to wait for it to be delivered. + */ static uint8_t ao_usb_in_pending; + +/* Marks when an OUT packet has been received by the hardware + * but not pulled to the shadow buffer. + */ static uint8_t ao_usb_out_avail; static uint8_t ao_usb_running; static uint8_t ao_usb_configuration; @@ -139,10 +174,104 @@ ao_usb_set_address(uint8_t address) ao_usb_address_pending = 0; } +/* + * Write these values to preserve register contents under HW changes + */ + +#define STM_USB_EPR_INVARIANT ((1 << STM_USB_EPR_CTR_RX) | \ + (STM_USB_EPR_DTOG_RX_WRITE_INVARIANT << STM_USB_EPR_DTOG_RX) | \ + (STM_USB_EPR_STAT_RX_WRITE_INVARIANT << STM_USB_EPR_STAT_RX) | \ + (1 << STM_USB_EPR_CTR_TX) | \ + (STM_USB_EPR_DTOG_TX_WRITE_INVARIANT << STM_USB_EPR_DTOG_TX) | \ + (STM_USB_EPR_STAT_TX_WRITE_INVARIANT << STM_USB_EPR_STAT_TX)) + +#define STM_USB_EPR_INVARIANT_MASK ((1 << STM_USB_EPR_CTR_RX) | \ + (STM_USB_EPR_DTOG_RX_MASK << STM_USB_EPR_DTOG_RX) | \ + (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX) | \ + (1 << STM_USB_EPR_CTR_TX) | \ + (STM_USB_EPR_DTOG_TX_MASK << STM_USB_EPR_DTOG_TX) | \ + (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX)) + +/* + * These bits are purely under sw control, so preserve them in the + * register by re-writing what was read + */ +#define STM_USB_EPR_PRESERVE_MASK ((STM_USB_EPR_EP_TYPE_MASK << STM_USB_EPR_EP_TYPE) | \ + (1 << STM_USB_EPR_EP_KIND) | \ + (STM_USB_EPR_EA_MASK << STM_USB_EPR_EA)) + +/* + * Set the state of the specified endpoint register to a new + * value. This is tricky because the bits toggle where the new + * value is one, and we need to write invariant values in other + * spots of the register. This hardware is strange... + */ +static void +_ao_usb_set_stat_tx(int ep, uint32_t stat_tx) +{ + uint32_t epr_write, epr_old; + + epr_old = epr_write = stm_usb.epr[ep]; + epr_write &= STM_USB_EPR_PRESERVE_MASK; + epr_write |= STM_USB_EPR_INVARIANT; + epr_write |= set_toggle(epr_old, + STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX, + stat_tx << STM_USB_EPR_STAT_TX); + stm_usb.epr[ep] = epr_write; +} + +static void +ao_usb_set_stat_tx(int ep, uint32_t stat_tx) +{ + cli(); + _ao_usb_set_stat_tx(ep, stat_tx); + sei(); +} + +static void +ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { + uint32_t epr_write, epr_old; + + cli(); + epr_write = epr_old = stm_usb.epr[ep]; + epr_write &= STM_USB_EPR_PRESERVE_MASK; + epr_write |= STM_USB_EPR_INVARIANT; + epr_write |= set_toggle(epr_old, + STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX, + stat_rx << STM_USB_EPR_STAT_RX); + stm_usb.epr[ep] = epr_write; + sei(); +} + /* * Set just endpoint 0, for use during startup */ +static void +ao_usb_init_ep(uint8_t ep, uint32_t addr, uint32_t type, uint32_t stat_rx, uint32_t stat_tx) +{ + uint32_t epr; + cli(); + epr = stm_usb.epr[ep]; + epr = ((0 << STM_USB_EPR_CTR_RX) | + (epr & (1 << STM_USB_EPR_DTOG_RX)) | + set_toggle(epr, + (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), + (stat_rx << STM_USB_EPR_STAT_RX)) | + (type << STM_USB_EPR_EP_TYPE) | + (0 << STM_USB_EPR_EP_KIND) | + (0 << STM_USB_EPR_CTR_TX) | + (epr & (1 << STM_USB_EPR_DTOG_TX)) | + set_toggle(epr, + (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), + (stat_tx << STM_USB_EPR_STAT_TX)) | + (addr << STM_USB_EPR_EA)); + stm_usb.epr[ep] = epr; + sei(); + debug ("writing epr[%d] 0x%08x wrote 0x%08x\n", + ep, epr, stm_usb.epr[ep]); +} + static void ao_usb_set_ep0(void) { @@ -170,44 +299,17 @@ ao_usb_set_ep0(void) ao_usb_ep0_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); ao_usb_sram_addr += AO_USB_CONTROL_SIZE; - cli(); - epr = stm_usb.epr[0]; - epr = ((STM_USB_EPR_CTR_RX_WRITE_INVARIANT << STM_USB_EPR_CTR_RX) | - (STM_USB_EPR_DTOG_RX_WRITE_INVARIANT << STM_USB_EPR_DTOG_RX) | - set_toggle(epr, - (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), - (STM_USB_EPR_STAT_RX_VALID << STM_USB_EPR_STAT_RX)) | - (STM_USB_EPR_EP_TYPE_CONTROL << STM_USB_EPR_EP_TYPE) | - (0 << STM_USB_EPR_EP_KIND) | - (STM_USB_CTR_TX_WRITE_INVARIANT << STM_USB_EPR_CTR_TX) | - (STM_USB_EPR_DTOG_TX_WRITE_INVARIANT << STM_USB_EPR_DTOG_TX) | - set_toggle(epr, - (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), - (STM_USB_EPR_STAT_TX_NAK << STM_USB_EPR_STAT_TX)) | - (AO_USB_CONTROL_EP << STM_USB_EPR_EA)); - stm_usb.epr[0] = epr; - sei(); - debug ("epr 0 now %x\n", stm_usb.epr[0]); + ao_usb_init_ep(AO_USB_CONTROL_EPR, AO_USB_CONTROL_EP, + STM_USB_EPR_EP_TYPE_CONTROL, + STM_USB_EPR_STAT_RX_VALID, + STM_USB_EPR_STAT_TX_NAK); /* Clear all of the other endpoints */ for (e = 1; e < 8; e++) { - cli(); - epr = stm_usb.epr[e]; - epr = ((STM_USB_EPR_CTR_RX_WRITE_INVARIANT << STM_USB_EPR_CTR_RX) | - (STM_USB_EPR_DTOG_RX_WRITE_INVARIANT << STM_USB_EPR_DTOG_RX) | - set_toggle(epr, - (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), - (STM_USB_EPR_STAT_RX_DISABLED << STM_USB_EPR_STAT_RX)) | - (STM_USB_EPR_EP_TYPE_CONTROL << STM_USB_EPR_EP_TYPE) | - (0 << STM_USB_EPR_EP_KIND) | - (STM_USB_CTR_TX_WRITE_INVARIANT << STM_USB_EPR_CTR_TX) | - (STM_USB_EPR_DTOG_TX_WRITE_INVARIANT << STM_USB_EPR_DTOG_TX) | - set_toggle(epr, - (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), - (STM_USB_EPR_STAT_TX_DISABLED << STM_USB_EPR_STAT_TX)) | - (0 << STM_USB_EPR_EA)); - stm_usb.epr[e] = epr; - sei(); + ao_usb_init_ep(e, 0, + STM_USB_EPR_EP_TYPE_CONTROL, + STM_USB_EPR_STAT_RX_DISABLED, + STM_USB_EPR_STAT_TX_DISABLED); } ao_usb_set_address(0); @@ -226,26 +328,12 @@ ao_usb_set_configuration(void) ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); ao_usb_sram_addr += AO_USB_INT_SIZE; - cli(); - epr = stm_usb.epr[AO_USB_INT_EPR]; - epr = ((0 << STM_USB_EPR_CTR_RX) | - (epr & (1 << STM_USB_EPR_DTOG_RX)) | - set_toggle(epr, - (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), - (STM_USB_EPR_STAT_RX_DISABLED << STM_USB_EPR_STAT_RX)) | - (STM_USB_EPR_EP_TYPE_CONTROL << STM_USB_EPR_EP_TYPE) | - (0 << STM_USB_EPR_EP_KIND) | - (0 << STM_USB_EPR_CTR_TX) | - (epr & (1 << STM_USB_EPR_DTOG_TX)) | - set_toggle(epr, - (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), - (STM_USB_EPR_STAT_TX_NAK << STM_USB_EPR_STAT_TX)) | - (AO_USB_INT_EP << STM_USB_EPR_EA)); - stm_usb.epr[AO_USB_INT_EPR] = epr; - sei(); - debug ("writing epr[%d] 0x%08x wrote 0x%08x\n", - AO_USB_INT_EPR, epr, stm_usb.epr[AO_USB_INT_EPR]); - + ao_usb_init_ep(AO_USB_INT_EPR, + AO_USB_INT_EP, + STM_USB_EPR_EP_TYPE_INTERRUPT, + STM_USB_EPR_STAT_RX_DISABLED, + STM_USB_EPR_STAT_TX_NAK); + /* Set up the OUT end point */ ao_usb_bdt[AO_USB_OUT_EPR].single.addr_rx = ao_usb_sram_addr; ao_usb_bdt[AO_USB_OUT_EPR].single.count_rx = ((1 << STM_USB_BDT_COUNT_RX_BL_SIZE) | @@ -253,25 +341,11 @@ ao_usb_set_configuration(void) ao_usb_out_rx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); ao_usb_sram_addr += AO_USB_OUT_SIZE; - cli(); - epr = stm_usb.epr[AO_USB_OUT_EPR]; - epr = ((0 << STM_USB_EPR_CTR_RX) | - (epr & (1 << STM_USB_EPR_DTOG_RX)) | - set_toggle(epr, - (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), - (STM_USB_EPR_STAT_RX_VALID << STM_USB_EPR_STAT_RX)) | - (STM_USB_EPR_EP_TYPE_CONTROL << STM_USB_EPR_EP_TYPE) | - (0 << STM_USB_EPR_EP_KIND) | - (0 << STM_USB_EPR_CTR_TX) | - (epr & (1 << STM_USB_EPR_DTOG_TX)) | - set_toggle(epr, - (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), - (STM_USB_EPR_STAT_TX_DISABLED << STM_USB_EPR_STAT_TX)) | - (AO_USB_OUT_EP << STM_USB_EPR_EA)); - stm_usb.epr[AO_USB_OUT_EPR] = epr; - sei(); - debug ("writing epr[%d] 0x%08x wrote 0x%08x\n", - AO_USB_OUT_EPR, epr, stm_usb.epr[AO_USB_OUT_EPR]); + ao_usb_init_ep(AO_USB_OUT_EPR, + AO_USB_OUT_EP, + STM_USB_EPR_EP_TYPE_BULK, + STM_USB_EPR_STAT_RX_VALID, + STM_USB_EPR_STAT_TX_DISABLED); /* Set up the IN end point */ ao_usb_bdt[AO_USB_IN_EPR].single.addr_tx = ao_usb_sram_addr; @@ -279,59 +353,21 @@ ao_usb_set_configuration(void) ao_usb_in_tx_buffer = ao_usb_packet_buffer_addr(ao_usb_sram_addr); ao_usb_sram_addr += AO_USB_IN_SIZE; - cli(); - epr = stm_usb.epr[AO_USB_IN_EPR]; - epr = ((0 << STM_USB_EPR_CTR_RX) | - (epr & (1 << STM_USB_EPR_DTOG_RX)) | - set_toggle(epr, - (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX), - (STM_USB_EPR_STAT_RX_DISABLED << STM_USB_EPR_STAT_RX)) | - (STM_USB_EPR_EP_TYPE_CONTROL << STM_USB_EPR_EP_TYPE) | - (0 << STM_USB_EPR_EP_KIND) | - (0 << STM_USB_EPR_CTR_TX) | - (epr & (1 << STM_USB_EPR_DTOG_TX)) | - set_toggle(epr, - (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX), - (STM_USB_EPR_STAT_TX_NAK << STM_USB_EPR_STAT_TX)) | - (AO_USB_IN_EP << STM_USB_EPR_EA)); - stm_usb.epr[AO_USB_IN_EPR] = epr; - sei(); - debug ("writing epr[%d] 0x%08x wrote 0x%08x\n", - AO_USB_IN_EPR, epr, stm_usb.epr[AO_USB_IN_EPR]); + ao_usb_init_ep(AO_USB_IN_EPR, + AO_USB_IN_EP, + STM_USB_EPR_EP_TYPE_BULK, + STM_USB_EPR_STAT_RX_DISABLED, + STM_USB_EPR_STAT_TX_NAK); + ao_usb_running = 1; } static uint16_t control_count; +static uint16_t int_count; static uint16_t in_count; static uint16_t out_count; static uint16_t reset_count; -/* - * Write these values to preserve register contents under HW changes - */ - -#define STM_USB_EPR_INVARIANT ((1 << STM_USB_EPR_CTR_RX) | \ - (STM_USB_EPR_DTOG_RX_WRITE_INVARIANT << STM_USB_EPR_DTOG_RX) | \ - (STM_USB_EPR_STAT_RX_WRITE_INVARIANT << STM_USB_EPR_STAT_RX) | \ - (1 << STM_USB_EPR_CTR_TX) | \ - (STM_USB_EPR_DTOG_TX_WRITE_INVARIANT << STM_USB_EPR_DTOG_TX) | \ - (STM_USB_EPR_STAT_TX_WRITE_INVARIANT << STM_USB_EPR_STAT_TX)) - -#define STM_USB_EPR_INVARIANT_MASK ((1 << STM_USB_EPR_CTR_RX) | \ - (STM_USB_EPR_DTOG_RX_MASK << STM_USB_EPR_DTOG_RX) | \ - (STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX) | \ - (1 << STM_USB_EPR_CTR_TX) | \ - (STM_USB_EPR_DTOG_TX_MASK << STM_USB_EPR_DTOG_TX) | \ - (STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX)) - -/* - * These bits are purely under sw control, so preserve them in the - * register by re-writing what was read - */ -#define STM_USB_EPR_PRESERVE_MASK ((STM_USB_EPR_EP_TYPE_MASK << STM_USB_EPR_EP_TYPE) | \ - (1 << STM_USB_EPR_EP_KIND) | \ - (STM_USB_EPR_EA_MASK << STM_USB_EPR_EA)) - void stm_usb_lp_isr(void) { @@ -379,6 +415,11 @@ stm_usb_lp_isr(void) ao_wakeup(&ao_usb_in_pending); } break; + case AO_USB_INT_EPR: + ++int_count; + if (ao_usb_epr_ctr_tx(epr)) + _ao_usb_set_stat_tx(AO_USB_INT_EPR, STM_USB_EPR_STAT_TX_NAK); + break; } return; } @@ -391,12 +432,6 @@ stm_usb_lp_isr(void) } } -void -stm_usb_hp_isr(void) -{ - stm_usb_lp_isr(); -} - void stm_usb_fs_wkup(void) { @@ -404,42 +439,6 @@ stm_usb_fs_wkup(void) stm_usb.istr &= ~(1 << STM_USB_ISTR_WKUP); } -static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; - -/* Walk through the list of descriptors and find a match - */ -static void -ao_usb_get_descriptor(uint16_t value) -{ - const uint8_t *descriptor; - uint8_t type = value >> 8; - uint8_t index = value; - - descriptor = ao_usb_descriptors; - while (descriptor[0] != 0) { - if (descriptor[1] == type && index-- == 0) { - if (type == AO_USB_DESC_CONFIGURATION) - ao_usb_ep0_in_len = descriptor[2]; - else - ao_usb_ep0_in_len = descriptor[0]; - ao_usb_ep0_in_data = descriptor; - break; - } - descriptor += descriptor[0]; - } -} - -static void -ao_usb_ep0_set_in_pending(uint8_t in_pending) -{ - ao_usb_ep0_in_pending = in_pending; - -#if 0 - if (in_pending) - ueienx_0 = ((1 << RXSTPE) | (1 << RXOUTE) | (1 << TXINE)); /* Enable IN interrupt */ -#endif -} - /* The USB memory holds 16 bit values on 32 bit boundaries * and must be accessed only in 32 bit units. Sigh. */ @@ -525,28 +524,6 @@ ao_usb_read(uint8_t *dst, uint32_t *base, uint16_t offset, uint16_t bytes) } } -static inline void -ao_usb_set_stat_tx(int ep, uint32_t stat_tx) { - uint32_t epr_write, epr_old, epr_new, epr_want; - - cli(); - epr_write = epr_old = stm_usb.epr[ep]; - epr_write &= STM_USB_EPR_PRESERVE_MASK; - epr_write |= STM_USB_EPR_INVARIANT; - epr_write |= set_toggle(epr_old, - STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX, - stat_tx << STM_USB_EPR_STAT_TX); - stm_usb.epr[ep] = epr_write; - epr_new = stm_usb.epr[ep]; - sei(); - epr_want = (epr_old & ~(STM_USB_EPR_STAT_TX_MASK << STM_USB_EPR_STAT_TX)) | - (stat_tx << STM_USB_EPR_STAT_TX); - if (epr_new != epr_want) { - debug ("**** set_stat_tx to %x. old %08x want %08x write %08x new %08x\n", - stat_tx, epr_old, epr_want, epr_write, epr_new); - } -} - /* Send an IN data packet */ static void ao_usb_ep0_flush(void) @@ -556,52 +533,27 @@ ao_usb_ep0_flush(void) /* Check to see if the endpoint is still busy */ if (ao_usb_epr_stat_tx(stm_usb.epr[0]) == STM_USB_EPR_STAT_TX_VALID) { debug("EP0 not accepting IN data\n"); - ao_usb_ep0_set_in_pending(1); - } else { - this_len = ao_usb_ep0_in_len; - if (this_len > AO_USB_CONTROL_SIZE) - this_len = AO_USB_CONTROL_SIZE; - - ao_usb_ep0_in_len -= this_len; - - /* Set IN interrupt enable */ - if (ao_usb_ep0_in_len == 0 && this_len != AO_USB_CONTROL_SIZE) - ao_usb_ep0_set_in_pending(0); - else - ao_usb_ep0_set_in_pending(1); - - debug_data ("Flush EP0 len %d:", this_len); - ao_usb_write(ao_usb_ep0_in_data, ao_usb_ep0_tx_buffer, 0, this_len); - debug_data ("\n"); - ao_usb_ep0_in_data += this_len; - - /* Mark the endpoint as TX valid to send the packet */ - ao_usb_bdt[0].single.count_tx = this_len; - ao_usb_set_stat_tx(0, STM_USB_EPR_STAT_TX_VALID); - debug ("queue tx. epr 0 now %08x\n", stm_usb.epr[0]); + return; } -} -static inline void -ao_usb_set_stat_rx(int ep, uint32_t stat_rx) { - uint32_t epr_write, epr_old, epr_new, epr_want; + this_len = ao_usb_ep0_in_len; + if (this_len > AO_USB_CONTROL_SIZE) + this_len = AO_USB_CONTROL_SIZE; - cli(); - epr_write = epr_old = stm_usb.epr[ep]; - epr_write &= STM_USB_EPR_PRESERVE_MASK; - epr_write |= STM_USB_EPR_INVARIANT; - epr_write |= set_toggle(epr_old, - STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX, - stat_rx << STM_USB_EPR_STAT_RX); - stm_usb.epr[ep] = epr_write; - epr_new = stm_usb.epr[ep]; - sei(); - epr_want = (epr_old & ~(STM_USB_EPR_STAT_RX_MASK << STM_USB_EPR_STAT_RX)) | - (stat_rx << STM_USB_EPR_STAT_RX); - if (epr_new != epr_want) { - debug ("**** set_stat_rx to %x. old %08x want %08x write %08x new %08x\n", - stat_rx, epr_old, epr_want, epr_write, epr_new); - } + if (this_len < AO_USB_CONTROL_SIZE) + ao_usb_ep0_state = AO_USB_EP0_IDLE; + + ao_usb_ep0_in_len -= this_len; + + debug_data ("Flush EP0 len %d:", this_len); + ao_usb_write(ao_usb_ep0_in_data, ao_usb_ep0_tx_buffer, 0, this_len); + debug_data ("\n"); + ao_usb_ep0_in_data += this_len; + + /* Mark the endpoint as TX valid to send the packet */ + ao_usb_bdt[AO_USB_CONTROL_EPR].single.count_tx = this_len; + ao_usb_set_stat_tx(AO_USB_CONTROL_EPR, STM_USB_EPR_STAT_TX_VALID); + debug ("queue tx. epr 0 now %08x\n", stm_usb.epr[AO_USB_CONTROL_EPR]); } /* Read data from the ep0 OUT fifo */ @@ -624,39 +576,87 @@ ao_usb_ep0_fill(void) ao_usb_set_stat_rx(0, STM_USB_EPR_STAT_RX_VALID); } -void -ao_usb_ep0_queue_byte(uint8_t a) +static void +ao_usb_ep0_in_reset(void) +{ + ao_usb_ep0_in_data = ao_usb_ep0_in_buf; + ao_usb_ep0_in_len = 0; +} + +static void +ao_usb_ep0_in_queue_byte(uint8_t a) { - ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a; + if (ao_usb_ep0_in_len < sizeof (ao_usb_ep0_in_buf)) + ao_usb_ep0_in_buf[ao_usb_ep0_in_len++] = a; +} + +static void +ao_usb_ep0_in_set(const uint8_t *data, uint8_t len) +{ + ao_usb_ep0_in_data = data; + ao_usb_ep0_in_len = len; +} + +static void +ao_usb_ep0_out_set(uint8_t *data, uint8_t len) +{ + ao_usb_ep0_out_data = data; + ao_usb_ep0_out_len = len; +} + +static void +ao_usb_ep0_in_start(uint8_t max) +{ + /* Don't send more than asked for */ + if (ao_usb_ep0_in_len > max) + ao_usb_ep0_in_len = max; + ao_usb_ep0_flush(); +} + +static struct ao_usb_line_coding ao_usb_line_coding = {115200, 0, 0, 8}; + +/* Walk through the list of descriptors and find a match + */ +static void +ao_usb_get_descriptor(uint16_t value) +{ + const uint8_t *descriptor; + uint8_t type = value >> 8; + uint8_t index = value; + + descriptor = ao_usb_descriptors; + while (descriptor[0] != 0) { + if (descriptor[1] == type && index-- == 0) { + uint8_t len; + if (type == AO_USB_DESC_CONFIGURATION) + len = descriptor[2]; + else + len = descriptor[0]; + ao_usb_ep0_in_set(descriptor, len); + break; + } + descriptor += descriptor[0]; + } } static void ao_usb_ep0_setup(void) { /* Pull the setup packet out of the fifo */ - ao_usb_ep0_out_data = (uint8_t *) &ao_usb_setup; - ao_usb_ep0_out_len = 8; + ao_usb_ep0_out_set((uint8_t *) &ao_usb_setup, 8); ao_usb_ep0_fill(); if (ao_usb_ep0_out_len != 0) { debug ("invalid setup packet length\n"); return; } - /* Figure out how to ACK the setup packet */ - if (ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) { - if (ao_usb_setup.length) - ao_usb_ep0_state = AO_USB_EP0_DATA_IN; - else - ao_usb_ep0_state = AO_USB_EP0_IDLE; - } else { - if (ao_usb_setup.length) - ao_usb_ep0_state = AO_USB_EP0_DATA_OUT; - else - ao_usb_ep0_state = AO_USB_EP0_IDLE; - } + if ((ao_usb_setup.dir_type_recip & AO_USB_DIR_IN) || ao_usb_setup.length == 0) + ao_usb_ep0_state = AO_USB_EP0_DATA_IN; + else + ao_usb_ep0_state = AO_USB_EP0_DATA_OUT; + + ao_usb_ep0_in_reset(); - ao_usb_ep0_in_data = ao_usb_ep0_in_buf; - ao_usb_ep0_in_len = 0; switch(ao_usb_setup.dir_type_recip & AO_USB_SETUP_TYPE_MASK) { case AO_USB_TYPE_STANDARD: debug ("Standard setup packet\n"); @@ -666,8 +666,8 @@ ao_usb_ep0_setup(void) switch(ao_usb_setup.request) { case AO_USB_REQ_GET_STATUS: debug ("get status\n"); - ao_usb_ep0_queue_byte(0); - ao_usb_ep0_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); break; case AO_USB_REQ_SET_ADDRESS: debug ("set address %d\n", ao_usb_setup.value); @@ -680,7 +680,7 @@ ao_usb_ep0_setup(void) break; case AO_USB_REQ_GET_CONFIGURATION: debug ("get configuration %d\n", ao_usb_configuration); - ao_usb_ep0_queue_byte(ao_usb_configuration); + ao_usb_ep0_in_queue_byte(ao_usb_configuration); break; case AO_USB_REQ_SET_CONFIGURATION: ao_usb_configuration = ao_usb_setup.value; @@ -693,11 +693,11 @@ ao_usb_ep0_setup(void) debug ("Interface setup packet\n"); switch(ao_usb_setup.request) { case AO_USB_REQ_GET_STATUS: - ao_usb_ep0_queue_byte(0); - ao_usb_ep0_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); break; case AO_USB_REQ_GET_INTERFACE: - ao_usb_ep0_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); break; case AO_USB_REQ_SET_INTERFACE: break; @@ -707,8 +707,8 @@ ao_usb_ep0_setup(void) debug ("Endpoint setup packet\n"); switch(ao_usb_setup.request) { case AO_USB_REQ_GET_STATUS: - ao_usb_ep0_queue_byte(0); - ao_usb_ep0_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); + ao_usb_ep0_in_queue_byte(0); break; } break; @@ -719,24 +719,23 @@ ao_usb_ep0_setup(void) switch (ao_usb_setup.request) { case AO_USB_SET_LINE_CODING: debug ("set line coding\n"); - ao_usb_ep0_out_len = 7; - ao_usb_ep0_out_data = (uint8_t *) &ao_usb_line_coding; + ao_usb_ep0_out_set((uint8_t *) &ao_usb_line_coding, 7); break; case AO_USB_GET_LINE_CODING: debug ("get line coding\n"); - ao_usb_ep0_in_len = 7; - ao_usb_ep0_in_data = (uint8_t *) &ao_usb_line_coding; + ao_usb_ep0_in_set((const uint8_t *) &ao_usb_line_coding, 7); break; case AO_USB_SET_CONTROL_LINE_STATE: break; } break; } - if (ao_usb_ep0_state != AO_USB_EP0_DATA_OUT) { - if (ao_usb_setup.length < ao_usb_ep0_in_len) - ao_usb_ep0_in_len = ao_usb_setup.length; - ao_usb_ep0_flush(); - } + + /* If we're not waiting to receive data from the host, + * queue an IN response + */ + if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN) + ao_usb_ep0_in_start(ao_usb_setup.length); } /* End point 0 receives all of the control messages. */ @@ -766,16 +765,24 @@ ao_usb_ep0(void) } if (receive & AO_USB_EP0_GOT_RX_DATA) { debug ("\tgot rx data\n"); - ao_usb_ep0_fill(); - ao_usb_ep0_set_in_pending(1); + if (ao_usb_ep0_state == AO_USB_EP0_DATA_OUT) { + ao_usb_ep0_fill(); + if (ao_usb_ep0_out_len == 0) { + ao_usb_ep0_state = AO_USB_EP0_DATA_IN; + ao_usb_ep0_in_start(0); + } + } } if (receive & AO_USB_EP0_GOT_TX_ACK) { debug ("\tgot tx ack\n"); - ao_usb_ep0_flush(); - if (ao_usb_address_pending) { + + /* Wait until the IN packet is received from addr 0 + * before assigning our local address + */ + if (ao_usb_address_pending) ao_usb_set_address(ao_usb_address); - ao_usb_set_configuration(); - } + if (ao_usb_ep0_state == AO_USB_EP0_DATA_IN) + ao_usb_ep0_flush(); } } } @@ -982,7 +989,7 @@ ao_usb_enable(void) stm_syscfg.pmc |= (1 << STM_SYSCFG_PMC_USB_PU); } -#if USB_DEBUG +#if USB_ECHO struct ao_task ao_usb_echo_task; static void @@ -1001,8 +1008,8 @@ ao_usb_echo(void) static void ao_usb_irq(void) { - printf ("control: %d out: %d in: %d reset: %d\n", - control_count, out_count, in_count, reset_count); + printf ("control: %d out: %d in: %d int: %d reset: %d\n", + control_count, out_count, in_count, int_count, reset_count); } __code struct ao_cmds ao_usb_cmds[] = { @@ -1017,11 +1024,11 @@ ao_usb_init(void) debug ("ao_usb_init\n"); ao_add_task(&ao_usb_task, ao_usb_ep0, "usb"); -#if USB_DEBUG +#if USB_ECHO ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo"); #endif ao_cmd_register(&ao_usb_cmds[0]); -#if !USB_DEBUG +#if !USB_ECHO ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); #endif } -- cgit v1.2.3 From 9a8fec1b6d8f3346f988882ffb03d7d0e45b3c81 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Apr 2012 12:00:32 -0700 Subject: altos: Clean up test scripts The flight test scripts were using invalid bash syntax. Clean that up and also switch the default flight directory to my new ~/misc/rockets/flights directory. Signed-off-by: Keith Packard --- src/test/run-one | 16 +++++++++++++--- src/test/run-tests | 10 +++++----- 2 files changed, 18 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/test/run-one b/src/test/run-one index 7d0f95ae..8fa0787c 100755 --- a/src/test/run-one +++ b/src/test/run-one @@ -1,10 +1,20 @@ #!/bin/sh +DIR=~/misc/rockets/flights + for i in "$@"; do -./ao_flight_test "$i" > run-out.full -./ao_flight_test_baro "$i" > run-out.baro +case "$i" in + */*) + file="$i" + ;; + *) + file="$DIR/$i" + ;; +esac +./ao_flight_test "$file" > run-out.full +./ao_flight_test_baro "$file" > run-out.baro -#./ao_flight_test_accel "$i" > run-out.accel +#./ao_flight_test_accel "$file" > run-out.accel #"run-out.accel" using 1:9 with lines lt 4 axes x1y1 title "accel height",\ #"run-out.accel" using 1:11 with lines lt 4 axes x1y2 title "accel speed",\ #"run-out.accel" using 1:13 with lines lt 4 axes x1y2 title "accel accel",\ diff --git a/src/test/run-tests b/src/test/run-tests index 3e0cad3c..a8a8dc3f 100755 --- a/src/test/run-tests +++ b/src/test/run-tests @@ -1,6 +1,6 @@ -#!/bin/sh +#!/bin/bash -DIR=~/src/cc1111/flights +DIR=~/misc/rockets/flights bad_baro=0 bad_full=0 @@ -8,15 +8,15 @@ while read flight description; do if ./ao_flight_test_baro -s $DIR/$flight; then : else - ((bad_baro++)) + : $((bad_baro++)) fi if ./ao_flight_test -s $DIR/$flight; then : else - ((bad_full++)) + : $((bad_full++)) fi done < test-flights echo baro errors $bad_baro echo full errors $bad_full -((bad = bad_baro + bad_full)) +: $((bad = bad_baro + bad_full)) exit $bad \ No newline at end of file -- cgit v1.2.3 From 6cb744e305116a738b5d71686c6748f6f08c12ea Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Apr 2012 12:02:14 -0700 Subject: altos: Respect apogee lockout time in flight algorithm This prevents any apogee detection from occurring until the specified number of seconds after boost. This also prevents the switch from accel+baro to baro only mode in the Kalman filter. The test frame work is also changed to look for Apogee lockout: in the eeprom input file. Signed-off-by: Keith Packard --- src/core/ao_flight.c | 11 +++++++++++ src/test/ao_flight_test.c | 4 ++++ 2 files changed, 15 insertions(+) (limited to 'src') diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index 5e194638..494e656d 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -223,6 +223,17 @@ ao_flight(void) #endif case ao_flight_coast: + /* + * By customer request - allow the user + * to lock out apogee detection for a specified + * number of seconds. + */ + if (ao_config.apogee_lockout) { + if ((ao_sample_tick - ao_boost_tick) < + AO_SEC_TO_TICKS(ao_config.apogee_lockout)) + break; + } + /* apogee detect: coast to drogue deploy: * * speed: < 0 diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 921d44e7..4a8625cf 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -184,6 +184,7 @@ struct ao_config { int16_t accel_plus_g; int16_t accel_minus_g; uint8_t pad_orientation; + uint16_t apogee_lockout; }; #define AO_PAD_ORIENTATION_ANTENNA_UP 0 @@ -523,6 +524,9 @@ ao_sleep(void *wchan) ao_config.accel_minus_g = atoi(words[5]); } else if (nword >= 4 && strcmp(words[0], "Main") == 0) { ao_config.main_deploy = atoi(words[2]); + } else if (nword >= 3 && strcmp(words[0], "Apogee") == 0 && + strcmp(words[1], "lockout:") == 0) { + ao_config.apogee_lockout = atoi(words[2]); } else if (nword >= 36 && strcmp(words[0], "CALL") == 0) { tick = atoi(words[10]); if (!ao_flight_started) { -- cgit v1.2.3 From 5c8af6d35ebfc8fd896dfbf9928ec8f9dbfa531f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Apr 2012 12:05:28 -0700 Subject: altos: Remove debug printf from cc1111 check-stack script Signed-off-by: Keith Packard --- src/util/check-stack | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/util/check-stack b/src/util/check-stack index 7b62e460..f4cada2b 100755 --- a/src/util/check-stack +++ b/src/util/check-stack @@ -6,7 +6,6 @@ HEADER_STACK=`awk '/#define AO_STACK_START/ {print strtonum($3)}' $HEADER` MEM_STACK=`awk '/Stack starts at/ {print strtonum ($4)}' $MEM` XRAM_END=`awk '/EXTERNAL RAM/ { print strtonum ($4)}' $MEM` FLASH_END=`awk '/ROM\/EPROM\/FLASH/ { print strtonum ($3)}' $MEM` -echo FLASH_END $FLASH_END if [ "$HEADER_STACK" -lt "$MEM_STACK" ]; then echo $MEM_STACK | awk '{ printf ("Set AO_STACK_START to at least 0x%x\n", $1); }' -- cgit v1.2.3 From 1489263b895a2a825e29d0560c9b1dbba8a3f431 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Apr 2012 11:01:18 -0700 Subject: altos: Starting to write cc1120 driver This does "something" in radio test mode, appearing to generate a 730MHz signal. Signed-off-by: Keith Packard --- src/cc1111/ao_packet.c | 161 ----------- src/cc1111/ao_packet_master.c | 151 ---------- src/cc1111/ao_packet_slave.c | 66 ----- src/drivers/ao_cc1120.c | 534 ++++++++++++++++++++++++++++++++++++ src/drivers/ao_cc1120.h | 320 +++++++++++++++++++++ src/drivers/ao_cc1120_CC1120.h | 191 +++++++++++++ src/drivers/ao_packet.c | 163 +++++++++++ src/drivers/ao_packet_master.c | 151 ++++++++++ src/drivers/ao_packet_slave.c | 66 +++++ src/megametrum-v0.1/Makefile | 5 +- src/megametrum-v0.1/ao_megametrum.c | 5 +- src/megametrum-v0.1/ao_pins.h | 13 + src/stm/Makefile.defs | 2 +- src/stm/ao_arch_funcs.h | 44 +-- src/stm/ao_dma_stm.c | 1 + src/stm/ao_exti.h | 38 +++ src/stm/ao_exti_stm.c | 109 ++++++++ src/stm/ao_spi_stm.c | 113 ++++++++ src/stm/ao_usb_stm.c | 4 + src/stm/stm32l.h | 16 +- 20 files changed, 1751 insertions(+), 402 deletions(-) delete mode 100644 src/cc1111/ao_packet.c delete mode 100644 src/cc1111/ao_packet_master.c delete mode 100644 src/cc1111/ao_packet_slave.c create mode 100644 src/drivers/ao_cc1120.h create mode 100644 src/drivers/ao_cc1120_CC1120.h create mode 100644 src/drivers/ao_packet.c create mode 100644 src/drivers/ao_packet_master.c create mode 100644 src/drivers/ao_packet_slave.c create mode 100644 src/stm/ao_exti.h create mode 100644 src/stm/ao_exti_stm.c (limited to 'src') diff --git a/src/cc1111/ao_packet.c b/src/cc1111/ao_packet.c deleted file mode 100644 index 7eeb0710..00000000 --- a/src/cc1111/ao_packet.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * 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" - -__xdata struct ao_packet_recv ao_rx_packet; -__xdata struct ao_packet ao_tx_packet; -__pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; - -static __xdata char tx_data[AO_PACKET_MAX]; -static __xdata char rx_data[AO_PACKET_MAX]; -static __pdata uint8_t rx_seq; - -__xdata struct ao_task ao_packet_task; -__xdata uint8_t ao_packet_enable; -__xdata uint8_t ao_packet_master_sleeping; - -void -ao_packet_send(void) -{ -#ifdef AO_LED_RED - ao_led_on(AO_LED_RED); -#endif - /* If any tx data is pending then copy it into the tx packet */ - if (ao_packet_tx_used && ao_tx_packet.len == 0) { - ao_xmemcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); - ao_tx_packet.len = ao_packet_tx_used; - ao_tx_packet.seq++; - ao_packet_tx_used = 0; - ao_wakeup(&tx_data); - } - ao_radio_send(&ao_tx_packet, sizeof (ao_tx_packet)); -#ifdef AO_LED_RED - ao_led_off(AO_LED_RED); -#endif -} - -uint8_t -ao_packet_recv(void) -{ - uint8_t dma_done; - -#ifdef AO_LED_GREEN - ao_led_on(AO_LED_GREEN); -#endif - dma_done = ao_radio_recv(&ao_rx_packet, sizeof (struct ao_packet_recv)); -#ifdef AO_LED_GREEN - ao_led_off(AO_LED_GREEN); -#endif - - /* Check to see if we got a valid packet */ - if (!dma_done) - return 0; - if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) - return 0; - - /* Accept packets with matching call signs, or any packet if - * our callsign hasn't been configured - */ - if (ao_xmemcmp(ao_rx_packet.packet.callsign, - ao_config.callsign, - AO_MAX_CALLSIGN) != 0 && - ao_xmemcmp(ao_config.callsign, CODE_TO_XDATA("N0CALL"), 7) != 0) - return 0; - - /* SYN packets carry no data */ - if (ao_rx_packet.packet.len == AO_PACKET_SYN) { - rx_seq = ao_rx_packet.packet.seq; - ao_tx_packet.seq = ao_rx_packet.packet.ack; - ao_tx_packet.ack = rx_seq; - } else if (ao_rx_packet.packet.len) { - - /* Check for incoming data at the next sequence and - * for an empty data buffer - */ - if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) && - ao_packet_rx_used == ao_packet_rx_len) { - - /* Copy data to the receive data buffer and set up the - * offsets - */ - ao_xmemcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); - ao_packet_rx_used = 0; - ao_packet_rx_len = ao_rx_packet.packet.len; - - /* Mark the sequence that we've received to - * let the sender know when we return a packet - */ - rx_seq = ao_rx_packet.packet.seq; - ao_tx_packet.ack = rx_seq; - - /* Poke anyone looking for received data */ - ao_wakeup(&ao_stdin_ready); - } - } - - /* If the other side has seen the latest data we queued, - * wake up any task waiting to send data and let them go again - */ - if (ao_rx_packet.packet.ack == ao_tx_packet.seq) { - ao_tx_packet.len = 0; - ao_wakeup(&ao_tx_packet); - } - return 1; -} - -#ifndef PACKET_HAS_MASTER -#define PACKET_HAS_MASTER 1 -#endif - -#if PACKET_HAS_MASTER -void -ao_packet_flush(void) -{ - /* If there is data to send, and this is the master, - * then poke the master to send all queued data - */ - if (ao_packet_tx_used && ao_packet_master_sleeping) - ao_wakeup(&ao_packet_master_sleeping); -} -#endif /* PACKET_HAS_MASTER */ - -void -ao_packet_putchar(char c) __reentrant -{ - while (ao_packet_tx_used == AO_PACKET_MAX && ao_packet_enable) { -#if PACKET_HAS_MASTER - ao_packet_flush(); -#endif - ao_sleep(&tx_data); - } - - if (ao_packet_enable) - tx_data[ao_packet_tx_used++] = c; -} - -char -ao_packet_pollchar(void) __critical -{ - if (!ao_packet_enable) - return AO_READ_AGAIN; - - if (ao_packet_rx_used == ao_packet_rx_len) - return AO_READ_AGAIN; - - return rx_data[ao_packet_rx_used++]; -} diff --git a/src/cc1111/ao_packet_master.c b/src/cc1111/ao_packet_master.c deleted file mode 100644 index 66f94288..00000000 --- a/src/cc1111/ao_packet_master.c +++ /dev/null @@ -1,151 +0,0 @@ -/* - * 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" - -static char -ao_packet_getchar(void) __critical -{ - char c; - while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) { - if (!ao_packet_enable) - break; - if (ao_packet_master_sleeping) - ao_wakeup(&ao_packet_master_sleeping); - flush(); - ao_sleep(&ao_stdin_ready); - } - return c; -} - -static void -ao_packet_echo(void) __reentrant -{ - char c; - while (ao_packet_enable) { - c = ao_packet_getchar(); - if (c != AO_READ_AGAIN) - putchar(c); - } - ao_exit(); -} - -static __xdata struct ao_task ao_packet_echo_task; -static __xdata uint16_t ao_packet_master_delay; -static __xdata uint16_t ao_packet_master_time; - -#define AO_PACKET_MASTER_DELAY_SHORT AO_MS_TO_TICKS(100) -#define AO_PACKET_MASTER_DELAY_LONG AO_MS_TO_TICKS(1000) -#define AO_PACKET_MASTER_DELAY_TIMEOUT AO_MS_TO_TICKS(2000) - -static void -ao_packet_master_busy(void) -{ - ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; - ao_packet_master_time = ao_time(); -} - -static void -ao_packet_master_check_busy(void) -{ - int16_t idle; - if (ao_packet_master_delay != AO_PACKET_MASTER_DELAY_SHORT) - return; - idle = (int16_t) (ao_time() - ao_packet_master_time); - - if (idle > AO_PACKET_MASTER_DELAY_TIMEOUT) - ao_packet_master_delay = AO_PACKET_MASTER_DELAY_LONG; -} - -void -ao_packet_master(void) -{ - ao_config_get(); - ao_tx_packet.addr = ao_serial_number; - ao_tx_packet.len = AO_PACKET_SYN; - ao_packet_master_time = ao_time(); - ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; - while (ao_packet_enable) { - uint8_t r; - ao_xmemcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN); - ao_packet_send(); - if (ao_tx_packet.len) - ao_packet_master_busy(); - ao_packet_master_check_busy(); - ao_alarm(ao_packet_master_delay); - r = ao_packet_recv(); - ao_clear_alarm(); - if (r) { - /* if we can transmit data, do so */ - if (ao_packet_tx_used && ao_tx_packet.len == 0) - continue; - if (ao_rx_packet.packet.len) - ao_packet_master_busy(); - ao_packet_master_sleeping = 1; - ao_alarm(ao_packet_master_delay); - ao_sleep(&ao_packet_master_sleeping); - ao_clear_alarm(); - ao_packet_master_sleeping = 0; - } - } - ao_exit(); -} - -static void -ao_packet_forward(void) __reentrant -{ - char c; - ao_packet_enable = 1; - ao_cmd_white(); - - flush(); -#if HAS_MONITOR - ao_monitor_disable(); -#endif - ao_add_task(&ao_packet_task, ao_packet_master, "master"); - ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); - while ((c = getchar()) != '~') { - if (c == '\r') c = '\n'; - ao_packet_putchar(c); - } - - /* Wait for a second if there is any pending data */ - for (c = 0; (ao_packet_tx_used || ao_tx_packet.len) && c < 10; c++) - ao_delay(AO_MS_TO_TICKS(100)); - ao_packet_enable = 0; - while (ao_packet_echo_task.wchan || ao_packet_task.wchan) { - ao_radio_recv_abort(); - ao_wakeup(&ao_stdin_ready); - ao_delay(AO_MS_TO_TICKS(10)); - } -#if HAS_MONITOR - ao_monitor_enable(); -#endif -} - - - -__code struct ao_cmds ao_packet_master_cmds[] = { - { ao_packet_forward, "p\0Remote packet link." }, - { 0, NULL }, -}; - -void -ao_packet_master_init(void) -{ - ao_cmd_register(&ao_packet_master_cmds[0]); -} diff --git a/src/cc1111/ao_packet_slave.c b/src/cc1111/ao_packet_slave.c deleted file mode 100644 index fd5d443e..00000000 --- a/src/cc1111/ao_packet_slave.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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_packet_slave(void) -{ - ao_tx_packet.addr = ao_serial_number; - ao_tx_packet.len = AO_PACKET_SYN; - while (ao_packet_enable) { - if (ao_packet_recv()) { - ao_xmemcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN); -#if HAS_FLIGHT - ao_flight_force_idle = TRUE; -#endif - ao_packet_send(); - } - } - ao_exit(); -} - -void -ao_packet_slave_start(void) -{ - if (!ao_packet_enable) { - ao_packet_enable = 1; - ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); - } -} - -void -ao_packet_slave_stop(void) -{ - if (ao_packet_enable) { - ao_packet_enable = 0; - while (ao_packet_task.wchan) { - ao_radio_recv_abort(); - ao_delay(AO_MS_TO_TICKS(10)); - } - } -} - -void -ao_packet_slave_init(uint8_t enable) -{ - ao_add_stdio(ao_packet_pollchar, - ao_packet_putchar, - NULL); - if (enable) - ao_packet_slave_start(); -} diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 9470fa87..272371d0 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -16,10 +16,544 @@ */ #include +#include +#include + +uint8_t ao_radio_done; +uint8_t ao_radio_mutex; +uint8_t ao_radio_abort; + +#define CC1120_DEBUG 1 uint32_t ao_radio_cal = 1186611; +#define ao_radio_select() ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS) +#define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS) +#define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS) +#define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS) +#define ao_radio_spi_recv(d,l) ao_spi_recv((d), (l), AO_CC1120_SPI_BUS) +#define ao_radio_duplex(o,i,l) ao_spi_duplex((o), (i), (l), AO_CC1120_SPI_BUS) + +static uint8_t +ao_radio_reg_read(uint16_t addr) +{ + uint8_t data[2]; + uint8_t d; + +#if CC1120_DEBUG + printf("ao_radio_reg_read (%04x): ", addr); flush(); +#endif + if (CC1120_IS_EXTENDED(addr)) { + data[0] = ((1 << CC1120_READ) | + (0 << CC1120_BURST) | + CC1120_EXTENDED); + data[1] = addr; + d = 2; + } else { + data[0] = ((1 << CC1120_READ) | + (0 << CC1120_BURST) | + addr); + d = 1; + } + ao_radio_select(); + ao_radio_spi_send(data, d); + ao_radio_spi_recv(data, 1); + ao_radio_deselect(); +#if CC1120_DEBUG + printf (" %02x\n", data[0]); +#endif + return data[0]; +} + +static void +ao_radio_reg_write(uint16_t addr, uint8_t value) +{ + uint8_t data[3]; + uint8_t d; + +#if CC1120_DEBUG + printf("ao_radio_reg_write (%04x): %02x\n", addr, value); +#endif + if (CC1120_IS_EXTENDED(addr)) { + data[0] = ((1 << CC1120_READ) | + (0 << CC1120_BURST) | + CC1120_EXTENDED); + data[1] = addr; + d = 2; + } else { + data[0] = ((1 << CC1120_READ) | + (0 << CC1120_BURST) | + addr); + d = 1; + } + data[d] = value; + ao_radio_select(); + ao_radio_spi_send(data, d+1); + ao_radio_deselect(); +} + +static uint8_t +ao_radio_strobe(uint8_t addr) +{ + uint8_t in; + + ao_radio_select(); + ao_radio_duplex(&addr, &in, 1); + ao_radio_deselect(); + return in; +} + +static uint8_t +ao_radio_fifo_read(uint8_t *data, uint8_t len) +{ + uint8_t addr = ((1 << CC1120_READ) | + (1 << CC1120_BURST) | + CC1120_FIFO); + uint8_t status; + + ao_radio_select(); + ao_radio_duplex(&addr, &status, 1); + ao_radio_spi_recv(data, len); + ao_radio_deselect(); + return status; +} + +static uint8_t +ao_radio_fifo_write(uint8_t *data, uint8_t len) +{ + uint8_t addr = ((0 << CC1120_READ) | + (1 << CC1120_BURST) | + CC1120_FIFO); + uint8_t status; + + ao_radio_select(); + ao_radio_duplex(&addr, &status, 1); + ao_radio_spi_send(data, len); + ao_radio_deselect(); + return status; +} + +static uint8_t +ao_radio_fifo_write_fixed(uint8_t data, uint8_t len) +{ + uint8_t addr = ((0 << CC1120_READ) | + (1 << CC1120_BURST) | + CC1120_FIFO); + uint8_t status; + + ao_radio_select(); + ao_radio_duplex(&addr, &status, 1); + ao_radio_spi_send_fixed(data, len); + ao_radio_deselect(); + return status; +} + +static uint8_t +ao_radio_status(void) +{ + return ao_radio_strobe (CC1120_SNOP); +} + void ao_radio_recv_abort(void) { + ao_radio_abort = 1; + ao_wakeup(&ao_radio_done); +} + +#define ao_radio_rdf_value 0x55 + +static const uint16_t rdf_setup[] = { +}; + +void +ao_radio_rdf(uint8_t len) +{ + int i; + + ao_radio_abort = 0; + ao_radio_get(len); + ao_radio_done = 0; + for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) + ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]); + ao_radio_fifo_write_fixed(ao_radio_rdf_value, len); + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); + ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_strobe(CC1120_STX); + cli(); + while (!ao_radio_done) + ao_sleep(&ao_radio_done); + sei(); + ao_radio_set_packet(); + ao_radio_put(); +} + +void +ao_radio_rdf_abort(void) +{ +} + +static void +ao_radio_test(void) +{ + uint8_t mode = 2; + uint8_t radio_on; + ao_cmd_white(); + if (ao_cmd_lex_c != '\n') { + ao_cmd_decimal(); + mode = (uint8_t) ao_cmd_lex_u32; + } + mode++; + if ((mode & 2) && !radio_on) { +#if HAS_MONITOR + ao_monitor_disable(); +#endif +#if PACKET_HAS_SLAVE + ao_packet_slave_stop(); +#endif + ao_radio_get(0xff); + ao_radio_strobe(CC1120_STX); + radio_on = 1; + } + if (mode == 3) { + printf ("Hit a character to stop..."); flush(); + getchar(); + putchar('\n'); + } + if ((mode & 1) && radio_on) { + ao_radio_idle(); + ao_radio_put(); + radio_on = 0; +#if HAS_MONITOR + ao_monitor_enable(); +#endif + } +} + +void +ao_radio_send(void *d, uint8_t size) +{ + ao_radio_get(size); + ao_radio_done = 0; + ao_radio_fifo_write(d, size); + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); + ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_strobe(CC1120_STX); + cli(); + while (!ao_radio_done) + ao_sleep(&ao_radio_done); + sei(); + ao_radio_put(); +} + +uint8_t +ao_radio_recv(__xdata void *d, uint8_t size) +{ + /* configure interrupt pin */ + ao_radio_get(size); + ao_radio_done = 0; + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RXFIFO_THR_PKT); + ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_strobe(CC1120_SRX); + cli(); + while (!ao_radio_done && !ao_radio_abort) + ao_sleep(&ao_radio_done); + sei(); + if (ao_radio_done) + ao_radio_fifo_read(d, size); + ao_radio_put(); + return 0; +} + +static const uint16_t packet_setup[] = { +}; + +void +ao_radio_set_packet(void) +{ + int i; + + for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) + ao_radio_reg_write(packet_setup[i], packet_setup[i+1]); +} + +void +ao_radio_idle(void) +{ + for (;;) { + uint8_t state = ao_radio_strobe(CC1120_SIDLE); + if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE) + break; + } +} + +static const uint16_t radio_setup[] = { +#include "ao_cc1120_CC1120.h" +}; + +static uint8_t ao_radio_configured = 0; + +static void +ao_radio_isr(void) +{ + ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_done = 1; + ao_wakeup(&ao_radio_done); +} + +static void +ao_radio_setup(void) +{ + int i; + + for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2) + ao_radio_reg_write(radio_setup[i], radio_setup[i+1]); + + /* Disable GPIO2 pin (radio_int) */ + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_HIGHZ); + + /* Enable the EXTI interrupt for the appropriate pin */ + ao_enable_port(AO_CC1120_INT_PORT); + ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_RISING, ao_radio_isr); + + ao_radio_set_packet(); + ao_radio_configured = 1; +} + +void +ao_radio_get(uint8_t len) +{ + ao_mutex_get(&ao_radio_mutex); + if (!ao_radio_configured) + ao_radio_setup(); + ao_radio_reg_write(CC1120_PKT_LEN, len); +} + +#if CC1120_DEBUG +static char *cc1120_state_name[] = { + [CC1120_STATUS_STATE_IDLE] = "IDLE", + [CC1120_STATUS_STATE_RX] = "RX", + [CC1120_STATUS_STATE_TX] = "TX", + [CC1120_STATUS_STATE_FSTXON] = "FSTXON", + [CC1120_STATUS_STATE_CALIBRATE] = "CALIBRATE", + [CC1120_STATUS_STATE_SETTLING] = "SETTLING", + [CC1120_STATUS_STATE_RX_FIFO_ERROR] = "RX_FIFO_ERROR", + [CC1120_STATUS_STATE_TX_FIFO_ERROR] = "TX_FIFO_ERROR", +}; + +struct ao_cc1120_reg { + uint16_t addr; + char *name; +}; + +const static struct ao_cc1120_reg ao_cc1120_reg[] = { + { .addr = CC1120_IOCFG3, .name = "IOCFG3" }, + { .addr = CC1120_IOCFG2, .name = "IOCFG2" }, + { .addr = CC1120_IOCFG1, .name = "IOCFG1" }, + { .addr = CC1120_IOCFG0, .name = "IOCFG0" }, + { .addr = CC1120_SYNC3, .name = "SYNC3" }, + { .addr = CC1120_SYNC2, .name = "SYNC2" }, + { .addr = CC1120_SYNC1, .name = "SYNC1" }, + { .addr = CC1120_SYNC0, .name = "SYNC0" }, + { .addr = CC1120_SYNC_CFG1, .name = "SYNC_CFG1" }, + { .addr = CC1120_SYNC_CFG0, .name = "SYNC_CFG0" }, + { .addr = CC1120_DEVIATION_M, .name = "DEVIATION_M" }, + { .addr = CC1120_MODCFG_DEV_E, .name = "MODCFG_DEV_E" }, + { .addr = CC1120_DCFILT_CFG, .name = "DCFILT_CFG" }, + { .addr = CC1120_PREAMBLE_CFG1, .name = "PREAMBLE_CFG1" }, + { .addr = CC1120_PREAMBLE_CFG0, .name = "PREAMBLE_CFG0" }, + { .addr = CC1120_FREQ_IF_CFG, .name = "FREQ_IF_CFG" }, + { .addr = CC1120_IQIC, .name = "IQIC" }, + { .addr = CC1120_CHAN_BW, .name = "CHAN_BW" }, + { .addr = CC1120_MDMCFG1, .name = "MDMCFG1" }, + { .addr = CC1120_MDMCFG0, .name = "MDMCFG0" }, + { .addr = CC1120_DRATE2, .name = "DRATE2" }, + { .addr = CC1120_DRATE1, .name = "DRATE1" }, + { .addr = CC1120_DRATE0, .name = "DRATE0" }, + { .addr = CC1120_AGC_REF, .name = "AGC_REF" }, + { .addr = CC1120_AGC_CS_THR, .name = "AGC_CS_THR" }, + { .addr = CC1120_AGC_GAIN_ADJUST, .name = "AGC_GAIN_ADJUST" }, + { .addr = CC1120_AGC_CFG3, .name = "AGC_CFG3" }, + { .addr = CC1120_AGC_CFG2, .name = "AGC_CFG2" }, + { .addr = CC1120_AGC_CFG1, .name = "AGC_CFG1" }, + { .addr = CC1120_AGC_CFG0, .name = "AGC_CFG0" }, + { .addr = CC1120_FIFO_CFG, .name = "FIFO_CFG" }, + { .addr = CC1120_DEV_ADDR, .name = "DEV_ADDR" }, + { .addr = CC1120_SETTLING_CFG, .name = "SETTLING_CFG" }, + { .addr = CC1120_FS_CFG, .name = "FS_CFG" }, + { .addr = CC1120_WOR_CFG1, .name = "WOR_CFG1" }, + { .addr = CC1120_WOR_CFG0, .name = "WOR_CFG0" }, + { .addr = CC1120_WOR_EVENT0_MSB, .name = "WOR_EVENT0_MSB" }, + { .addr = CC1120_WOR_EVENT0_LSB, .name = "WOR_EVENT0_LSB" }, + { .addr = CC1120_PKT_CFG2, .name = "PKT_CFG2" }, + { .addr = CC1120_PKT_CFG1, .name = "PKT_CFG1" }, + { .addr = CC1120_PKT_CFG0, .name = "PKT_CFG0" }, + { .addr = CC1120_RFEND_CFG1, .name = "RFEND_CFG1" }, + { .addr = CC1120_RFEND_CFG0, .name = "RFEND_CFG0" }, + { .addr = CC1120_PA_CFG2, .name = "PA_CFG2" }, + { .addr = CC1120_PA_CFG1, .name = "PA_CFG1" }, + { .addr = CC1120_PA_CFG0, .name = "PA_CFG0" }, + { .addr = CC1120_PKT_LEN, .name = "PKT_LEN" }, + { .addr = CC1120_IF_MIX_CFG, .name = "IF_MIX_CFG" }, + { .addr = CC1120_FREQOFF_CFG, .name = "FREQOFF_CFG" }, + { .addr = CC1120_TOC_CFG, .name = "TOC_CFG" }, + { .addr = CC1120_MARC_SPARE, .name = "MARC_SPARE" }, + { .addr = CC1120_ECG_CFG, .name = "ECG_CFG" }, + { .addr = CC1120_SOFT_TX_DATA_CFG, .name = "SOFT_TX_DATA_CFG" }, + { .addr = CC1120_EXT_CTRL, .name = "EXT_CTRL" }, + { .addr = CC1120_RCCAL_FINE, .name = "RCCAL_FINE" }, + { .addr = CC1120_RCCAL_COARSE, .name = "RCCAL_COARSE" }, + { .addr = CC1120_RCCAL_OFFSET, .name = "RCCAL_OFFSET" }, + { .addr = CC1120_FREQOFF1, .name = "FREQOFF1" }, + { .addr = CC1120_FREQOFF0, .name = "FREQOFF0" }, + { .addr = CC1120_FREQ2, .name = "FREQ2" }, + { .addr = CC1120_FREQ1, .name = "FREQ1" }, + { .addr = CC1120_FREQ0, .name = "FREQ0" }, + { .addr = CC1120_IF_ADC2, .name = "IF_ADC2" }, + { .addr = CC1120_IF_ADC1, .name = "IF_ADC1" }, + { .addr = CC1120_IF_ADC0, .name = "IF_ADC0" }, + { .addr = CC1120_FS_DIG1, .name = "FS_DIG1" }, + { .addr = CC1120_FS_DIG0, .name = "FS_DIG0" }, + { .addr = CC1120_FS_CAL3, .name = "FS_CAL3" }, + { .addr = CC1120_FS_CAL2, .name = "FS_CAL2" }, + { .addr = CC1120_FS_CAL1, .name = "FS_CAL1" }, + { .addr = CC1120_FS_CAL0, .name = "FS_CAL0" }, + { .addr = CC1120_FS_CHP, .name = "FS_CHP" }, + { .addr = CC1120_FS_DIVTWO, .name = "FS_DIVTWO" }, + { .addr = CC1120_FS_DSM1, .name = "FS_DSM1" }, + { .addr = CC1120_FS_DSM0, .name = "FS_DSM0" }, + { .addr = CC1120_FS_DVC1, .name = "FS_DVC1" }, + { .addr = CC1120_FS_DVC0, .name = "FS_DVC0" }, + { .addr = CC1120_FS_LBI, .name = "FS_LBI" }, + { .addr = CC1120_FS_PFD, .name = "FS_PFD" }, + { .addr = CC1120_FS_PRE, .name = "FS_PRE" }, + { .addr = CC1120_FS_REG_DIV_CML, .name = "FS_REG_DIV_CML" }, + { .addr = CC1120_FS_SPARE, .name = "FS_SPARE" }, + { .addr = CC1120_FS_VCO4, .name = "FS_VCO4" }, + { .addr = CC1120_FS_VCO3, .name = "FS_VCO3" }, + { .addr = CC1120_FS_VCO2, .name = "FS_VCO2" }, + { .addr = CC1120_FS_VCO1, .name = "FS_VCO1" }, + { .addr = CC1120_FS_VCO0, .name = "FS_VCO0" }, + { .addr = CC1120_GBIAS6, .name = "GBIAS6" }, + { .addr = CC1120_GBIAS5, .name = "GBIAS5" }, + { .addr = CC1120_GBIAS4, .name = "GBIAS4" }, + { .addr = CC1120_GBIAS3, .name = "GBIAS3" }, + { .addr = CC1120_GBIAS2, .name = "GBIAS2" }, + { .addr = CC1120_GBIAS1, .name = "GBIAS1" }, + { .addr = CC1120_GBIAS0, .name = "GBIAS0" }, + { .addr = CC1120_IFAMP, .name = "IFAMP" }, + { .addr = CC1120_LNA, .name = "LNA" }, + { .addr = CC1120_RXMIX, .name = "RXMIX" }, + { .addr = CC1120_XOSC5, .name = "XOSC5" }, + { .addr = CC1120_XOSC4, .name = "XOSC4" }, + { .addr = CC1120_XOSC3, .name = "XOSC3" }, + { .addr = CC1120_XOSC2, .name = "XOSC2" }, + { .addr = CC1120_XOSC1, .name = "XOSC1" }, + { .addr = CC1120_XOSC0, .name = "XOSC0" }, + { .addr = CC1120_ANALOG_SPARE, .name = "ANALOG_SPARE" }, + { .addr = CC1120_PA_CFG3, .name = "PA_CFG3" }, + { .addr = CC1120_WOR_TIME1, .name = "WOR_TIME1" }, + { .addr = CC1120_WOR_TIME0, .name = "WOR_TIME0" }, + { .addr = CC1120_WOR_CAPTURE1, .name = "WOR_CAPTURE1" }, + { .addr = CC1120_WOR_CAPTURE0, .name = "WOR_CAPTURE0" }, + { .addr = CC1120_BIST, .name = "BIST" }, + { .addr = CC1120_DCFILTOFFSET_I1, .name = "DCFILTOFFSET_I1" }, + { .addr = CC1120_DCFILTOFFSET_I0, .name = "DCFILTOFFSET_I0" }, + { .addr = CC1120_DCFILTOFFSET_Q1, .name = "DCFILTOFFSET_Q1" }, + { .addr = CC1120_DCFILTOFFSET_Q0, .name = "DCFILTOFFSET_Q0" }, + { .addr = CC1120_IQIE_I1, .name = "IQIE_I1" }, + { .addr = CC1120_IQIE_I0, .name = "IQIE_I0" }, + { .addr = CC1120_IQIE_Q1, .name = "IQIE_Q1" }, + { .addr = CC1120_IQIE_Q0, .name = "IQIE_Q0" }, + { .addr = CC1120_RSSI1, .name = "RSSI1" }, + { .addr = CC1120_RSSI0, .name = "RSSI0" }, + { .addr = CC1120_MARCSTATE, .name = "MARCSTATE" }, + { .addr = CC1120_LQI_VAL, .name = "LQI_VAL" }, + { .addr = CC1120_PQT_SYNC_ERR, .name = "PQT_SYNC_ERR" }, + { .addr = CC1120_DEM_STATUS, .name = "DEM_STATUS" }, + { .addr = CC1120_FREQOFF_EST1, .name = "FREQOFF_EST1" }, + { .addr = CC1120_FREQOFF_EST0, .name = "FREQOFF_EST0" }, + { .addr = CC1120_AGC_GAIN3, .name = "AGC_GAIN3" }, + { .addr = CC1120_AGC_GAIN2, .name = "AGC_GAIN2" }, + { .addr = CC1120_AGC_GAIN1, .name = "AGC_GAIN1" }, + { .addr = CC1120_AGC_GAIN0, .name = "AGC_GAIN0" }, + { .addr = CC1120_SOFT_RX_DATA_OUT, .name = "SOFT_RX_DATA_OUT" }, + { .addr = CC1120_SOFT_TX_DATA_IN, .name = "SOFT_TX_DATA_IN" }, + { .addr = CC1120_ASK_SOFT_RX_DATA, .name = "ASK_SOFT_RX_DATA" }, + { .addr = CC1120_RNDGEN, .name = "RNDGEN" }, + { .addr = CC1120_MAGN2, .name = "MAGN2" }, + { .addr = CC1120_MAGN1, .name = "MAGN1" }, + { .addr = CC1120_MAGN0, .name = "MAGN0" }, + { .addr = CC1120_ANG1, .name = "ANG1" }, + { .addr = CC1120_ANG0, .name = "ANG0" }, + { .addr = CC1120_CHFILT_I2, .name = "CHFILT_I2" }, + { .addr = CC1120_CHFILT_I1, .name = "CHFILT_I1" }, + { .addr = CC1120_CHFILT_I0, .name = "CHFILT_I0" }, + { .addr = CC1120_CHFILT_Q2, .name = "CHFILT_Q2" }, + { .addr = CC1120_CHFILT_Q1, .name = "CHFILT_Q1" }, + { .addr = CC1120_CHFILT_Q0, .name = "CHFILT_Q0" }, + { .addr = CC1120_GPIO_STATUS, .name = "GPIO_STATUS" }, + { .addr = CC1120_FSCAL_CTRL, .name = "FSCAL_CTRL" }, + { .addr = CC1120_PHASE_ADJUST, .name = "PHASE_ADJUST" }, + { .addr = CC1120_PARTNUMBER, .name = "PARTNUMBER" }, + { .addr = CC1120_PARTVERSION, .name = "PARTVERSION" }, + { .addr = CC1120_SERIAL_STATUS, .name = "SERIAL_STATUS" }, + { .addr = CC1120_RX_STATUS, .name = "RX_STATUS" }, + { .addr = CC1120_TX_STATUS, .name = "TX_STATUS" }, + { .addr = CC1120_MARC_STATUS1, .name = "MARC_STATUS1" }, + { .addr = CC1120_MARC_STATUS0, .name = "MARC_STATUS0" }, + { .addr = CC1120_PA_IFAMP_TEST, .name = "PA_IFAMP_TEST" }, + { .addr = CC1120_FSRF_TEST, .name = "FSRF_TEST" }, + { .addr = CC1120_PRE_TEST, .name = "PRE_TEST" }, + { .addr = CC1120_PRE_OVR, .name = "PRE_OVR" }, + { .addr = CC1120_ADC_TEST, .name = "ADC_TEST" }, + { .addr = CC1120_DVC_TEST, .name = "DVC_TEST" }, + { .addr = CC1120_ATEST, .name = "ATEST" }, + { .addr = CC1120_ATEST_LVDS, .name = "ATEST_LVDS" }, + { .addr = CC1120_ATEST_MODE, .name = "ATEST_MODE" }, + { .addr = CC1120_XOSC_TEST1, .name = "XOSC_TEST1" }, + { .addr = CC1120_XOSC_TEST0, .name = "XOSC_TEST0" }, + { .addr = CC1120_RXFIRST, .name = "RXFIRST" }, + { .addr = CC1120_TXFIRST, .name = "TXFIRST" }, + { .addr = CC1120_RXLAST, .name = "RXLAST" }, + { .addr = CC1120_TXLAST, .name = "TXLAST" }, + { .addr = CC1120_NUM_TXBYTES, .name = "NUM_TXBYTES" }, + { .addr = CC1120_NUM_RXBYTES, .name = "NUM_RXBYTES" }, + { .addr = CC1120_FIFO_NUM_TXBYTES, .name = "FIFO_NUM_TXBYTES" }, + { .addr = CC1120_FIFO_NUM_RXBYTES, .name = "FIFO_NUM_RXBYTES" }, +}; + +#define AO_NUM_CC1120_REG (sizeof ao_cc1120_reg / sizeof ao_cc1120_reg[0]) + +static void ao_radio_show(void) { + uint8_t status = ao_radio_status(); + int i; + + ao_radio_get(0xff); + status = ao_radio_status(); + printf ("Status: %02x\n", status); + printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1); + printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]); + + for (i = 0; i < AO_NUM_CC1120_REG; i++) + printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name); + ao_radio_put(); +} +#endif + +static const struct ao_cmds ao_radio_cmds[] = { + { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" }, +#if CC1120_DEBUG + { ao_radio_show, "R\0Show CC1120 status" }, +#endif + { 0, NULL } +}; + +void +ao_radio_init(void) +{ + ao_radio_configured = 0; + ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN)); + + ao_cmd_register(&ao_radio_cmds[0]); } diff --git a/src/drivers/ao_cc1120.h b/src/drivers/ao_cc1120.h new file mode 100644 index 00000000..67c0a1b8 --- /dev/null +++ b/src/drivers/ao_cc1120.h @@ -0,0 +1,320 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_CC1120_H_ +#define _AO_CC1120_H_ + +#define CC1120_READ (7) +#define CC1120_BURST (6) + +/* Register space */ +#define CC1120_IOCFG3 0x00 +#define CC1120_IOCFG_GPIO_ATRAN 7 +#define CC1120_IOCFG_GPIO_INV 6 +#define CC1120_IOCFG_GPIO_CFG 0 +#define CC1120_IOCFG_GPIO_CFG_RXFIFO_THR 0 +#define CC1120_IOCFG_GPIO_CFG_RXFIFO_THR_PKT 1 +#define CC1120_IOCFG_GPIO_CFG_TXFIFO_THR 2 +#define CC1120_IOCFG_GPIO_CFG_TXFIFO_THR_PKT 3 +#define CC1120_IOCFG_GPIO_CFG_RXFIFO_OVERFLOW 4 +#define CC1120_IOCFG_GPIO_CFG_TXFIFO_UNDERFLOW 5 +#define CC1120_IOCFG_GPIO_CFG_PKT_SYNC_RXTX 6 +#define CC1120_IOCFG_GPIO_CFG_CRC_OK 7 +#define CC1120_IOCFG_GPIO_CFG_SERIAL_CLK 8 +#define CC1120_IOCFG_GPIO_CFG_SERIAL_RX 9 +#define CC1120_IOCFG_GPIO_CFG_PQT_REACHED 11 +#define CC1120_IOCFG_GPIO_CFG_PQT_VALID 12 +#define CC1120_IOCFG_GPIO_CFG_RSSI_VALID 13 +#define CC1120_IOCFG_GPIO3_CFG_RSSI_UPDATE 14 +#define CC1120_IOCFG_GPIO2_CFG_RSSI_UPDATE 14 +#define CC1120_IOCFG_GPIO1_CFG_AGC_HOLD 14 +#define CC1120_IOCFG_GPIO0_CFG_AGC_UPDATE 14 +#define CC1120_IOCFG_GPIO3_CFG_CGA_STATUS 15 +#define CC1120_IOCFG_GPIO2_CFG_TXONCCA_DONE 15 +#define CC1120_IOCFG_GPIO1_CFG_CCA_STATUS 15 +#define CC1120_IOCFG_GPIO0_CFG_TXONCCA_FAILED 15 +#define CC1120_IOCFG_GPIO_CFG_CARRIER_SENSE_VALID 16 +#define CC1120_IOCFG_GPIO_CFG_CARRIER_SENSE 17 +#define CC1120_IOCFG_GPIO3_CFG_DSSS_CLK 18 +#define CC1120_IOCFG_GPIO2_CFG_DSSS_DATA0 18 +#define CC1120_IOCFG_GPIO1_CFG_DSSS_CLK 18 +#define CC1120_IOCFG_GPIO0_CFG_DSSS_DATA1 18 +#define CC1120_IOCFG_GPIO_CFG_PKT_CRC_OK 19 +#define CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP 20 +#define CC1120_IOCFG_GPIO_CFG_SYNC_LOW0_HIGH1 21 +#define CC1120_IOCFG_GPIO_CFG_LNA_PA_REG_PD 23 +#define CC1120_IOCFG_GPIO_CFG_LNA_PD 24 +#define CC1120_IOCFG_GPIO_CFG_PA_RD 25 +#define CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG 26 +#define CC1120_IOCFG_GPIO_CFG_IMAGE_FOUND 28 +#define CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT 29 +#define CC1120_IOCFG_GPIO_CFG_SOFT_TX_DATA_CLK 30 +#define CC1120_IOCFG_GPIO_CFG_RSSI_STEP_FOUND 33 +#define CC1120_IOCFG_GPIO_CFG_RSSI_STEP_EVENT 34 +#define CC1120_IOCFG_GPIO_CFG_ANTENNA_SELECT 36 +#define CC1120_IOCFG_GPIO_CFG_MARC_2PIN_STATUS1 37 +#define CC1120_IOCFG_GPIO_CFG_MARC_2PIN_STATUS0 38 +#define CC1120_IOCFG_GPIO2_CFG_TXFIFO_OVERFLOW 39 +#define CC1120_IOCFG_GPIO0_CFG_RXFIFO_UNDERFLOW 39 +#define CC1120_IOCFG_GPIO3_CFG_MAGN_VALID 40 +#define CC1120_IOCFG_GPIO2_CFG_CHFILT_VALID 40 +#define CC1120_IOCFG_GPIO1_CFG_RCC_CAL_VALID 40 +#define CC1120_IOCFG_GPIO0_CFG_CHFILTER_STARTUP_VALID 40 +#define CC1120_IOCFG_GPIO3_CFG_COLLISION_FOUND 41 +#define CC1120_IOCFG_GPIO2_CFG_SYNC_EVENT 41 +#define CC1120_IOCFG_GPIO1_CFG_COLLISION_FOUND 41 +#define CC1120_IOCFG_GPIO0_CFG_COLLISION_EVENT 41 +#define CC1120_IOCFG_GPIO_CFG_PA_RAMP_UP 42 +#define CC1120_IOCFG_GPIO3_CFG_CRC_FAILED 43 +#define CC1120_IOCFG_GPIO2_CFG_LENGTH_FAILED 43 +#define CC1120_IOCFG_GPIO1_CFG_ADDR_FAILED 43 +#define CC1120_IOCFG_GPIO0_CFG_UART_FRAMING_ERROR 43 +#define CC1120_IOCFG_GPIO_CFG_AGC_STABLE_GAIN 44 +#define CC1120_IOCFG_GPIO_CFG_AGC_UPDATE 45 +#define CC1120_IOCFG_GPIO3_CFG_ADC_CLOCK 46 +#define CC1120_IOCFG_GPIO2_CFG_ADC_Q_DATA_SAMPLE 46 +#define CC1120_IOCFG_GPIO1_CFG_ADC_CLOCK 46 +#define CC1120_IOCFG_GPIO0_CFG_ADC_I_DATA_SAMPLE 46 +#define CC1120_IOCFG_GPIO_CFG_HIGHZ 48 +#define CC1120_IOCFG_GPIO_CFG_EXT_CLOCK 49 +#define CC1120_IOCFG_GPIO_CFG_CHIP_RDY 50 +#define CC1120_IOCFG_GPIO_CFG_HW0 51 +#define CC1120_IOCFG_GPIO_CFG_CLOCK_32K 54 +#define CC1120_IOCFG_GPIO_CFG_WOR_EVENT0 55 +#define CC1120_IOCFG_GPIO_CFG_WOR_EVENT1 56 +#define CC1120_IOCFG_GPIO_CFG_WOR_EVENT2 57 +#define CC1120_IOCFG_GPIO_CFG_XOSC_STABLE 59 +#define CC1120_IOCFG_GPIO_CFG_EXT_OSC_EN 60 +#define CC1120_IOCFG_GPIO_CFG_MASK 0x3f + +#define CC1120_IOCFG3 0x00 +#define CC1120_IOCFG2 0x01 +#define CC1120_IOCFG1 0x02 +#define CC1120_IOCFG0 0x03 +#define CC1120_SYNC3 0x04 +#define CC1120_SYNC2 0x05 +#define CC1120_SYNC1 0x06 +#define CC1120_SYNC0 0x07 +#define CC1120_SYNC_CFG1 0x08 +#define CC1120_SYNC_CFG0 0x09 +#define CC1120_DEVIATION_M 0x0a +#define CC1120_MODCFG_DEV_E 0x0b +#define CC1120_DCFILT_CFG 0x0c +#define CC1120_PREAMBLE_CFG1 0x0d +#define CC1120_PREAMBLE_CFG0 0x0e +#define CC1120_FREQ_IF_CFG 0x0f +#define CC1120_IQIC 0x10 +#define CC1120_CHAN_BW 0x11 +#define CC1120_MDMCFG1 0x12 +#define CC1120_MDMCFG0 0x13 +#define CC1120_DRATE2 0x14 +#define CC1120_DRATE1 0x15 +#define CC1120_DRATE0 0x16 +#define CC1120_AGC_REF 0x17 +#define CC1120_AGC_CS_THR 0x18 +#define CC1120_AGC_GAIN_ADJUST 0x19 +#define CC1120_AGC_CFG3 0x1a +#define CC1120_AGC_CFG2 0x1b +#define CC1120_AGC_CFG1 0x1c +#define CC1120_AGC_CFG0 0x1d +#define CC1120_FIFO_CFG 0x1e +#define CC1120_DEV_ADDR 0x1f +#define CC1120_SETTLING_CFG 0x20 +#define CC1120_FS_CFG 0x21 +#define CC1120_WOR_CFG1 0x22 +#define CC1120_WOR_CFG0 0x23 +#define CC1120_WOR_EVENT0_MSB 0x24 +#define CC1120_WOR_EVENT0_LSB 0x25 +#define CC1120_PKT_CFG2 0x26 +#define CC1120_PKT_CFG1 0x27 +#define CC1120_PKT_CFG0 0x28 +#define CC1120_RFEND_CFG1 0x29 +#define CC1120_RFEND_CFG0 0x2a +#define CC1120_PA_CFG2 0x2b +#define CC1120_PA_CFG1 0x2c +#define CC1120_PA_CFG0 0x2d +#define CC1120_PKT_LEN 0x2e + +#define CC1120_EXTENDED 0x2f + +/* Command strobes */ +#define CC1120_SRES 0x30 +#define CC1120_SFSTXON 0x31 +#define CC1120_SXOFF 0x32 +#define CC1120_SCAL 0x33 +#define CC1120_SRX 0x34 +#define CC1120_STX 0x35 +#define CC1120_SIDLE 0x36 +#define CC1120_SAFC 0x37 +#define CC1120_SWOR 0x38 +#define CC1120_SPWD 0x39 +#define CC1120_SFRX 0x3a +#define CC1120_SFTX 0x3b +#define CC1120_SWORRST 0x3c +#define CC1120_SNOP 0x3d + +#define CC1120_DIRECT_FIFO 0x3e +#define CC1120_FIFO 0x3f + +/* Extended register space */ + +#define CC1120_EXTENDED_BIT 0x8000 + +#define CC1120_IS_EXTENDED(r) ((r) & CC1120_EXTENDED_BIT) + +#define CC1120_IF_MIX_CFG (CC1120_EXTENDED_BIT | 0x00) +#define CC1120_FREQOFF_CFG (CC1120_EXTENDED_BIT | 0x01) +#define CC1120_TOC_CFG (CC1120_EXTENDED_BIT | 0x02) +#define CC1120_MARC_SPARE (CC1120_EXTENDED_BIT | 0x03) +#define CC1120_ECG_CFG (CC1120_EXTENDED_BIT | 0x04) +#define CC1120_SOFT_TX_DATA_CFG (CC1120_EXTENDED_BIT | 0x05) +#define CC1120_EXT_CTRL (CC1120_EXTENDED_BIT | 0x06) +#define CC1120_RCCAL_FINE (CC1120_EXTENDED_BIT | 0x07) +#define CC1120_RCCAL_COARSE (CC1120_EXTENDED_BIT | 0x08) +#define CC1120_RCCAL_OFFSET (CC1120_EXTENDED_BIT | 0x09) +#define CC1120_FREQOFF1 (CC1120_EXTENDED_BIT | 0x0A) +#define CC1120_FREQOFF0 (CC1120_EXTENDED_BIT | 0x0B) +#define CC1120_FREQ2 (CC1120_EXTENDED_BIT | 0x0C) +#define CC1120_FREQ1 (CC1120_EXTENDED_BIT | 0x0D) +#define CC1120_FREQ0 (CC1120_EXTENDED_BIT | 0x0E) +#define CC1120_IF_ADC2 (CC1120_EXTENDED_BIT | 0x0F) +#define CC1120_IF_ADC1 (CC1120_EXTENDED_BIT | 0x10) +#define CC1120_IF_ADC0 (CC1120_EXTENDED_BIT | 0x11) +#define CC1120_FS_DIG1 (CC1120_EXTENDED_BIT | 0x12) +#define CC1120_FS_DIG0 (CC1120_EXTENDED_BIT | 0x13) +#define CC1120_FS_CAL3 (CC1120_EXTENDED_BIT | 0x14) +#define CC1120_FS_CAL2 (CC1120_EXTENDED_BIT | 0x15) +#define CC1120_FS_CAL1 (CC1120_EXTENDED_BIT | 0x16) +#define CC1120_FS_CAL0 (CC1120_EXTENDED_BIT | 0x17) +#define CC1120_FS_CHP (CC1120_EXTENDED_BIT | 0x18) +#define CC1120_FS_DIVTWO (CC1120_EXTENDED_BIT | 0x19) +#define CC1120_FS_DSM1 (CC1120_EXTENDED_BIT | 0x1A) +#define CC1120_FS_DSM0 (CC1120_EXTENDED_BIT | 0x1B) +#define CC1120_FS_DVC1 (CC1120_EXTENDED_BIT | 0x1C) +#define CC1120_FS_DVC0 (CC1120_EXTENDED_BIT | 0x1D) +#define CC1120_FS_LBI (CC1120_EXTENDED_BIT | 0x1E) +#define CC1120_FS_PFD (CC1120_EXTENDED_BIT | 0x1F) +#define CC1120_FS_PRE (CC1120_EXTENDED_BIT | 0x20) +#define CC1120_FS_REG_DIV_CML (CC1120_EXTENDED_BIT | 0x21) +#define CC1120_FS_SPARE (CC1120_EXTENDED_BIT | 0x22) +#define CC1120_FS_VCO4 (CC1120_EXTENDED_BIT | 0x23) +#define CC1120_FS_VCO3 (CC1120_EXTENDED_BIT | 0x24) +#define CC1120_FS_VCO2 (CC1120_EXTENDED_BIT | 0x25) +#define CC1120_FS_VCO1 (CC1120_EXTENDED_BIT | 0x26) +#define CC1120_FS_VCO0 (CC1120_EXTENDED_BIT | 0x27) +#define CC1120_GBIAS6 (CC1120_EXTENDED_BIT | 0x28) +#define CC1120_GBIAS5 (CC1120_EXTENDED_BIT | 0x29) +#define CC1120_GBIAS4 (CC1120_EXTENDED_BIT | 0x2A) +#define CC1120_GBIAS3 (CC1120_EXTENDED_BIT | 0x2B) +#define CC1120_GBIAS2 (CC1120_EXTENDED_BIT | 0x2C) +#define CC1120_GBIAS1 (CC1120_EXTENDED_BIT | 0x2D) +#define CC1120_GBIAS0 (CC1120_EXTENDED_BIT | 0x2E) +#define CC1120_IFAMP (CC1120_EXTENDED_BIT | 0x2F) +#define CC1120_LNA (CC1120_EXTENDED_BIT | 0x30) +#define CC1120_RXMIX (CC1120_EXTENDED_BIT | 0x31) +#define CC1120_XOSC5 (CC1120_EXTENDED_BIT | 0x32) +#define CC1120_XOSC4 (CC1120_EXTENDED_BIT | 0x33) +#define CC1120_XOSC3 (CC1120_EXTENDED_BIT | 0x34) +#define CC1120_XOSC2 (CC1120_EXTENDED_BIT | 0x35) +#define CC1120_XOSC1 (CC1120_EXTENDED_BIT | 0x36) +#define CC1120_XOSC0 (CC1120_EXTENDED_BIT | 0x37) +#define CC1120_ANALOG_SPARE (CC1120_EXTENDED_BIT | 0x38) +#define CC1120_PA_CFG3 (CC1120_EXTENDED_BIT | 0x39) +#define CC1120_WOR_TIME1 (CC1120_EXTENDED_BIT | 0x64) +#define CC1120_WOR_TIME0 (CC1120_EXTENDED_BIT | 0x65) +#define CC1120_WOR_CAPTURE1 (CC1120_EXTENDED_BIT | 0x66) +#define CC1120_WOR_CAPTURE0 (CC1120_EXTENDED_BIT | 0x67) +#define CC1120_BIST (CC1120_EXTENDED_BIT | 0x68) +#define CC1120_DCFILTOFFSET_I1 (CC1120_EXTENDED_BIT | 0x69) +#define CC1120_DCFILTOFFSET_I0 (CC1120_EXTENDED_BIT | 0x6A) +#define CC1120_DCFILTOFFSET_Q1 (CC1120_EXTENDED_BIT | 0x6B) +#define CC1120_DCFILTOFFSET_Q0 (CC1120_EXTENDED_BIT | 0x6C) +#define CC1120_IQIE_I1 (CC1120_EXTENDED_BIT | 0x6D) +#define CC1120_IQIE_I0 (CC1120_EXTENDED_BIT | 0x6E) +#define CC1120_IQIE_Q1 (CC1120_EXTENDED_BIT | 0x6f) +#define CC1120_IQIE_Q0 (CC1120_EXTENDED_BIT | 0x70) +#define CC1120_RSSI1 (CC1120_EXTENDED_BIT | 0x71) +#define CC1120_RSSI0 (CC1120_EXTENDED_BIT | 0x72) +#define CC1120_MARCSTATE (CC1120_EXTENDED_BIT | 0x73) +#define CC1120_LQI_VAL (CC1120_EXTENDED_BIT | 0x74) +#define CC1120_PQT_SYNC_ERR (CC1120_EXTENDED_BIT | 0x75) +#define CC1120_DEM_STATUS (CC1120_EXTENDED_BIT | 0x76) +#define CC1120_FREQOFF_EST1 (CC1120_EXTENDED_BIT | 0x77) +#define CC1120_FREQOFF_EST0 (CC1120_EXTENDED_BIT | 0x78) +#define CC1120_AGC_GAIN3 (CC1120_EXTENDED_BIT | 0x79) +#define CC1120_AGC_GAIN2 (CC1120_EXTENDED_BIT | 0x7a) +#define CC1120_AGC_GAIN1 (CC1120_EXTENDED_BIT | 0x7b) +#define CC1120_AGC_GAIN0 (CC1120_EXTENDED_BIT | 0x7c) +#define CC1120_SOFT_RX_DATA_OUT (CC1120_EXTENDED_BIT | 0x7d) +#define CC1120_SOFT_TX_DATA_IN (CC1120_EXTENDED_BIT | 0x7e) +#define CC1120_ASK_SOFT_RX_DATA (CC1120_EXTENDED_BIT | 0x7f) +#define CC1120_RNDGEN (CC1120_EXTENDED_BIT | 0x80) +#define CC1120_MAGN2 (CC1120_EXTENDED_BIT | 0x81) +#define CC1120_MAGN1 (CC1120_EXTENDED_BIT | 0x82) +#define CC1120_MAGN0 (CC1120_EXTENDED_BIT | 0x83) +#define CC1120_ANG1 (CC1120_EXTENDED_BIT | 0x84) +#define CC1120_ANG0 (CC1120_EXTENDED_BIT | 0x85) +#define CC1120_CHFILT_I2 (CC1120_EXTENDED_BIT | 0x86) +#define CC1120_CHFILT_I1 (CC1120_EXTENDED_BIT | 0x87) +#define CC1120_CHFILT_I0 (CC1120_EXTENDED_BIT | 0x88) +#define CC1120_CHFILT_Q2 (CC1120_EXTENDED_BIT | 0x89) +#define CC1120_CHFILT_Q1 (CC1120_EXTENDED_BIT | 0x8a) +#define CC1120_CHFILT_Q0 (CC1120_EXTENDED_BIT | 0x8b) +#define CC1120_GPIO_STATUS (CC1120_EXTENDED_BIT | 0x8c) +#define CC1120_FSCAL_CTRL (CC1120_EXTENDED_BIT | 0x8d) +#define CC1120_PHASE_ADJUST (CC1120_EXTENDED_BIT | 0x8e) +#define CC1120_PARTNUMBER (CC1120_EXTENDED_BIT | 0x8f) +#define CC1120_PARTVERSION (CC1120_EXTENDED_BIT | 0x90) +#define CC1120_SERIAL_STATUS (CC1120_EXTENDED_BIT | 0x91) +#define CC1120_RX_STATUS (CC1120_EXTENDED_BIT | 0x92) +#define CC1120_TX_STATUS (CC1120_EXTENDED_BIT | 0x93) +#define CC1120_MARC_STATUS1 (CC1120_EXTENDED_BIT | 0x94) +#define CC1120_MARC_STATUS0 (CC1120_EXTENDED_BIT | 0x95) +#define CC1120_PA_IFAMP_TEST (CC1120_EXTENDED_BIT | 0x96) +#define CC1120_FSRF_TEST (CC1120_EXTENDED_BIT | 0x97) +#define CC1120_PRE_TEST (CC1120_EXTENDED_BIT | 0x98) +#define CC1120_PRE_OVR (CC1120_EXTENDED_BIT | 0x99) +#define CC1120_ADC_TEST (CC1120_EXTENDED_BIT | 0x9a) +#define CC1120_DVC_TEST (CC1120_EXTENDED_BIT | 0x9b) +#define CC1120_ATEST (CC1120_EXTENDED_BIT | 0x9c) +#define CC1120_ATEST_LVDS (CC1120_EXTENDED_BIT | 0x9d) +#define CC1120_ATEST_MODE (CC1120_EXTENDED_BIT | 0x9e) +#define CC1120_XOSC_TEST1 (CC1120_EXTENDED_BIT | 0x9f) +#define CC1120_XOSC_TEST0 (CC1120_EXTENDED_BIT | 0xa0) +#define CC1120_RXFIRST (CC1120_EXTENDED_BIT | 0xd2) +#define CC1120_TXFIRST (CC1120_EXTENDED_BIT | 0xd3) +#define CC1120_RXLAST (CC1120_EXTENDED_BIT | 0xd4) +#define CC1120_TXLAST (CC1120_EXTENDED_BIT | 0xd5) +#define CC1120_NUM_TXBYTES (CC1120_EXTENDED_BIT | 0xd6) +#define CC1120_NUM_RXBYTES (CC1120_EXTENDED_BIT | 0xd7) +#define CC1120_FIFO_NUM_TXBYTES (CC1120_EXTENDED_BIT | 0xd8) +#define CC1120_FIFO_NUM_RXBYTES (CC1120_EXTENDED_BIT | 0xd9) + +/* Status byte */ +#define CC1120_STATUS_CHIP_RDY 7 +#define CC1120_STATUS_STATE 4 +#define CC1120_STATUS_STATE_IDLE 0 +#define CC1120_STATUS_STATE_RX 1 +#define CC1120_STATUS_STATE_TX 2 +#define CC1120_STATUS_STATE_FSTXON 3 +#define CC1120_STATUS_STATE_CALIBRATE 4 +#define CC1120_STATUS_STATE_SETTLING 5 +#define CC1120_STATUS_STATE_RX_FIFO_ERROR 6 +#define CC1120_STATUS_STATE_TX_FIFO_ERROR 7 +#define CC1120_STATUS_STATE_MASK 7 + +#endif /* _AO_CC1120_H_ */ diff --git a/src/drivers/ao_cc1120_CC1120.h b/src/drivers/ao_cc1120_CC1120.h new file mode 100644 index 00000000..a96c22fc --- /dev/null +++ b/src/drivers/ao_cc1120_CC1120.h @@ -0,0 +1,191 @@ +/* RX filter BW = 100.000000 */ +/* Address config = No address check */ +/* Packet length = 255 */ +/* Symbol rate = 38.3606 */ +/* PA ramping = false */ +/* Carrier frequency = 434.549988 */ +/* Bit rate = 38.3606 */ +/* Whitening = true */ +/* Manchester enable = false */ +/* Modulation format = 2-GFSK */ +/* Packet length mode = Variable */ +/* Device address = 0 */ +/* TX power = 15 */ +/* Deviation = 20.507812 */ +/*************************************************************** + * SmartRF Studio(tm) Export + * + * Radio register settings specifed with address, value + * + * RF device: CC1120 + * + ***************************************************************/ + + + CC1120_SYNC3, 0x93, /* Sync Word Configuration [31:24] */ + CC1120_SYNC2, 0x0b, /* Sync Word Configuration [23:16] */ + CC1120_SYNC1, 0x51, /* Sync Word Configuration [15:8] */ + CC1120_SYNC0, 0xde, /* Sync Word Configuration [7:0] */ + CC1120_SYNC_CFG1, 0x08, /* Sync Word Detection Configuration */ + CC1120_SYNC_CFG0, 0x17, /* Sync Word Length Configuration */ + CC1120_DEVIATION_M, 0x50, /* Frequency Deviation Configuration */ + CC1120_MODCFG_DEV_E, 0x0d, /* Modulation Format and Frequency Deviation Configuration */ + CC1120_DCFILT_CFG, 0x1c, /* Digital DC Removal Configuration */ + CC1120_PREAMBLE_CFG1, 0x18, /* Preamble Length Configuration */ + CC1120_PREAMBLE_CFG0, 0x2a, /* */ + CC1120_FREQ_IF_CFG, 0x40, /* RX Mixer Frequency Configuration */ + CC1120_IQIC, 0x46, /* Digital Image Channel Compensation Configuration */ + CC1120_CHAN_BW, 0x02, /* Channel Filter Configuration */ + CC1120_MDMCFG1, 0x46, /* General Modem Parameter Configuration */ + CC1120_MDMCFG0, 0x05, /* General Modem Parameter Configuration */ + CC1120_DRATE2, 0x93, /* Data Rate Configuration Exponent and Mantissa [19:16] */ + CC1120_DRATE1, 0xa4, /* Data Rate Configuration Mantissa [15:8] */ + CC1120_DRATE0, 0x00, /* Data Rate Configuration Mantissa [7:0] */ + CC1120_AGC_REF, 0x20, /* AGC Reference Level Configuration */ + CC1120_AGC_CS_THR, 0x19, /* Carrier Sense Threshold Configuration */ + CC1120_AGC_GAIN_ADJUST, 0x00, /* RSSI Offset Configuration */ + CC1120_AGC_CFG3, 0x91, /* AGC Configuration */ + CC1120_AGC_CFG2, 0x20, /* AGC Configuration */ + CC1120_AGC_CFG1, 0xa9, /* AGC Configuration */ + CC1120_AGC_CFG0, 0xcf, /* AGC Configuration */ + CC1120_FIFO_CFG, 0x00, /* FIFO Configuration */ + CC1120_DEV_ADDR, 0x00, /* Device Address Configuration */ + CC1120_SETTLING_CFG, 0x03, /* Frequency Synthesizer Calibration and Settling Configuration */ + CC1120_FS_CFG, 0x14, /* Frequency Synthesizer Configuration */ + CC1120_WOR_CFG1, 0x08, /* eWOR Configuration, Reg 1 */ + CC1120_WOR_CFG0, 0x21, /* eWOR Configuration, Reg 0 */ + CC1120_WOR_EVENT0_MSB, 0x00, /* Event 0 Configuration */ + CC1120_WOR_EVENT0_LSB, 0x00, /* Event 0 Configuration */ + CC1120_PKT_CFG2, 0x04, /* Packet Configuration, Reg 2 */ + CC1120_PKT_CFG1, 0x45, /* Packet Configuration, Reg 1 */ + CC1120_PKT_CFG0, 0x20, /* Packet Configuration, Reg 0 */ + CC1120_RFEND_CFG1, 0x0f, /* RFEND Configuration, Reg 1 */ + CC1120_RFEND_CFG0, 0x00, /* RFEND Configuration, Reg 0 */ + CC1120_PA_CFG2, 0x3f, /* Power Amplifier Configuration, Reg 2 */ + CC1120_PA_CFG1, 0x56, /* Power Amplifier Configuration, Reg 1 */ + CC1120_PA_CFG0, 0x7b, /* Power Amplifier Configuration, Reg 0 */ + CC1120_PKT_LEN, 0xff, /* Packet Length Configuration */ + CC1120_IF_MIX_CFG, 0x00, /* IF Mix Configuration */ + CC1120_FREQOFF_CFG, 0x22, /* Frequency Offset Correction Configuration */ + CC1120_TOC_CFG, 0x0b, /* Timing Offset Correction Configuration */ + CC1120_MARC_SPARE, 0x00, /* MARC Spare */ + CC1120_ECG_CFG, 0x00, /* External Clock Frequency Configuration */ + CC1120_SOFT_TX_DATA_CFG, 0x00, /* Soft TX Data Configuration */ + CC1120_EXT_CTRL, 0x01, /* External Control Configuration */ + CC1120_RCCAL_FINE, 0x00, /* RC Oscillator Calibration (fine) */ + CC1120_RCCAL_COARSE, 0x00, /* RC Oscillator Calibration (coarse) */ + CC1120_RCCAL_OFFSET, 0x00, /* RC Oscillator Calibration Clock Offset */ + CC1120_FREQOFF1, 0x00, /* Frequency Offset (MSB) */ + CC1120_FREQOFF0, 0x00, /* Frequency Offset (LSB) */ + CC1120_FREQ2, 0x6c, /* Frequency Configuration [23:16] */ + CC1120_FREQ1, 0xa3, /* Frequency Configuration [15:8] */ + CC1120_FREQ0, 0x33, /* Frequency Configuration [7:0] */ + CC1120_IF_ADC2, 0x02, /* Analog to Digital Converter Configuration, Reg 2 */ + CC1120_IF_ADC1, 0xa6, /* Analog to Digital Converter Configuration, Reg 1 */ + CC1120_IF_ADC0, 0x04, /* Analog to Digital Converter Configuration, Reg 0 */ + CC1120_FS_DIG1, 0x00, /* */ + CC1120_FS_DIG0, 0x5f, /* */ + CC1120_FS_CAL3, 0x00, /* */ + CC1120_FS_CAL2, 0x20, /* */ + CC1120_FS_CAL1, 0x40, /* */ + CC1120_FS_CAL0, 0x0e, /* */ + CC1120_FS_CHP, 0x28, /* Charge Pump Configuration */ + CC1120_FS_DIVTWO, 0x03, /* Divide by 2 */ + CC1120_FS_DSM1, 0x00, /* Digital Synthesizer Module Configuration, Reg 1 */ + CC1120_FS_DSM0, 0x33, /* Digital Synthesizer Module Configuration, Reg 0 */ + CC1120_FS_DVC1, 0xff, /* Divider Chain Configuration, Reg 1 */ + CC1120_FS_DVC0, 0x17, /* Divider Chain Configuration, Reg 0 */ + CC1120_FS_LBI, 0x00, /* Local Bias Configuration */ + CC1120_FS_PFD, 0x50, /* Phase Frequency Detector Configuration */ + CC1120_FS_PRE, 0x6e, /* Prescaler Configuration */ + CC1120_FS_REG_DIV_CML, 0x14, /* */ + CC1120_FS_SPARE, 0xac, /* */ + CC1120_FS_VCO4, 0x14, /* VCO Configuration, Reg 4 */ + CC1120_FS_VCO3, 0x00, /* VCO Configuration, Reg 3 */ + CC1120_FS_VCO2, 0x00, /* VCO Configuration, Reg 2 */ + CC1120_FS_VCO1, 0x00, /* VCO Configuration, Reg 1 */ + CC1120_FS_VCO0, 0xb4, /* VCO Configuration, Reg 0 */ + CC1120_GBIAS6, 0x00, /* Global Bias Configuration, Reg 6 */ + CC1120_GBIAS5, 0x02, /* Global Bias Configuration, Reg 5 */ + CC1120_GBIAS4, 0x00, /* Global Bias Configuration, Reg 4 */ + CC1120_GBIAS3, 0x00, /* Global Bias Configuration, Reg 3 */ + CC1120_GBIAS2, 0x10, /* Global Bias Configuration, Reg 2 */ + CC1120_GBIAS1, 0x00, /* Global Bias Configuration, Reg 1 */ + CC1120_GBIAS0, 0x00, /* Global Bias Configuration, Reg 0 */ + CC1120_IFAMP, 0x01, /* Intermediate Frequency Amplifier Configuration */ + CC1120_LNA, 0x01, /* Low Noise Amplifier Configuration */ + CC1120_RXMIX, 0x01, /* RX Mixer Configuration */ + CC1120_XOSC5, 0x0e, /* Crystal Oscillator Configuration, Reg 5 */ + CC1120_XOSC4, 0xa0, /* Crystal Oscillator Configuration, Reg 4 */ + CC1120_XOSC3, 0x03, /* Crystal Oscillator Configuration, Reg 3 */ + CC1120_XOSC2, 0x04, /* Crystal Oscillator Configuration, Reg 2 */ + CC1120_XOSC1, 0x01, /* Crystal Oscillator Configuration, Reg 1 */ + CC1120_XOSC0, 0x00, /* Crystal Oscillator Configuration, Reg 0 */ + CC1120_ANALOG_SPARE, 0x00, /* */ + CC1120_PA_CFG3, 0x00, /* Power Amplifier Configuration, Reg 3 */ + CC1120_WOR_TIME1, 0x00, /* eWOR Timer Status (MSB) */ + CC1120_WOR_TIME0, 0x00, /* eWOR Timer Status (LSB) */ + CC1120_WOR_CAPTURE1, 0x00, /* eWOR Timer Capture (MSB) */ + CC1120_WOR_CAPTURE0, 0x00, /* eWOR Timer Capture (LSB) */ + CC1120_BIST, 0x00, /* MARC BIST */ + CC1120_DCFILTOFFSET_I1, 0x00, /* DC Filter Offset I (MSB) */ + CC1120_DCFILTOFFSET_I0, 0x00, /* DC Filter Offset I (LSB) */ + CC1120_DCFILTOFFSET_Q1, 0x00, /* DC Filter Offset Q (MSB) */ + CC1120_DCFILTOFFSET_Q0, 0x00, /* DC Filter Offset Q (LSB) */ + CC1120_IQIE_I1, 0x00, /* IQ Imbalance Value I (MSB) */ + CC1120_IQIE_I0, 0x00, /* IQ Imbalance Value I (LSB) */ + CC1120_IQIE_Q1, 0x00, /* IQ Imbalance Value Q (MSB) */ + CC1120_IQIE_Q0, 0x00, /* IQ Imbalance Value Q (LSB) */ + CC1120_RSSI1, 0x80, /* Received Signal Strength Indicator (MSB) */ + CC1120_RSSI0, 0x00, /* Received Signal Strength Indicator (LSB) */ + CC1120_MARCSTATE, 0x41, /* MARC State */ + CC1120_LQI_VAL, 0x00, /* Link Quality Indicator Value */ + CC1120_PQT_SYNC_ERR, 0xff, /* Preamble and Sync Word Error */ + CC1120_DEM_STATUS, 0x00, /* Demodulator Status */ + CC1120_FREQOFF_EST1, 0x00, /* Frequency Offset Estimate (MSB) */ + CC1120_FREQOFF_EST0, 0x00, /* Frequency Offset Estimate (LSB) */ + CC1120_AGC_GAIN3, 0x00, /* AGC Gain, Reg 3 */ + CC1120_AGC_GAIN2, 0xd1, /* AGC Gain, Reg 2 */ + CC1120_AGC_GAIN1, 0x00, /* AGC Gain, Reg 1 */ + CC1120_AGC_GAIN0, 0x3f, /* AGC Gain, Reg 0 */ + CC1120_SOFT_RX_DATA_OUT, 0x00, /* Soft Decision Symbol Data */ + CC1120_SOFT_TX_DATA_IN, 0x00, /* Soft TX Data Input Register */ + CC1120_ASK_SOFT_RX_DATA, 0x30, /* AGC ASK Soft Decision Output */ + CC1120_RNDGEN, 0x7f, /* Random Number Value */ + CC1120_MAGN2, 0x00, /* Signal Magnitude after CORDIC [16] */ + CC1120_MAGN1, 0x00, /* Signal Magnitude after CORDIC [15:8] */ + CC1120_MAGN0, 0x00, /* Signal Magnitude after CORDIC [7:0] */ + CC1120_ANG1, 0x00, /* Signal Angular after CORDIC [9:8] */ + CC1120_ANG0, 0x00, /* Signal Angular after CORDIC [7:0] */ + CC1120_CHFILT_I2, 0x08, /* Channel Filter Data Real Part [18:16] */ + CC1120_CHFILT_I1, 0x00, /* Channel Filter Data Real Part [15:8] */ + CC1120_CHFILT_I0, 0x00, /* Channel Filter Data Real Part [7:0] */ + CC1120_CHFILT_Q2, 0x00, /* Channel Filter Data Imaginary Part [18:16] */ + CC1120_CHFILT_Q1, 0x00, /* Channel Filter Data Imaginary Part [15:8] */ + CC1120_CHFILT_Q0, 0x00, /* Channel Filter Data Imaginary Part [7:0] */ + CC1120_GPIO_STATUS, 0x00, /* GPIO Status */ + CC1120_FSCAL_CTRL, 0x01, /* */ + CC1120_PHASE_ADJUST, 0x00, /* */ + CC1120_PARTNUMBER, 0x00, /* Part Number */ + CC1120_PARTVERSION, 0x00, /* Part Revision */ + CC1120_SERIAL_STATUS, 0x00, /* Serial Status */ + CC1120_RX_STATUS, 0x01, /* RX Status */ + CC1120_TX_STATUS, 0x00, /* TX Status */ + CC1120_MARC_STATUS1, 0x00, /* MARC Status, Reg 1 */ + CC1120_MARC_STATUS0, 0x00, /* MARC Status, Reg 0 */ + CC1120_PA_IFAMP_TEST, 0x00, /* */ + CC1120_FSRF_TEST, 0x00, /* */ + CC1120_PRE_TEST, 0x00, /* */ + CC1120_PRE_OVR, 0x00, /* */ + CC1120_ADC_TEST, 0x00, /* ADC Test */ + CC1120_DVC_TEST, 0x0b, /* DVC Test */ + CC1120_ATEST, 0x40, /* */ + CC1120_ATEST_LVDS, 0x00, /* */ + CC1120_ATEST_MODE, 0x00, /* */ + CC1120_XOSC_TEST1, 0x3c, /* */ + CC1120_XOSC_TEST0, 0x00, /* */ + CC1120_RXFIRST, 0x00, /* RX FIFO Pointer (first entry) */ + CC1120_TXFIRST, 0x00, /* TX FIFO Pointer (first entry) */ + CC1120_RXLAST, 0x00, /* RX FIFO Pointer (last entry) */ + CC1120_TXLAST, 0x00, /* TX FIFO Pointer (last entry) */ + diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c new file mode 100644 index 00000000..19fe0558 --- /dev/null +++ b/src/drivers/ao_packet.c @@ -0,0 +1,163 @@ +/* + * 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" + +__xdata struct ao_packet_recv ao_rx_packet; +__xdata struct ao_packet ao_tx_packet; +__pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; + +static __xdata char tx_data[AO_PACKET_MAX]; +static __xdata char rx_data[AO_PACKET_MAX]; +static __pdata uint8_t rx_seq; + +__xdata struct ao_task ao_packet_task; +__xdata uint8_t ao_packet_enable; +__xdata uint8_t ao_packet_master_sleeping; + +void +ao_packet_send(void) +{ +#ifdef AO_LED_RED + ao_led_on(AO_LED_RED); +#endif + /* If any tx data is pending then copy it into the tx packet */ + if (ao_packet_tx_used && ao_tx_packet.len == 0) { + ao_xmemcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); + ao_tx_packet.len = ao_packet_tx_used; + ao_tx_packet.seq++; + ao_packet_tx_used = 0; + ao_wakeup(&tx_data); + } + ao_radio_send(&ao_tx_packet, sizeof (ao_tx_packet)); +#ifdef AO_LED_RED + ao_led_off(AO_LED_RED); +#endif +} + +uint8_t +ao_packet_recv(void) +{ + uint8_t dma_done; + +#ifdef AO_LED_GREEN + ao_led_on(AO_LED_GREEN); +#endif + dma_done = ao_radio_recv(&ao_rx_packet, sizeof (struct ao_packet_recv)); +#ifdef AO_LED_GREEN + ao_led_off(AO_LED_GREEN); +#endif + + /* Check to see if we got a valid packet */ + if (!dma_done) + return 0; +#ifdef PKT_APPEND_STATUS_1_CRC_OK + if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) + return 0; +#endif + + /* Accept packets with matching call signs, or any packet if + * our callsign hasn't been configured + */ + if (ao_xmemcmp(ao_rx_packet.packet.callsign, + ao_config.callsign, + AO_MAX_CALLSIGN) != 0 && + ao_xmemcmp(ao_config.callsign, CODE_TO_XDATA("N0CALL"), 7) != 0) + return 0; + + /* SYN packets carry no data */ + if (ao_rx_packet.packet.len == AO_PACKET_SYN) { + rx_seq = ao_rx_packet.packet.seq; + ao_tx_packet.seq = ao_rx_packet.packet.ack; + ao_tx_packet.ack = rx_seq; + } else if (ao_rx_packet.packet.len) { + + /* Check for incoming data at the next sequence and + * for an empty data buffer + */ + if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) && + ao_packet_rx_used == ao_packet_rx_len) { + + /* Copy data to the receive data buffer and set up the + * offsets + */ + ao_xmemcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); + ao_packet_rx_used = 0; + ao_packet_rx_len = ao_rx_packet.packet.len; + + /* Mark the sequence that we've received to + * let the sender know when we return a packet + */ + rx_seq = ao_rx_packet.packet.seq; + ao_tx_packet.ack = rx_seq; + + /* Poke anyone looking for received data */ + ao_wakeup(&ao_stdin_ready); + } + } + + /* If the other side has seen the latest data we queued, + * wake up any task waiting to send data and let them go again + */ + if (ao_rx_packet.packet.ack == ao_tx_packet.seq) { + ao_tx_packet.len = 0; + ao_wakeup(&ao_tx_packet); + } + return 1; +} + +#ifndef PACKET_HAS_MASTER +#define PACKET_HAS_MASTER 1 +#endif + +#if PACKET_HAS_MASTER +void +ao_packet_flush(void) +{ + /* If there is data to send, and this is the master, + * then poke the master to send all queued data + */ + if (ao_packet_tx_used && ao_packet_master_sleeping) + ao_wakeup(&ao_packet_master_sleeping); +} +#endif /* PACKET_HAS_MASTER */ + +void +ao_packet_putchar(char c) __reentrant +{ + while (ao_packet_tx_used == AO_PACKET_MAX && ao_packet_enable) { +#if PACKET_HAS_MASTER + ao_packet_flush(); +#endif + ao_sleep(&tx_data); + } + + if (ao_packet_enable) + tx_data[ao_packet_tx_used++] = c; +} + +char +ao_packet_pollchar(void) __critical +{ + if (!ao_packet_enable) + return AO_READ_AGAIN; + + if (ao_packet_rx_used == ao_packet_rx_len) + return AO_READ_AGAIN; + + return rx_data[ao_packet_rx_used++]; +} diff --git a/src/drivers/ao_packet_master.c b/src/drivers/ao_packet_master.c new file mode 100644 index 00000000..66f94288 --- /dev/null +++ b/src/drivers/ao_packet_master.c @@ -0,0 +1,151 @@ +/* + * 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" + +static char +ao_packet_getchar(void) __critical +{ + char c; + while ((c = ao_packet_pollchar()) == AO_READ_AGAIN) { + if (!ao_packet_enable) + break; + if (ao_packet_master_sleeping) + ao_wakeup(&ao_packet_master_sleeping); + flush(); + ao_sleep(&ao_stdin_ready); + } + return c; +} + +static void +ao_packet_echo(void) __reentrant +{ + char c; + while (ao_packet_enable) { + c = ao_packet_getchar(); + if (c != AO_READ_AGAIN) + putchar(c); + } + ao_exit(); +} + +static __xdata struct ao_task ao_packet_echo_task; +static __xdata uint16_t ao_packet_master_delay; +static __xdata uint16_t ao_packet_master_time; + +#define AO_PACKET_MASTER_DELAY_SHORT AO_MS_TO_TICKS(100) +#define AO_PACKET_MASTER_DELAY_LONG AO_MS_TO_TICKS(1000) +#define AO_PACKET_MASTER_DELAY_TIMEOUT AO_MS_TO_TICKS(2000) + +static void +ao_packet_master_busy(void) +{ + ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; + ao_packet_master_time = ao_time(); +} + +static void +ao_packet_master_check_busy(void) +{ + int16_t idle; + if (ao_packet_master_delay != AO_PACKET_MASTER_DELAY_SHORT) + return; + idle = (int16_t) (ao_time() - ao_packet_master_time); + + if (idle > AO_PACKET_MASTER_DELAY_TIMEOUT) + ao_packet_master_delay = AO_PACKET_MASTER_DELAY_LONG; +} + +void +ao_packet_master(void) +{ + ao_config_get(); + ao_tx_packet.addr = ao_serial_number; + ao_tx_packet.len = AO_PACKET_SYN; + ao_packet_master_time = ao_time(); + ao_packet_master_delay = AO_PACKET_MASTER_DELAY_SHORT; + while (ao_packet_enable) { + uint8_t r; + ao_xmemcpy(ao_tx_packet.callsign, ao_config.callsign, AO_MAX_CALLSIGN); + ao_packet_send(); + if (ao_tx_packet.len) + ao_packet_master_busy(); + ao_packet_master_check_busy(); + ao_alarm(ao_packet_master_delay); + r = ao_packet_recv(); + ao_clear_alarm(); + if (r) { + /* if we can transmit data, do so */ + if (ao_packet_tx_used && ao_tx_packet.len == 0) + continue; + if (ao_rx_packet.packet.len) + ao_packet_master_busy(); + ao_packet_master_sleeping = 1; + ao_alarm(ao_packet_master_delay); + ao_sleep(&ao_packet_master_sleeping); + ao_clear_alarm(); + ao_packet_master_sleeping = 0; + } + } + ao_exit(); +} + +static void +ao_packet_forward(void) __reentrant +{ + char c; + ao_packet_enable = 1; + ao_cmd_white(); + + flush(); +#if HAS_MONITOR + ao_monitor_disable(); +#endif + ao_add_task(&ao_packet_task, ao_packet_master, "master"); + ao_add_task(&ao_packet_echo_task, ao_packet_echo, "echo"); + while ((c = getchar()) != '~') { + if (c == '\r') c = '\n'; + ao_packet_putchar(c); + } + + /* Wait for a second if there is any pending data */ + for (c = 0; (ao_packet_tx_used || ao_tx_packet.len) && c < 10; c++) + ao_delay(AO_MS_TO_TICKS(100)); + ao_packet_enable = 0; + while (ao_packet_echo_task.wchan || ao_packet_task.wchan) { + ao_radio_recv_abort(); + ao_wakeup(&ao_stdin_ready); + ao_delay(AO_MS_TO_TICKS(10)); + } +#if HAS_MONITOR + ao_monitor_enable(); +#endif +} + + + +__code struct ao_cmds ao_packet_master_cmds[] = { + { ao_packet_forward, "p\0Remote packet link." }, + { 0, NULL }, +}; + +void +ao_packet_master_init(void) +{ + ao_cmd_register(&ao_packet_master_cmds[0]); +} diff --git a/src/drivers/ao_packet_slave.c b/src/drivers/ao_packet_slave.c new file mode 100644 index 00000000..fd5d443e --- /dev/null +++ b/src/drivers/ao_packet_slave.c @@ -0,0 +1,66 @@ +/* + * 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_packet_slave(void) +{ + ao_tx_packet.addr = ao_serial_number; + ao_tx_packet.len = AO_PACKET_SYN; + while (ao_packet_enable) { + if (ao_packet_recv()) { + ao_xmemcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN); +#if HAS_FLIGHT + ao_flight_force_idle = TRUE; +#endif + ao_packet_send(); + } + } + ao_exit(); +} + +void +ao_packet_slave_start(void) +{ + if (!ao_packet_enable) { + ao_packet_enable = 1; + ao_add_task(&ao_packet_task, ao_packet_slave, "slave"); + } +} + +void +ao_packet_slave_stop(void) +{ + if (ao_packet_enable) { + ao_packet_enable = 0; + while (ao_packet_task.wchan) { + ao_radio_recv_abort(); + ao_delay(AO_MS_TO_TICKS(10)); + } + } +} + +void +ao_packet_slave_init(uint8_t enable) +{ + ao_add_stdio(ao_packet_pollchar, + ao_packet_putchar, + NULL); + if (enable) + ao_packet_slave_start(); +} diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 3c3d7173..37832d16 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -41,7 +41,10 @@ ALTOS_SRC = \ ao_beep_stm.c \ ao_storage.c \ ao_m25.c \ - ao_usb_stm.c + ao_usb_stm.c \ + ao_exti_stm.c \ + ao_packet.c \ + ao_packet_slave.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 9efde598..d93480f2 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -15,7 +15,8 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" +#include +#include void beep(void) @@ -51,6 +52,8 @@ main(void) ao_adc_init(); ao_storage_init(); ao_usb_init(); + ao_exti_init(); + ao_radio_init(); ao_cmd_register(&ao_mm_cmds[0]); ao_start_scheduler(); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index f761e5c3..2e83de8a 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -193,4 +193,17 @@ struct ao_adc { #define AO_M25_SPI_CS_MASK (1 << 3) #define AO_M25_SPI_BUS STM_SPI_INDEX(2) +/* + * Radio (cc1120) + */ + +#define AO_CC1120_SPI_CS_PORT stm_gpioc +#define AO_CC1120_SPI_CS_PIN 5 +#define AO_CC1120_SPI_BUS STM_SPI_INDEX(2) + +#define AO_CC1120_INT_PORT stm_gpioc +#define AO_CC1120_INT_PIN 14 + +#define AO_CC1120_INT_GPIO 2 + #endif /* _AO_PINS_H_ */ diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index 76962a3e..3edfa41d 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -16,7 +16,7 @@ ifndef VERSION include ../Version endif -AO_CFLAGS=-I. -I../stm -I../core -I.. +AO_CFLAGS=-I. -I../stm -I../core -I../drivers -I.. STM_CFLAGS=-std=gnu99 -mlittle-endian -mcpu=cortex-m3 -mthumb -ffreestanding -nostdlib $(AO_CFLAGS) $(SAT_CFLAGS) LDFLAGS=-L../stm -Wl,-Taltos.ld diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 309937d5..05bb7784 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -31,9 +31,15 @@ ao_spi_put(uint8_t spi_index); void ao_spi_send(void *block, uint16_t len, uint8_t spi_index); +void +ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index); + void ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); +void +ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index); + void ao_spi_init(void); @@ -47,7 +53,7 @@ ao_spi_init(void); ao_spi_put(bus); \ } while (0) -#define ao_stm_enable_port(port) do { \ +#define ao_enable_port(port) do { \ if (&(port) == &stm_gpioa) \ stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); \ else if (&(port) == &stm_gpiob) \ @@ -61,29 +67,29 @@ ao_spi_init(void); } while (0) -#define ao_stm_enable_cs(port,bit) do { \ +#define ao_enable_cs(port,bit) do { \ stm_gpio_set(&(port), bit, 1); \ stm_moder_set(&(port), bit, STM_MODER_OUTPUT); \ } while (0) #define ao_spi_init_cs(port, mask) do { \ - ao_stm_enable_port(port); \ - if (mask & 0x0001) ao_stm_enable_cs(port, 0); \ - if (mask & 0x0002) ao_stm_enable_cs(port, 1); \ - if (mask & 0x0004) ao_stm_enable_cs(port, 2); \ - if (mask & 0x0008) ao_stm_enable_cs(port, 3); \ - if (mask & 0x0010) ao_stm_enable_cs(port, 4); \ - if (mask & 0x0020) ao_stm_enable_cs(port, 5); \ - if (mask & 0x0040) ao_stm_enable_cs(port, 6); \ - if (mask & 0x0080) ao_stm_enable_cs(port, 7); \ - if (mask & 0x0100) ao_stm_enable_cs(port, 8); \ - if (mask & 0x0200) ao_stm_enable_cs(port, 9); \ - if (mask & 0x0400) ao_stm_enable_cs(port, 10); \ - if (mask & 0x0800) ao_stm_enable_cs(port, 11); \ - if (mask & 0x1000) ao_stm_enable_cs(port, 12); \ - if (mask & 0x2000) ao_stm_enable_cs(port, 13); \ - if (mask & 0x4000) ao_stm_enable_cs(port, 14); \ - if (mask & 0x8000) ao_stm_enable_cs(port, 15); \ + ao_enable_port(port); \ + if ((mask) & 0x0001) ao_enable_cs(port, 0); \ + if ((mask) & 0x0002) ao_enable_cs(port, 1); \ + if ((mask) & 0x0004) ao_enable_cs(port, 2); \ + if ((mask) & 0x0008) ao_enable_cs(port, 3); \ + if ((mask) & 0x0010) ao_enable_cs(port, 4); \ + if ((mask) & 0x0020) ao_enable_cs(port, 5); \ + if ((mask) & 0x0040) ao_enable_cs(port, 6); \ + if ((mask) & 0x0080) ao_enable_cs(port, 7); \ + if ((mask) & 0x0100) ao_enable_cs(port, 8); \ + if ((mask) & 0x0200) ao_enable_cs(port, 9); \ + if ((mask) & 0x0400) ao_enable_cs(port, 10);\ + if ((mask) & 0x0800) ao_enable_cs(port, 11);\ + if ((mask) & 0x1000) ao_enable_cs(port, 12);\ + if ((mask) & 0x2000) ao_enable_cs(port, 13);\ + if ((mask) & 0x4000) ao_enable_cs(port, 14);\ + if ((mask) & 0x8000) ao_enable_cs(port, 15);\ } while (0) /* ao_dma_stm.c diff --git a/src/stm/ao_dma_stm.c b/src/stm/ao_dma_stm.c index 21390748..e76c8e8c 100644 --- a/src/stm/ao_dma_stm.c +++ b/src/stm/ao_dma_stm.c @@ -109,6 +109,7 @@ void ao_dma_abort(uint8_t index) { stm_dma.channel[index].ccr &= ~(1 << STM_DMA_CCR_EN); + ao_wakeup(&ao_dma_done[index]); } void diff --git a/src/stm/ao_exti.h b/src/stm/ao_exti.h new file mode 100644 index 00000000..43eaa52f --- /dev/null +++ b/src/stm/ao_exti.h @@ -0,0 +1,38 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_EXTI_H_ +#define _AO_EXTI_H_ + +#define AO_EXTI_MODE_RISING 1 +#define AO_EXTI_MODE_FALLING 2 +#define AO_EXTI_MODE_PULL_UP 4 +#define AO_EXTI_MODE_PULL_DOWN 8 + +void +ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)()); + +void +ao_exti_enable(struct stm_gpio *gpio, uint8_t pin); + +void +ao_exti_disable(struct stm_gpio *gpio, uint8_t pin); + +void +ao_exti_init(void); + +#endif /* _AO_EXTI_H_ */ diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c new file mode 100644 index 00000000..013d453b --- /dev/null +++ b/src/stm/ao_exti_stm.c @@ -0,0 +1,109 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +static void (*ao_exti_callback[16])(void); + +static void +ao_exti_isr(void) { + uint32_t pending = stm_exti.pr; + uint8_t pin; + + /* Clear pending interrupts */ + stm_exti.pr = pending; + for (pin = 0; pin < 16 && pending; pin++) { + uint32_t mask = (1 << pin); + + if (pending & mask) { + pending &= ~mask; + if (ao_exti_callback[pin]) + (*ao_exti_callback[pin])(); + } + } +} + +void stm_exti0_isr(void) { ao_exti_isr(); } +void stm_exti1_isr(void) { ao_exti_isr(); } +void stm_exti2_isr(void) { ao_exti_isr(); } +void stm_exti3_isr(void) { ao_exti_isr(); } +void stm_exti4_isr(void) { ao_exti_isr(); } +void stm_exti9_5_isr(void) { ao_exti_isr(); } +void stm_exti15_10_isr(void) { ao_exti_isr(); } + +void +ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void)) { + uint32_t mask = 1 << pin; + uint32_t pupdr; + uint8_t irq; + + ao_exti_callback[pin] = callback; + /* configure pin as input, setting selected pull-up/down mode */ + stm_moder_set(gpio, pin, STM_MODER_INPUT); + switch (mode & (AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_PULL_DOWN)) { + case 0: + default: + pupdr = STM_PUPDR_NONE; + break; + case AO_EXTI_MODE_PULL_UP: + pupdr = STM_PUPDR_PULL_UP; + break; + case AO_EXTI_MODE_PULL_DOWN: + pupdr = STM_PUPDR_PULL_DOWN; + break; + } + stm_pupdr_set(gpio, pin, pupdr); + + /* Set interrupt mask and rising/falling mode */ + stm_exti.imr &= ~mask; + stm_exti.rtsr |= mask; + if (mode & AO_EXTI_MODE_RISING) + stm_exti.rtsr |= mask; + if (mode & AO_EXTI_MODE_FALLING) + stm_exti.ftsr |= mask; + + if (pin <= 4) + irq = STM_ISR_EXTI0_POS + pin; + else if (pin <= 9) + irq = STM_ISR_EXTI9_5_POS; + else + irq = STM_ISR_EXTI15_10_POS; + stm_nvic_set_priority(irq, 10); + stm_nvic_set_enable(irq); +} + +void +ao_exti_enable(struct stm_gpio *gpio, uint8_t pin) { + stm_exti.imr |= (1 << pin); +} + +void +ao_exti_disable(struct stm_gpio *gpio, uint8_t pin) { + stm_exti.imr &= ~(1 << pin); +} + +void +ao_exti_init(void) +{ + stm_nvic_set_priority(STM_ISR_EXTI1_POS, 10); + stm_nvic_set_priority(STM_ISR_EXTI2_POS, 10); + stm_nvic_set_priority(STM_ISR_EXTI3_POS, 10); + stm_nvic_set_priority(STM_ISR_EXTI4_POS, 10); + stm_nvic_set_priority(STM_ISR_EXTI9_5_POS, 10); + stm_nvic_set_priority(STM_ISR_EXTI15_10_POS, 10); +} diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index be24ebcf..8bb0d8e8 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -96,6 +96,62 @@ ao_spi_send(void *block, uint16_t len, uint8_t spi_index) ao_dma_done_transfer(miso_dma_index); } +void +ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; + uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + + /* Set up the transmit DMA to deliver data */ + ao_dma_set_transfer(mosi_dma_index, + &stm_spi->dr, + &value, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (0 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); + + /* Clear RXNE */ + (void) stm_spi->dr; + + /* Set up the receive DMA -- when this is done, we know the SPI unit + * is idle. Without this, we'd have to poll waiting for the BSY bit to + * be cleared + */ + ao_dma_set_transfer(miso_dma_index, + &stm_spi->dr, + &spi_dev_null, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (0 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (1 << STM_SPI_CR2_TXDMAEN) | + (1 << STM_SPI_CR2_RXDMAEN)); + ao_dma_start(miso_dma_index); + ao_dma_start(mosi_dma_index); + ao_arch_critical( + while (!ao_dma_done[miso_dma_index]) + ao_sleep(&ao_dma_done[miso_dma_index]); + ); + ao_dma_done_transfer(mosi_dma_index); + ao_dma_done_transfer(miso_dma_index); +} + void ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) { @@ -153,6 +209,63 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) ao_dma_done_transfer(miso_dma_index); } +void +ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index) +{ + struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; + uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + + /* Set up transmit DMA to send data */ + ao_dma_set_transfer(mosi_dma_index, + &stm_spi->dr, + out, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); + + /* Clear RXNE */ + (void) stm_spi->dr; + + /* Set up the receive DMA to capture data */ + ao_dma_set_transfer(miso_dma_index, + &stm_spi->dr, + in, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + + stm_spi->cr2 = ((0 << STM_SPI_CR2_TXEIE) | + (0 << STM_SPI_CR2_RXNEIE) | + (0 << STM_SPI_CR2_ERRIE) | + (0 << STM_SPI_CR2_SSOE) | + (1 << STM_SPI_CR2_TXDMAEN) | + (1 << STM_SPI_CR2_RXDMAEN)); + ao_dma_start(miso_dma_index); + ao_dma_start(mosi_dma_index); + + /* Wait until the SPI unit is done */ + ao_arch_critical( + while (!ao_dma_done[miso_dma_index]) + ao_sleep(&ao_dma_done[miso_dma_index]); + ); + + ao_dma_done_transfer(mosi_dma_index); + ao_dma_done_transfer(miso_dma_index); +} + void ao_spi_get(uint8_t spi_index) { diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index 223fdeaa..71bf1bc7 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -1005,6 +1005,7 @@ ao_usb_echo(void) } #endif +#if USB_DEBUG static void ao_usb_irq(void) { @@ -1016,6 +1017,7 @@ __code struct ao_cmds ao_usb_cmds[] = { { ao_usb_irq, "I\0Show USB interrupt counts" }, { 0, NULL } }; +#endif void ao_usb_init(void) @@ -1027,7 +1029,9 @@ ao_usb_init(void) #if USB_ECHO ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo"); #endif +#if USB_DEBUG ao_cmd_register(&ao_usb_cmds[0]); +#endif #if !USB_ECHO ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); #endif diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index e884ef04..10a53a47 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -101,13 +101,13 @@ stm_ospeedr_get(struct stm_gpio *gpio, int pin) { #define STM_PUPDR_RESERVED 3 static inline void -stm_pupdr_set(struct stm_gpio *gpio, int pin, vuint32_t value) { +stm_pupdr_set(struct stm_gpio *gpio, int pin, uint32_t value) { gpio->pupdr = ((gpio->pupdr & ~(STM_PUPDR_MASK << STM_PUPDR_SHIFT(pin))) | value << STM_PUPDR_SHIFT(pin)); } -static inline vuint32_t +static inline uint32_t stm_pupdr_get(struct stm_gpio *gpio, int pin) { return (gpio->pupdr >> STM_PUPDR_SHIFT(pin)) & STM_PUPDR_MASK; } @@ -1589,4 +1589,16 @@ union stm_usb_bdt { extern uint8_t stm_usb_sram[]; +struct stm_exti { + vuint32_t imr; + vuint32_t emr; + vuint32_t rtsr; + vuint32_t ftsr; + + vuint32_t swier; + vuint32_t pr; +}; + +extern struct stm_exti stm_exti; + #endif /* _STM32L_H_ */ -- cgit v1.2.3 From 962476911aaab17fd482593a0e8b95fe47de2f29 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 25 Apr 2012 23:25:43 -0700 Subject: altos: Oopsed the STM DMA channels for I2C1 TX is 6, RX is 7 Signed-off-by: Keith Packard --- src/stm/stm32l.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 10a53a47..0bc7483e 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -953,8 +953,8 @@ extern struct stm_dma stm_dma; #define STM_DMA_CHANNEL_USART2_TX 7 #define STM_DMA_CHANNEL_I2C2_TX 4 #define STM_DMA_CHANNEL_I2C2_RX 5 -#define STM_DMA_CHANNEL_I2C1_RX 6 -#define STM_DMA_CHANNEL_I2C1_TX 7 +#define STM_DMA_CHANNEL_I2C1_TX 6 +#define STM_DMA_CHANNEL_I2C1_RX 7 #define STM_DMA_CHANNEL_TIM2_CH3 1 #define STM_DMA_CHANNEL_TIM2_UP 2 #define STM_DMA_CHANNEL_TIM2_CH1 5 -- cgit v1.2.3 From 0266e08dbf19e2204fb5f758d5d0f944d2afff7d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 25 Apr 2012 23:26:57 -0700 Subject: altos: Add STM I2C recv and stop funcs Recv doesn't appear to work with more than one byte Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 3 +++ src/stm/ao_i2c_stm.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+) (limited to 'src') diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 05bb7784..3027b337 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -130,6 +130,9 @@ ao_i2c_get(uint8_t i2c_index); uint8_t ao_i2c_start(uint8_t i2c_index, uint16_t address); +void +ao_i2c_stop(uint8_t i2c_index); + void ao_i2c_put(uint8_t i2c_index); diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index 1a0280d3..0717be98 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -134,12 +134,22 @@ ao_i2c_start(uint8_t index, uint16_t addr) return ao_i2c_state[index] == I2C_RUNNING; } +void +ao_i2c_stop(uint8_t index) +{ + struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + + ao_i2c_state[index] = I2C_IDLE; + stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP); +} + void ao_i2c_send(void *block, uint16_t len, uint8_t index) { struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; uint8_t tx_dma_index = ao_i2c_stm_info[index].tx_dma_index; + stm_i2c->cr2 &= ~(1 << STM_I2C_CR2_LAST); ao_dma_set_transfer(tx_dma_index, &stm_i2c->dr, block, @@ -161,6 +171,34 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index) ao_dma_done_transfer(tx_dma_index); } +void +ao_i2c_recv(void *block, uint16_t len, uint8_t index) +{ + struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + uint8_t rx_dma_index = ao_i2c_stm_info[index].rx_dma_index; + + stm_i2c->cr2 |= (1 << STM_I2C_CR2_LAST); + ao_dma_set_transfer(rx_dma_index, + &stm_i2c->dr, + block, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + + ao_dma_start(rx_dma_index); + cli(); + while (!ao_dma_done[rx_dma_index]) + ao_sleep(&ao_dma_done[rx_dma_index]); + sei(); + ao_dma_done_transfer(rx_dma_index); +} + void ao_i2c_channel_init(uint8_t index) { -- cgit v1.2.3 From e0b8c614ec4d11f432963e48d94e4497d31a9ddc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 25 Apr 2012 23:27:58 -0700 Subject: altos: Add mpu6000 and hmc5883 stubs No real drivers here yet, just some testing stubs Signed-off-by: Keith Packard --- src/drivers/ao_hmc5883.c | 139 +++++++++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_hmc5883.h | 41 ++++++++++++++ src/drivers/ao_mpu6000.c | 97 +++++++++++++++++++++++++++++++++ src/drivers/ao_mpu6000.h | 30 ++++++++++ 4 files changed, 307 insertions(+) create mode 100644 src/drivers/ao_hmc5883.c create mode 100644 src/drivers/ao_hmc5883.h create mode 100644 src/drivers/ao_mpu6000.c create mode 100644 src/drivers/ao_mpu6000.h (limited to 'src') diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c new file mode 100644 index 00000000..0077daf9 --- /dev/null +++ b/src/drivers/ao_hmc5883.c @@ -0,0 +1,139 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include + +static uint8_t ao_hmc5883_wake; +static uint8_t ao_hmc5883_configured; + +static void +ao_hmc5883_isr(void) +{ + ao_exti_disable(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); + ao_hmc5883_wake = 1; + ao_wakeup(&ao_hmc5883_wake); +} + +static uint8_t ao_hmc5883_addr_reg; + +static void +ao_hmc5883_update_addr (uint8_t len) +{ + ao_hmc5883_addr_reg += len; + if (ao_hmc5883_addr_reg == 9) + ao_hmc5883_addr_reg = 3; + else if (ao_hmc5883_addr_reg > 12) + ao_hmc5883_addr_reg = 0; + +} + +static void +ao_hmc5883_write(uint8_t addr, uint8_t *data, uint8_t len) +{ + ao_i2c_get(AO_HMC5883_I2C_INDEX); + ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); + ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX); + ao_hmc5883_addr_reg = addr; + if (len) { + ao_i2c_send(data, len, AO_HMC5883_I2C_INDEX); + ao_hmc5883_update_addr(len); + } + ao_i2c_stop(AO_HMC5883_I2C_INDEX); + ao_i2c_put(AO_HMC5883_I2C_INDEX); +} + +static void +ao_hmc5883_read(uint8_t addr, uint8_t *data, uint8_t len) +{ + ao_i2c_get(AO_HMC5883_I2C_INDEX); + if (addr != ao_hmc5883_addr_reg) { + ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); + ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX); + ao_hmc5883_addr_reg = addr; + } + ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_READ); + if (len) { + ao_i2c_recv(data, len, AO_HMC5883_I2C_INDEX); + ao_hmc5883_update_addr(len); + } + ao_i2c_stop(AO_HMC5883_I2C_INDEX); + ao_i2c_put(AO_HMC5883_I2C_INDEX); +} + +static uint8_t +ao_hmc5883_setup(void) +{ + uint8_t present; + if (ao_hmc5883_configured) + return 1; + + /* Enable the EXTI interrupt for the appropriate pin */ + ao_enable_port(AO_HMC5883_INT_PORT); + ao_exti_setup(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN, + AO_EXTI_MODE_FALLING, ao_hmc5883_isr); + + ao_hmc5883_addr_reg = 0xff; + + ao_i2c_get(AO_HMC5883_I2C_INDEX); + present = ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_READ); + ao_i2c_stop(AO_HMC5883_I2C_INDEX); + ao_i2c_put(AO_HMC5883_I2C_INDEX); + if (!present) + return 0; + ao_hmc5883_configured = 1; + return 1; +} + +static void +ao_hmc5883_show(void) +{ + uint8_t addr, data; + + for (addr = 0x00; addr <= 0x7f; addr++) + { + ao_i2c_get(AO_HMC5883_I2C_INDEX); + data = ao_i2c_start(AO_HMC5883_I2C_INDEX, addr << 1); + ao_i2c_stop(AO_HMC5883_I2C_INDEX); + ao_i2c_put(AO_HMC5883_I2C_INDEX); + if (data) + printf("address %02x responds\n", addr << 1); + } + if (!ao_hmc5883_setup()) { + printf("hmc5883 not present\n"); + return; + } + for (addr = 0; addr <= 12; addr++) { + ao_hmc5883_read(addr, &data, 1); + printf ("hmc5883 register %2d: %02x\n", + addr, data); + } +} + +static const struct ao_cmds ao_hmc5883_cmds[] = { + { ao_hmc5883_show, "M\0Show HMC5883 status" }, + { 0, NULL } +}; + +void +ao_hmc5883_init(void) +{ + ao_hmc5883_configured = 0; + + ao_cmd_register(&ao_hmc5883_cmds[0]); +} diff --git a/src/drivers/ao_hmc5883.h b/src/drivers/ao_hmc5883.h new file mode 100644 index 00000000..399ddcdd --- /dev/null +++ b/src/drivers/ao_hmc5883.h @@ -0,0 +1,41 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_HMC5883_H_ +#define _AO_HMC5883_H_ + +#define HMC5883_ADDR_WRITE 0x3c +#define HMC5883_ADDR_READ 0x3d + +#define HMC5883_CONFIG_A 0 +#define HMC5883_CONFIG_B 1 +#define HMC5883_MODE 2 +#define HMC5883_X_MSB 3 +#define HMC5883_X_LSB 4 +#define HMC5883_Y_MSB 5 +#define HMC5883_Y_LSB 6 +#define HMC5883_Z_MSB 7 +#define HMC5883_Z_LSB 8 +#define HMC5883_STATUS 9 +#define HMC5883_ID_A 10 +#define HMC5883_ID_B 11 +#define HMC5883_ID_C 12 + +void +ao_hmc5883_init(void); + +#endif /* _AO_HMC5883_H_ */ diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c new file mode 100644 index 00000000..290f1390 --- /dev/null +++ b/src/drivers/ao_mpu6000.c @@ -0,0 +1,97 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include + +static uint8_t ao_mpu6000_wake; +static uint8_t ao_mpu6000_configured; + +static void +ao_mpu6000_isr(void) +{ + ao_exti_disable(&AO_MPU6000_INT_PORT, AO_MPU6000_INT_PIN); + ao_mpu6000_wake = 1; + ao_wakeup(&ao_mpu6000_wake); +} + +static void +ao_mpu6000_write(uint8_t addr, uint8_t *data, uint8_t len) +{ + ao_i2c_get(AO_MPU6000_I2C_INDEX); + ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); + ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX); + if (len) + ao_i2c_send(data, len, AO_MPU6000_I2C_INDEX); + ao_i2c_stop(AO_MPU6000_I2C_INDEX); + ao_i2c_put(AO_MPU6000_I2C_INDEX); +} + +static void +ao_mpu6000_read(uint8_t addr, uint8_t *data, uint8_t len) +{ + ao_i2c_get(AO_MPU6000_I2C_INDEX); + ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); + ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX); + ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_READ); + if (len) + ao_i2c_recv(data, len, AO_MPU6000_I2C_INDEX); + ao_i2c_stop(AO_MPU6000_I2C_INDEX); + ao_i2c_put(AO_MPU6000_I2C_INDEX); +} + +static void +ao_mpu6000_setup(void) +{ + if (ao_mpu6000_configured) + return; + + /* Enable the EXTI interrupt for the appropriate pin */ + ao_enable_port(AO_MPU6000_INT_PORT); + ao_exti_setup(&AO_MPU6000_INT_PORT, AO_MPU6000_INT_PIN, + AO_EXTI_MODE_FALLING, ao_mpu6000_isr); + + ao_mpu6000_configured = 1; +} + +static void +ao_mpu6000_show(void) +{ + uint8_t addr; + uint8_t data[14]; + uint8_t i; + + ao_mpu6000_read(MPU6000_WHO_AM_I, data, 1); + printf ("mpu6000 WHO_AM_I: %02x\n", data[0]); + ao_mpu6000_read(MPU6000_ACCEL_XOUT_H, data, 1); + for (i = 0; i < 14; i++) + printf ("reg %02x: %02x\n", i + MPU6000_ACCEL_XOUT_H, data[i]); +} + +static const struct ao_cmds ao_mpu6000_cmds[] = { + { ao_mpu6000_show, "I\0Show MPU6000 status" }, + { 0, NULL } +}; + +void +ao_mpu6000_init(void) +{ + ao_mpu6000_configured = 0; + + ao_cmd_register(&ao_mpu6000_cmds[0]); +} diff --git a/src/drivers/ao_mpu6000.h b/src/drivers/ao_mpu6000.h new file mode 100644 index 00000000..d436a3e0 --- /dev/null +++ b/src/drivers/ao_mpu6000.h @@ -0,0 +1,30 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_MPU6000_H_ +#define _AO_MPU6000_H_ + +#define MPU6000_ADDR_WRITE 0xd0 +#define MPU6000_ADDR_READ 0xd1 + +#define MPU6000_ACCEL_XOUT_H 0x3b +#define MPU6000_WHO_AM_I 0x75 + +void +ao_mpu6000_init(void); + +#endif /* _AO_MPU6000_H_ */ -- cgit v1.2.3 From 7b0b6bcc40891d8dd106d091d3af8107b2941c66 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 25 Apr 2012 23:29:20 -0700 Subject: altos: Add hmc5883 and mpu6000 drivers to megametrum build Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 12 +++++++++--- src/megametrum-v0.1/ao_megametrum.c | 4 ++++ src/megametrum-v0.1/ao_pins.h | 18 +++++++++++++++++- 3 files changed, 30 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 37832d16..5d73c1d0 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -13,7 +13,10 @@ INC = \ altitude.h \ ao_kalman.h \ ao_product.h \ - ao_ms5607.h + ao_ms5607.h \ + ao_hmc5883.h \ + ao_mpu6000.h \ + stm32l.h # # Common AltOS sources @@ -44,13 +47,16 @@ ALTOS_SRC = \ ao_usb_stm.c \ ao_exti_stm.c \ ao_packet.c \ - ao_packet_slave.c + ao_packet_slave.c \ + ao_i2c_stm.c \ + ao_hmc5883.c \ + ao_mpu6000.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM IDPRODUCT=0x000a -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -Os -g +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -O0 -g PROG=megametrum-v0.1-$(VERSION).elf diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index d93480f2..8283f533 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -16,6 +16,7 @@ */ #include +#include #include void @@ -54,6 +55,9 @@ main(void) ao_usb_init(); ao_exti_init(); ao_radio_init(); + ao_i2c_init(); + ao_hmc5883_init(); + ao_mpu6000_init(); ao_cmd_register(&ao_mm_cmds[0]); ao_start_scheduler(); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 2e83de8a..cd270739 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -42,7 +42,7 @@ #define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2 #define HAS_SERIAL_1 1 -#define USE_SERIAL_1_STDIN 1 +#define USE_SERIAL_1_STDIN 0 #define SERIAL_1_PB6_PB7 0 #define SERIAL_1_PA9_PA10 1 @@ -206,4 +206,20 @@ struct ao_adc { #define AO_CC1120_INT_GPIO 2 +/* + * Mag sensor (hmc5883) + */ + +#define AO_HMC5883_INT_PORT stm_gpioc +#define AO_HMC5883_INT_PIN 12 +#define AO_HMC5883_I2C_INDEX STM_SPI_INDEX(1) + +/* + * mpu6000 + */ + +#define AO_MPU6000_INT_PORT stm_gpioc +#define AO_MPU6000_INT_PIN 13 +#define AO_MPU6000_I2C_INDEX STM_SPI_INDEX(1) + #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 8b08095b3d41e21684a10bddfb54431019da5af6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 1 May 2012 11:08:49 -0700 Subject: altos: Report latest telemetry data, rather than using the oldest ao_sample_adc points to the *next* ADC entry, rather than the most recent one. Step back one entry to get the latest valid data. Signed-off-by: Keith Packard --- src/core/ao_telemetry.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index eb614b0f..46d72609 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -53,8 +53,7 @@ static __xdata union ao_telemetry_all telemetry; static void ao_send_sensor(void) { - uint8_t sample; - sample = ao_sample_adc; + uint8_t sample = ao_adc_ring_prev(ao_sample_adc); telemetry.generic.tick = ao_adc_ring[sample].tick; telemetry.generic.type = AO_TELEMETRY_SENSOR; -- cgit v1.2.3 From 0f0cc91ce8e9807dca48a5c0c53d821f5060e245 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 May 2012 22:47:33 -0700 Subject: altos: STM i2c work. Start now driven by interrupts Send now done with DMA and interrupts Signed-off-by: Keith Packard --- src/drivers/ao_hmc5883.c | 22 ++-- src/drivers/ao_mpu6000.c | 16 +-- src/stm/ao_arch_funcs.h | 13 +- src/stm/ao_i2c_stm.c | 328 ++++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 327 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c index 0077daf9..43d04f70 100644 --- a/src/drivers/ao_hmc5883.c +++ b/src/drivers/ao_hmc5883.c @@ -48,13 +48,10 @@ ao_hmc5883_write(uint8_t addr, uint8_t *data, uint8_t len) { ao_i2c_get(AO_HMC5883_I2C_INDEX); ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); - ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX); + ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX, FALSE); ao_hmc5883_addr_reg = addr; - if (len) { - ao_i2c_send(data, len, AO_HMC5883_I2C_INDEX); - ao_hmc5883_update_addr(len); - } - ao_i2c_stop(AO_HMC5883_I2C_INDEX); + ao_i2c_send(data, len, AO_HMC5883_I2C_INDEX, TRUE); + ao_hmc5883_update_addr(len); ao_i2c_put(AO_HMC5883_I2C_INDEX); } @@ -64,15 +61,12 @@ ao_hmc5883_read(uint8_t addr, uint8_t *data, uint8_t len) ao_i2c_get(AO_HMC5883_I2C_INDEX); if (addr != ao_hmc5883_addr_reg) { ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); - ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX); + ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX, FALSE); ao_hmc5883_addr_reg = addr; } ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_READ); - if (len) { - ao_i2c_recv(data, len, AO_HMC5883_I2C_INDEX); - ao_hmc5883_update_addr(len); - } - ao_i2c_stop(AO_HMC5883_I2C_INDEX); + ao_i2c_recv(data, len, AO_HMC5883_I2C_INDEX, TRUE); + ao_hmc5883_update_addr(len); ao_i2c_put(AO_HMC5883_I2C_INDEX); } @@ -92,7 +86,7 @@ ao_hmc5883_setup(void) ao_i2c_get(AO_HMC5883_I2C_INDEX); present = ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_READ); - ao_i2c_stop(AO_HMC5883_I2C_INDEX); + ao_i2c_recv(NULL, 0, AO_HMC5883_I2C_INDEX, TRUE); ao_i2c_put(AO_HMC5883_I2C_INDEX); if (!present) return 0; @@ -109,7 +103,7 @@ ao_hmc5883_show(void) { ao_i2c_get(AO_HMC5883_I2C_INDEX); data = ao_i2c_start(AO_HMC5883_I2C_INDEX, addr << 1); - ao_i2c_stop(AO_HMC5883_I2C_INDEX); + ao_i2c_recv(NULL, 0, AO_HMC5883_I2C_INDEX, TRUE); ao_i2c_put(AO_HMC5883_I2C_INDEX); if (data) printf("address %02x responds\n", addr << 1); diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index 290f1390..d7f67d6e 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -35,10 +35,8 @@ ao_mpu6000_write(uint8_t addr, uint8_t *data, uint8_t len) { ao_i2c_get(AO_MPU6000_I2C_INDEX); ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); - ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX); - if (len) - ao_i2c_send(data, len, AO_MPU6000_I2C_INDEX); - ao_i2c_stop(AO_MPU6000_I2C_INDEX); + ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX, FALSE); + ao_i2c_send(data, len, AO_MPU6000_I2C_INDEX, TRUE); ao_i2c_put(AO_MPU6000_I2C_INDEX); } @@ -47,11 +45,9 @@ ao_mpu6000_read(uint8_t addr, uint8_t *data, uint8_t len) { ao_i2c_get(AO_MPU6000_I2C_INDEX); ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); - ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX); + ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX, FALSE); ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_READ); - if (len) - ao_i2c_recv(data, len, AO_MPU6000_I2C_INDEX); - ao_i2c_stop(AO_MPU6000_I2C_INDEX); + ao_i2c_recv(data, len, AO_MPU6000_I2C_INDEX, TRUE); ao_i2c_put(AO_MPU6000_I2C_INDEX); } @@ -78,9 +74,11 @@ ao_mpu6000_show(void) ao_mpu6000_read(MPU6000_WHO_AM_I, data, 1); printf ("mpu6000 WHO_AM_I: %02x\n", data[0]); - ao_mpu6000_read(MPU6000_ACCEL_XOUT_H, data, 1); +#if 0 + ao_mpu6000_read(MPU6000_ACCEL_XOUT_H, data, 14); for (i = 0; i < 14; i++) printf ("reg %02x: %02x\n", i + MPU6000_ACCEL_XOUT_H, data[i]); +#endif } static const struct ao_cmds ao_mpu6000_cmds[] = { diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 3027b337..447042dd 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -105,7 +105,7 @@ ao_dma_set_transfer(uint8_t index, uint32_t ccr); void -ao_dma_set_isr(uint8_t index, void (*isr)(void)); +ao_dma_set_isr(uint8_t index, void (*isr)(int index)); void ao_dma_start(uint8_t index); @@ -130,17 +130,14 @@ ao_i2c_get(uint8_t i2c_index); uint8_t ao_i2c_start(uint8_t i2c_index, uint16_t address); -void -ao_i2c_stop(uint8_t i2c_index); - void ao_i2c_put(uint8_t i2c_index); -void -ao_i2c_send(void *block, uint16_t len, uint8_t i2c_index); +uint8_t +ao_i2c_send(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop); -void -ao_i2c_recv(void *block, uint16_t len, uint8_t i2c_index); +uint8_t +ao_i2c_recv(void *block, uint16_t len, uint8_t i2c_index, uint8_t stop); void ao_i2c_init(void); diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index 0717be98..9ab001d7 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -23,6 +23,8 @@ struct ao_i2c_stm_info { struct stm_i2c *stm_i2c; }; +#define I2C_TIMEOUT 100 + #define I2C_IDLE 0 #define I2C_RUNNING 1 #define I2C_ERROR 2 @@ -47,7 +49,7 @@ uint8_t ao_i2c_mutex[STM_NUM_I2C]; (1 << STM_I2C_CR1_PE)) #define AO_STM_I2C_CR2 ((0 << STM_I2C_CR2_LAST) | \ - (1 << STM_I2C_CR2_DMAEN) | \ + (0 << STM_I2C_CR2_DMAEN) | \ (0 << STM_I2C_CR2_ITBUFEN) | \ (0 << STM_I2C_CR2_ITEVTEN) | \ (0 << STM_I2C_CR2_ITERREN) | \ @@ -66,20 +68,44 @@ static const struct ao_i2c_stm_info ao_i2c_stm_info[STM_NUM_I2C] = { }, }; +static uint8_t *ao_i2c_recv_data[STM_NUM_I2C]; +static uint16_t ao_i2c_recv_len[STM_NUM_I2C]; +static uint16_t ev_count; + static void ao_i2c_ev_isr(uint8_t index) { struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; uint32_t sr1; + ++ev_count; sr1 = stm_i2c->sr1; if (sr1 & (1 << STM_I2C_SR1_SB)) stm_i2c->dr = ao_i2c_addr[index]; if (sr1 & (1 << STM_I2C_SR1_ADDR)) { - (void) stm_i2c->sr2; + stm_i2c->cr2 &= ~(1 << STM_I2C_CR2_ITEVTEN); ao_i2c_state[index] = I2C_RUNNING; ao_wakeup(&ao_i2c_state[index]); } + if (sr1 & (1 << STM_I2C_SR1_BTF)) { + stm_i2c->cr2 &= ~(1 << STM_I2C_CR2_ITEVTEN); + ao_wakeup(&ao_i2c_state[index]); + } +#if 0 + if (sr1 & (1 << STM_I2C_SR1_RXNE)) { + if (ao_i2c_recv_len[index]) { + switch (--ao_i2c_recv_len[index]) { + case 0: + ao_wakeup(&ao_i2c_recv_len[index]); + break; + case 1: + stm_i2c->cr1 &= ~(1 << STM_I2C_CR1_ACK); + break; + } + *(ao_i2c_recv_data[index]++) = stm_i2c->dr; + } + } +#endif } void stm_i2c1_ev_isr(void) { ao_i2c_ev_isr(0); } @@ -118,38 +144,205 @@ ao_i2c_put(uint8_t index) ao_mutex_put(&ao_i2c_mutex[index]); } +static inline uint32_t in_sr1(char *where, struct stm_i2c *stm_i2c) { + uint32_t sr1 = stm_i2c->sr1; + printf("%s: sr1: %x\n", where, sr1); flush(); + return sr1; +} + +static inline uint32_t in_sr2(char *where, struct stm_i2c *stm_i2c) { + uint32_t sr2 = stm_i2c->sr2; + printf("%s: sr2: %x\n", where, sr2); flush(); + return sr2; +} + +static inline void out_cr1(char *where, struct stm_i2c *stm_i2c, uint32_t cr1) { + printf("%s: cr1: %x\n", where, cr1); flush(); + stm_i2c->cr1 = cr1; +} + +static inline uint32_t in_cr1(char *where, struct stm_i2c *stm_i2c) { + uint32_t cr1 = stm_i2c->cr1; + printf("%s: cr1: %x\n", where, cr1); flush(); + return cr1; +} + +static inline void out_cr2(char *where, struct stm_i2c *stm_i2c, uint32_t cr2) { + printf("%s: cr2: %x\n", where, cr2); flush(); + stm_i2c->cr2 = cr2; +} + +static inline uint32_t in_dr(char *where, struct stm_i2c *stm_i2c) { + uint32_t dr = stm_i2c->dr; + printf("%s: dr: %x\n", where, dr); flush(); + return dr; +} + +static inline void out_dr(char *where, struct stm_i2c *stm_i2c, uint32_t dr) { + printf("%s: dr: %x\n", where, dr); flush(); + stm_i2c->dr = dr; +} + uint8_t -ao_i2c_start(uint8_t index, uint16_t addr) +ao_i2c_check_status(char *where, uint8_t index, uint32_t sr1_want, uint32_t sr2_want) { struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + uint32_t sr1_got, sr2_got; + + if (sr1_want) { + sr1_got = in_sr1(where, stm_i2c); + if ((sr1_got & sr1_want) != sr1_want) { + printf ("%s: sr1 wanted %x got %x\n", where, sr1_want, sr1_got); + return FALSE; + } + } + if (sr2_want) { + sr2_got = in_sr2(where, stm_i2c); + if ((sr2_got & sr2_want) != sr2_want) { + printf ("%s: sr1 wanted %x got %x\n", + where, sr2_want, sr2_got); + return FALSE; + } + } + printf ("%s: got sr1 %x and sr2 %x\n", where, sr1_want, sr2_want); + return TRUE; +} + +static uint8_t +ao_i2c_check_idle(uint8_t index) +{ + struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + uint32_t s = 0; + int t; + for (t = 0; t < I2C_TIMEOUT; t++) { + if (!ao_i2c_check_status("check idle", index, + 0, + (1 << STM_I2C_SR2_BUSY))) + { + break; + } + ao_yield(); + } + if (t == I2C_TIMEOUT) + return FALSE; + return TRUE; +} + +uint8_t +ao_i2c_start(uint8_t index, uint16_t addr) +{ + struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + uint32_t sr1, sr2; + int t; + +#if 0 + if (!ao_i2c_check_idle(index)) { + printf ("i2c busy\n"); + return FALSE; + } +#endif + ao_i2c_state[index] = I2C_IDLE; ao_i2c_addr[index] = addr; - stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN); - stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START); - ao_arch_critical( - while (ao_i2c_state[index] == I2C_IDLE) - ao_sleep(&ao_i2c_state[index]); - ); +#if 0 + out_cr2("start", stm_i2c, AO_STM_I2C_CR2); + out_cr1("start", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START)); + for (t = 0; t < I2C_TIMEOUT; t++) { + if (ao_i2c_check_status("waiting for start", + index, + (1 << STM_I2C_SR1_SB), + (1 << STM_I2C_SR2_BUSY) | + (1 << STM_I2C_SR2_MSL))) + break; + ao_yield(); + } + if (t == I2C_TIMEOUT) { + printf ("No start mode\n"); + return FALSE; + } + out_dr("address", stm_i2c, addr); + if (addr & 1) { + sr1 = (1 << STM_I2C_SR1_ADDR); + sr2 = (1 << STM_I2C_SR2_BUSY) | (1 << STM_I2C_SR2_MSL); + } else { + sr1 = (1 << STM_I2C_SR1_TXE) | (1 << STM_I2C_SR1_ADDR); + sr2 = (1 << STM_I2C_SR2_TRA) | (1 << STM_I2C_SR2_BUSY) | (1 << STM_I2C_SR2_MSL); + } + + for (t = 0; t < I2C_TIMEOUT; t++) { + if (ao_i2c_check_status("waiting for addr", + index, + sr1, sr2)) + break; + ao_yield(); + } + if (t == I2C_TIMEOUT) { + printf ("Set addr failed\n"); + return FALSE; + } + ao_i2c_state[index] = I2C_RUNNING; +#else + out_cr2("start", stm_i2c, AO_STM_I2C_CR2); + out_cr1("start", stm_i2c, + AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START)); + out_cr2("start", stm_i2c, + AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN)); + ao_alarm(1); + cli(); + while (ao_i2c_state[index] == I2C_IDLE) + if (ao_sleep(&ao_i2c_state[index])) + break; + sei(); + ao_clear_alarm(); +#endif return ao_i2c_state[index] == I2C_RUNNING; } -void +static void ao_i2c_stop(uint8_t index) { struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; ao_i2c_state[index] = I2C_IDLE; - stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP); + out_cr2("enable isr", stm_i2c, + AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN)); + ev_count = 0; + out_cr1("stop", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); + + /* XXX check to see if there is an interrupt here */ + while (in_cr1("stop", stm_i2c) & (1 << STM_I2C_CR1_STOP)) + ao_yield(); + printf ("ev_count in stop: %d\n", ev_count); } -void -ao_i2c_send(void *block, uint16_t len, uint8_t index) +uint8_t +ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) { struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + uint8_t *b = block; + uint32_t sr1; + int t; + +#if 0 + while (len--) { + for (t = 0; t < I2C_TIMEOUT; t++) { + if (ao_i2c_check_status("send", index, + (1 << STM_I2C_SR1_TXE), + 0)) + break; + ao_yield(); + } + if (t == I2C_TIMEOUT) + return FALSE; + out_dr("send", stm_i2c, *b++); + } +#else uint8_t tx_dma_index = ao_i2c_stm_info[index].tx_dma_index; - stm_i2c->cr2 &= ~(1 << STM_I2C_CR2_LAST); + /* Clear any pending ADDR bit */ + in_sr2("send clear addr", stm_i2c); + out_cr2("send", stm_i2c, AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_DMAEN)); ao_dma_set_transfer(tx_dma_index, &stm_i2c->dr, block, @@ -164,20 +357,104 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index) (STM_DMA_CCR_DIR_MEM_TO_PER << STM_DMA_CCR_DIR)); ao_dma_start(tx_dma_index); - ao_arch_critical( - while (!ao_dma_done[tx_dma_index]) - ao_sleep(&ao_dma_done[tx_dma_index]); - ); + ao_alarm(1 + len); + cli(); + while (!ao_dma_done[tx_dma_index]) + if (ao_sleep(&ao_dma_done[tx_dma_index])) { + printf ("send timeout\n"); + break; + } ao_dma_done_transfer(tx_dma_index); + out_cr2("send enable isr", stm_i2c, + AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN)); + while ((in_sr1("send_btf", stm_i2c) & (1 << STM_I2C_SR1_BTF)) == 0) + if (ao_sleep(&ao_i2c_state[index])) + break; + out_cr2("send disable isr", stm_i2c, AO_STM_I2C_CR2); + sei(); +#endif + if (stop) + ao_i2c_stop(index); + return TRUE; } void -ao_i2c_recv(void *block, uint16_t len, uint8_t index) +ao_i2c_recv_dma_isr(int index) +{ + int i; + struct stm_i2c *stm_i2c = NULL; + + for (i = 0; i < STM_NUM_I2C; i++) + if (index == ao_i2c_stm_info[i].rx_dma_index) { + stm_i2c = ao_i2c_stm_info[i].stm_i2c; + break; + } + if (!stm_i2c) + return; + stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_LAST); + ao_dma_done[index] = 1; + ao_wakeup(&ao_dma_done[index]); +} + +uint8_t +ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) { struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; - uint8_t rx_dma_index = ao_i2c_stm_info[index].rx_dma_index; + uint8_t *b = block; + int t; + + switch (len) { + case 0: + return TRUE; + case 1: + out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1); + /* Clear any pending ADDR bit */ + in_sr2("clear addr", stm_i2c); + out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); + break; + case 2: + /* Clear any pending ADDR bit */ + out_cr1("setup recv 2", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_POS)); + if (in_sr1("clear addr", stm_i2c) & (1 << STM_I2C_SR1_ADDR)) + in_sr2("clear addr", stm_i2c); + out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); + break; + default: +// out_cr1("setup recv 2", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK) | (1 << STM_I2C_CR1_POS)); + out_cr1("setup recv 2", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK)); + /* Clear any pending ADDR bit */ + if (in_sr1("clear addr", stm_i2c) & (1 << STM_I2C_SR1_ADDR)) + in_sr2("clear addr", stm_i2c); + break; + } + + while (len--) { + for (t = 0; t < I2C_TIMEOUT; t++) { + if (in_sr1("recv", stm_i2c) & (1 << STM_I2C_SR1_RXNE)) + break; + ao_yield(); + } + if (t == I2C_TIMEOUT) + return FALSE; + *b++ = in_dr("recv", stm_i2c); + if (len == 2 && stop) { + out_cr1("clear ack", stm_i2c, +// AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP) | (1 << STM_I2C_CR1_POS)); + AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); + } + } + if (stop) { + for (t = 0; t < I2C_TIMEOUT; t++) { + if (!(in_cr1("recv stop", stm_i2c) & (1 << STM_I2C_CR1_STOP))) + break; + ao_yield(); + } + if (t == I2C_TIMEOUT) + return FALSE; + } - stm_i2c->cr2 |= (1 << STM_I2C_CR2_LAST); +#if 0 + uint8_t rx_dma_index = ao_i2c_stm_info[index].rx_dma_index; ao_dma_set_transfer(rx_dma_index, &stm_i2c->dr, block, @@ -190,6 +467,13 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index) (0 << STM_DMA_CCR_PINC) | (0 << STM_DMA_CCR_CIRC) | (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + if (len >= 2) { + stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK) | (1 << STM_I2C_CR1_POS); + stm_i2c->cr2 = AO_STM_I2C_CR2; + } else { + stm_i2c->cr1 = AO_STM_I2C_CR1; + stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_LAST); + } ao_dma_start(rx_dma_index); cli(); @@ -197,6 +481,7 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index) ao_sleep(&ao_dma_done[rx_dma_index]); sei(); ao_dma_done_transfer(rx_dma_index); +#endif } void @@ -219,6 +504,7 @@ ao_i2c_channel_init(uint8_t index) (0 << STM_I2C_CCR_DUTY) | (20 << STM_I2C_CCR_CCR)); + stm_i2c->cr1 = AO_STM_I2C_CR1; } -- cgit v1.2.3 From f66f5de7a6cae71948da777ad0638bc6267a710f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 May 2012 22:52:56 -0700 Subject: altos: Switch megametrum compile to -Os Looks like gcc has compiler bugs with -O0 Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 5d73c1d0..437e1a9e 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -56,7 +56,7 @@ PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM IDPRODUCT=0x000a -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -O0 -g +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -Os -g PROG=megametrum-v0.1-$(VERSION).elf -- cgit v1.2.3 From fad6cda3d081d438b18305611f37fe05335aa372 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 May 2012 22:53:25 -0700 Subject: altos: megametrum needs ao_mpu6000.h Signed-off-by: Keith Packard --- src/megametrum-v0.1/ao_megametrum.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 8283f533..2e1f9298 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -17,6 +17,7 @@ #include #include +#include #include void -- cgit v1.2.3 From ddaf501ddcfc1a5f74a1ef1b6b76e1c82d89c77a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 6 May 2012 23:54:13 -0700 Subject: altos: stm i2c DMA for large recv appears to work Transaction appears to be clean on the i2c bus now; correct number of bytes received, and the nack and stop at the right time. This tests > 2 length reads; should try that too. Signed-off-by: Keith Packard --- src/stm/ao_i2c_stm.c | 256 ++++++++++++++------------------------------------- 1 file changed, 70 insertions(+), 186 deletions(-) (limited to 'src') diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index 9ab001d7..e46211cd 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -91,21 +91,13 @@ ao_i2c_ev_isr(uint8_t index) stm_i2c->cr2 &= ~(1 << STM_I2C_CR2_ITEVTEN); ao_wakeup(&ao_i2c_state[index]); } -#if 0 if (sr1 & (1 << STM_I2C_SR1_RXNE)) { if (ao_i2c_recv_len[index]) { - switch (--ao_i2c_recv_len[index]) { - case 0: - ao_wakeup(&ao_i2c_recv_len[index]); - break; - case 1: - stm_i2c->cr1 &= ~(1 << STM_I2C_CR1_ACK); - break; - } *(ao_i2c_recv_data[index]++) = stm_i2c->dr; + if (!--ao_i2c_recv_len[index]) + ao_wakeup(&ao_i2c_recv_len[index]); } } -#endif } void stm_i2c1_ev_isr(void) { ao_i2c_ev_isr(0); } @@ -144,91 +136,52 @@ ao_i2c_put(uint8_t index) ao_mutex_put(&ao_i2c_mutex[index]); } +#define I2C_DEBUG 0 +#if I2C_DEBUG +#define DBG(x...) printf(x) +#else +#define DBG(x...) +#endif + static inline uint32_t in_sr1(char *where, struct stm_i2c *stm_i2c) { uint32_t sr1 = stm_i2c->sr1; - printf("%s: sr1: %x\n", where, sr1); flush(); + DBG("%s: sr1: %x\n", where, sr1); flush(); return sr1; } static inline uint32_t in_sr2(char *where, struct stm_i2c *stm_i2c) { uint32_t sr2 = stm_i2c->sr2; - printf("%s: sr2: %x\n", where, sr2); flush(); + DBG("%s: sr2: %x\n", where, sr2); flush(); return sr2; } static inline void out_cr1(char *where, struct stm_i2c *stm_i2c, uint32_t cr1) { - printf("%s: cr1: %x\n", where, cr1); flush(); + DBG("%s: cr1: %x\n", where, cr1); flush(); stm_i2c->cr1 = cr1; } static inline uint32_t in_cr1(char *where, struct stm_i2c *stm_i2c) { uint32_t cr1 = stm_i2c->cr1; - printf("%s: cr1: %x\n", where, cr1); flush(); + DBG("%s: cr1: %x\n", where, cr1); flush(); return cr1; } static inline void out_cr2(char *where, struct stm_i2c *stm_i2c, uint32_t cr2) { - printf("%s: cr2: %x\n", where, cr2); flush(); + DBG("%s: cr2: %x\n", where, cr2); flush(); stm_i2c->cr2 = cr2; } static inline uint32_t in_dr(char *where, struct stm_i2c *stm_i2c) { uint32_t dr = stm_i2c->dr; - printf("%s: dr: %x\n", where, dr); flush(); + DBG("%s: dr: %x\n", where, dr); flush(); return dr; } static inline void out_dr(char *where, struct stm_i2c *stm_i2c, uint32_t dr) { - printf("%s: dr: %x\n", where, dr); flush(); + DBG("%s: dr: %x\n", where, dr); flush(); stm_i2c->dr = dr; } -uint8_t -ao_i2c_check_status(char *where, uint8_t index, uint32_t sr1_want, uint32_t sr2_want) -{ - struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; - uint32_t sr1_got, sr2_got; - - if (sr1_want) { - sr1_got = in_sr1(where, stm_i2c); - if ((sr1_got & sr1_want) != sr1_want) { - printf ("%s: sr1 wanted %x got %x\n", where, sr1_want, sr1_got); - return FALSE; - } - } - if (sr2_want) { - sr2_got = in_sr2(where, stm_i2c); - if ((sr2_got & sr2_want) != sr2_want) { - printf ("%s: sr1 wanted %x got %x\n", - where, sr2_want, sr2_got); - return FALSE; - } - } - printf ("%s: got sr1 %x and sr2 %x\n", where, sr1_want, sr2_want); - return TRUE; -} - -static uint8_t -ao_i2c_check_idle(uint8_t index) -{ - struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; - uint32_t s = 0; - int t; - - for (t = 0; t < I2C_TIMEOUT; t++) { - if (!ao_i2c_check_status("check idle", index, - 0, - (1 << STM_I2C_SR2_BUSY))) - { - break; - } - ao_yield(); - } - if (t == I2C_TIMEOUT) - return FALSE; - return TRUE; -} - uint8_t ao_i2c_start(uint8_t index, uint16_t addr) { @@ -236,53 +189,9 @@ ao_i2c_start(uint8_t index, uint16_t addr) uint32_t sr1, sr2; int t; -#if 0 - if (!ao_i2c_check_idle(index)) { - printf ("i2c busy\n"); - return FALSE; - } -#endif - ao_i2c_state[index] = I2C_IDLE; ao_i2c_addr[index] = addr; -#if 0 - out_cr2("start", stm_i2c, AO_STM_I2C_CR2); - out_cr1("start", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START)); - for (t = 0; t < I2C_TIMEOUT; t++) { - if (ao_i2c_check_status("waiting for start", - index, - (1 << STM_I2C_SR1_SB), - (1 << STM_I2C_SR2_BUSY) | - (1 << STM_I2C_SR2_MSL))) - break; - ao_yield(); - } - if (t == I2C_TIMEOUT) { - printf ("No start mode\n"); - return FALSE; - } - out_dr("address", stm_i2c, addr); - if (addr & 1) { - sr1 = (1 << STM_I2C_SR1_ADDR); - sr2 = (1 << STM_I2C_SR2_BUSY) | (1 << STM_I2C_SR2_MSL); - } else { - sr1 = (1 << STM_I2C_SR1_TXE) | (1 << STM_I2C_SR1_ADDR); - sr2 = (1 << STM_I2C_SR2_TRA) | (1 << STM_I2C_SR2_BUSY) | (1 << STM_I2C_SR2_MSL); - } - - for (t = 0; t < I2C_TIMEOUT; t++) { - if (ao_i2c_check_status("waiting for addr", - index, - sr1, sr2)) - break; - ao_yield(); - } - if (t == I2C_TIMEOUT) { - printf ("Set addr failed\n"); - return FALSE; - } - ao_i2c_state[index] = I2C_RUNNING; -#else + printf ("start sr1: %x\n", stm_i2c->sr1); out_cr2("start", stm_i2c, AO_STM_I2C_CR2); out_cr1("start", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START)); @@ -295,7 +204,6 @@ ao_i2c_start(uint8_t index, uint16_t addr) break; sei(); ao_clear_alarm(); -#endif return ao_i2c_state[index] == I2C_RUNNING; } @@ -324,20 +232,6 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) uint32_t sr1; int t; -#if 0 - while (len--) { - for (t = 0; t < I2C_TIMEOUT; t++) { - if (ao_i2c_check_status("send", index, - (1 << STM_I2C_SR1_TXE), - 0)) - break; - ao_yield(); - } - if (t == I2C_TIMEOUT) - return FALSE; - out_dr("send", stm_i2c, *b++); - } -#else uint8_t tx_dma_index = ao_i2c_stm_info[index].tx_dma_index; /* Clear any pending ADDR bit */ @@ -372,7 +266,6 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) break; out_cr2("send disable isr", stm_i2c, AO_STM_I2C_CR2); sei(); -#endif if (stop) ao_i2c_stop(index); return TRUE; @@ -402,46 +295,66 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; uint8_t *b = block; int t; + uint8_t ret = TRUE; - switch (len) { - case 0: + if (len == 0) return TRUE; - case 1: + if (len == 1) { + ao_i2c_recv_data[index] = block; + ao_i2c_recv_len[index] = 1; out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1); + /* Clear any pending ADDR bit */ in_sr2("clear addr", stm_i2c); - out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); - break; - case 2: - /* Clear any pending ADDR bit */ - out_cr1("setup recv 2", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_POS)); - if (in_sr1("clear addr", stm_i2c) & (1 << STM_I2C_SR1_ADDR)) - in_sr2("clear addr", stm_i2c); - out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); - break; - default: -// out_cr1("setup recv 2", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK) | (1 << STM_I2C_CR1_POS)); - out_cr1("setup recv 2", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK)); + + /* Enable interrupts to transfer the byte */ + out_cr2("setup recv 1", stm_i2c, + AO_STM_I2C_CR2 | + (1 << STM_I2C_CR2_ITEVTEN) | + (1 << STM_I2C_CR2_ITERREN) | + (1 << STM_I2C_CR2_ITBUFEN)); + if (stop) + out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); + + ao_alarm(1); + cli(); + while (ao_i2c_recv_len[index]) + if (ao_sleep(&ao_i2c_recv_len[index])) + break; + sei(); + ret = ao_i2c_recv_len[index] == 0; + ao_clear_alarm(); + } else { + uint8_t rx_dma_index = ao_i2c_stm_info[index].rx_dma_index; + ao_dma_set_transfer(rx_dma_index, + &stm_i2c->dr, + block, + len, + (0 << STM_DMA_CCR_MEM2MEM) | + (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | + (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | + (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | + (1 << STM_DMA_CCR_MINC) | + (0 << STM_DMA_CCR_PINC) | + (0 << STM_DMA_CCR_CIRC) | + (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); + out_cr1("recv > 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK)); + out_cr2("recv > 1", stm_i2c, AO_STM_I2C_CR2 | + (1 << STM_I2C_CR2_DMAEN) | (1 << STM_I2C_CR2_LAST)); /* Clear any pending ADDR bit */ - if (in_sr1("clear addr", stm_i2c) & (1 << STM_I2C_SR1_ADDR)) - in_sr2("clear addr", stm_i2c); - break; - } + in_sr2("clear addr", stm_i2c); - while (len--) { - for (t = 0; t < I2C_TIMEOUT; t++) { - if (in_sr1("recv", stm_i2c) & (1 << STM_I2C_SR1_RXNE)) + ao_dma_start(rx_dma_index); + ao_alarm(len); + cli(); + while (!ao_dma_done[rx_dma_index]) + if (ao_sleep(&ao_dma_done[rx_dma_index])) break; - ao_yield(); - } - if (t == I2C_TIMEOUT) - return FALSE; - *b++ = in_dr("recv", stm_i2c); - if (len == 2 && stop) { - out_cr1("clear ack", stm_i2c, -// AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP) | (1 << STM_I2C_CR1_POS)); - AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); - } + sei(); + ao_clear_alarm(); + ret = ao_dma_done[rx_dma_index]; + ao_dma_done_transfer(rx_dma_index); + out_cr1("stop recv > 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); } if (stop) { for (t = 0; t < I2C_TIMEOUT; t++) { @@ -452,36 +365,7 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) if (t == I2C_TIMEOUT) return FALSE; } - -#if 0 - uint8_t rx_dma_index = ao_i2c_stm_info[index].rx_dma_index; - ao_dma_set_transfer(rx_dma_index, - &stm_i2c->dr, - block, - len, - (0 << STM_DMA_CCR_MEM2MEM) | - (STM_DMA_CCR_PL_MEDIUM << STM_DMA_CCR_PL) | - (STM_DMA_CCR_MSIZE_8 << STM_DMA_CCR_MSIZE) | - (STM_DMA_CCR_PSIZE_8 << STM_DMA_CCR_PSIZE) | - (1 << STM_DMA_CCR_MINC) | - (0 << STM_DMA_CCR_PINC) | - (0 << STM_DMA_CCR_CIRC) | - (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); - if (len >= 2) { - stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK) | (1 << STM_I2C_CR1_POS); - stm_i2c->cr2 = AO_STM_I2C_CR2; - } else { - stm_i2c->cr1 = AO_STM_I2C_CR1; - stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_LAST); - } - - ao_dma_start(rx_dma_index); - cli(); - while (!ao_dma_done[rx_dma_index]) - ao_sleep(&ao_dma_done[rx_dma_index]); - sei(); - ao_dma_done_transfer(rx_dma_index); -#endif + return ret; } void -- cgit v1.2.3 From 744d05e6037ffc11688a9faa9c7b5dcda4065ee3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 May 2012 21:47:17 -0700 Subject: altos: stm: share i2c_stop code between send and recv This waits for the stop signal to appear on the bus, necessary before starting another transaction. Signed-off-by: Keith Packard --- src/stm/ao_i2c_stm.c | 35 +++++++++++++---------------------- 1 file changed, 13 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index e46211cd..763ae6cd 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -191,7 +191,6 @@ ao_i2c_start(uint8_t index, uint16_t addr) ao_i2c_state[index] = I2C_IDLE; ao_i2c_addr[index] = addr; - printf ("start sr1: %x\n", stm_i2c->sr1); out_cr2("start", stm_i2c, AO_STM_I2C_CR2); out_cr1("start", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START)); @@ -208,20 +207,17 @@ ao_i2c_start(uint8_t index, uint16_t addr) } static void -ao_i2c_stop(uint8_t index) +ao_i2c_wait_stop(uint8_t index) { struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; - - ao_i2c_state[index] = I2C_IDLE; - out_cr2("enable isr", stm_i2c, - AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN)); - ev_count = 0; - out_cr1("stop", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); + int t; - /* XXX check to see if there is an interrupt here */ - while (in_cr1("stop", stm_i2c) & (1 << STM_I2C_CR1_STOP)) + for (t = 0; t < I2C_TIMEOUT; t++) { + if (!(in_cr1("wait stop", stm_i2c) & (1 << STM_I2C_CR1_STOP))) + break; ao_yield(); - printf ("ev_count in stop: %d\n", ev_count); + } + ao_i2c_state[index] = I2C_IDLE; } uint8_t @@ -266,8 +262,10 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) break; out_cr2("send disable isr", stm_i2c, AO_STM_I2C_CR2); sei(); - if (stop) - ao_i2c_stop(index); + if (stop) { + out_cr1("stop", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); + ao_i2c_wait_stop(index); + } return TRUE; } @@ -356,15 +354,8 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) ao_dma_done_transfer(rx_dma_index); out_cr1("stop recv > 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); } - if (stop) { - for (t = 0; t < I2C_TIMEOUT; t++) { - if (!(in_cr1("recv stop", stm_i2c) & (1 << STM_I2C_CR1_STOP))) - break; - ao_yield(); - } - if (t == I2C_TIMEOUT) - return FALSE; - } + if (stop) + ao_i2c_wait_stop(index); return ret; } -- cgit v1.2.3 From dd7699cf8daded17ac41abf5c5170cfb599b6ff5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 May 2012 21:49:24 -0700 Subject: altos: stm: delay during USB config with pull-up off This makes sure that a reboot will reliably cause the device to disconnect from the USB bus. Signed-off-by: Keith Packard --- src/stm/ao_usb_stm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index 71bf1bc7..c093f526 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -937,7 +937,7 @@ ao_usb_disable(void) void ao_usb_enable(void) { - uint16_t tick; + int t; /* Enable SYSCFG */ stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGEN); @@ -985,6 +985,8 @@ ao_usb_enable(void) (0 << STM_USB_CNTR_PDWN) | (0 << STM_USB_CNTR_FRES)); + for (t = 0; t < 1000; t++) + ao_arch_nop(); /* Enable USB pull-up */ stm_syscfg.pmc |= (1 << STM_SYSCFG_PMC_USB_PU); } -- cgit v1.2.3 From af949c67eeb9dc310b1430d3435d241adccfc0a9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 May 2012 21:50:26 -0700 Subject: altos: stm: pass DMA buffer index to DMA completion callback This lets the user know which DMA has finished. Signed-off-by: Keith Packard --- src/stm/ao_adc_stm.c | 2 +- src/stm/ao_dma_stm.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index 729551c4..a2569908 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -41,7 +41,7 @@ static uint8_t ao_adc_ready; * * Mark time in ring, shut down DMA engine */ -static void ao_adc_done(void) +static void ao_adc_done(int index) { ao_adc_ring[ao_adc_head].tick = ao_time(); ao_adc_head = ao_adc_ring_next(ao_adc_head); diff --git a/src/stm/ao_dma_stm.c b/src/stm/ao_dma_stm.c index e76c8e8c..8379a1a5 100644 --- a/src/stm/ao_dma_stm.c +++ b/src/stm/ao_dma_stm.c @@ -20,7 +20,7 @@ #define NUM_DMA 7 struct ao_dma_config { - void (*isr)(void); + void (*isr)(int index); }; uint8_t ao_dma_done[NUM_DMA]; @@ -39,7 +39,7 @@ ao_dma_isr(uint8_t index) { /* Ack them */ stm_dma.ifcr = isr; if (ao_dma_config[index].isr) - (*ao_dma_config[index].isr)(); + (*ao_dma_config[index].isr)(index); else { ao_dma_done[index] = 1; ao_wakeup(&ao_dma_done[index]); @@ -79,7 +79,7 @@ ao_dma_set_transfer(uint8_t index, } void -ao_dma_set_isr(uint8_t index, void (*isr)(void)) +ao_dma_set_isr(uint8_t index, void (*isr)(int)) { ao_dma_config[index].isr = isr; } -- cgit v1.2.3 From 318b564486aa9965bbad54c71e51fcb32b414162 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 May 2012 21:51:25 -0700 Subject: altos: Get mpu6000 working This initializes the device appropraitely, and provides a command to dump the current values in converted form. Signed-off-by: Keith Packard --- src/drivers/ao_mpu6000.c | 225 ++++++++++++++++++++++++++++++++++++++++++----- src/drivers/ao_mpu6000.h | 133 +++++++++++++++++++++++++++- 2 files changed, 334 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index d7f67d6e..d27c42b0 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -23,25 +23,27 @@ static uint8_t ao_mpu6000_wake; static uint8_t ao_mpu6000_configured; static void -ao_mpu6000_isr(void) +ao_mpu6000_write(uint8_t addr, uint8_t *data, uint8_t len) { - ao_exti_disable(&AO_MPU6000_INT_PORT, AO_MPU6000_INT_PIN); - ao_mpu6000_wake = 1; - ao_wakeup(&ao_mpu6000_wake); + ao_i2c_get(AO_MPU6000_I2C_INDEX); + ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); + ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX, FALSE); + ao_i2c_send(data, len, AO_MPU6000_I2C_INDEX, TRUE); + ao_i2c_put(AO_MPU6000_I2C_INDEX); } static void -ao_mpu6000_write(uint8_t addr, uint8_t *data, uint8_t len) +ao_mpu6000_reg_write(uint8_t addr, uint8_t value) { + uint8_t d[2] = { addr, value }; ao_i2c_get(AO_MPU6000_I2C_INDEX); ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); - ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX, FALSE); - ao_i2c_send(data, len, AO_MPU6000_I2C_INDEX, TRUE); + ao_i2c_send(d, 2, AO_MPU6000_I2C_INDEX, TRUE); ao_i2c_put(AO_MPU6000_I2C_INDEX); } static void -ao_mpu6000_read(uint8_t addr, uint8_t *data, uint8_t len) +ao_mpu6000_read(uint8_t addr, void *data, uint8_t len) { ao_i2c_get(AO_MPU6000_I2C_INDEX); ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); @@ -51,34 +53,211 @@ ao_mpu6000_read(uint8_t addr, uint8_t *data, uint8_t len) ao_i2c_put(AO_MPU6000_I2C_INDEX); } +static uint8_t +ao_mpu6000_reg_read(uint8_t addr) +{ + uint8_t value; + ao_i2c_get(AO_MPU6000_I2C_INDEX); + ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_WRITE); + ao_i2c_send(&addr, 1, AO_MPU6000_I2C_INDEX, FALSE); + ao_i2c_start(AO_MPU6000_I2C_INDEX, MPU6000_ADDR_READ); + ao_i2c_recv(&value, 1, AO_MPU6000_I2C_INDEX, TRUE); + ao_i2c_put(AO_MPU6000_I2C_INDEX); + return value; +} + +static void +ao_mpu6000_sample(struct ao_mpu6000_sample *sample) +{ + uint16_t *d = (uint16_t *) sample; + int i = sizeof (*sample) / 2; + + ao_mpu6000_read(MPU6000_ACCEL_XOUT_H, sample, sizeof (*sample)); + /* byte swap (sigh) */ + while (i--) { + uint16_t t = *d; + *d++ = (t >> 8) | (t << 8); + } +} + +#define G 981 /* in cm/s² */ + +static int16_t /* cm/s² */ +ao_mpu6000_accel(int16_t v) +{ + return (int16_t) ((v * (int32_t) (16.0 * 980.665 + 0.5)) / 32767); +} + +static int16_t /* deg*10/s */ +ao_mpu6000_gyro(int16_t v) +{ + return (int16_t) ((v * (int32_t) 20000) / 32767); +} + +static uint8_t +ao_mpu6000_accel_check(int16_t normal, int16_t test, char *which) +{ + int16_t diff = test - normal; + + if (diff < MPU6000_ST_ACCEL(16) / 2) { + printf ("%s accel self test value too small (normal %d, test %d)\n", + which, normal, test); + return FALSE; + } + if (diff > MPU6000_ST_ACCEL(16) * 2) { + printf ("%s accel self test value too large (normal %d, test %d)\n", + which, normal, test); + return FALSE; + } + return TRUE; +} + +static uint8_t +ao_mpu6000_gyro_check(int16_t normal, int16_t test, char *which) +{ + int16_t diff = test - normal; + + if (diff < 0) + diff = -diff; + if (diff < MPU6000_ST_GYRO(2000) / 2) { + printf ("%s gyro self test value too small (normal %d, test %d)\n", + which, normal, test); + return FALSE; + } + if (diff > MPU6000_ST_GYRO(2000) * 2) { + printf ("%s gyro self test value too large (normal %d, test %d)\n", + which, normal, test); + return FALSE; + } + return TRUE; +} + static void ao_mpu6000_setup(void) { + struct ao_mpu6000_sample normal_mode, test_mode; + int t; + if (ao_mpu6000_configured) return; - /* Enable the EXTI interrupt for the appropriate pin */ - ao_enable_port(AO_MPU6000_INT_PORT); - ao_exti_setup(&AO_MPU6000_INT_PORT, AO_MPU6000_INT_PIN, - AO_EXTI_MODE_FALLING, ao_mpu6000_isr); + /* Reset the whole chip */ + + ao_mpu6000_reg_write(MPU6000_PWR_MGMT_1, + (1 << MPU6000_PWR_MGMT_1_DEVICE_RESET)); + while (ao_mpu6000_reg_read(MPU6000_PWR_MGMT_1) & + (1 << MPU6000_PWR_MGMT_1_DEVICE_RESET)) + ao_yield(); + + /* Reset signal conditioning */ + ao_mpu6000_reg_write(MPU6000_USER_CONTROL, + (0 << MPU6000_USER_CONTROL_FIFO_EN) | + (0 << MPU6000_USER_CONTROL_I2C_MST_EN) | + (0 << MPU6000_USER_CONTROL_I2C_IF_DIS) | + (0 << MPU6000_USER_CONTROL_FIFO_RESET) | + (0 << MPU6000_USER_CONTROL_I2C_MST_RESET) | + (1 << MPU6000_USER_CONTROL_SIG_COND_RESET)); + + while (ao_mpu6000_reg_read(MPU6000_USER_CONTROL) & (1 << MPU6000_USER_CONTROL_SIG_COND_RESET)) + ao_yield(); + + /* Reset signal paths */ + ao_mpu6000_reg_write(MPU6000_SIGNAL_PATH_RESET, + (1 << MPU6000_SIGNAL_PATH_RESET_GYRO_RESET) | + (1 << MPU6000_SIGNAL_PATH_RESET_ACCEL_RESET) | + (1 << MPU6000_SIGNAL_PATH_RESET_TEMP_RESET)); + + ao_mpu6000_reg_write(MPU6000_SIGNAL_PATH_RESET, + (0 << MPU6000_SIGNAL_PATH_RESET_GYRO_RESET) | + (0 << MPU6000_SIGNAL_PATH_RESET_ACCEL_RESET) | + (0 << MPU6000_SIGNAL_PATH_RESET_TEMP_RESET)); + /* Select clocks, disable sleep */ + ao_mpu6000_reg_write(MPU6000_PWR_MGMT_1, + (0 << MPU6000_PWR_MGMT_1_DEVICE_RESET) | + (0 << MPU6000_PWR_MGMT_1_SLEEP) | + (0 << MPU6000_PWR_MGMT_1_CYCLE) | + (0 << MPU6000_PWR_MGMT_1_TEMP_DIS) | + (MPU6000_PWR_MGMT_1_CLKSEL_PLL_X_AXIS << MPU6000_PWR_MGMT_1_CLKSEL)); + + /* Set sample rate divider to sample at full speed + ao_mpu6000_reg_write(MPU6000_SMPRT_DIV, 0); + + /* Disable filtering */ + ao_mpu6000_reg_write(MPU6000_CONFIG, + (MPU6000_CONFIG_EXT_SYNC_SET_DISABLED << MPU6000_CONFIG_EXT_SYNC_SET) | + (MPU6000_CONFIG_DLPF_CFG_260_256 << MPU6000_CONFIG_DLPF_CFG)); + + /* Configure accelerometer to +/-16G in self-test mode */ + ao_mpu6000_reg_write(MPU6000_ACCEL_CONFIG, + (1 << MPU600_ACCEL_CONFIG_XA_ST) | + (1 << MPU600_ACCEL_CONFIG_YA_ST) | + (1 << MPU600_ACCEL_CONFIG_ZA_ST) | + (MPU600_ACCEL_CONFIG_AFS_SEL_16G << MPU600_ACCEL_CONFIG_AFS_SEL)); + + /* Configure gyro to +/- 2000°/s in self-test mode */ + ao_mpu6000_reg_write(MPU6000_GYRO_CONFIG, + (1 << MPU600_GYRO_CONFIG_XG_ST) | + (1 << MPU600_GYRO_CONFIG_YG_ST) | + (1 << MPU600_GYRO_CONFIG_ZG_ST) | + (MPU600_GYRO_CONFIG_FS_SEL_2000 << MPU600_GYRO_CONFIG_FS_SEL)); + + ao_delay(AO_MS_TO_TICKS(200)); + ao_mpu6000_sample(&test_mode); + + /* Configure accelerometer to +/-16G */ + ao_mpu6000_reg_write(MPU6000_ACCEL_CONFIG, + (0 << MPU600_ACCEL_CONFIG_XA_ST) | + (0 << MPU600_ACCEL_CONFIG_YA_ST) | + (0 << MPU600_ACCEL_CONFIG_ZA_ST) | + (MPU600_ACCEL_CONFIG_AFS_SEL_16G << MPU600_ACCEL_CONFIG_AFS_SEL)); + + /* Configure gyro to +/- 2000°/s */ + ao_mpu6000_reg_write(MPU6000_GYRO_CONFIG, + (0 << MPU600_GYRO_CONFIG_XG_ST) | + (0 << MPU600_GYRO_CONFIG_YG_ST) | + (0 << MPU600_GYRO_CONFIG_ZG_ST) | + (MPU600_GYRO_CONFIG_FS_SEL_2000 << MPU600_GYRO_CONFIG_FS_SEL)); + + ao_delay(AO_MS_TO_TICKS(10)); + ao_mpu6000_sample(&normal_mode); + + ao_mpu6000_accel_check(normal_mode.accel_x, test_mode.accel_x, "x"); + ao_mpu6000_accel_check(normal_mode.accel_y, test_mode.accel_y, "y"); + ao_mpu6000_accel_check(normal_mode.accel_z, test_mode.accel_z, "z"); + + ao_mpu6000_gyro_check(normal_mode.gyro_x, test_mode.gyro_x, "x"); + ao_mpu6000_gyro_check(normal_mode.gyro_y, test_mode.gyro_y, "y"); + ao_mpu6000_gyro_check(normal_mode.gyro_z, test_mode.gyro_z, "z"); + + /* Filter to about 100Hz, which also sets the gyro rate to 1000Hz */ + ao_mpu6000_reg_write(MPU6000_CONFIG, + (MPU6000_CONFIG_EXT_SYNC_SET_DISABLED << MPU6000_CONFIG_EXT_SYNC_SET) | + (MPU6000_CONFIG_DLPF_CFG_94_98 << MPU6000_CONFIG_DLPF_CFG)); + + /* Set sample rate divider to sample at 200Hz (v = gyro/rate - 1) */ + ao_mpu6000_reg_write(MPU6000_SMPRT_DIV, + 1000 / 200 - 1); + + ao_delay(AO_MS_TO_TICKS(100)); ao_mpu6000_configured = 1; } + static void ao_mpu6000_show(void) { - uint8_t addr; - uint8_t data[14]; - uint8_t i; - - ao_mpu6000_read(MPU6000_WHO_AM_I, data, 1); - printf ("mpu6000 WHO_AM_I: %02x\n", data[0]); -#if 0 - ao_mpu6000_read(MPU6000_ACCEL_XOUT_H, data, 14); - for (i = 0; i < 14; i++) - printf ("reg %02x: %02x\n", i + MPU6000_ACCEL_XOUT_H, data[i]); -#endif + struct ao_mpu6000_sample sample; + + ao_mpu6000_setup(); + ao_mpu6000_sample(&sample); + printf ("Accel: %7d %7d %7d Gyro: %7d %7d %7d\n", + ao_mpu6000_accel(sample.accel_x), + ao_mpu6000_accel(sample.accel_y), + ao_mpu6000_accel(sample.accel_z), + ao_mpu6000_gyro(sample.gyro_x), + ao_mpu6000_gyro(sample.gyro_y), + ao_mpu6000_gyro(sample.gyro_z)); } static const struct ao_cmds ao_mpu6000_cmds[] = { diff --git a/src/drivers/ao_mpu6000.h b/src/drivers/ao_mpu6000.h index d436a3e0..ca76b081 100644 --- a/src/drivers/ao_mpu6000.h +++ b/src/drivers/ao_mpu6000.h @@ -21,9 +21,140 @@ #define MPU6000_ADDR_WRITE 0xd0 #define MPU6000_ADDR_READ 0xd1 -#define MPU6000_ACCEL_XOUT_H 0x3b +#define MPU6000_SMPRT_DIV 0x19 + +#define MPU6000_CONFIG 0x1a + +#define MPU6000_CONFIG_EXT_SYNC_SET 3 +#define MPU6000_CONFIG_EXT_SYNC_SET_DISABLED 0 +#define MPU6000_CONFIG_EXT_SYNC_SET_TEMP_OUT_L 1 +#define MPU6000_CONFIG_EXT_SYNC_SET_GYRO_XOUT_L 2 +#define MPU6000_CONFIG_EXT_SYNC_SET_GYRO_YOUT_L 3 +#define MPU6000_CONFIG_EXT_SYNC_SET_GYRO_ZOUT_L 4 +#define MPU6000_CONFIG_EXT_SYNC_SET_ACCEL_XOUT_L 5 +#define MPU6000_CONFIG_EXT_SYNC_SET_ACCEL_YOUT_L 6 +#define MPU6000_CONFIG_EXT_SYNC_SET_ACCEL_ZOUT_L 7 +#define MPU6000_CONFIG_EXT_SYNC_SET_MASK 7 + +#define MPU6000_CONFIG_DLPF_CFG 0 +#define MPU6000_CONFIG_DLPF_CFG_260_256 0 +#define MPU6000_CONFIG_DLPF_CFG_184_188 1 +#define MPU6000_CONFIG_DLPF_CFG_94_98 2 +#define MPU6000_CONFIG_DLPF_CFG_44_42 3 +#define MPU6000_CONFIG_DLPF_CFG_21_20 4 +#define MPU6000_CONFIG_DLPF_CFG_10_10 5 +#define MPU6000_CONFIG_DLPF_CFG_5_5 6 +#define MPU6000_CONFIG_DLPF_CFG_MASK 7 + +#define MPU6000_GYRO_CONFIG 0x1b +# define MPU600_GYRO_CONFIG_XG_ST 7 +# define MPU600_GYRO_CONFIG_YG_ST 6 +# define MPU600_GYRO_CONFIG_ZG_ST 5 +# define MPU600_GYRO_CONFIG_FS_SEL 3 +# define MPU600_GYRO_CONFIG_FS_SEL_250 0 +# define MPU600_GYRO_CONFIG_FS_SEL_500 1 +# define MPU600_GYRO_CONFIG_FS_SEL_1000 2 +# define MPU600_GYRO_CONFIG_FS_SEL_2000 3 +# define MPU600_GYRO_CONFIG_FS_SEL_MASK 3 + +#define MPU6000_ACCEL_CONFIG 0x1c +# define MPU600_ACCEL_CONFIG_XA_ST 7 +# define MPU600_ACCEL_CONFIG_YA_ST 6 +# define MPU600_ACCEL_CONFIG_ZA_ST 5 +# define MPU600_ACCEL_CONFIG_AFS_SEL 3 +# define MPU600_ACCEL_CONFIG_AFS_SEL_2G 0 +# define MPU600_ACCEL_CONFIG_AFS_SEL_4G 1 +# define MPU600_ACCEL_CONFIG_AFS_SEL_8G 2 +# define MPU600_ACCEL_CONFIG_AFS_SEL_16G 3 +# define MPU600_ACCEL_CONFIG_AFS_SEL_MASK 3 +# define MPU600_ACCEL_CONFIG_ACCEL_HPF 0 +# define MPU600_ACCEL_CONFIG_ACCEL_HPF_RESET 0 +# define MPU600_ACCEL_CONFIG_ACCEL_HPF_5Hz 1 +# define MPU600_ACCEL_CONFIG_ACCEL_HPF_2_5Hz 2 +# define MPU600_ACCEL_CONFIG_ACCEL_HPF_1_25Hz 3 +# define MPU600_ACCEL_CONFIG_ACCEL_HPF_0_63Hz 4 +# define MPU600_ACCEL_CONFIG_ACCEL_HPF_HOLD 7 +# define MPU600_ACCEL_CONFIG_ACCEL_HPF_MASK 7 + +#define MPU6000_INT_ENABLE 0x38 +#define MPU6000_INT_ENABLE_FF_EN 7 +#define MPU6000_INT_ENABLE_MOT_EN 6 +#define MPU6000_INT_ENABLE_ZMOT_EN 5 +#define MPU6000_INT_ENABLE_FIFO_OFLOW_EN 4 +#define MPU6000_INT_ENABLE_I2C_MST_INT_EN 3 +#define MPU6000_INT_ENABLE_DATA_RDY_EN 0 + +#define MPU6000_INT_STATUS 0x3a +#define MPU6000_INT_STATUS_FF_EN 7 +#define MPU6000_INT_STATUS_MOT_EN 6 +#define MPU6000_INT_STATUS_ZMOT_EN 5 +#define MPU6000_INT_STATUS_FIFO_OFLOW_EN 4 +#define MPU6000_INT_STATUS_I2C_MST_INT_EN 3 +#define MPU6000_INT_STATUS_DATA_RDY_EN 0 + +#define MPU6000_ACCEL_XOUT_H 0x3b +#define MPU6000_ACCEL_XOUT_L 0x3c +#define MPU6000_ACCEL_YOUT_H 0x3d +#define MPU6000_ACCEL_YOUT_L 0x3e +#define MPU6000_ACCEL_ZOUT_H 0x3f +#define MPU6000_ACCEL_ZOUT_L 0x40 +#define MPU6000_TEMP_H 0x41 +#define MPU6000_TEMP_L 0x42 +#define MPU6000_GYRO_XOUT_H 0x43 +#define MPU6000_GYRO_XOUT_L 0x44 +#define MPU6000_GYRO_YOUT_H 0x45 +#define MPU6000_GYRO_YOUT_L 0x46 +#define MPU6000_GYRO_ZOUT_H 0x47 +#define MPU6000_GYRO_ZOUT_L 0x48 + +#define MPU6000_SIGNAL_PATH_RESET 0x68 +#define MPU6000_SIGNAL_PATH_RESET_GYRO_RESET 2 +#define MPU6000_SIGNAL_PATH_RESET_ACCEL_RESET 1 +#define MPU6000_SIGNAL_PATH_RESET_TEMP_RESET 0 + +#define MPU6000_USER_CONTROL 0x6a +#define MPU6000_USER_CONTROL_FIFO_EN 6 +#define MPU6000_USER_CONTROL_I2C_MST_EN 5 +#define MPU6000_USER_CONTROL_I2C_IF_DIS 4 +#define MPU6000_USER_CONTROL_FIFO_RESET 2 +#define MPU6000_USER_CONTROL_I2C_MST_RESET 1 +#define MPU6000_USER_CONTROL_SIG_COND_RESET 0 + +#define MPU6000_PWR_MGMT_1 0x6b +#define MPU6000_PWR_MGMT_1_DEVICE_RESET 7 +#define MPU6000_PWR_MGMT_1_SLEEP 6 +#define MPU6000_PWR_MGMT_1_CYCLE 5 +#define MPU6000_PWR_MGMT_1_TEMP_DIS 3 +#define MPU6000_PWR_MGMT_1_CLKSEL 0 +#define MPU6000_PWR_MGMT_1_CLKSEL_INTERNAL 0 +#define MPU6000_PWR_MGMT_1_CLKSEL_PLL_X_AXIS 1 +#define MPU6000_PWR_MGMT_1_CLKSEL_PLL_Y_AXIS 2 +#define MPU6000_PWR_MGMT_1_CLKSEL_PLL_Z_AXIS 3 +#define MPU6000_PWR_MGMT_1_CLKSEL_PLL_EXTERNAL_32K 4 +#define MPU6000_PWR_MGMT_1_CLKSEL_PLL_EXTERNAL_19M 5 +#define MPU6000_PWR_MGMT_1_CLKSEL_STOP 7 +#define MPU6000_PWR_MGMT_1_CLKSEL_MASK 7 + +#define MPU6000_PWR_MGMT_2 0x6c + #define MPU6000_WHO_AM_I 0x75 +/* Self test acceleration is approximately 0.5g */ +#define MPU6000_ST_ACCEL(full_scale) (32767 / ((full_scale) * 2)) + +/* Self test gyro is approximately 50°/s */ +#define MPU6000_ST_GYRO(full_scale) ((int16_t) (((int32_t) 32767 * (int32_t) 50) / (full_scale))) + +struct ao_mpu6000_sample { + int16_t accel_x; + int16_t accel_y; + int16_t accel_z; + int16_t temp; + int16_t gyro_x; + int16_t gyro_y; + int16_t gyro_z; +}; + void ao_mpu6000_init(void); -- cgit v1.2.3 From 73c26f39b1a08fcc13e23a5b1a4293bc7df9f163 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 May 2012 21:52:12 -0700 Subject: altos: Hacking at cc1120 driver Still doesn't work, but this adds a ton more register definitions Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 225 ++++++++++++++++++++++++++++++++++++----- src/drivers/ao_cc1120.h | 164 ++++++++++++++++++++++++++++++ src/drivers/ao_cc1120_CC1120.h | 16 ++- 3 files changed, 376 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 272371d0..95b21170 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -19,7 +19,7 @@ #include #include -uint8_t ao_radio_done; +uint8_t ao_radio_wake; uint8_t ao_radio_mutex; uint8_t ao_radio_abort; @@ -27,6 +27,8 @@ uint8_t ao_radio_abort; uint32_t ao_radio_cal = 1186611; +#define FOSC 32000000 + #define ao_radio_select() ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS) #define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS) #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS) @@ -41,7 +43,7 @@ ao_radio_reg_read(uint16_t addr) uint8_t d; #if CC1120_DEBUG - printf("ao_radio_reg_read (%04x): ", addr); flush(); + printf("\t\tao_radio_reg_read (%04x): ", addr); flush(); #endif if (CC1120_IS_EXTENDED(addr)) { data[0] = ((1 << CC1120_READ) | @@ -72,7 +74,7 @@ ao_radio_reg_write(uint16_t addr, uint8_t value) uint8_t d; #if CC1120_DEBUG - printf("ao_radio_reg_write (%04x): %02x\n", addr, value); + printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value); #endif if (CC1120_IS_EXTENDED(addr)) { data[0] = ((1 << CC1120_READ) | @@ -97,9 +99,15 @@ ao_radio_strobe(uint8_t addr) { uint8_t in; +#if CC1120_DEBUG + printf("\t\tao_radio_strobe (%02x): ", addr); flush(); +#endif ao_radio_select(); ao_radio_duplex(&addr, &in, 1); ao_radio_deselect(); +#if CC1120_DEBUG + printf("%02x\n", in); +#endif return in; } @@ -141,10 +149,12 @@ ao_radio_fifo_write_fixed(uint8_t data, uint8_t len) CC1120_FIFO); uint8_t status; + printf ("num tx bytes: %d\n", ao_radio_reg_read(CC1120_NUM_TXBYTES)); ao_radio_select(); ao_radio_duplex(&addr, &status, 1); ao_radio_spi_send_fixed(data, len); ao_radio_deselect(); + printf ("num tx bytes: %d\n", ao_radio_reg_read(CC1120_NUM_TXBYTES)); return status; } @@ -158,32 +168,116 @@ void ao_radio_recv_abort(void) { ao_radio_abort = 1; - ao_wakeup(&ao_radio_done); + ao_wakeup(&ao_radio_wake); } #define ao_radio_rdf_value 0x55 -static const uint16_t rdf_setup[] = { +/* + * RDF deviation is 5kHz + * + * fdev = fosc >> 24 * (256 + dev_m) << dev_e + * + * 32e6Hz / (2 ** 24) * (256 + 71) * (2 ** 3) = 4989 + */ + +#define RDF_DEV_E 3 +#define RDF_DEV_M 71 +#define RDF_PACKET_LEN 50 + +/* + * For our RDF beacon, set the symbol rate to 2kBaud (for a 1kHz tone) + * + * (2**20 - DATARATE_M) * 2 ** DATARATE_E + * Rdata = -------------------------------------- * fosc + * 2 ** 39 + * + * DATARATE_M = 511705 + * DATARATE_E = 6 + * + * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes + */ +#define RDF_DRATE_E 6 +#define RDF_DRATE_M 511705 +#define RDF_PACKET_LEN 50 + +static const uint16_t rdf_setup[] = { + CC1120_DEVIATION_M, RDF_DEV_M, + CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) | + (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) | + (RDF_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)), + CC1120_DRATE2, ((RDF_DRATE_E << CC1120_DRATE2_DATARATE_E) | + (((RDF_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)), + CC1120_DRATE1, ((RDF_DRATE_M >> 8) & 0xff), + CC1120_DRATE0, ((RDF_DRATE_M >> 0) & 0xff), + CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | + (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)), + CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) | + (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) | + (0 << CC1120_PKT_CFG1_APPEND_STATUS)), }; +#define int_pin(w) printf("\t%s: %d\n", \ + w,\ + (AO_CC1120_INT_PORT.idr >> AO_CC1120_INT_PIN) & 1) + +static uint8_t +ao_radio_marc_status(void) +{ + return ao_radio_reg_read(CC1120_MARC_STATUS1); +} + +static uint8_t +ao_radio_tx_done(void) +{ + return ao_radio_marc_status() == CC1120_MARC_STATUS1_TX_FINISHED; +} + +static uint8_t +ao_radio_rx_done(void) +{ + return ao_radio_marc_status() == CC1120_MARC_STATUS1_RX_FINISHED; +} + void ao_radio_rdf(uint8_t len) { int i; - ao_radio_abort = 0; ao_radio_get(len); - ao_radio_done = 0; + ao_radio_abort = 0; for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]); - ao_radio_fifo_write_fixed(ao_radio_rdf_value, len); + ao_radio_reg_write(CC1120_PKT_LEN, len); + int_pin ("Before CFG"); ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); - ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + int_pin ("After CFG"); ao_radio_strobe(CC1120_STX); + ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + int_pin ("After strobe"); + ao_delay(AO_MS_TO_TICKS(100)); + ao_radio_fifo_write_fixed(ao_radio_rdf_value, len); + int_pin ("After delay"); cli(); - while (!ao_radio_done) - ao_sleep(&ao_radio_done); + for (i = 0; i < 20; i++) { +#if CC1120_DEBUG + ao_delay(AO_MS_TO_TICKS(50)); + int_pin ("Waited"); + printf ("Status %02x num_tx_bytes %d marc status %x\n", + ao_radio_status(), + ao_radio_reg_read(CC1120_NUM_TXBYTES), + ao_radio_marc_status()); +#else + ao_sleep(&ao_radio_wake); +#endif + } sei(); + printf ("num_tx_bytes %d marc status %x\n", + ao_radio_reg_read(CC1120_NUM_TXBYTES), + ao_radio_marc_status()); + if (!ao_radio_tx_done()) + ao_radio_idle(); ao_radio_set_packet(); ao_radio_put(); } @@ -191,6 +285,8 @@ ao_radio_rdf(uint8_t len) void ao_radio_rdf_abort(void) { + ao_radio_abort = 1; + ao_wakeup(&ao_radio_wake); } static void @@ -213,6 +309,14 @@ ao_radio_test(void) #endif ao_radio_get(0xff); ao_radio_strobe(CC1120_STX); +#if CC1120_DEBUG + { int t; + for (t = 0; t < 10; t++) { + printf ("status: %02x\n", ao_radio_status()); + ao_delay(AO_MS_TO_TICKS(100)); + } + } +#endif radio_on = 1; } if (mode == 3) { @@ -233,15 +337,23 @@ ao_radio_test(void) void ao_radio_send(void *d, uint8_t size) { + uint8_t marc_status; + ao_radio_get(size); - ao_radio_done = 0; + ao_radio_wake = 0; ao_radio_fifo_write(d, size); - ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); ao_radio_strobe(CC1120_STX); cli(); - while (!ao_radio_done) - ao_sleep(&ao_radio_done); + for (;;) { + if (ao_radio_wake) { + marc_status = ao_radio_marc_status(); + if (marc_status != CC1120_MARC_STATUS1_NO_FAILURE) + break; + ao_radio_wake = 0; + } + ao_sleep(&ao_radio_wake); + } sei(); ao_radio_put(); } @@ -249,23 +361,73 @@ ao_radio_send(void *d, uint8_t size) uint8_t ao_radio_recv(__xdata void *d, uint8_t size) { + uint8_t marc_status = CC1120_MARC_STATUS1_NO_FAILURE; + /* configure interrupt pin */ ao_radio_get(size); - ao_radio_done = 0; - ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RXFIFO_THR_PKT); + ao_radio_wake = 0; ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); ao_radio_strobe(CC1120_SRX); cli(); - while (!ao_radio_done && !ao_radio_abort) - ao_sleep(&ao_radio_done); + for (;;) { + if (ao_radio_abort) + break; + if (ao_radio_wake) { + marc_status = ao_radio_marc_status(); + if (marc_status != CC1120_MARC_STATUS1_NO_FAILURE) + break; + ao_radio_wake = 0; + } + ao_sleep(&ao_radio_wake); + } sei(); - if (ao_radio_done) + if (marc_status != CC1120_MARC_STATUS1_RX_FINISHED) ao_radio_fifo_read(d, size); ao_radio_put(); - return 0; + return marc_status == CC1120_MARC_STATUS1_RX_FINISHED; } +/* + * Packet deviation is 20.5kHz + * + * fdev = fosc >> 24 * (256 + dev_m) << dev_e + * + * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz + */ + +#define PACKET_DEV_E 5 +#define PACKET_DEV_M 80 + +/* + * For our packet data, set the symbol rate to 38360 Baud + * + * (2**20 - DATARATE_M) * 2 ** DATARATE_E + * Rdata = -------------------------------------- * fosc + * 2 ** 39 + * + * DATARATE_M = 405002 + * DATARATE_E = 10 + * + * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes + */ +#define PACKET_DRATE_E 10 +#define PACKET_DRATE_M 405002 + static const uint16_t packet_setup[] = { + CC1120_DEVIATION_M, PACKET_DEV_M, + CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) | + (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) | + (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)), + CC1120_DRATE2, ((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) | + (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)), + CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff), + CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff), + CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | + (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)), + CC1120_PKT_CFG1, ((1 << CC1120_PKT_CFG1_WHITE_DATA) | + (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) | + (1 << CC1120_PKT_CFG1_APPEND_STATUS)), }; void @@ -285,6 +447,8 @@ ao_radio_idle(void) if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE) break; } + ao_radio_strobe(CC1120_SFTX); + ao_radio_strobe(CC1120_SFRX); } static const uint16_t radio_setup[] = { @@ -297,8 +461,8 @@ static void ao_radio_isr(void) { ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - ao_radio_done = 1; - ao_wakeup(&ao_radio_done); + ao_radio_wake = 1; + ao_wakeup(&ao_radio_wake); } static void @@ -306,15 +470,17 @@ ao_radio_setup(void) { int i; + ao_radio_strobe(CC1120_SRES); + for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2) ao_radio_reg_write(radio_setup[i], radio_setup[i+1]); - /* Disable GPIO2 pin (radio_int) */ - ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_HIGHZ); + /* Enable marc status interrupt on gpio 2 pin */ + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP); /* Enable the EXTI interrupt for the appropriate pin */ ao_enable_port(AO_CC1120_INT_PORT); - ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_RISING, ao_radio_isr); + ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_isr); ao_radio_set_packet(); ao_radio_configured = 1; @@ -534,17 +700,24 @@ static void ao_radio_show(void) { printf ("Status: %02x\n", status); printf ("CHIP_RDY: %d\n", (status >> CC1120_STATUS_CHIP_RDY) & 1); printf ("STATE: %s\n", cc1120_state_name[(status >> CC1120_STATUS_STATE) & CC1120_STATUS_STATE_MASK]); + printf ("MARC: %02x\n", ao_radio_marc_status()); for (i = 0; i < AO_NUM_CC1120_REG; i++) printf ("\t%02x %-20.20s\n", ao_radio_reg_read(ao_cc1120_reg[i].addr), ao_cc1120_reg[i].name); ao_radio_put(); } + +static void ao_radio_beep(void) { + ao_radio_rdf(120); +} + #endif static const struct ao_cmds ao_radio_cmds[] = { { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" }, #if CC1120_DEBUG { ao_radio_show, "R\0Show CC1120 status" }, + { ao_radio_beep, "B\0Emit an RDF beacon" }, #endif { 0, NULL } }; diff --git a/src/drivers/ao_cc1120.h b/src/drivers/ao_cc1120.h index 67c0a1b8..0f03f2c7 100644 --- a/src/drivers/ao_cc1120.h +++ b/src/drivers/ao_cc1120.h @@ -110,18 +110,101 @@ #define CC1120_SYNC1 0x06 #define CC1120_SYNC0 0x07 #define CC1120_SYNC_CFG1 0x08 +#define CC1120_SYNC_CFG1_DEM_CFG 5 +#define CC1120_SYNC_CFG1_DEM_CFG_PQT_GATING_DISABLED 0 +#define CC1120_SYNC_CFG1_DEM_CFG_PQT_GATING_ENABLED 2 +#define CC1120_SYNC_CFG1_DEM_CFG_MASK 0x7 + +#define CC1120_SYNC_CFG1_SYNC_THR 0 +#define CC1120_SYNC_CFG1_SYNC_MASK 0x1f + #define CC1120_SYNC_CFG0 0x09 +#define CC1120_SYNC_CFG0_SYNC_MODE 2 +#define CC1120_SYNC_CFG0_SYNC_MODE_NONE 0 +#define CC1120_SYNC_CFG0_SYNC_MODE_11_BITS 1 +#define CC1120_SYNC_CFG0_SYNC_MODE_16_BITS 2 +#define CC1120_SYNC_CFG0_SYNC_MODE_18_BITS 3 +#define CC1120_SYNC_CFG0_SYNC_MODE_24_BITS 4 +#define CC1120_SYNC_CFG0_SYNC_MODE_32_BITS 5 +#define CC1120_SYNC_CFG0_SYNC_MODE_16H_BITS 6 +#define CC1120_SYNC_CFG0_SYNC_MODE_16D_BITS 7 +#define CC1120_SYNC_CFG0_SYNC_MODE_MASK 7 +#define CC1120_SYNC_CFG0_SYNC_NUM_ERROR 0 +#define CC1120_SYNC_CFG0_SYNC_NUM_ERROR_0 0 +#define CC1120_SYNC_CFG0_SYNC_NUM_ERROR_2 1 +#define CC1120_SYNC_CFG0_SYNC_NUM_ERROR_DISABLED 3 +#define CC1120_SYNC_CFG0_SYNC_NUM_ERROR_MASK 3 + #define CC1120_DEVIATION_M 0x0a #define CC1120_MODCFG_DEV_E 0x0b +#define CC1120_MODCFG_DEV_E_MODEM_MODE 6 +#define CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL 0 +#define CC1120_MODCFG_DEV_E_MODEM_MODE_DSSS_REPEAT 1 +#define CC1120_MODCFG_DEV_E_MODEM_MODE_DSSS_PN 2 +#define CC1120_MODCFG_DEV_E_MODEM_MODE_MASK 3 +#define CC1120_MODCFG_DEV_E_MOD_FORMAT 3 +#define CC1120_MODCFG_DEV_E_MOD_FORMAT_2_FSK 0 +#define CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK 1 +#define CC1120_MODCFG_DEV_E_MOD_FORMAT_ASK_OOK 3 +#define CC1120_MODCFG_DEV_E_MOD_FORMAT_4_FSK 4 +#define CC1120_MODCFG_DEV_E_MOD_FORMAT_4_GFSK 5 +#define CC1120_MODCFG_DEV_E_MOD_FORMAT_SC_MSK_UNSHAPED 6 +#define CC1120_MODCFG_DEV_E_MOD_FORMAT_SC_MSK_SHAPED 7 +#define CC1120_MODCFG_DEV_E_MOD_FORMAT_MASK 7 +#define CC1120_MODCFG_DEV_E_DEV_E 0 +#define CC1120_MODCFG_DEV_E_DEV_E_MASK 7 + #define CC1120_DCFILT_CFG 0x0c #define CC1120_PREAMBLE_CFG1 0x0d +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE 2 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_NONE 0 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_0_5_BYTE 1 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_1_BYTE 2 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_1_5_BYTE 3 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_2_BYTES 4 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_3_BYTES 5 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES 6 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_5_BYTES 7 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_6_BYTES 8 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_7_BYTES 9 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_8_BYTES 10 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_12_BYTES 11 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_24_BYTES 12 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_30_BYTES 13 +#define CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_MASK 0xf + +#define CC1120_PREAMBLE_CFG1_PREAMBLE_WORD 0 +#define CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA 0 +#define CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_55 1 +#define CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_33 2 +#define CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_CC 3 +#define CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_MASK 3 + #define CC1120_PREAMBLE_CFG0 0x0e #define CC1120_FREQ_IF_CFG 0x0f #define CC1120_IQIC 0x10 #define CC1120_CHAN_BW 0x11 #define CC1120_MDMCFG1 0x12 +#define CC1120_MDMCFG1_CARRIER_SENSE_GATE 7 +#define CC1120_MDMCFG1_FIFO_EN 6 +#define CC1120_MDMCFG1_MANCHESTER_EN 5 +#define CC1120_MDMCFG1_INVERT_DATA_EN 4 +#define CC1120_MDMCFG1_COLLISION_DETECT_EN 3 +#define CC1120_MDMCFG1_DVGA_GAIN 1 +#define CC1120_MDMCFG1_DVGA_GAIN_0 0 +#define CC1120_MDMCFG1_DVGA_GAIN_3 1 +#define CC1120_MDMCFG1_DVGA_GAIN_6 2 +#define CC1120_MDMCFG1_DVGA_GAIN_9 3 +#define CC1120_MDMCFG1_DVGA_GAIN_MASK 3 +#define CC1120_MDMCFG1_SINGLE_ADC_EN 0 + #define CC1120_MDMCFG0 0x13 #define CC1120_DRATE2 0x14 +#define CC1120_DRATE2_DATARATE_E 4 +#define CC1120_DRATE2_DATARATE_E_MASK 0xf +#define CC1120_DRATE2_DATARATE_M_19_16 0 +#define CC1120_DRATE2_DATARATE_M_19_16_MASK 0xf + #define CC1120_DRATE1 0x15 #define CC1120_DRATE0 0x16 #define CC1120_AGC_REF 0x17 @@ -134,14 +217,81 @@ #define CC1120_FIFO_CFG 0x1e #define CC1120_DEV_ADDR 0x1f #define CC1120_SETTLING_CFG 0x20 +#define CC1120_SETTLING_CFG_FS_AUTOCAL 3 +#define CC1120_SETTLING_CFG_FS_AUTOCAL_NEVER 0 +#define CC1120_SETTLING_CFG_FS_AUTOCAL_IDLE_TO_ON 1 +#define CC1120_SETTLING_CFG_FS_AUTOCAL_ON_TO_IDLE 2 +#define CC1120_SETTLING_CFG_FS_AUTOCAL_EVERY_4TH_TIME 3 +#define CC1120_SETTLING_CFG_FS_AUTOCAL_MASK 3 +#define CC1120_SETTLING_CFG_LOCK_TIME 1 +#define CC1120_SETTLING_CFG_LOCK_TIME_50_20 0 +#define CC1120_SETTLING_CFG_LOCK_TIME_70_30 1 +#define CC1120_SETTLING_CFG_LOCK_TIME_100_40 2 +#define CC1120_SETTLING_CFG_LOCK_TIME_150_60 3 +#define CC1120_SETTLING_CFG_LOCK_TIME_MASK 3 +#define CC1120_SETTLING_CFG_FSREG_TIME 0 +#define CC1120_SETTLING_CFG_FSREG_TIME_30 0 +#define CC1120_SETTLING_CFG_FSREG_TIME_60 1 +#define CC1120_SETTLING_CFG_FSREG_TIME_MASK 1 + #define CC1120_FS_CFG 0x21 +#define CC1120_FS_CFG_LOCK_EN 4 +#define CC1120_FS_CFG_FSD_BANDSELECT 0 +#define CC1120_FS_CFG_FSD_BANDSELECT_820_960 2 +#define CC1120_FS_CFG_FSD_BANDSELECT_410_480 4 +#define CC1120_FS_CFG_FSD_BANDSELECT_273_320 6 +#define CC1120_FS_CFG_FSD_BANDSELECT_205_240 8 +#define CC1120_FS_CFG_FSD_BANDSELECT_164_192 10 +#define CC1120_FS_CFG_FSD_BANDSELECT_136_160 11 +#define CC1120_FS_CFG_FSD_BANDSELECT_MASK 0xf + #define CC1120_WOR_CFG1 0x22 #define CC1120_WOR_CFG0 0x23 #define CC1120_WOR_EVENT0_MSB 0x24 #define CC1120_WOR_EVENT0_LSB 0x25 #define CC1120_PKT_CFG2 0x26 +#define CC1120_PKT_CFG2_CCA_MODE 2 +#define CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR 0 +#define CC1120_PKT_CFG2_CCA_MODE_RSSI_THRESHOLD 1 +#define CC1120_PKT_CFG2_CCA_MODE_NOT_RECEIVING 2 +#define CC1120_PKT_CFG2_CCA_MODE_RSSI_OR_NOT 3 +#define CC1120_PKT_CFG2_CCA_MODE_RSSI_AND_ETSI_LBT 4 +#define CC1120_PKT_CFG2_CCA_MODE_MASK 7 +#define CC1120_PKT_CFG2_PKT_FORMAT 0 +#define CC1120_PKT_CFG2_PKT_FORMAT_NORMAL 0 +#define CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL 1 +#define CC1120_PKT_CFG2_PKT_FORMAT_RANDOM 2 +#define CC1120_PKT_CFG2_PKT_FORMAT_TRANSPARENT_SERIAL 3 +#define CC1120_PKT_CFG2_PKT_FORMAT_MASK 3 + #define CC1120_PKT_CFG1 0x27 +#define CC1120_PKT_CFG1_WHITE_DATA 6 +#define CC1120_PKT_CFG1_ADDR_CHECK_CFG 4 +#define CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE 0 +#define CC1120_PKT_CFG1_ADDR_CHECK_CFG_CHECK 1 +#define CC1120_PKT_CFG1_ADDR_CHECK_CFG_00_BROADCAST 2 +#define CC1120_PKT_CFG1_ADDR_CHECK_CFG_00_FF_BROADCAST 3 +#define CC1120_PKT_CFG1_ADDR_CHECK_CFG_MASK 3 +#define CC1120_PKT_CFG1_CRC_CFG 2 +#define CC1120_PKT_CFG1_CRC_CFG_DISABLED 0 +#define CC1120_PKT_CFG1_CRC_CFG_CRC16_INIT_ONES 1 +#define CC1120_PKT_CFG1_CRC_CFG_CRC16_INIT_ZEROS 2 +#define CC1120_PKT_CFG1_CRC_CFG_MASK 3 +#define CC1120_PKT_CFG1_BYTE_SWAP_EN 1 +#define CC1120_PKT_CFG1_APPEND_STATUS 0 + #define CC1120_PKT_CFG0 0x28 +#define CC1120_PKT_CFG0_LENGTH_CONFIG 5 +#define CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED 0 +#define CC1120_PKT_CFG0_LENGTH_CONFIG_VARIABLE 1 +#define CC1120_PKT_CFG0_LENGTH_CONFIG_INFINITE 2 +#define CC1120_PKT_CFG0_LENGTH_CONFIG_VARIABLE_5LSB 3 +#define CC1120_PKT_CFG0_LENGTH_CONFIG_MASK 3 +#define CC1120_PKT_CFG0_PKG_BIT_LEN 2 +#define CC1120_PKT_CFG0_PKG_BIT_LEN_MASK 7 +#define CC1120_PKT_CFG0_UART_MODE_EN 1 +#define CC1120_PKT_CFG0_UART_SWAP_EN 0 + #define CC1120_RFEND_CFG1 0x29 #define CC1120_RFEND_CFG0 0x2a #define CC1120_PA_CFG2 0x2b @@ -283,6 +433,20 @@ #define CC1120_RX_STATUS (CC1120_EXTENDED_BIT | 0x92) #define CC1120_TX_STATUS (CC1120_EXTENDED_BIT | 0x93) #define CC1120_MARC_STATUS1 (CC1120_EXTENDED_BIT | 0x94) +# define CC1120_MARC_STATUS1_NO_FAILURE 0 +# define CC1120_MARC_STATUS1_RX_TIMEOUT 1 +# define CC1120_MARC_STATUS1_RX_TERMINATION 2 +# define CC1120_MARC_STATUS1_EWOR_SYNC_LOST 3 +# define CC1120_MARC_STATUS1_MAXIMUM_LENGTH 4 +# define CC1120_MARC_STATUS1_ADDRESS 5 +# define CC1120_MARC_STATUS1_CRC 6 +# define CC1120_MARC_STATUS1_TX_FIFO_OVERFLOW 7 +# define CC1120_MARC_STATUS1_TX_FIFO_UNDERFLOW 8 +# define CC1120_MARC_STATUS1_RX_FIFO_OVERFLOW 9 +# define CC1120_MARC_STATUS1_RX_FIFO_UNDERFLOW 10 +# define CC1120_MARC_STATUS1_TX_ON_CCA_FAILED 11 +# define CC1120_MARC_STATUS1_TX_FINISHED 0x40 +# define CC1120_MARC_STATUS1_RX_FINISHED 0x80 #define CC1120_MARC_STATUS0 (CC1120_EXTENDED_BIT | 0x95) #define CC1120_PA_IFAMP_TEST (CC1120_EXTENDED_BIT | 0x96) #define CC1120_FSRF_TEST (CC1120_EXTENDED_BIT | 0x97) diff --git a/src/drivers/ao_cc1120_CC1120.h b/src/drivers/ao_cc1120_CC1120.h index a96c22fc..1799c274 100644 --- a/src/drivers/ao_cc1120_CC1120.h +++ b/src/drivers/ao_cc1120_CC1120.h @@ -21,15 +21,16 @@ * ***************************************************************/ - CC1120_SYNC3, 0x93, /* Sync Word Configuration [31:24] */ CC1120_SYNC2, 0x0b, /* Sync Word Configuration [23:16] */ CC1120_SYNC1, 0x51, /* Sync Word Configuration [15:8] */ CC1120_SYNC0, 0xde, /* Sync Word Configuration [7:0] */ CC1120_SYNC_CFG1, 0x08, /* Sync Word Detection Configuration */ CC1120_SYNC_CFG0, 0x17, /* Sync Word Length Configuration */ +#if 0 CC1120_DEVIATION_M, 0x50, /* Frequency Deviation Configuration */ CC1120_MODCFG_DEV_E, 0x0d, /* Modulation Format and Frequency Deviation Configuration */ +#endif CC1120_DCFILT_CFG, 0x1c, /* Digital DC Removal Configuration */ CC1120_PREAMBLE_CFG1, 0x18, /* Preamble Length Configuration */ CC1120_PREAMBLE_CFG0, 0x2a, /* */ @@ -38,9 +39,11 @@ CC1120_CHAN_BW, 0x02, /* Channel Filter Configuration */ CC1120_MDMCFG1, 0x46, /* General Modem Parameter Configuration */ CC1120_MDMCFG0, 0x05, /* General Modem Parameter Configuration */ +#if 0 CC1120_DRATE2, 0x93, /* Data Rate Configuration Exponent and Mantissa [19:16] */ CC1120_DRATE1, 0xa4, /* Data Rate Configuration Mantissa [15:8] */ CC1120_DRATE0, 0x00, /* Data Rate Configuration Mantissa [7:0] */ +#endif CC1120_AGC_REF, 0x20, /* AGC Reference Level Configuration */ CC1120_AGC_CS_THR, 0x19, /* Carrier Sense Threshold Configuration */ CC1120_AGC_GAIN_ADJUST, 0x00, /* RSSI Offset Configuration */ @@ -50,14 +53,21 @@ CC1120_AGC_CFG0, 0xcf, /* AGC Configuration */ CC1120_FIFO_CFG, 0x00, /* FIFO Configuration */ CC1120_DEV_ADDR, 0x00, /* Device Address Configuration */ - CC1120_SETTLING_CFG, 0x03, /* Frequency Synthesizer Calibration and Settling Configuration */ - CC1120_FS_CFG, 0x14, /* Frequency Synthesizer Configuration */ + CC1120_SETTLING_CFG, /* Frequency Synthesizer Calibration and Settling Configuration */ + (CC1120_SETTLING_CFG_FS_AUTOCAL_IDLE_TO_ON << CC1120_SETTLING_CFG_FS_AUTOCAL) | + (CC1120_SETTLING_CFG_LOCK_TIME_50_20 << CC1120_SETTLING_CFG_LOCK_TIME) | + (CC1120_SETTLING_CFG_FSREG_TIME_60 << CC1120_SETTLING_CFG_FSREG_TIME), + CC1120_FS_CFG, /* Frequency Synthesizer Configuration */ + (1 << CC1120_FS_CFG_LOCK_EN) | + (CC1120_FS_CFG_FSD_BANDSELECT_410_480 << CC1120_FS_CFG_FSD_BANDSELECT), CC1120_WOR_CFG1, 0x08, /* eWOR Configuration, Reg 1 */ CC1120_WOR_CFG0, 0x21, /* eWOR Configuration, Reg 0 */ CC1120_WOR_EVENT0_MSB, 0x00, /* Event 0 Configuration */ CC1120_WOR_EVENT0_LSB, 0x00, /* Event 0 Configuration */ +#if 0 CC1120_PKT_CFG2, 0x04, /* Packet Configuration, Reg 2 */ CC1120_PKT_CFG1, 0x45, /* Packet Configuration, Reg 1 */ +#endif CC1120_PKT_CFG0, 0x20, /* Packet Configuration, Reg 0 */ CC1120_RFEND_CFG1, 0x0f, /* RFEND Configuration, Reg 1 */ CC1120_RFEND_CFG0, 0x00, /* RFEND Configuration, Reg 0 */ -- cgit v1.2.3 From 6a62edd4a1f01a6ee380c3aabaff3f437e8d6f1e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 May 2012 23:14:14 -0700 Subject: altos: Conditional byte swapping in mpu6000 driver Only needed on LSB machines. Signed-off-by: Keith Packard --- src/drivers/ao_mpu6000.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index d27c42b0..eb4044be 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -73,11 +73,13 @@ ao_mpu6000_sample(struct ao_mpu6000_sample *sample) int i = sizeof (*sample) / 2; ao_mpu6000_read(MPU6000_ACCEL_XOUT_H, sample, sizeof (*sample)); - /* byte swap (sigh) */ +#if __BYTE_ORDER == __LITTLE_ENDIAN + /* byte swap */ while (i--) { uint16_t t = *d; *d++ = (t >> 8) | (t << 8); } +#endif } #define G 981 /* in cm/s² */ -- cgit v1.2.3 From 1541fc0bde71f503b1ae5757497e9e1e6d023111 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 7 May 2012 23:14:57 -0700 Subject: altos: Check MS5607 CRC. Clean up MS5607 API It's not ready for flight yet, but at least it's sensible now. Signed-off-by: Keith Packard --- src/drivers/ao_ms5607.c | 124 ++++++++++++++++++++++++++++++++---------------- src/drivers/ao_ms5607.h | 22 +++++++++ 2 files changed, 104 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 3c0a310d..4594f07c 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -18,18 +18,8 @@ #include #include "ao_ms5607.h" -struct ms5607_prom { - uint16_t reserved; - uint16_t sens; - uint16_t off; - uint16_t tcs; - uint16_t tco; - uint16_t tref; - uint16_t tempsens; - uint16_t crc; -}; - static struct ms5607_prom ms5607_prom; +static uint8_t ms5607_configured; static void ao_ms5607_start(void) { @@ -54,38 +44,68 @@ ao_ms5607_reset(void) { ao_ms5607_stop(); } -static uint16_t -ao_ms5607_prom_read(uint8_t addr) +static uint8_t +ao_ms5607_crc(uint8_t *prom) { - uint8_t cmd = AO_MS5607_PROM_READ(addr); - uint8_t d[2]; - uint16_t v; - - ao_ms5607_start(); - ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); - ao_spi_recv(d, 2, AO_MS5607_SPI_INDEX); - ao_ms5607_stop(); - return ((uint16_t) d[0] << 8) | (uint16_t) d[1]; + uint8_t crc_byte = prom[15]; + uint8_t cnt; + uint16_t n_rem = 0; + uint16_t crc_read; + uint8_t n_bit; + + prom[15] = 0; + for (cnt = 0; cnt < 16; cnt++) { + n_rem ^= prom[cnt]; + for (n_bit = 8; n_bit > 0; n_bit--) { + if (n_rem & 0x8000) + n_rem = (n_rem << 1) ^ 0x3000; + else + n_rem = (n_rem << 1); + } + } + n_rem = (n_rem >> 12) & 0xf; + prom[15] = crc_byte; + return n_rem; } static void -ao_ms5607_init_chip(void) { +ao_ms5607_prom_read(struct ms5607_prom *prom) +{ uint8_t addr; - uint16_t *prom; + uint8_t crc; + uint16_t *r; + + r = (uint16_t *) prom; + for (addr = 0; addr < 8; addr++) { + uint8_t cmd = AO_MS5607_PROM_READ(addr); + ao_ms5607_start(); + ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); + ao_spi_recv(r, 2, AO_MS5607_SPI_INDEX); + ao_ms5607_stop(); + r++; + } + crc = ao_ms5607_crc((uint8_t *) prom); + if (crc != (((uint8_t *) prom)[15] & 0xf)) + printf ("MS5607 PROM CRC error (computed %x actual %x)\n", crc, (((uint8_t *) prom)[15] & 0xf)); + +#if __BYTE_ORDER == __LITTLE_ENDIAN + /* Byte swap */ + r = (uint16_t *) prom; + for (addr = 0; addr < 8; addr++) { + uint16_t t = *r; + *r++ = (t << 8) | (t >> 8); + } +#endif +} +static void +ao_ms5607_setup(void) +{ + if (ms5607_configured) + return; + ms5607_configured = 1; ao_ms5607_reset(); - prom = &ms5607_prom.reserved; - - for (addr = 0; addr <= 7; addr++) - prom[addr] = ao_ms5607_prom_read(addr); - printf ("reserved: 0x%x\n", ms5607_prom.reserved); - printf ("sens: 0x%x\n", ms5607_prom.sens); - printf ("off: 0x%x\n", ms5607_prom.off); - printf ("tcs: 0x%x\n", ms5607_prom.tcs); - printf ("tco: 0x%x\n", ms5607_prom.tco); - printf ("tref: 0x%x\n", ms5607_prom.tref); - printf ("tempsens: 0x%x\n", ms5607_prom.tempsens); - printf ("crc: 0x%x\n", ms5607_prom.crc); + ao_ms5607_prom_read(&ms5607_prom); } static uint32_t @@ -108,8 +128,8 @@ ao_ms5607_convert(uint8_t cmd) { return ((uint32_t) reply[0] << 16) | ((uint32_t) reply[1] << 8) | (uint32_t) reply[2]; } -static void -ao_ms5607_dump(void) +void +ao_ms5607_sample(struct ao_ms5607_sample *sample) { uint8_t addr; uint32_t D1, D2; @@ -119,6 +139,8 @@ ao_ms5607_dump(void) int64_t SENS; int32_t P; + ao_ms5607_setup(); + D2 = ao_ms5607_convert(AO_MS5607_CONVERT_D2_4096); printf ("Conversion D2: %d\n", D2); D1 = ao_ms5607_convert(AO_MS5607_CONVERT_D1_4096); @@ -137,16 +159,33 @@ ao_ms5607_dump(void) int32_t TEMPM = TEMP - 2000; int64_t OFF2 = (61 * (int64_t) TEMPM * (int64_t) TEMPM) >> 4; int64_t SENS2 = 2 * (int64_t) TEMPM * (int64_t) TEMPM; + if (TEMP < 1500) { + int32_t TEMPP = TEMP + 1500; + int64_t TEMPP2 = TEMPP * TEMPP; + OFF2 = OFF2 + 15 * TEMPP2; + SENS2 = SENS2 + 8 * TEMPP2; + } + TEMP -= T2; + OFF -= OFF2; + SENS -= SENS2; } P = ((((int64_t) D1 * SENS) >> 21) - OFF) >> 15; - - printf ("Temperature: %d\n", TEMP); - printf ("Pressure %d\n", P); + sample->temp = TEMP; + sample->pres = P; +} + +static void +ao_ms5607_dump(void) +{ + struct ao_ms5607_sample sample; + + ao_ms5607_sample(&sample); + printf ("Temperature: %d\n", sample.temp); + printf ("Pressure %d\n", sample.pres); } __code struct ao_cmds ao_ms5607_cmds[] = { - { ao_ms5607_init_chip, "i\0Init MS5607" }, { ao_ms5607_dump, "p\0Display MS5607 data" }, { 0, NULL }, }; @@ -154,6 +193,7 @@ __code struct ao_cmds ao_ms5607_cmds[] = { void ao_ms5607_init(void) { + ms5607_configured = 0; ao_cmd_register(&ao_ms5607_cmds[0]); ao_spi_init_cs(AO_MS5607_CS_GPIO, (1 << AO_MS5607_CS)); } diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h index 489190a4..29df25e4 100644 --- a/src/drivers/ao_ms5607.h +++ b/src/drivers/ao_ms5607.h @@ -35,4 +35,26 @@ #define AO_MS5607_ADC_READ 0x00 #define AO_MS5607_PROM_READ(ad) (0xA0 | ((ad) << 1)) +struct ms5607_prom { + uint16_t reserved; + uint16_t sens; + uint16_t off; + uint16_t tcs; + uint16_t tco; + uint16_t tref; + uint16_t tempsens; + uint16_t crc; +}; + +struct ao_ms5607_sample { + int32_t temp; + int32_t pres; +}; + +void +ao_ms5607_init(void); + +void +ao_ms5607_sample(struct ao_ms5607_sample *sample); + #endif /* _AO_MS5607_H_ */ -- cgit v1.2.3 From 5d8b9d524d6424ff98dcc4155fe8b8bd892b6d8f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 May 2012 20:04:57 -0700 Subject: altos: Add conversion between Pa and meters To be used with the MS5607 which generates data in calibrated units. Signed-off-by: Keith Packard --- src/Makefile | 6 +- src/core/ao.h | 12 ++ src/core/ao_convert_pa.c | 72 +++++++++++ src/core/ao_convert_pa_test.c | 76 ++++++++++++ src/test/Makefile | 5 +- src/util/make-altitude-pa | 275 ++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 444 insertions(+), 2 deletions(-) create mode 100644 src/core/ao_convert_pa.c create mode 100644 src/core/ao_convert_pa_test.c create mode 100644 src/util/make-altitude-pa (limited to 'src') diff --git a/src/Makefile b/src/Makefile index db9bd508..c2e324c4 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,6 +4,7 @@ # vpath make-altitude util +vpath make-altitude-pa util vpath make-kalman util vpath kalman.5c kalman vpath kalman_filter.5c kalman @@ -45,11 +46,14 @@ uninstall: all-recursive: all-local -all-local: altitude.h ao_kalman.h +all-local: altitude.h altitude-pa.h ao_kalman.h altitude.h: make-altitude nickle $< > $@ +altitude-pa.h: make-altitude-pa + nickle $< > $@ + ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c bash $< kalman > $@ diff --git a/src/core/ao.h b/src/core/ao.h index 27b9c5c4..a2092cfe 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -282,6 +282,18 @@ ao_altitude_to_pres(int16_t alt) __reentrant; int16_t ao_temp_to_dC(int16_t temp) __reentrant; +/* + * ao_convert_pa.c + * + * Convert between pressure in Pa and altitude in meters + */ + +int32_t +ao_pa_to_altitude(int32_t pa); + +int32_t +ao_altitude_to_pa(int32_t alt); + #if HAS_DBG #include #endif diff --git a/src/core/ao_convert_pa.c b/src/core/ao_convert_pa.c new file mode 100644 index 00000000..0c93caea --- /dev/null +++ b/src/core/ao_convert_pa.c @@ -0,0 +1,72 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#if !defined(AO_CONVERT_TEST) && !defined(AO_FLIGHT_TEST) +#include "ao.h" +#endif + +static const int32_t altitude_table[] = { +#include "altitude-pa.h" +}; + +#define ALT_SCALE (1 << ALT_SHIFT) +#define ALT_MASK (ALT_SCALE - 1) + +int32_t +ao_pa_to_altitude(int32_t pa) +{ + int16_t o; + int16_t part; + int32_t low, high; + + if (pa < 0) + pa = 0; + if (pa > 120000) + pa = 120000; + o = pa >> ALT_SHIFT; + part = pa & ALT_MASK; + + low = (int32_t) altitude_table[o] * (ALT_SCALE - part); + high = (int32_t) altitude_table[o+1] * part + (ALT_SCALE >> 1); + return (low + high) >> ALT_SHIFT; +} + +int32_t +ao_altitude_to_pa(int32_t alt) +{ + int32_t span, sub_span; + uint16_t l, h, m; + int32_t pa; + + l = 0; + h = NALT - 1; + while ((h - l) != 1) { + m = (l + h) >> 1; + if (altitude_table[m] < alt) + h = m; + else + l = m; + } + span = altitude_table[l] - altitude_table[h]; + sub_span = altitude_table[l] - alt; + pa = ((((int32_t) l * (span - sub_span) + (int32_t) h * sub_span) << ALT_SHIFT) + (span >> 1)) / span; + if (pa > 120000) + pa = 120000; + if (pa < 0) + pa = 0; + return pa; +} diff --git a/src/core/ao_convert_pa_test.c b/src/core/ao_convert_pa_test.c new file mode 100644 index 00000000..972a4d4c --- /dev/null +++ b/src/core/ao_convert_pa_test.c @@ -0,0 +1,76 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#define AO_CONVERT_TEST +#include "ao_host.h" +#include "ao_convert_pa.c" + +#define STEP_P 1 +#define STEP_A 1 + +static inline i_abs(int i) { return i < 0 ? -i : i; } + +main () +{ + int i; + int32_t p_to_a, p_to_a_to_p; + int32_t a_to_p, a_to_p_to_a; + int max_p_error = 0, max_p_error_p = -1; + int max_a_error = 0, max_a_error_a = -1; + int p_error; + int a_error; + int ret = 0; + + for (i = 0; i < 120000 + STEP_P; i += STEP_P) { + if (i > 120000) + i = 120000; + p_to_a = ao_pa_to_altitude(i); + p_to_a_to_p = ao_altitude_to_pa(p_to_a); + p_error = i_abs(p_to_a_to_p - i); + if (p_error > max_p_error) { + max_p_error = p_error; + max_p_error_p = i; + } +// printf ("pa %d alt %d pa %d\n", +// i, p_to_a, p_to_a_to_p); + } + for (i = -1450; i < 74250 + STEP_A; i += STEP_A) { + if (i > 74250) + i = 74250; + a_to_p = ao_altitude_to_pa(i); + a_to_p_to_a = ao_pa_to_altitude(a_to_p); + a_error = i_abs(a_to_p_to_a - i); + if (a_error > max_a_error) { + max_a_error = a_error; + max_a_error_a = i; + } +// printf ("alt %d pa %d alt %d\n", +// i, a_to_p, a_to_p_to_a); + } + if (max_p_error > 2) { + printf ("max p error %d at %d\n", max_p_error, + max_p_error_p); + ret++; + } + if (max_a_error > 1) { + printf ("max a error %d at %d\n", max_a_error, + max_a_error_a); + ret++; + } + return ret; +} diff --git a/src/test/Makefile b/src/test/Makefile index 4e403da6..3c2b8732 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,6 +1,6 @@ vpath % ..:../core:../drivers:../util -PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_gps_test ao_gps_test_skytraq ao_convert_test +PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_gps_test ao_gps_test_skytraq ao_convert_test ao_convert_pa_test KALMAN=make-kalman @@ -34,5 +34,8 @@ ao_gps_test_skytraq: ao_gps_test_skytraq.c ao_gps_skytraq.c ao_gps_print.c ao_ho ao_convert_test: ao_convert_test.c ao_convert.c altitude.h cc $(CFLAGS) -o $@ $< +ao_convert_pa_test: ao_convert_pa_test.c ao_convert_pa.c altitude-pa.h + cc $(CFLAGS) -o $@ $< + ao_kalman.h: $(KALMAN) (cd .. && make ao_kalman.h) \ No newline at end of file diff --git a/src/util/make-altitude-pa b/src/util/make-altitude-pa new file mode 100644 index 00000000..190b36fc --- /dev/null +++ b/src/util/make-altitude-pa @@ -0,0 +1,275 @@ +#!/usr/bin/nickle -f +/* + * Pressure Sensor Model, version 1.1 + * + * written by Holly Grimes + * + * Uses the International Standard Atmosphere as described in + * "A Quick Derivation relating altitude to air pressure" (version 1.03) + * from the Portland State Aerospace Society, except that the atmosphere + * is divided into layers with each layer having a different lapse rate. + * + * Lapse rate data for each layer was obtained from Wikipedia on Sept. 1, 2007 + * at site MAXIMUM_ALTITUDE) /* FIX ME: use sensor data to improve model */ + return 0; + + /* calculate the base temperature and pressure for the atmospheric layer + associated with the inputted altitude */ + for(layer_number = 0; layer_number < NUMBER_OF_LAYERS - 1 && altitude > base_altitude[layer_number + 1]; layer_number++) { + delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + base_pressure *= exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + base_pressure *= pow(base, exponent); + } + base_temperature += delta_z * lapse_rate[layer_number]; + } + + /* calculate the pressure at the inputted altitude */ + delta_z = altitude - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + pressure = base_pressure * exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + pressure = base_pressure * pow(base, exponent); + } + + return pressure; +} + + +/* outputs the altitude associated with the given pressure. the altitude + returned is measured with respect to the mean sea level */ +real pressure_to_altitude(real pressure) { + + real next_base_temperature = LAYER0_BASE_TEMPERATURE; + real next_base_pressure = LAYER0_BASE_PRESSURE; + + real altitude; + real base_pressure; + real base_temperature; + real base; /* base for function to determine base pressure of next layer */ + real exponent; /* exponent for function to determine base pressure + of next layer */ + real coefficient; + int layer_number; /* identifies layer in the atmosphere */ + int delta_z; /* difference between two altitudes */ + + if (pressure < 0) /* illegal pressure */ + return -1; + if (pressure < MINIMUM_PRESSURE) /* FIX ME: use sensor data to improve model */ + return MAXIMUM_ALTITUDE; + + /* calculate the base temperature and pressure for the atmospheric layer + associated with the inputted pressure. */ + layer_number = -1; + do { + layer_number++; + base_pressure = next_base_pressure; + base_temperature = next_base_temperature; + delta_z = base_altitude[layer_number + 1] - base_altitude[layer_number]; + if (lapse_rate[layer_number] == 0.0) { + exponent = GRAVITATIONAL_ACCELERATION * delta_z + / AIR_GAS_CONSTANT / base_temperature; + next_base_pressure *= exp(exponent); + } + else { + base = (lapse_rate[layer_number] * delta_z / base_temperature) + 1.0; + exponent = GRAVITATIONAL_ACCELERATION / + (AIR_GAS_CONSTANT * lapse_rate[layer_number]); + next_base_pressure *= pow(base, exponent); + } + next_base_temperature += delta_z * lapse_rate[layer_number]; + } + while(layer_number < NUMBER_OF_LAYERS - 1 && pressure < next_base_pressure); + + /* calculate the altitude associated with the inputted pressure */ + if (lapse_rate[layer_number] == 0.0) { + coefficient = (AIR_GAS_CONSTANT / GRAVITATIONAL_ACCELERATION) + * base_temperature; + altitude = base_altitude[layer_number] + + coefficient * log(pressure / base_pressure); + } + else { + base = pressure / base_pressure; + exponent = AIR_GAS_CONSTANT * lapse_rate[layer_number] + / GRAVITATIONAL_ACCELERATION; + coefficient = base_temperature / lapse_rate[layer_number]; + altitude = base_altitude[layer_number] + + coefficient * (pow(base, exponent) - 1); + } + + return altitude; +} + +real feet_to_meters(real feet) +{ + return feet * (12 * 2.54 / 100); +} + +real meters_to_feet(real meters) +{ + return meters / (12 * 2.54 / 100); +} + +/* + * Values for our MS5607 + * + * From the data sheet: + * + * Pressure range: 10-1200 mbar (1000 - 120000 Pa) + * + * Pressure data is reported in units of Pa + */ + +typedef struct { + real m, b; + int m_i, b_i; +} line_t; + +line_t best_fit(real[] values, int first, int last) { + real sum_x = 0, sum_x2 = 0, sum_y = 0, sum_xy = 0; + int n = last - first + 1; + real m, b; + int m_i, b_i; + + for (int i = first; i <= last; i++) { + sum_x += i; + sum_x2 += i**2; + sum_y += values[i]; + sum_xy += values[i] * i; + } + m = (n*sum_xy - sum_y*sum_x) / (n*sum_x2 - sum_x**2); + b = sum_y/n - m*(sum_x/n); + return (line_t) { m = m, b = b }; +} + +real min_Pa = 0; +real max_Pa = 120000; + +/* Target is an array of < 2000 entries */ +int pa_sample_shift = 3; +int pa_part_shift = 3; + +int num_part = ceil(max_Pa / (2 ** (pa_part_shift + pa_sample_shift))); + +int num_samples = num_part << pa_part_shift; + +real sample_to_Pa(int sample) = sample << pa_sample_shift; + +real sample_to_altitude(int sample) = pressure_to_altitude(sample_to_Pa(sample)); + +int part_to_sample(int part) = part << pa_part_shift; + +real[num_samples] alt = { [n] = sample_to_altitude(n) }; + +int seg_len = 1 << pa_part_shift; + +line_t [num_part] fit = { + [n] = best_fit(alt, n * seg_len, n * seg_len + seg_len - 1) +}; + +int[num_samples/seg_len + 1] alt_part; + +alt_part[0] = floor (fit[0].b + 0.5); +alt_part[dim(fit)] = floor(fit[dim(fit)-1].m * dim(fit) * seg_len + fit[dim(fit)-1].b + 0.5); + +for (int i = 0; i < dim(fit) - 1; i++) { + real here, there; + here = fit[i].m * (i+1) * seg_len + fit[i].b; + there = fit[i+1].m * (i+1) * seg_len + fit[i+1].b; + alt_part[i+1] = floor ((here + there) / 2 + 0.5); +} + +real sample_to_fit_altitude(int sample) { + int sub = sample // seg_len; + int off = sample % seg_len; + line_t l = fit[sub]; + real r_v; + real i_v; + + r_v = sample * l.m + l.b; + i_v = (alt_part[sub] * (seg_len - off) + alt_part[sub+1] * off) / seg_len; + return i_v; +} + +real max_error = 0; +int max_error_sample = 0; +real total_error = 0; + +for (int sample = 0; sample < num_samples; sample++) { + real Pa = sample_to_Pa(sample); + real meters = pressure_to_altitude(Pa); + + real meters_approx = sample_to_fit_altitude(sample); + real error = abs(meters - meters_approx); + + total_error += error; + if (error > max_error) { + max_error = error; + max_error_sample = sample; + } +# printf (" %7d, /* %6.2f kPa %5d sample approx %d */\n", +# floor (meters + 0.5), Pa / 1000, sample, floor(sample_to_fit_altitude(sample) + 0.5)); +} + +printf ("/*max error %f at %7.3f%%. Average error %f*/\n", max_error, max_error_sample / (num_samples - 1) * 100, total_error / num_samples); + +printf ("#define NALT %d\n", dim(alt_part)); +printf ("#define ALT_SHIFT %d\n", pa_part_shift + pa_sample_shift); + +for (int part = 0; part < dim(alt_part); part++) { + real kPa = sample_to_Pa(part_to_sample(part)) / 1000; + printf ("%9d, /* %6.2f kPa */\n", + alt_part[part], kPa); +} -- cgit v1.2.3 From 34bb17bc1a3d8a1c95b5e57f059e7a1747e17a03 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 May 2012 20:16:35 -0700 Subject: altos: Finish ms5607 support This has the MS5607 polling once each tick for pressure and temperature and then saving that in a global variable. The command UI provides for dumping the prom data so that an eeprom file can have raw sensor data along with the conversion factors necessary to compute useful values. Signed-off-by: Keith Packard --- src/core/ao.h | 1 + src/drivers/ao_ms5607.c | 114 +++++++++++++++++++++++++++++++++--------- src/drivers/ao_ms5607.h | 19 +++++-- src/megametrum-v0.1/Makefile | 3 +- src/megametrum-v0.1/ao_pins.h | 7 ++- 5 files changed, 115 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index a2092cfe..da1fd67b 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -115,6 +115,7 @@ ao_start_scheduler(void); #define AO_PANIC_BT 11 /* Communications with bluetooth device failed */ #define AO_PANIC_STACK 12 /* Stack overflow */ #define AO_PANIC_SPI 13 /* SPI communication failure */ +#define AO_PANIC_SELF_TEST 14 /* Self test failure */ /* Stop the operating system, beeping and blinking the reason */ void diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 4594f07c..f79c315a 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -16,10 +16,11 @@ */ #include +#include #include "ao_ms5607.h" -static struct ms5607_prom ms5607_prom; -static uint8_t ms5607_configured; +static struct ao_ms5607_prom ms5607_prom; +static uint8_t ms5607_configured; static void ao_ms5607_start(void) { @@ -69,7 +70,7 @@ ao_ms5607_crc(uint8_t *prom) } static void -ao_ms5607_prom_read(struct ms5607_prom *prom) +ao_ms5607_prom_read(struct ao_ms5607_prom *prom) { uint8_t addr; uint8_t crc; @@ -85,8 +86,12 @@ ao_ms5607_prom_read(struct ms5607_prom *prom) r++; } crc = ao_ms5607_crc((uint8_t *) prom); - if (crc != (((uint8_t *) prom)[15] & 0xf)) - printf ("MS5607 PROM CRC error (computed %x actual %x)\n", crc, (((uint8_t *) prom)[15] & 0xf)); + if (crc != (((uint8_t *) prom)[15] & 0xf)) { + printf ("MS5607 PROM CRC error (computed %x actual %x)\n", + crc, (((uint8_t *) prom)[15] & 0xf)); + flush(); + ao_panic(AO_PANIC_SELF_TEST); + } #if __BYTE_ORDER == __LITTLE_ENDIAN /* Byte swap */ @@ -108,17 +113,33 @@ ao_ms5607_setup(void) ao_ms5607_prom_read(&ms5607_prom); } +static uint8_t ao_ms5607_done; + +static void +ao_ms5607_isr(void) +{ + ao_ms5607_done = 1; + ao_wakeup(&ao_ms5607_done); +} + static uint32_t -ao_ms5607_convert(uint8_t cmd) { +ao_ms5607_get_sample(uint8_t cmd) { uint8_t reply[3]; uint8_t read; + uint16_t now; + + ao_ms5607_done = 0; ao_ms5607_start(); ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); + ao_exti_enable(&AO_MS5607_MISO_GPIO, AO_MS5607_MISO); + cli(); + while (!ao_ms5607_done) + ao_sleep(&ao_ms5607_done); + sei(); + ao_exti_disable(&AO_MS5607_MISO_GPIO, AO_MS5607_MISO); ao_ms5607_stop(); - ao_delay(AO_MS_TO_TICKS(20)); - ao_ms5607_start(); read = AO_MS5607_ADC_READ; ao_spi_send(&read, 1, AO_MS5607_SPI_INDEX); @@ -130,23 +151,22 @@ ao_ms5607_convert(uint8_t cmd) { void ao_ms5607_sample(struct ao_ms5607_sample *sample) +{ + sample->pres = ao_ms5607_get_sample(AO_MS5607_CONVERT_D1_2048); + sample->temp = ao_ms5607_get_sample(AO_MS5607_CONVERT_D2_2048); +} + +void +ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value) { uint8_t addr; - uint32_t D1, D2; int32_t dT; int32_t TEMP; int64_t OFF; int64_t SENS; int32_t P; - ao_ms5607_setup(); - - D2 = ao_ms5607_convert(AO_MS5607_CONVERT_D2_4096); - printf ("Conversion D2: %d\n", D2); - D1 = ao_ms5607_convert(AO_MS5607_CONVERT_D1_4096); - printf ("Conversion D1: %d\n", D1); - - dT = D2 - ((int32_t) ms5607_prom.tref << 8); + dT = sample->temp - ((int32_t) ms5607_prom.tref << 8); TEMP = 2000 + (((int64_t) dT * ms5607_prom.tempsens) >> 23); @@ -170,19 +190,49 @@ ao_ms5607_sample(struct ao_ms5607_sample *sample) SENS -= SENS2; } - P = ((((int64_t) D1 * SENS) >> 21) - OFF) >> 15; - sample->temp = TEMP; - sample->pres = P; + value->pres = ((((int64_t) sample->pres * SENS) >> 21) - OFF) >> 15; + value->temp = TEMP; } +struct ao_ms5607_sample ao_ms5607_current; + +static void +ao_ms5607(void) +{ + ao_ms5607_setup(); + for (;;) + { + struct ao_ms5607_sample ao_ms5607_next; + ao_ms5607_sample(&ao_ms5607_next); + ao_arch_critical( + ao_ms5607_current = ao_ms5607_next; + ); + ao_delay(0); + } +} + +__xdata struct ao_task ao_ms5607_task; + static void ao_ms5607_dump(void) { struct ao_ms5607_sample sample; + struct ao_ms5607_value value; + + printf ("ms5607 reserved: %u\n", ms5607_prom.reserved); + printf ("ms5607 sens: %u\n", ms5607_prom.sens); + printf ("ms5607 off: %u\n", ms5607_prom.off); + printf ("ms5607 tcs: %u\n", ms5607_prom.tcs); + printf ("ms5607 tco: %u\n", ms5607_prom.tco); + printf ("ms5607 tref: %u\n", ms5607_prom.tref); + printf ("ms5607 tempsens: %u\n", ms5607_prom.tempsens); + printf ("ms5607 crc: %u\n", ms5607_prom.crc); - ao_ms5607_sample(&sample); - printf ("Temperature: %d\n", sample.temp); - printf ("Pressure %d\n", sample.pres); + sample = ao_ms5607_current; + ao_ms5607_convert(&sample, &value); + printf ("Pressure: %8u %8d\n", sample.pres, value.pres); + printf ("Temperature: %8u %8d\n", sample.temp, value.temp); + printf ("Altitude: %ld\n", ao_pa_to_altitude(value.pres)); } __code struct ao_cmds ao_ms5607_cmds[] = { @@ -196,4 +246,22 @@ ao_ms5607_init(void) ms5607_configured = 0; ao_cmd_register(&ao_ms5607_cmds[0]); ao_spi_init_cs(AO_MS5607_CS_GPIO, (1 << AO_MS5607_CS)); + + ao_add_task(&ao_ms5607_task, ao_ms5607, "ms5607"); + + /* Configure the MISO pin as an interrupt; when the + * conversion is complete, the MS5607 will raise this + * pin as a signal + */ + ao_exti_setup(&AO_MS5607_MISO_GPIO, + AO_MS5607_MISO, + AO_EXTI_MODE_RISING, + ao_ms5607_isr); + + /* Reset the pin from INPUT to ALTERNATE so that SPI works + * This needs an abstraction at some point... + */ + stm_moder_set(&AO_MS5607_MISO_GPIO, + AO_MS5607_MISO, + STM_MODER_ALTERNATE); } diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h index 29df25e4..fd5bc984 100644 --- a/src/drivers/ao_ms5607.h +++ b/src/drivers/ao_ms5607.h @@ -35,7 +35,7 @@ #define AO_MS5607_ADC_READ 0x00 #define AO_MS5607_PROM_READ(ad) (0xA0 | ((ad) << 1)) -struct ms5607_prom { +struct ao_ms5607_prom { uint16_t reserved; uint16_t sens; uint16_t off; @@ -47,8 +47,15 @@ struct ms5607_prom { }; struct ao_ms5607_sample { - int32_t temp; - int32_t pres; + uint32_t pres; /* raw 24 bit sensor */ + uint32_t temp; /* raw 24 bit sensor */ +}; + +extern struct ao_ms5607_sample ao_ms5607_current; + +struct ao_ms5607_value { + int32_t pres; /* in Pa * 10 */ + int32_t temp; /* in °C * 100 */ }; void @@ -57,4 +64,10 @@ ao_ms5607_init(void); void ao_ms5607_sample(struct ao_ms5607_sample *sample); +void +ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value); + +void +ao_ms5607_get_prom(struct ao_ms5607_prom *prom); + #endif /* _AO_MS5607_H_ */ diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 437e1a9e..6524d8b8 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -50,7 +50,8 @@ ALTOS_SRC = \ ao_packet_slave.c \ ao_i2c_stm.c \ ao_hmc5883.c \ - ao_mpu6000.c + ao_mpu6000.c \ + ao_convert_pa.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index cd270739..adc56151 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -182,6 +182,9 @@ struct ao_adc { #define AO_MS5607_CS_GPIO stm_gpioc #define AO_MS5607_CS 4 #define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) +#define AO_MS5607_MISO_GPIO stm_gpioa +#define AO_MS5607_MISO 6 +#define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO) #define AO_MS5607_SPI_INDEX (STM_SPI_INDEX(1)) /* @@ -212,7 +215,7 @@ struct ao_adc { #define AO_HMC5883_INT_PORT stm_gpioc #define AO_HMC5883_INT_PIN 12 -#define AO_HMC5883_I2C_INDEX STM_SPI_INDEX(1) +#define AO_HMC5883_I2C_INDEX STM_I2C_INDEX(1) /* * mpu6000 @@ -220,6 +223,6 @@ struct ao_adc { #define AO_MPU6000_INT_PORT stm_gpioc #define AO_MPU6000_INT_PIN 13 -#define AO_MPU6000_I2C_INDEX STM_SPI_INDEX(1) +#define AO_MPU6000_I2C_INDEX STM_I2C_INDEX(1) #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 0239e4dfe587528524b6380bbf6d9583047e52d6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 18 May 2012 21:23:47 -0700 Subject: altos: Poll mpu6000 values every tick and stash them locally. Signed-off-by: Keith Packard --- src/drivers/ao_mpu6000.c | 28 +++++++++++++++++++++++----- src/drivers/ao_mpu6000.h | 2 ++ 2 files changed, 25 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index eb4044be..df400fcb 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -147,9 +147,9 @@ ao_mpu6000_setup(void) ao_mpu6000_reg_write(MPU6000_PWR_MGMT_1, (1 << MPU6000_PWR_MGMT_1_DEVICE_RESET)); - while (ao_mpu6000_reg_read(MPU6000_PWR_MGMT_1) & - (1 << MPU6000_PWR_MGMT_1_DEVICE_RESET)) - ao_yield(); + + /* Wait for it to reset. If we talk too quickly, it appears to get confused */ + ao_delay(AO_MS_TO_TICKS(100)); /* Reset signal conditioning */ ao_mpu6000_reg_write(MPU6000_USER_CONTROL, @@ -245,14 +245,31 @@ ao_mpu6000_setup(void) ao_mpu6000_configured = 1; } +struct ao_mpu6000_sample ao_mpu6000_current; + +static void +ao_mpu6000(void) +{ + ao_mpu6000_setup(); + for (;;) + { + struct ao_mpu6000_sample ao_mpu6000_next; + ao_mpu6000_sample(&ao_mpu6000_next); + ao_arch_critical( + ao_mpu6000_current = ao_mpu6000_next; + ); + ao_delay(0); + } +} + +static struct ao_task ao_mpu6000_task; static void ao_mpu6000_show(void) { struct ao_mpu6000_sample sample; - ao_mpu6000_setup(); - ao_mpu6000_sample(&sample); + sample = ao_mpu6000_current; printf ("Accel: %7d %7d %7d Gyro: %7d %7d %7d\n", ao_mpu6000_accel(sample.accel_x), ao_mpu6000_accel(sample.accel_y), @@ -272,5 +289,6 @@ ao_mpu6000_init(void) { ao_mpu6000_configured = 0; + ao_add_task(&ao_mpu6000_task, ao_mpu6000, "mpu6000"); ao_cmd_register(&ao_mpu6000_cmds[0]); } diff --git a/src/drivers/ao_mpu6000.h b/src/drivers/ao_mpu6000.h index ca76b081..5e52148d 100644 --- a/src/drivers/ao_mpu6000.h +++ b/src/drivers/ao_mpu6000.h @@ -155,6 +155,8 @@ struct ao_mpu6000_sample { int16_t gyro_z; }; +extern struct ao_mpu6000_sample ao_mpu6000_current; + void ao_mpu6000_init(void); -- cgit v1.2.3 From 78423f3fc5164ea9fd428606419784c1700ad5c5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 25 May 2012 23:18:06 -0600 Subject: Get megametrum ready to at least log flight data Doesn't track flight state changes correctly. Signed-off-by: Keith Packard --- src/core/ao_adc.h | 5 ++- src/core/ao_config.c | 33 ++++++++++++++++---- src/core/ao_kalman.c | 3 ++ src/core/ao_log.c | 3 +- src/core/ao_log.h | 62 ++++++++++++++++++++++++++++++++++++- src/core/ao_sample.h | 19 +++++++----- src/megametrum-v0.1/Makefile | 19 +++++++++--- src/megametrum-v0.1/ao_megametrum.c | 8 +++-- src/megametrum-v0.1/ao_pins.h | 7 ++++- src/stm/ao_adc_stm.c | 42 ++++++++++++++++++------- 10 files changed, 164 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/core/ao_adc.h b/src/core/ao_adc.h index db5bfab3..8ec740c4 100644 --- a/src/core/ao_adc.h +++ b/src/core/ao_adc.h @@ -18,13 +18,11 @@ #ifndef _AO_ADC_H_ #define _AO_ADC_H_ - - /* * One set of samples read from the A/D converter or telemetry */ - +#if AO_ADC_RING /* * ao_adc.c */ @@ -42,6 +40,7 @@ extern volatile __data uint8_t ao_adc_head; #if HAS_ACCEL_REF extern volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; #endif +#endif /* Trigger a conversion sequence (called from the timer interrupt) */ void diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 55fb8590..55ec9f40 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -16,6 +16,9 @@ */ #include "ao.h" +#include "ao_log.h" +#include +#include __xdata struct ao_config ao_config; __pdata uint8_t ao_config_loaded; @@ -64,11 +67,13 @@ ao_config_put(void) } #endif +#if HAS_RADIO void ao_config_set_radio(void) { ao_config.radio_setting = ao_freq_to_set(ao_config.frequency, ao_config.radio_cal); } +#endif /* HAS_RADIO */ static void _ao_config_get(void) @@ -100,8 +105,10 @@ _ao_config_get(void) ao_config.accel_minus_g = 0; } /* Fixups for minor version 3 */ +#if HAS_RADIO if (ao_config.minor < 3) ao_config.radio_cal = ao_radio_cal; +#endif /* Fixups for minor version 4 */ if (ao_config.minor < 4) ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; @@ -121,7 +128,9 @@ _ao_config_get(void) ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } +#if HAS_RADIO ao_config_set_radio(); +#endif ao_config_loaded = 1; } @@ -176,6 +185,7 @@ ao_config_callsign_set(void) __reentrant _ao_config_edit_finish(); } +#if HAS_RADIO void ao_config_frequency_show(void) __reentrant { @@ -195,6 +205,7 @@ ao_config_frequency_set(void) __reentrant _ao_config_edit_finish(); ao_radio_recv_abort(); } +#endif #if HAS_FLIGHT @@ -232,7 +243,7 @@ ao_config_accel_calibrate_auto(char *orientation) __reentrant { uint16_t i; int32_t accel_total; - uint8_t cal_adc_ring; + uint8_t cal_data_ring; printf("Orient antenna %s and press a key...", orientation); flush(); @@ -241,12 +252,14 @@ ao_config_accel_calibrate_auto(char *orientation) __reentrant puts("Calibrating..."); flush(); i = ACCEL_CALIBRATE_SAMPLES; accel_total = 0; - cal_adc_ring = ao_sample_adc; + cal_data_ring = ao_sample_data; while (i) { - ao_sleep(DATA_TO_XDATA(&ao_sample_adc)); - while (i && cal_adc_ring != ao_sample_adc) { - accel_total += (int32_t) ao_adc_ring[cal_adc_ring].accel; - cal_adc_ring = ao_adc_ring_next(cal_adc_ring); + ao_sleep(DATA_TO_XDATA(&ao_sample_data)); + while (i && cal_data_ring != ao_sample_data) { + int16_t accel = ao_data_accel(&ao_data_ring[cal_data_ring]); + printf ("accel %d\n", accel); + accel_total += (int32_t) ao_data_accel(&ao_data_ring[cal_data_ring]); + cal_data_ring = ao_data_ring_next(cal_data_ring); i--; } } @@ -320,6 +333,7 @@ ao_config_apogee_lockout_set(void) __reentrant #endif /* HAS_FLIGHT */ +#if HAS_RADIO void ao_config_radio_cal_show(void) __reentrant { @@ -337,6 +351,7 @@ ao_config_radio_cal_set(void) __reentrant ao_config_set_radio(); _ao_config_edit_finish(); } +#endif #if HAS_LOG void @@ -413,6 +428,7 @@ ao_config_pad_orientation_set(void) __reentrant } #endif +#if HAS_RADIO void ao_config_radio_enable_show(void) __reentrant { @@ -429,6 +445,7 @@ ao_config_radio_enable_set(void) __reentrant ao_config.radio_enable = ao_cmd_lex_i; _ao_config_edit_finish(); } +#endif /* HAS_RADIO */ #if HAS_AES void @@ -481,18 +498,22 @@ __code struct ao_config_var ao_config_vars[] = { { "L \0Apogee detect lockout (s)", ao_config_apogee_lockout_set, ao_config_apogee_lockout_show, }, #endif /* HAS_FLIGHT */ +#if HAS_RADIO { "F \0Frequency (kHz)", ao_config_frequency_set, ao_config_frequency_show }, { "c \0Callsign (8 char max)", ao_config_callsign_set, ao_config_callsign_show }, { "e <0 disable, 1 enable>\0Enable telemetry and RDF", ao_config_radio_enable_set, ao_config_radio_enable_show }, +#endif /* HAS_RADIO */ #if HAS_ACCEL { "a <+g> <-g>\0Accel calib (0 for auto)", ao_config_accel_calibrate_set,ao_config_accel_calibrate_show }, #endif /* HAS_ACCEL */ +#if HAS_RADIO { "f \0Radio calib (cal = rf/(xtal/2^16))", ao_config_radio_cal_set, ao_config_radio_cal_show }, +#endif /* HAS_RADIO */ #if HAS_LOG { "l \0Flight log size (kB)", ao_config_log_set, ao_config_log_show }, diff --git a/src/core/ao_kalman.c b/src/core/ao_kalman.c index ee01949e..68725f69 100644 --- a/src/core/ao_kalman.c +++ b/src/core/ao_kalman.c @@ -17,10 +17,13 @@ #ifndef AO_FLIGHT_TEST #include "ao.h" +#include "ao_flight.h" #endif +#include "ao_sample.h" #include "ao_kalman.h" + static __pdata int32_t ao_k_height; static __pdata int32_t ao_k_speed; static __pdata int32_t ao_k_accel; diff --git a/src/core/ao_log.c b/src/core/ao_log.c index db60707d..d696625e 100644 --- a/src/core/ao_log.c +++ b/src/core/ao_log.c @@ -16,12 +16,13 @@ */ #include "ao.h" +#include __pdata uint32_t ao_log_current_pos; __pdata uint32_t ao_log_end_pos; __pdata uint32_t ao_log_start_pos; __xdata uint8_t ao_log_running; -__pdata enum flight_state ao_log_state; +__pdata enum ao_flight_state ao_log_state; __xdata uint16_t ao_flight_number; __code uint8_t ao_log_format = AO_LOG_FORMAT_FULL; diff --git a/src/core/ao_log.h b/src/core/ao_log.h index 611c00d5..e585750f 100644 --- a/src/core/ao_log.h +++ b/src/core/ao_log.h @@ -18,6 +18,8 @@ #ifndef _AO_LOG_H_ #define _AO_LOG_H_ +#include + /* * ao_log.c */ @@ -32,7 +34,7 @@ extern __pdata uint32_t ao_log_current_pos; extern __pdata uint32_t ao_log_end_pos; extern __pdata uint32_t ao_log_start_pos; extern __xdata uint8_t ao_log_running; -extern __pdata enum flight_state ao_log_state; +extern __pdata enum ao_flight_state ao_log_state; /* required functions from the underlying log system */ @@ -41,6 +43,7 @@ extern __pdata enum flight_state ao_log_state; #define AO_LOG_FORMAT_TINY 2 /* two byte state/baro records */ #define AO_LOG_FORMAT_TELEMETRY 3 /* 32 byte ao_telemetry records */ #define AO_LOG_FORMAT_TELESCIENCE 4 /* 32 byte typed telescience records */ +#define AO_LOG_FORMAT_MEGAMETRUM 5 /* 32 byte typed megametrum records */ #define AO_LOG_FORMAT_NONE 127 /* No log at all */ extern __code uint8_t ao_log_format; @@ -189,8 +192,65 @@ struct ao_log_record { } u; }; +struct ao_log_mega { + char type; /* 0 */ + uint8_t csum; /* 1 */ + uint16_t tick; /* 2 */ + union { /* 4 */ + struct { + uint16_t flight; /* 4 */ + int16_t ground_accel; /* 6 */ + uint32_t ground_pres; /* 8 */ + uint32_t ground_temp; /* 12 */ + } flight; /* 16 */ + struct { + uint16_t state; + uint16_t reason; + } state; + struct { + uint32_t pres; /* 4 */ + uint32_t temp; /* 8 */ + int16_t accel_x; /* 12 */ + int16_t accel_y; /* 14 */ + int16_t accel_z; /* 16 */ + int16_t gyro_x; /* 18 */ + int16_t gyro_y; /* 20 */ + int16_t gyro_z; /* 22 */ + } sensor; /* 24 */ + struct { + int16_t v_batt; /* 4 */ + int16_t v_pbatt; /* 8 */ + int16_t n_sense; /* 10 */ + int16_t sense[10]; /* 12 */ + } volt; /* 32 */ + struct { + int32_t latitude; /* 4 */ + int32_t longitude; /* 8 */ + int16_t altitude; /* 12 */ + uint8_t hour; /* 14 */ + uint8_t minute; /* 15 */ + uint8_t second; /* 16 */ + uint8_t flags; /* 17 */ + uint8_t year; /* 18 */ + uint8_t month; /* 19 */ + uint8_t day; /* 20 */ + uint8_t pad; /* 21 */ + } gps; /* 22 */ + struct { + uint16_t channels; /* 4 */ + struct { + uint8_t svid; + uint8_t c_n; + } sats[12]; /* 6 */ + } gps_sat; /* 30 */ + } u; +}; + /* Write a record to the eeprom log */ uint8_t ao_log_data(__xdata struct ao_log_record *log) __reentrant; +uint8_t +ao_log_mega(__xdata struct ao_log_mega *log) __reentrant; + #endif /* _AO_LOG_H_ */ diff --git a/src/core/ao_sample.h b/src/core/ao_sample.h index fb0e69e8..189b2019 100644 --- a/src/core/ao_sample.h +++ b/src/core/ao_sample.h @@ -18,6 +18,8 @@ #ifndef _AO_SAMPLE_H_ #define _AO_SAMPLE_H_ +#include + /* * ao_sample.c */ @@ -88,21 +90,22 @@ #define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) extern __pdata uint16_t ao_sample_tick; /* time of last data */ -extern __pdata int16_t ao_sample_pres; /* most recent pressure sensor reading */ -extern __pdata int16_t ao_sample_alt; /* MSL of ao_sample_pres */ -extern __pdata int16_t ao_sample_height; /* AGL of ao_sample_pres */ +extern __pdata pres_t ao_sample_pres; /* most recent pressure sensor reading */ +extern __pdata alt_t ao_sample_alt; /* MSL of ao_sample_pres */ +extern __pdata alt_t ao_sample_height; /* AGL of ao_sample_pres */ extern __data uint8_t ao_sample_adc; /* Ring position of last processed sample */ +extern __data uint8_t ao_sample_data; /* Ring position of last processed sample */ #if HAS_ACCEL -extern __pdata int16_t ao_sample_accel; /* most recent accel sensor reading */ +extern __pdata accel_t ao_sample_accel; /* most recent accel sensor reading */ #endif -extern __pdata int16_t ao_ground_pres; /* startup pressure */ -extern __pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ +extern __pdata pres_t ao_ground_pres; /* startup pressure */ +extern __pdata alt_t ao_ground_height; /* MSL of ao_ground_pres */ #if HAS_ACCEL -extern __pdata int16_t ao_ground_accel; /* startup acceleration */ -extern __pdata int16_t ao_accel_2g; /* factory accel calibration */ +extern __pdata accel_t ao_ground_accel; /* startup acceleration */ +extern __pdata accel_t ao_accel_2g; /* factory accel calibration */ extern __pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ #endif diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 6524d8b8..a07b25ee 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -9,6 +9,8 @@ INC = \ ao.h \ ao_arch.h \ ao_arch_funcs.h \ + ao_data.h \ + ao_sample.h \ ao_pins.h \ altitude.h \ ao_kalman.h \ @@ -21,6 +23,11 @@ INC = \ # # Common AltOS sources # + +# ao_cc1120.c \ +# ao_packet.c \ +# ao_packet_slave.c \ + ALTOS_SRC = \ ao_interrupt.c \ ao_product.c \ @@ -35,7 +42,6 @@ ALTOS_SRC = \ ao_mutex.c \ ao_serial_stm.c \ ao_gps_skytraq.c \ - ao_cc1120.c \ ao_freq.c \ ao_dma_stm.c \ ao_spi_stm.c \ @@ -46,12 +52,17 @@ ALTOS_SRC = \ ao_m25.c \ ao_usb_stm.c \ ao_exti_stm.c \ - ao_packet.c \ - ao_packet_slave.c \ + ao_report.c \ ao_i2c_stm.c \ ao_hmc5883.c \ ao_mpu6000.c \ - ao_convert_pa.c + ao_convert_pa.c \ + ao_log.c \ + ao_log_mega.c \ + ao_sample_mm.c \ + ao_kalman.c \ + ao_flight_mm.c + PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 2e1f9298..19746d37 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -18,6 +18,7 @@ #include #include #include +#include #include void @@ -46,7 +47,6 @@ main(void) ao_timer_init(); ao_cmd_init(); ao_gps_init(); - ao_config_init(); ao_dma_init(); ao_spi_init(); ao_ms5607_init(); @@ -55,10 +55,14 @@ main(void) ao_storage_init(); ao_usb_init(); ao_exti_init(); - ao_radio_init(); +// ao_radio_init(); ao_i2c_init(); ao_hmc5883_init(); ao_mpu6000_init(); + ao_flight_init(); + ao_log_init(); + ao_report_init(); + ao_config_init(); ao_cmd_register(&ao_mm_cmds[0]); ao_start_scheduler(); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index adc56151..3ab7e15a 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -94,9 +94,12 @@ #define LEDS_AVAILABLE (AO_LED_RED | AO_LED_GREEN) +#define HAS_GPS 1 +#define HAS_FLIGHT 1 #define HAS_ADC 1 +#define HAS_ACCEL 1 -#define AO_ADC_RING 32 +#define AO_DATA_RING 32 #define AO_ADC_NUM_SENSE 6 struct ao_adc { @@ -179,6 +182,7 @@ struct ao_adc { /* * Pressure sensor settings */ +#define HAS_MS5607 1 #define AO_MS5607_CS_GPIO stm_gpioc #define AO_MS5607_CS 4 #define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) @@ -221,6 +225,7 @@ struct ao_adc { * mpu6000 */ +#define HAS_MPU6000 1 #define AO_MPU6000_INT_PORT stm_gpioc #define AO_MPU6000_INT_PIN 13 #define AO_MPU6000_I2C_INDEX STM_I2C_INDEX(1) diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index a2569908..af2968d6 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -16,10 +16,17 @@ */ #include +#include +#if HAS_MPU6000 +#include +#endif +#if HAS_MS5607 +#include +#endif +volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; +volatile __data uint8_t ao_data_head; -volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; -volatile __data uint8_t ao_adc_head; static uint8_t ao_adc_ready; #define AO_ADC_CR2_VAL ((0 << STM_ADC_CR2_SWSTART) | \ @@ -43,9 +50,15 @@ static uint8_t ao_adc_ready; */ static void ao_adc_done(int index) { - ao_adc_ring[ao_adc_head].tick = ao_time(); - ao_adc_head = ao_adc_ring_next(ao_adc_head); - ao_wakeup((void *) &ao_adc_head); + ao_data_ring[ao_data_head].adc.tick = ao_time(); +#if HAS_MPU6000 + ao_data_ring[ao_data_head].mpu6000 = ao_mpu6000_current; +#endif +#if HAS_MS5607 + ao_data_ring[ao_data_head].ms5607 = ao_ms5607_current; +#endif + ao_data_head = ao_data_ring_next(ao_data_head); + ao_wakeup((void *) &ao_data_head); ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1)); ao_adc_ready = 1; } @@ -62,7 +75,7 @@ ao_adc_poll(void) stm_adc.sr = 0; ao_dma_set_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1), &stm_adc.dr, - (void *) (&ao_adc_ring[ao_adc_head].tick + 1), + (void *) (&ao_data_ring[ao_data_head].tick + 1), AO_NUM_ADC, (0 << STM_DMA_CCR_MEM2MEM) | (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) | @@ -84,20 +97,27 @@ ao_adc_poll(void) void ao_adc_get(__xdata struct ao_adc *packet) { - uint8_t i = ao_adc_ring_prev(ao_adc_head); - memcpy(packet, (void *) &ao_adc_ring[i], sizeof (struct ao_adc)); + uint8_t i = ao_data_ring_prev(ao_data_head); + memcpy(packet, (void *) &ao_data_ring[i].adc, sizeof (struct ao_adc)); +} + +void +ao_data_get(__xdata struct ao_data *packet) +{ + uint8_t i = ao_data_ring_prev(ao_data_head); + memcpy(packet, (void *) &ao_data_ring[i], sizeof (struct ao_data)); } static void ao_adc_dump(void) __reentrant { - struct ao_adc packet; + struct ao_data packet; int16_t *d; uint8_t i; - ao_adc_get(&packet); + ao_data_get(&packet); printf("tick: %5u", packet.tick); - d = (int16_t *) (&packet.tick + 1); + d = (int16_t *) (&packet.adc); for (i = 0; i < AO_NUM_ADC; i++) printf (" %2d: %5d", i, d[i]); printf("\n"); -- cgit v1.2.3 From d01c10eff4b70af13347969a7cece8730cf1a3f1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 16:44:38 -0600 Subject: altos: Data packet tick count does not live in adc structure It was moved to the global structure. Having two is confusing. Signed-off-by: Keith Packard --- src/megametrum-v0.1/ao_pins.h | 1 - src/stm/ao_adc_stm.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'src') diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 3ab7e15a..2ae3cea8 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -103,7 +103,6 @@ #define AO_ADC_NUM_SENSE 6 struct ao_adc { - uint16_t tick; int16_t sense[AO_ADC_NUM_SENSE]; int16_t v_batt; int16_t v_pbatt; diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index af2968d6..576dbf5d 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -50,7 +50,7 @@ static uint8_t ao_adc_ready; */ static void ao_adc_done(int index) { - ao_data_ring[ao_data_head].adc.tick = ao_time(); + ao_data_ring[ao_data_head].tick = ao_time(); #if HAS_MPU6000 ao_data_ring[ao_data_head].mpu6000 = ao_mpu6000_current; #endif -- cgit v1.2.3 From 9eeba439ce8c9dc1def8528f96b6a67c6578d656 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 16:46:00 -0600 Subject: altos: Don't start ADC ring until the other sensors have a valid value Yes, this is still an ugly kludge, but it's easy. Signed-off-by: Keith Packard --- src/drivers/ao_mpu6000.c | 3 +++ src/drivers/ao_mpu6000.h | 1 + src/drivers/ao_ms5607.c | 3 +++ src/drivers/ao_ms5607.h | 1 + src/stm/ao_adc_stm.c | 11 +++++++++-- 5 files changed, 17 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index df400fcb..065ed221 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -246,6 +246,7 @@ ao_mpu6000_setup(void) } struct ao_mpu6000_sample ao_mpu6000_current; +uint8_t ao_mpu6000_valid; static void ao_mpu6000(void) @@ -257,6 +258,7 @@ ao_mpu6000(void) ao_mpu6000_sample(&ao_mpu6000_next); ao_arch_critical( ao_mpu6000_current = ao_mpu6000_next; + ao_mpu6000_valid = 1; ); ao_delay(0); } @@ -288,6 +290,7 @@ void ao_mpu6000_init(void) { ao_mpu6000_configured = 0; + ao_mpu6000_valid = 0; ao_add_task(&ao_mpu6000_task, ao_mpu6000, "mpu6000"); ao_cmd_register(&ao_mpu6000_cmds[0]); diff --git a/src/drivers/ao_mpu6000.h b/src/drivers/ao_mpu6000.h index 5e52148d..fc7af1e0 100644 --- a/src/drivers/ao_mpu6000.h +++ b/src/drivers/ao_mpu6000.h @@ -156,6 +156,7 @@ struct ao_mpu6000_sample { }; extern struct ao_mpu6000_sample ao_mpu6000_current; +extern uint8_t ao_mpu6000_valid; void ao_mpu6000_init(void); diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index f79c315a..7db7022f 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -195,6 +195,7 @@ ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value } struct ao_ms5607_sample ao_ms5607_current; +uint8_t ao_ms5607_valid; static void ao_ms5607(void) @@ -206,6 +207,7 @@ ao_ms5607(void) ao_ms5607_sample(&ao_ms5607_next); ao_arch_critical( ao_ms5607_current = ao_ms5607_next; + ao_ms5607_valid = 1; ); ao_delay(0); } @@ -244,6 +246,7 @@ void ao_ms5607_init(void) { ms5607_configured = 0; + ao_ms5607_valid = 0; ao_cmd_register(&ao_ms5607_cmds[0]); ao_spi_init_cs(AO_MS5607_CS_GPIO, (1 << AO_MS5607_CS)); diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h index fd5bc984..1384d3a2 100644 --- a/src/drivers/ao_ms5607.h +++ b/src/drivers/ao_ms5607.h @@ -51,6 +51,7 @@ struct ao_ms5607_sample { uint32_t temp; /* raw 24 bit sensor */ }; +extern uint8_t ao_ms5607_valid; extern struct ao_ms5607_sample ao_ms5607_current; struct ao_ms5607_value { diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index 576dbf5d..02187205 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -50,15 +50,22 @@ static uint8_t ao_adc_ready; */ static void ao_adc_done(int index) { + uint8_t step = 1; ao_data_ring[ao_data_head].tick = ao_time(); #if HAS_MPU6000 + if (!ao_mpu6000_valid) + step = 0; ao_data_ring[ao_data_head].mpu6000 = ao_mpu6000_current; #endif #if HAS_MS5607 + if (!ao_ms5607_valid) + step = 0; ao_data_ring[ao_data_head].ms5607 = ao_ms5607_current; #endif - ao_data_head = ao_data_ring_next(ao_data_head); - ao_wakeup((void *) &ao_data_head); + if (step) { + ao_data_head = ao_data_ring_next(ao_data_head); + ao_wakeup((void *) &ao_data_head); + } ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1)); ao_adc_ready = 1; } -- cgit v1.2.3 From dd73c9b441f7672fb9982c4caeb5178df30f5d2b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 16:47:30 -0600 Subject: altos: Split out mm-specific versions of sampling code Avoid breaking telemetrum (too much) by splitting this stuff apart. Signed-off-by: Keith Packard --- src/core/ao_data.h | 191 +++++++++++++++++++++++++ src/core/ao_flight_mm.c | 362 ++++++++++++++++++++++++++++++++++++++++++++++++ src/core/ao_log_mega.c | 174 +++++++++++++++++++++++ src/core/ao_sample_mm.c | 135 ++++++++++++++++++ 4 files changed, 862 insertions(+) create mode 100644 src/core/ao_data.h create mode 100644 src/core/ao_flight_mm.c create mode 100644 src/core/ao_log_mega.c create mode 100644 src/core/ao_sample_mm.c (limited to 'src') diff --git a/src/core/ao_data.h b/src/core/ao_data.h new file mode 100644 index 00000000..d28730a8 --- /dev/null +++ b/src/core/ao_data.h @@ -0,0 +1,191 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_DATA_H_ +#define _AO_DATA_H_ + +#if HAS_MS5607 +#include +#endif + +#if HAS_MPU6000 +#include +#endif + +struct ao_data { + uint16_t tick; +#if HAS_ADC + struct ao_adc adc; +#endif +#if HAS_ACCEL_REF + uint16_t accel_ref; +#endif +#if HAS_MS5607 + struct ao_ms5607_sample ms5607; +#endif +#if HAS_MPU6000 + struct ao_mpu6000_sample mpu6000; +#endif +}; + +#define ao_data_ring_next(n) (((n) + 1) & (AO_DATA_RING - 1)) +#define ao_data_ring_prev(n) (((n) - 1) & (AO_DATA_RING - 1)) + +extern volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; +extern volatile __data uint8_t ao_data_head; + +#if HAS_MS5607 + +typedef int32_t pres_t; +typedef int32_t alt_t; + +static inline pres_t ao_data_pres(struct ao_data *packet) +{ + struct ao_ms5607_value value; + + ao_ms5607_convert(&packet->ms5607, &value); + return value.pres; +} + +#define pres_to_altitude(p) ao_pa_to_altitude(p) + +#else + +typedef int16_t pres_t; +typedef int16_t alt_t; + +#define ao_data_pres(packet) ((packet)->adc.pres) +#define pres_to_altitude(p) ao_pres_to_altitude(p) + +#endif + +/* + * Need a few macros to pull data from the sensors: + * + * ao_data_accel_sample - pull raw sensor and convert to normalized values + * ao_data_accel - pull normalized value (lives in the same memory) + * ao_data_set_accel - store normalized value back in the sensor location + * ao_data_accel_invert - flip rocket ends for positive acceleration + */ + +#if HAS_MPU6000 + +typedef int16_t accel_t; + +/* MPU6000 is hooked up so that positive y is positive acceleration */ +#define ao_data_accel(packet) ((packet)->mpu6000.accel_y) +#define ao_data_accel_sample(packet) (-ao_data_accel(packet)) +#define ao_data_set_accel(packet, accel) ((packet)->mpu6000.accel_y = (accel)) +#define ao_data_accel_invert(a) (-(a)) + +#else + +typedef int16_t accel_t; +#define ao_data_accel(packet) ((packet)->adc.accel) +#define ao_data_set_accel(packet, accel) ((packet)->adc.accel = (accel)) +#define ao_data_accel_invert(a) (0x7fff -(a)) + +/* + * Ok, the math here is a bit tricky. + * + * ao_sample_accel: ADC output for acceleration + * ao_accel_ref: ADC output for the 5V reference. + * ao_cook_accel: Corrected acceleration value + * Vcc: 3.3V supply to the CC1111 + * Vac: 5V supply to the accelerometer + * accel: input voltage to accelerometer ADC pin + * ref: input voltage to 5V reference ADC pin + * + * + * Measured acceleration is ratiometric to Vcc: + * + * ao_sample_accel accel + * ------------ = ----- + * 32767 Vcc + * + * Measured 5v reference is also ratiometric to Vcc: + * + * ao_accel_ref ref + * ------------ = ----- + * 32767 Vcc + * + * + * ao_accel_ref = 32767 * (ref / Vcc) + * + * Acceleration is measured ratiometric to the 5V supply, + * so what we want is: + * + * ao_cook_accel accel + * ------------- = ----- + * 32767 ref + * + * + * accel Vcc + * = ----- * --- + * Vcc ref + * + * ao_sample_accel 32767 + * = ------------ * ------------ + * 32767 ao_accel_ref + * + * Multiply through by 32767: + * + * ao_sample_accel * 32767 + * ao_cook_accel = -------------------- + * ao_accel_ref + * + * Now, the tricky part. Getting this to compile efficiently + * and keeping all of the values in-range. + * + * First off, we need to use a shift of 16 instead of * 32767 as SDCC + * does the obvious optimizations for byte-granularity shifts: + * + * ao_cook_accel = (ao_sample_accel << 16) / ao_accel_ref + * + * Next, lets check our input ranges: + * + * 0 <= ao_sample_accel <= 0x7fff (singled ended ADC conversion) + * 0x7000 <= ao_accel_ref <= 0x7fff (the 5V ref value is close to 0x7fff) + * + * Plugging in our input ranges, we get an output range of 0 - 0x12490, + * which is 17 bits. That won't work. If we take the accel ref and shift + * by a bit, we'll change its range: + * + * 0xe000 <= ao_accel_ref<<1 <= 0xfffe + * + * ao_cook_accel = (ao_sample_accel << 16) / (ao_accel_ref << 1) + * + * Now the output range is 0 - 0x9248, which nicely fits in 16 bits. It + * is, however, one bit too large for our signed computations. So, we + * take the result and shift that by a bit: + * + * ao_cook_accel = ((ao_sample_accel << 16) / (ao_accel_ref << 1)) >> 1 + * + * This finally creates an output range of 0 - 0x4924. As the ADC only + * provides 11 bits of data, we haven't actually lost any precision, + * just dropped a bit of noise off the low end. + */ +#if HAS_ACCEL_REF +#define ao_data_accel_sample(packet) \ + ((uint16_t) ((((uint32_t) (packet)->adc.accel << 16) / ((packet)->accel_ref << 1))) >> 1) +#else +#define ao_data_accel(packet) ((packet)->adc.accel) +#endif /* HAS_ACCEL_REF */ + +#endif /* else some other pressure sensor */ + +#endif /* _AO_DATA_H_ */ diff --git a/src/core/ao_flight_mm.c b/src/core/ao_flight_mm.c new file mode 100644 index 00000000..27087e55 --- /dev/null +++ b/src/core/ao_flight_mm.c @@ -0,0 +1,362 @@ +/* + * 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. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#include +#endif + +#ifndef HAS_ACCEL +#error Please define HAS_ACCEL +#endif + +#ifndef HAS_GPS +#error Please define HAS_GPS +#endif + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + +/* Main flight thread. */ + +__pdata enum ao_flight_state ao_flight_state; /* current flight state */ +__pdata uint16_t ao_boost_tick; /* time of launch detect */ + +/* + * track min/max data over a long interval to detect + * resting + */ +static __data uint16_t ao_interval_end; +static __data int16_t ao_interval_min_height; +static __data int16_t ao_interval_max_height; +static __data int16_t ao_coast_avg_accel; + +__pdata uint8_t ao_flight_force_idle; + +/* We also have a clock, which can be used to sanity check things in + * case of other failures + */ + +#define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) + +/* Landing is detected by getting constant readings from both pressure and accelerometer + * for a fairly long time (AO_INTERVAL_TICKS) + */ +#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(10) + +#define abs(a) ((a) < 0 ? -(a) : (a)) + +void +ao_flight(void) +{ + ao_sample_init(); + ao_flight_state = ao_flight_startup; + for (;;) { + + /* + * Process ADC samples, just looping + * until the sensors are calibrated. + */ + if (!ao_sample()) + continue; + + switch (ao_flight_state) { + case ao_flight_startup: + + /* Check to see what mode we should go to. + * - Invalid mode if accel cal appears to be out + * - pad mode if we're upright, + * - idle mode otherwise + */ +#if HAS_ACCEL + if (ao_config.accel_plus_g == 0 || + ao_config.accel_minus_g == 0 || + ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || + ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) + { + /* Detected an accel value outside -1.5g to 1.5g + * (or uncalibrated values), so we go into invalid mode + */ + ao_flight_state = ao_flight_invalid; + +#if HAS_RADIO + /* Turn on packet system in invalid mode on TeleMetrum */ + ao_packet_slave_start(); +#endif + } else +#endif + if (!ao_flight_force_idle +#if HAS_ACCEL + && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP +#endif + ) + { + /* Set pad mode - we can fly! */ + ao_flight_state = ao_flight_pad; +#if HAS_USB + /* Disable the USB controller in flight mode + * to save power + */ + ao_usb_disable(); +#endif + +#if !HAS_ACCEL + /* Disable packet mode in pad state on TeleMini */ + ao_packet_slave_stop(); +#endif + +#if HAS_RADIO + /* Turn on telemetry system */ + ao_rdf_set(1); + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); +#endif + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } else { + /* Set idle mode */ + ao_flight_state = ao_flight_idle; + +#if HAS_ACCEL && HAS_RADIO + /* Turn on packet system in idle mode on TeleMetrum */ + ao_packet_slave_start(); +#endif + + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } + /* wakeup threads due to state change */ + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + + break; + case ao_flight_pad: + + /* pad to boost: + * + * barometer: > 20m vertical motion + * OR + * accelerometer: > 2g AND velocity > 5m/s + * + * The accelerometer should always detect motion before + * the barometer, but we use both to make sure this + * transition is detected. If the device + * doesn't have an accelerometer, then ignore the + * speed and acceleration as they are quite noisy + * on the pad. + */ + if (ao_height > AO_M_TO_HEIGHT(20) +#if HAS_ACCEL + || (ao_accel > AO_MSS_TO_ACCEL(20) && + ao_speed > AO_MS_TO_SPEED(5)) +#endif + ) + { + ao_flight_state = ao_flight_boost; + ao_boost_tick = ao_sample_tick; + + /* start logging data */ + ao_log_start(); + +#if HAS_RADIO + /* Increase telemetry rate */ + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); + + /* disable RDF beacon */ + ao_rdf_set(0); +#endif + +#if HAS_GPS + /* Record current GPS position by waking up GPS log tasks */ + ao_wakeup(&ao_gps_data); + ao_wakeup(&ao_gps_tracking_data); +#endif + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + case ao_flight_boost: + + /* boost to fast: + * + * accelerometer: start to fall at > 1/4 G + * OR + * time: boost for more than 15 seconds + * + * Detects motor burn out by the switch from acceleration to + * deceleration, or by waiting until the maximum burn duration + * (15 seconds) has past. + */ + if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || + (int16_t) (ao_sample_tick - ao_boost_tick) > BOOST_TICKS_MAX) + { +#if HAS_ACCEL + ao_flight_state = ao_flight_fast; + ao_coast_avg_accel = ao_accel; +#else + ao_flight_state = ao_flight_coast; +#endif + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; +#if HAS_ACCEL + case ao_flight_fast: + /* + * This is essentially the same as coast, + * but the barometer is being ignored as + * it may be unreliable. + */ + if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) + { + ao_flight_state = ao_flight_coast; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } else + goto check_re_boost; + break; +#endif + case ao_flight_coast: + + /* + * By customer request - allow the user + * to lock out apogee detection for a specified + * number of seconds. + */ + if (ao_config.apogee_lockout) { + if ((ao_sample_tick - ao_boost_tick) < + AO_SEC_TO_TICKS(ao_config.apogee_lockout)) + break; + } + + /* apogee detect: coast to drogue deploy: + * + * speed: < 0 + * + * Also make sure the model altitude is tracking + * the measured altitude reasonably closely; otherwise + * we're probably transsonic. + */ + if (ao_speed < 0 +#if !HAS_ACCEL + && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) +#endif + ) + { +#if HAS_IGNITE + /* ignite the drogue charge */ + ao_ignite(ao_igniter_drogue); +#endif + +#if HAS_RADIO + /* slow down the telemetry system */ + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); + + /* Turn the RDF beacon back on */ + ao_rdf_set(1); +#endif + + /* and enter drogue state */ + ao_flight_state = ao_flight_drogue; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } +#if HAS_ACCEL + else { + check_re_boost: + ao_coast_avg_accel = ao_coast_avg_accel - (ao_coast_avg_accel >> 6) + (ao_accel >> 6); + if (ao_coast_avg_accel > AO_MSS_TO_ACCEL(20)) { + ao_boost_tick = ao_sample_tick; + ao_flight_state = ao_flight_boost; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + } +#endif + + break; + case ao_flight_drogue: + + /* drogue to main deploy: + * + * barometer: reach main deploy altitude + * + * Would like to use the accelerometer for this test, but + * the orientation of the flight computer is unknown after + * drogue deploy, so we ignore it. Could also detect + * high descent rate using the pressure sensor to + * recognize drogue deploy failure and eject the main + * at that point. Perhaps also use the drogue sense lines + * to notice continutity? + */ + if (ao_height <= ao_config.main_deploy) + { +#if HAS_IGNITE + ao_ignite(ao_igniter_main); +#endif + + /* + * Start recording min/max height + * to figure out when the rocket has landed + */ + + /* initialize interval values */ + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + + ao_interval_min_height = ao_interval_max_height = ao_avg_height; + + ao_flight_state = ao_flight_main; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + + /* fall through... */ + case ao_flight_main: + + /* main to land: + * + * barometer: altitude stable + */ + + if (ao_avg_height < ao_interval_min_height) + ao_interval_min_height = ao_avg_height; + if (ao_avg_height > ao_interval_max_height) + ao_interval_max_height = ao_avg_height; + + if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { + if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4)) + { + ao_flight_state = ao_flight_landed; + + /* turn off the ADC capture */ + ao_timer_set_adc_interval(0); + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + ao_interval_min_height = ao_interval_max_height = ao_avg_height; + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + } + break; + case ao_flight_landed: + break; + } + } +} + +static __xdata struct ao_task flight_task; + +void +ao_flight_init(void) +{ + ao_flight_state = ao_flight_startup; + ao_add_task(&flight_task, ao_flight, "flight"); +} diff --git a/src/core/ao_log_mega.c b/src/core/ao_log_mega.c new file mode 100644 index 00000000..1763b9eb --- /dev/null +++ b/src/core/ao_log_mega.c @@ -0,0 +1,174 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include +#include +#include + +static __xdata uint8_t ao_log_mutex; +static __xdata struct ao_log_mega log; + +static uint8_t +ao_log_csum(__xdata uint8_t *b) __reentrant +{ + uint8_t sum = 0x5a; + uint8_t i; + + for (i = 0; i < sizeof (struct ao_log_mega); i++) + sum += *b++; + return -sum; +} + +uint8_t +ao_log_mega(__xdata struct ao_log_mega *log) __reentrant +{ + uint8_t wrote = 0; + /* set checksum */ + log->csum = 0; + log->csum = ao_log_csum((__xdata uint8_t *) log); + ao_mutex_get(&ao_log_mutex); { + if (ao_log_current_pos >= ao_log_end_pos && ao_log_running) + ao_log_stop(); + if (ao_log_running) { + wrote = 1; + ao_storage_write(ao_log_current_pos, + log, + sizeof (struct ao_log_mega)); + ao_log_current_pos += sizeof (struct ao_log_mega); + } + } ao_mutex_put(&ao_log_mutex); + return wrote; +} + +static uint8_t +ao_log_dump_check_data(void) +{ + if (ao_log_csum((uint8_t *) &log) != 0) + return 0; + return 1; +} + +static __data uint8_t ao_log_data_pos; + +/* a hack to make sure that ao_log_megas fill the eeprom block in even units */ +typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_mega))] ; + +#ifndef AO_SENSOR_INTERVAL_ASCENT +#define AO_SENSOR_INTERVAL_ASCENT 1 +#define AO_SENSOR_INTERVAL_DESCENT 10 +#define AO_OTHER_INTERVAL 32 +#endif + +void +ao_log(void) +{ + __pdata uint16_t next_sensor, next_other; + uint8_t i; + + ao_storage_setup(); + + ao_log_scan(); + + while (!ao_log_running) + ao_sleep(&ao_log_running); + +#if HAS_FLIGHT + log.type = AO_LOG_FLIGHT; + log.tick = ao_sample_tick; +#if HAS_ACCEL + log.u.flight.ground_accel = ao_ground_accel; +#endif + log.u.flight.ground_pres = ao_ground_pres; + log.u.flight.flight = ao_flight_number; + ao_log_mega(&log); +#endif + + /* Write the whole contents of the ring to the log + * when starting up. + */ + ao_log_data_pos = ao_data_ring_next(ao_data_head); + next_other = next_sensor = ao_data_ring[ao_log_data_pos].tick; + ao_log_state = ao_flight_startup; + for (;;) { + /* Write samples to EEPROM */ + while (ao_log_data_pos != ao_data_head) { + log.tick = ao_data_ring[ao_log_data_pos].tick; + if ((int16_t) (log.tick - next_sensor) >= 0) { + log.type = AO_LOG_SENSOR; + log.u.sensor.pres = ao_data_ring[ao_log_data_pos].ms5607.pres; + log.u.sensor.temp = ao_data_ring[ao_log_data_pos].ms5607.temp; + log.u.sensor.accel_x = ao_data_ring[ao_log_data_pos].mpu6000.accel_x; + log.u.sensor.accel_y = ao_data_ring[ao_log_data_pos].mpu6000.accel_y; + log.u.sensor.accel_z = ao_data_ring[ao_log_data_pos].mpu6000.accel_z; + log.u.sensor.gyro_x = ao_data_ring[ao_log_data_pos].mpu6000.gyro_x; + log.u.sensor.gyro_y = ao_data_ring[ao_log_data_pos].mpu6000.gyro_y; + log.u.sensor.gyro_z = ao_data_ring[ao_log_data_pos].mpu6000.gyro_z; + ao_log_mega(&log); + if (ao_log_state <= ao_flight_coast) + next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; + else + next_sensor = log.tick + AO_SENSOR_INTERVAL_DESCENT; + } + if ((int16_t) (log.tick - next_other) >= 0) { + log.type = AO_LOG_TEMP_VOLT; + log.u.volt.v_batt = ao_data_ring[ao_log_data_pos].adc.v_batt; + log.u.volt.v_pbatt = ao_data_ring[ao_log_data_pos].adc.v_pbatt; + log.u.volt.n_sense = AO_ADC_NUM_SENSE; + for (i = 0; i < AO_ADC_NUM_SENSE; i++) + log.u.volt.sense[i] = ao_data_ring[ao_log_data_pos].adc.sense[i]; + ao_log_mega(&log); + next_other = log.tick + AO_OTHER_INTERVAL; + } + ao_log_data_pos = ao_data_ring_next(ao_log_data_pos); + } +#if HAS_FLIGHT + /* Write state change to EEPROM */ + if (ao_flight_state != ao_log_state) { + ao_log_state = ao_flight_state; + log.type = AO_LOG_STATE; + log.tick = ao_time(); + log.u.state.state = ao_log_state; + log.u.state.reason = 0; + ao_log_mega(&log); + + if (ao_log_state == ao_flight_landed) + ao_log_stop(); + } +#endif + + /* Wait for a while */ + ao_delay(AO_MS_TO_TICKS(100)); + + /* Stop logging when told to */ + while (!ao_log_running) + ao_sleep(&ao_log_running); + } +} + +uint16_t +ao_log_flight(uint8_t slot) +{ + if (!ao_storage_read(ao_log_pos(slot), + &log, + sizeof (struct ao_log_mega))) + return 0; + + if (ao_log_dump_check_data() && log.type == AO_LOG_FLIGHT) + return log.u.flight.flight; + return 0; +} diff --git a/src/core/ao_sample_mm.c b/src/core/ao_sample_mm.c new file mode 100644 index 00000000..8cfadc40 --- /dev/null +++ b/src/core/ao_sample_mm.c @@ -0,0 +1,135 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#include +#endif + +/* + * Current sensor values + */ + +#ifndef PRES_TYPE +#define PRES_TYPE int32_t +#define ALT_TYPE int32_t +#define ACCEL_TYPE int16_t +#endif + +__pdata uint16_t ao_sample_tick; /* time of last data */ +__pdata pres_t ao_sample_pres; +__pdata alt_t ao_sample_alt; +__pdata alt_t ao_sample_height; +#if HAS_ACCEL +__pdata accel_t ao_sample_accel; +#endif + +__data uint8_t ao_sample_data; + +/* + * Sensor calibration values + */ + +__pdata pres_t ao_ground_pres; /* startup pressure */ +__pdata alt_t ao_ground_height; /* MSL of ao_ground_pres */ + +#if HAS_ACCEL +__pdata accel_t ao_ground_accel; /* startup acceleration */ +__pdata accel_t ao_accel_2g; /* factory accel calibration */ +__pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +#endif + +static __pdata uint8_t ao_preflight; /* in preflight mode */ + +static __pdata uint16_t nsamples; +__pdata int32_t ao_sample_pres_sum; +#if HAS_ACCEL +__pdata int32_t ao_sample_accel_sum; +#endif + +static void +ao_sample_preflight(void) +{ + /* startup state: + * + * Collect 512 samples of acceleration and pressure + * data and average them to find the resting values + */ + if (nsamples < 512) { +#if HAS_ACCEL + ao_sample_accel_sum += ao_sample_accel; +#endif + ao_sample_pres_sum += ao_sample_pres; + ++nsamples; + } else { + ao_config_get(); +#if HAS_ACCEL + ao_ground_accel = ao_sample_accel_sum >> 9; + ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; + ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; +#endif + ao_ground_pres = ao_sample_pres_sum >> 9; + ao_ground_height = pres_to_altitude(ao_ground_pres); + ao_preflight = FALSE; + } +} + + +uint8_t +ao_sample(void) +{ + ao_config_get(); + ao_wakeup(DATA_TO_XDATA(&ao_sample_data)); + ao_sleep((void *) DATA_TO_XDATA(&ao_data_head)); + while (ao_sample_data != ao_data_head) { + __xdata struct ao_data *ao_data; + + /* Capture a sample */ + ao_data = (struct ao_data *) &ao_data_ring[ao_sample_data]; + ao_sample_tick = ao_data->tick; + ao_sample_pres = ao_data_pres(ao_data); + ao_sample_alt = pres_to_altitude(ao_sample_pres); + ao_sample_height = ao_sample_alt - ao_ground_height; +#if HAS_ACCEL + ao_sample_accel = ao_data_accel_sample(ao_data); + if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) + ao_sample_accel = ao_data_accel_invert(ao_sample_accel); + ao_data_set_accel(ao_data, ao_sample_accel); +#endif + + if (ao_preflight) + ao_sample_preflight(); + else + ao_kalman(); + ao_sample_data = ao_data_ring_next(ao_sample_data); + } + return !ao_preflight; +} + +void +ao_sample_init(void) +{ + nsamples = 0; + ao_sample_pres_sum = 0; + ao_sample_pres = 0; +#if HAS_ACCEL + ao_sample_accel_sum = 0; + ao_sample_accel = 0; +#endif + ao_sample_data = ao_data_head; + ao_preflight = TRUE; +} -- cgit v1.2.3 From ed635545e0b965901032ed2c3474ffe997c73de3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 16:52:45 -0600 Subject: ignore pa to altitude conversion file Signed-off-by: Keith Packard --- src/.gitignore | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/.gitignore b/src/.gitignore index 7a5d6ef5..c6e1e353 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1 +1,2 @@ altitude.h +altitude-pa.h -- cgit v1.2.3 From ce8153472069ed56b24ac36f297ac569d1f767d4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 17:24:09 -0600 Subject: altos: Make telemetrum-v1.1 compile with new ao_data structure Signed-off-by: Keith Packard --- src/cc1111/ao_adc.c | 36 ++++++++++++++++-------------------- src/cc1111/ao_arch.h | 3 +-- src/cc1111/ao_ignite.c | 9 +++++---- src/core/ao_adc.h | 28 +++------------------------- src/core/ao_data.h | 2 +- src/core/ao_log_big.c | 24 ++++++++++++------------ src/core/ao_telemetry.c | 28 ++++++++++++++-------------- src/product/Makefile.telemetrum | 4 ++-- src/stm/ao_adc_stm.c | 8 ++++++++ 9 files changed, 62 insertions(+), 80 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index 1688eceb..1e3d8cab 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -16,13 +16,9 @@ */ #include "ao.h" -#include "ao_pins.h" -volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; -#if HAS_ACCEL_REF -volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; -#endif -volatile __data uint8_t ao_adc_head; +volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; +volatile __data uint8_t ao_data_head; void ao_adc_poll(void) @@ -39,14 +35,14 @@ ao_adc_poll(void) } void -ao_adc_get(__xdata struct ao_adc *packet) +ao_data_get(__xdata struct ao_data *packet) { #if HAS_FLIGHT - uint8_t i = ao_adc_ring_prev(ao_sample_adc); + uint8_t i = ao_data_ring_prev(ao_sample_data); #else - uint8_t i = ao_adc_ring_prev(ao_adc_head); + uint8_t i = ao_data_ring_prev(ao_data_head); #endif - ao_xmemcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); + ao_xmemcpy(packet, (void __xdata *) &ao_data_ring[i], sizeof (struct ao_data)); } void @@ -60,14 +56,14 @@ ao_adc_isr(void) __interrupt 1 /* TeleMetrum readings */ #if HAS_ACCEL_REF if (sequence == 2) { - a = (uint8_t __xdata *) (&ao_accel_ref[ao_adc_head]); + a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].accel_ref); sequence = 0; } else #endif { if (sequence == ADCCON3_ECH_TEMP) sequence = 2; - a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].accel + sequence); + a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.accel + sequence); sequence++; } #define GOT_ADC @@ -87,7 +83,7 @@ ao_adc_isr(void) __interrupt 1 #if IGNITE_ON_P0 /* TeleMini readings */ - a = (uint8_t __xdata *) (&ao_adc_ring[ao_adc_head].pres); + a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].pres); #ifdef TELEMINI_V_1_0 switch (sequence) { case 0: @@ -149,20 +145,20 @@ ao_adc_isr(void) __interrupt 1 else { /* record this conversion series */ - ao_adc_ring[ao_adc_head].tick = ao_time(); - ao_adc_head = ao_adc_ring_next(ao_adc_head); - ao_wakeup(DATA_TO_XDATA(&ao_adc_head)); + ao_data_ring[ao_data_head].tick = ao_time(); + ao_data_head = ao_data_ring_next(ao_data_head); + ao_wakeup(DATA_TO_XDATA(&ao_data_head)); } } static void ao_adc_dump(void) __reentrant { - static __xdata struct ao_adc packet; - ao_adc_get(&packet); + static __xdata struct ao_data packet; + ao_data_get(&packet); printf("tick: %5u accel: %5d pres: %5d temp: %5d batt: %5d drogue: %5d main: %5d\n", - packet.tick, packet.accel, packet.pres, packet.temp, - packet.v_batt, packet.sense_d, packet.sense_m); + packet.tick, packet.adc.accel, packet.adc.pres, packet.adc.temp, + packet.adc.v_batt, packet.adc.sense_d, packet.adc.sense_m); } __code struct ao_cmds ao_adc_cmds[] = { diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 9d0643b4..704ae4f9 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -199,7 +199,6 @@ extern __code __at (0x00a6) uint32_t ao_radio_cal; #define ao_arch_critical(b) __critical { b } struct ao_adc { - uint16_t tick; /* tick when the sample was read */ int16_t accel; /* accelerometer */ int16_t pres; /* pressure sensor */ int16_t temp; /* temperature sensor */ @@ -208,7 +207,7 @@ struct ao_adc { int16_t sense_m; /* main continuity sense */ }; -#define AO_ADC_RING 32 +#define AO_DATA_RING 32 /* ao_button.c */ #ifdef HAS_BUTTON diff --git a/src/cc1111/ao_ignite.c b/src/cc1111/ao_ignite.c index dd529088..cf07dfe8 100644 --- a/src/cc1111/ao_ignite.c +++ b/src/cc1111/ao_ignite.c @@ -16,6 +16,7 @@ */ #include "ao.h" +#include __xdata struct ao_ignition ao_ignition[2]; @@ -29,12 +30,12 @@ ao_ignite(enum ao_igniter igniter) __critical enum ao_igniter_status ao_igniter_status(enum ao_igniter igniter) { - __xdata struct ao_adc adc; + __xdata struct ao_data packet; __pdata int16_t value; __pdata uint8_t request, firing, fired; __critical { - ao_adc_get(&adc); + ao_data_get(&packet); request = ao_ignition[igniter].request; fired = ao_ignition[igniter].fired; firing = ao_ignition[igniter].firing; @@ -45,10 +46,10 @@ ao_igniter_status(enum ao_igniter igniter) value = (AO_IGNITER_CLOSED>>1); switch (igniter) { case ao_igniter_drogue: - value = adc.sense_d; + value = packet.adc.sense_d; break; case ao_igniter_main: - value = adc.sense_m; + value = packet.adc.sense_m; break; } if (value < AO_IGNITER_OPEN) diff --git a/src/core/ao_adc.h b/src/core/ao_adc.h index 8ec740c4..0dd87080 100644 --- a/src/core/ao_adc.h +++ b/src/core/ao_adc.h @@ -18,29 +18,7 @@ #ifndef _AO_ADC_H_ #define _AO_ADC_H_ -/* - * One set of samples read from the A/D converter or telemetry - */ - -#if AO_ADC_RING -/* - * ao_adc.c - */ - -#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) -#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) - - -/* - * A/D data is stored in a ring, with the next sample to be written - * at ao_adc_head - */ -extern volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; -extern volatile __data uint8_t ao_adc_head; -#if HAS_ACCEL_REF -extern volatile __xdata uint16_t ao_accel_ref[AO_ADC_RING]; -#endif -#endif +#include /* Trigger a conversion sequence (called from the timer interrupt) */ void @@ -50,9 +28,9 @@ ao_adc_poll(void); void ao_adc_sleep(void); -/* Get a copy of the last complete A/D sample set */ +/* Get a copy of the last complete sample set */ void -ao_adc_get(__xdata struct ao_adc *packet); +ao_data_get(__xdata struct ao_data *packet); /* Initialize the A/D converter */ void diff --git a/src/core/ao_data.h b/src/core/ao_data.h index d28730a8..bd7e2d54 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -96,7 +96,7 @@ typedef int16_t accel_t; typedef int16_t accel_t; #define ao_data_accel(packet) ((packet)->adc.accel) -#define ao_data_set_accel(packet, accel) ((packet)->adc.accel = (accel)) +#define ao_data_set_accel(packet, a) ((packet)->adc.accel = (a)) #define ao_data_accel_invert(a) (0x7fff -(a)) /* diff --git a/src/core/ao_log_big.c b/src/core/ao_log_big.c index 43b3aa0c..50eca069 100644 --- a/src/core/ao_log_big.c +++ b/src/core/ao_log_big.c @@ -60,7 +60,7 @@ ao_log_dump_check_data(void) return 1; } -static __data uint8_t ao_log_adc_pos; +static __data uint8_t ao_log_data_pos; /* a hack to make sure that ao_log_records fill the eeprom block in even units */ typedef uint8_t check_log_size[1-(256 % sizeof(struct ao_log_record))] ; @@ -94,17 +94,17 @@ ao_log(void) /* Write the whole contents of the ring to the log * when starting up. */ - ao_log_adc_pos = ao_adc_ring_next(ao_sample_adc); - next_other = next_sensor = ao_adc_ring[ao_log_adc_pos].tick; + ao_log_data_pos = ao_data_ring_next(ao_sample_data); + next_other = next_sensor = ao_data_ring[ao_log_data_pos].tick; ao_log_state = ao_flight_startup; for (;;) { /* Write samples to EEPROM */ - while (ao_log_adc_pos != ao_sample_adc) { - log.tick = ao_adc_ring[ao_log_adc_pos].tick; + while (ao_log_data_pos != ao_sample_data) { + log.tick = ao_data_ring[ao_log_data_pos].tick; if ((int16_t) (log.tick - next_sensor) >= 0) { log.type = AO_LOG_SENSOR; - log.u.sensor.accel = ao_adc_ring[ao_log_adc_pos].accel; - log.u.sensor.pres = ao_adc_ring[ao_log_adc_pos].pres; + log.u.sensor.accel = ao_data_ring[ao_log_data_pos].adc.accel; + log.u.sensor.pres = ao_data_ring[ao_log_data_pos].adc.pres; ao_log_data(&log); if (ao_log_state <= ao_flight_coast) next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; @@ -113,16 +113,16 @@ ao_log(void) } if ((int16_t) (log.tick - next_other) >= 0) { log.type = AO_LOG_TEMP_VOLT; - log.u.temp_volt.temp = ao_adc_ring[ao_log_adc_pos].temp; - log.u.temp_volt.v_batt = ao_adc_ring[ao_log_adc_pos].v_batt; + log.u.temp_volt.temp = ao_data_ring[ao_log_data_pos].adc.temp; + log.u.temp_volt.v_batt = ao_data_ring[ao_log_data_pos].adc.v_batt; ao_log_data(&log); log.type = AO_LOG_DEPLOY; - log.u.deploy.drogue = ao_adc_ring[ao_log_adc_pos].sense_d; - log.u.deploy.main = ao_adc_ring[ao_log_adc_pos].sense_m; + log.u.deploy.drogue = ao_data_ring[ao_log_data_pos].adc.sense_d; + log.u.deploy.main = ao_data_ring[ao_log_data_pos].adc.sense_m; ao_log_data(&log); next_other = log.tick + AO_OTHER_INTERVAL; } - ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); + ao_log_data_pos = ao_data_ring_next(ao_log_data_pos); } /* Write state change to EEPROM */ if (ao_flight_state != ao_log_state) { diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 46d72609..800adfcb 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -53,23 +53,23 @@ static __xdata union ao_telemetry_all telemetry; static void ao_send_sensor(void) { - uint8_t sample = ao_adc_ring_prev(ao_sample_adc); + uint8_t sample = ao_data_ring_prev(ao_sample_data); - telemetry.generic.tick = ao_adc_ring[sample].tick; + telemetry.generic.tick = ao_data_ring[sample].tick; telemetry.generic.type = AO_TELEMETRY_SENSOR; telemetry.sensor.state = ao_flight_state; #if HAS_ACCEL - telemetry.sensor.accel = ao_adc_ring[sample].accel; + telemetry.sensor.accel = ao_data_ring[sample].adc.accel; #else telemetry.sensor.accel = 0; #endif - telemetry.sensor.pres = ao_adc_ring[sample].pres; - telemetry.sensor.temp = ao_adc_ring[sample].temp; - telemetry.sensor.v_batt = ao_adc_ring[sample].v_batt; + telemetry.sensor.pres = ao_data_ring[sample].adc.pres; + telemetry.sensor.temp = ao_data_ring[sample].adc.temp; + telemetry.sensor.v_batt = ao_data_ring[sample].adc.v_batt; #if HAS_IGNITE - telemetry.sensor.sense_d = ao_adc_ring[sample].sense_d; - telemetry.sensor.sense_m = ao_adc_ring[sample].sense_m; + telemetry.sensor.sense_d = ao_data_ring[sample].adc.sense_d; + telemetry.sensor.sense_m = ao_data_ring[sample].adc.sense_m; #else telemetry.sensor.sense_d = 0; telemetry.sensor.sense_m = 0; @@ -99,19 +99,19 @@ static uint8_t ao_baro_sample; static void ao_send_baro(void) { - uint8_t sample = ao_sample_adc; - uint8_t samples = (sample - ao_baro_sample) & (AO_ADC_RING - 1); + uint8_t sample = ao_sample_data; + uint8_t samples = (sample - ao_baro_sample) & (AO_DATA_RING - 1); if (samples > 12) { - ao_baro_sample = (ao_baro_sample + (samples - 12)) & (AO_ADC_RING - 1); + ao_baro_sample = (ao_baro_sample + (samples - 12)) & (AO_DATA_RING - 1); samples = 12; } - telemetry.generic.tick = ao_adc_ring[sample].tick; + telemetry.generic.tick = ao_data_ring[sample].tick; telemetry.generic.type = AO_TELEMETRY_BARO; telemetry.baro.samples = samples; for (sample = 0; sample < samples; sample++) { - telemetry.baro.baro[sample] = ao_adc_ring[ao_baro_sample].pres; - ao_baro_sample = ao_adc_ring_next(ao_baro_sample); + telemetry.baro.baro[sample] = ao_data_ring[ao_baro_sample].adc.pres; + ao_baro_sample = ao_data_ring_next(ao_baro_sample); } ao_radio_send(&telemetry, sizeof (telemetry)); } diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index e4f55f88..b1111053 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -34,8 +34,8 @@ CORE_SRC = \ ao_stdio.c \ ao_storage.c \ ao_task.c \ - ao_flight.c \ - ao_sample.c \ + ao_flight_mm.c \ + ao_sample_mm.c \ ao_kalman.c \ ao_log.c \ ao_log_big.c \ diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index 02187205..ea9e25e4 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -104,14 +104,22 @@ ao_adc_poll(void) void ao_adc_get(__xdata struct ao_adc *packet) { +#if HAS_FLIGHT + uint8_t i = ao_data_ring_prev(ao_sample_data); +#else uint8_t i = ao_data_ring_prev(ao_data_head); +#endif memcpy(packet, (void *) &ao_data_ring[i].adc, sizeof (struct ao_adc)); } void ao_data_get(__xdata struct ao_data *packet) { +#if HAS_FLIGHT + uint8_t i = ao_data_ring_prev(ao_sample_data); +#else uint8_t i = ao_data_ring_prev(ao_data_head); +#endif memcpy(packet, (void *) &ao_data_ring[i], sizeof (struct ao_data)); } -- cgit v1.2.3 From 98e992b65d366d9f79d7d2dd2dd4d1886dd1d9c4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 17:25:17 -0600 Subject: altos: Make telemetrum-v1.0 build with new ao_data structure Signed-off-by: Keith Packard --- src/core/ao_data.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_data.h b/src/core/ao_data.h index bd7e2d54..bb26c4c0 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -183,7 +183,7 @@ typedef int16_t accel_t; #define ao_data_accel_sample(packet) \ ((uint16_t) ((((uint32_t) (packet)->adc.accel << 16) / ((packet)->accel_ref << 1))) >> 1) #else -#define ao_data_accel(packet) ((packet)->adc.accel) +#define ao_data_accel_sample(packet) ((packet)->adc.accel) #endif /* HAS_ACCEL_REF */ #endif /* else some other pressure sensor */ -- cgit v1.2.3 From 090dc9aecdf4cfd1ac727325ae141d441c5b28aa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 17:26:43 -0600 Subject: altos: Make telemini-v1.0 compile with new ao_data structure Signed-off-by: Keith Packard --- src/cc1111/ao_adc.c | 2 +- src/core/ao_log_tiny.c | 12 ++++++------ src/product/Makefile.telemini | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index 1e3d8cab..f34bc042 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -83,7 +83,7 @@ ao_adc_isr(void) __interrupt 1 #if IGNITE_ON_P0 /* TeleMini readings */ - a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].pres); + a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.pres); #ifdef TELEMINI_V_1_0 switch (sequence) { case 0: diff --git a/src/core/ao_log_tiny.c b/src/core/ao_log_tiny.c index d5a3b99f..492658ea 100644 --- a/src/core/ao_log_tiny.c +++ b/src/core/ao_log_tiny.c @@ -85,7 +85,7 @@ ao_log(void) enum ao_flight_state ao_log_tiny_state; int32_t sum; int16_t count; - uint8_t ao_log_adc; + uint8_t ao_log_data; uint8_t ao_log_started = 0; ao_storage_setup(); @@ -96,18 +96,18 @@ ao_log(void) ao_log_tiny_interval = AO_LOG_TINY_INTERVAL_ASCENT; sum = 0; count = 0; - ao_log_adc = ao_sample_adc; + ao_log_data = ao_sample_data; last_time = ao_time(); for (;;) { /* * Add in pending sample data */ - ao_sleep(DATA_TO_XDATA(&ao_sample_adc)); - while (ao_log_adc != ao_sample_adc) { - sum += ao_adc_ring[ao_log_adc].pres; + ao_sleep(DATA_TO_XDATA(&ao_sample_data)); + while (ao_log_data != ao_sample_data) { + sum += ao_data_ring[ao_log_data].adc.pres; count++; - ao_log_adc = ao_adc_ring_next(ao_log_adc); + ao_log_data = ao_data_ring_next(ao_log_data); } if (ao_log_running) { if (!ao_log_started) { diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini index 82ec42a2..9506eb65 100644 --- a/src/product/Makefile.telemini +++ b/src/product/Makefile.telemini @@ -22,14 +22,14 @@ CORE_SRC = \ ao_cmd.c \ ao_config.c \ ao_convert.c \ - ao_flight.c \ + ao_flight_mm.c \ ao_kalman.c \ ao_log.c \ ao_log_tiny.c \ ao_mutex.c \ ao_panic.c \ ao_report.c \ - ao_sample.c \ + ao_sample_mm.c \ ao_stdio.c \ ao_storage.c \ ao_task.c \ -- cgit v1.2.3 From 627b904b36e129ff2ead436a626699abfc3b3211 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 17:29:27 -0600 Subject: altos: Make stm-demo compile with new ao_data structure Signed-off-by: Keith Packard --- src/stm-demo/ao_demo.c | 8 ++++---- src/stm-demo/ao_pins.h | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 7bb53047..232c2313 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -119,7 +119,7 @@ ao_i2c_write(void) { for (i = 0; i < 10; i++) { ao_i2c_get(0); if (ao_i2c_start(0, 0x55)) - ao_i2c_send(data, 4, 0); + ao_i2c_send(data, 4, 0, TRUE); else { printf ("i2c start failed\n"); ao_i2c_put(0); @@ -135,16 +135,16 @@ ao_i2c_write(void) { static void ao_temp (void) { - struct ao_adc adc; + struct ao_data packet; int temp; - ao_adc_get(&adc); + ao_data_get(&packet); /* * r = (110 - 25) / (ts_cal_hot - ts_cal_cold) * 25 + (110 - 25) * (temp - ts_cal_cold) / (ts_cal_hot - ts_cal_cold) */ - temp = 25 + (110 - 25) * (adc.temp - stm_temp_cal.ts_cal_cold) / (stm_temp_cal.ts_cal_hot - stm_temp_cal.ts_cal_cold); + temp = 25 + (110 - 25) * (packet.adc.temp - stm_temp_cal.ts_cal_cold) / (stm_temp_cal.ts_cal_hot - stm_temp_cal.ts_cal_cold); printf ("temp: %d\n", temp); } diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 1daab351..d02c071c 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -156,6 +156,7 @@ struct ao_adc { #define HAS_ADC_TEMP 1 +#define AO_DATA_RING 32 #define AO_NUM_ADC 3 #define AO_ADC_SQ1 AO_ADC_IDD -- cgit v1.2.3 From 5fd869b244f8f2b76258dc31a5507a73fd47cf1d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 17:31:12 -0600 Subject: altos: Make telenano build with new ao_data structure Signed-off-by: Keith Packard --- src/core/ao_flight_nano.c | 4 ++-- src/product/Makefile.telenano | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/core/ao_flight_nano.c b/src/core/ao_flight_nano.c index 2e332b12..406d81ad 100644 --- a/src/core/ao_flight_nano.c +++ b/src/core/ao_flight_nano.c @@ -27,8 +27,8 @@ __pdata uint16_t ao_launch_tick; /* time of launch detect */ * resting */ __pdata uint16_t ao_interval_end; -__pdata int16_t ao_interval_min_height; -__pdata int16_t ao_interval_max_height; +__pdata alt_t ao_interval_min_height; +__pdata alt_t ao_interval_max_height; __pdata uint8_t ao_flight_force_idle; diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index cf27527c..56db1c2c 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -29,7 +29,7 @@ CORE_SRC = \ ao_mutex.c \ ao_panic.c \ ao_report.c \ - ao_sample.c \ + ao_sample_mm.c \ ao_stdio.c \ ao_storage.c \ ao_task.c \ -- cgit v1.2.3 From 29edf6d901432a1afc65900ff599c963edac5a2b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 17:44:01 -0600 Subject: altos: Make telescience-v0.1 build with new ao_data struct Signed-off-by: Keith Packard --- src/avr/ao_adc_avr.c | 24 ++++++++--------- src/avr/ao_pins.h | 3 +-- src/core/ao_log_telescience.c | 14 +++++----- src/core/ao_stdio.c | 16 ++++++------ src/drivers/ao_science_slave.c | 2 +- src/test/Makefile | 4 +-- src/test/ao_flight_test.c | 58 ++++++++++++++++++++++-------------------- 7 files changed, 61 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c index 4f6f0e60..928cd3e1 100644 --- a/src/avr/ao_adc_avr.c +++ b/src/avr/ao_adc_avr.c @@ -17,8 +17,8 @@ #include "ao.h" -volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; -volatile __data uint8_t ao_adc_head; +volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; +volatile __data uint8_t ao_data_head; #ifdef TELESCIENCE const uint8_t adc_channels[AO_LOG_TELESCIENCE_NUM_ADC] = { @@ -92,14 +92,14 @@ ISR(ADC_vect) /* Must read ADCL first or the value there will be lost */ value = ADCL; value |= (ADCH << 8); - ao_adc_ring[ao_adc_head].adc[ao_adc_channel] = value; + ao_data_ring[ao_data_head].adc.adc[ao_adc_channel] = value; if (++ao_adc_channel < NUM_ADC) ao_adc_start(); else { ADCSRA = ADCSRA_INIT; - ao_adc_ring[ao_adc_head].tick = ao_time(); - ao_adc_head = ao_adc_ring_next(ao_adc_head); - ao_wakeup((void *) &ao_adc_head); + ao_data_ring[ao_data_head].tick = ao_time(); + ao_data_head = ao_data_ring_next(ao_data_head); + ao_wakeup((void *) &ao_data_head); ao_cpu_sleep_disable = 0; } } @@ -113,18 +113,18 @@ ao_adc_poll(void) } void -ao_adc_get(__xdata struct ao_adc *packet) +ao_data_get(__xdata struct ao_data *packet) { - uint8_t i = ao_adc_ring_prev(ao_adc_head); - memcpy(packet, (void *) &ao_adc_ring[i], sizeof (struct ao_adc)); + uint8_t i = ao_data_ring_prev(ao_data_head); + memcpy(packet, (void *) &ao_data_ring[i], sizeof (struct ao_data)); } static void ao_adc_dump(void) __reentrant { - static __xdata struct ao_adc packet; + static __xdata struct ao_data packet; uint8_t i; - ao_adc_get(&packet); + ao_data_get(&packet); #ifdef TELEPYRO printf("ADMUX: %02x\n", ADMUX); printf("ADCSRA: %02x\n", ADCSRA); @@ -137,7 +137,7 @@ ao_adc_dump(void) __reentrant #endif printf("tick: %5u", packet.tick); for (i = 0; i < NUM_ADC; i++) - printf (" %2d: %5u", i, packet.adc[i]); + printf (" %2d: %5u", i, packet.adc.adc[i]); printf("\n"); diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index f2b40fb4..850a08ec 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -91,10 +91,9 @@ #define AO_TELESCIENCE_NUM_ADC 12 struct ao_adc { - uint16_t tick; /* tick when the sample was read */ uint16_t adc[AO_TELESCIENCE_NUM_ADC]; /* samples */ }; -#define AO_ADC_RING 16 +#define AO_DATA_RING 16 #endif /* _AO_PINS_H_ */ diff --git a/src/core/ao_log_telescience.c b/src/core/ao_log_telescience.c index ae045281..002a10bd 100644 --- a/src/core/ao_log_telescience.c +++ b/src/core/ao_log_telescience.c @@ -20,7 +20,7 @@ #include "ao_log.h" #include "ao_companion.h" -static uint8_t ao_log_adc_pos; +static uint8_t ao_log_data_pos; __code uint8_t ao_log_format = AO_LOG_FORMAT_TELESCIENCE; @@ -62,20 +62,20 @@ ao_log_single(void) /* Write the whole contents of the ring to the log * when starting up. */ - ao_log_adc_pos = ao_adc_ring_next(ao_adc_head); + ao_log_data_pos = ao_data_ring_next(ao_data_head); ao_log_single_write_data.telescience.type = AO_LOG_TELESCIENCE_DATA; while (ao_log_running) { /* Write samples to EEPROM */ - while (ao_log_adc_pos != ao_adc_head) { - ao_log_single_write_data.telescience.tick = ao_adc_ring[ao_log_adc_pos].tick; - memcpy(&ao_log_single_write_data.telescience.adc, (void *) ao_adc_ring[ao_log_adc_pos].adc, + while (ao_log_data_pos != ao_data_head) { + ao_log_single_write_data.telescience.tick = ao_data_ring[ao_log_data_pos].tick; + memcpy(&ao_log_single_write_data.telescience.adc, (void *) ao_data_ring[ao_log_data_pos].adc.adc, AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); ao_log_telescience_csum(); ao_log_single_write(); - ao_log_adc_pos = ao_adc_ring_next(ao_log_adc_pos); + ao_log_data_pos = ao_data_ring_next(ao_log_data_pos); } /* Wait for more ADC data to arrive */ - ao_sleep((void *) &ao_adc_head); + ao_sleep((void *) &ao_data_head); } memset(&ao_log_single_write_data.telescience.adc, '\0', sizeof (ao_log_single_write_data.telescience.adc)); } diff --git a/src/core/ao_stdio.c b/src/core/ao_stdio.c index 9b4ea473..656b23c9 100644 --- a/src/core/ao_stdio.c +++ b/src/core/ao_stdio.c @@ -53,14 +53,14 @@ #endif #define USE_SERIAL_STDIN (USE_SERIAL_0_STDIN + \ - USE_SERIAL_1_STDIN | \ - USE_SERIAL_2_STDIN | \ - USE_SERIAL_3_STDIN | \ - USE_SERIAL_4_STDIN | \ - USE_SERIAL_5_STDIN | \ - USE_SERIAL_6_STDIN | \ - USE_SERIAL_7_STDIN | \ - USE_SERIAL_8_STDIN | \ + USE_SERIAL_1_STDIN + \ + USE_SERIAL_2_STDIN + \ + USE_SERIAL_3_STDIN + \ + USE_SERIAL_4_STDIN + \ + USE_SERIAL_5_STDIN + \ + USE_SERIAL_6_STDIN + \ + USE_SERIAL_7_STDIN + \ + USE_SERIAL_8_STDIN + \ USE_SERIAL_9_STDIN) #define AO_NUM_STDIOS (HAS_USB + PACKET_HAS_SLAVE + USE_SERIAL_STDIN) diff --git a/src/drivers/ao_science_slave.c b/src/drivers/ao_science_slave.c index a86b5151..996e98d9 100644 --- a/src/drivers/ao_science_slave.c +++ b/src/drivers/ao_science_slave.c @@ -42,7 +42,7 @@ void ao_spi_slave(void) sizeof (ao_telescience_setup)); break; case AO_COMPANION_FETCH: - ao_spi_slave_send((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, + ao_spi_slave_send((uint8_t *) &ao_data_ring[ao_data_ring_prev(ao_data_head)].adc, AO_LOG_TELESCIENCE_NUM_ADC * sizeof (uint16_t)); break; case AO_COMPANION_NOTIFY: diff --git a/src/test/Makefile b/src/test/Makefile index 3c2b8732..1e54f5e0 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -13,10 +13,10 @@ clean: install: -ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h +ao_flight_test: ao_flight_test.c ao_host.h ao_flight_mm.c ao_sample_mm.c ao_kalman.c altitude.h ao_kalman.h cc $(CFLAGS) -o $@ $< -ao_flight_test_noisy_accel: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h +ao_flight_test_noisy_accel: ao_flight_test.c ao_host.h ao_flight_mm.c ao_sample_mm.c ao_kalman.c altitude.h ao_kalman.h cc -DNOISY_ACCEL=1 $(CFLAGS) -o $@ $< ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 4a8625cf..baf2ad1d 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -26,9 +26,10 @@ #define AO_HERTZ 100 -#define AO_ADC_RING 64 -#define ao_adc_ring_next(n) (((n) + 1) & (AO_ADC_RING - 1)) -#define ao_adc_ring_prev(n) (((n) - 1) & (AO_ADC_RING - 1)) +#define HAS_ADC 1 +#define AO_DATA_RING 64 +#define ao_data_ring_next(n) (((n) + 1) & (AO_DATA_RING - 1)) +#define ao_data_ring_prev(n) (((n) - 1) & (AO_DATA_RING - 1)) #define AO_M_TO_HEIGHT(m) ((int16_t) (m)) #define AO_MS_TO_SPEED(ms) ((int16_t) ((ms) * 16)) @@ -38,7 +39,6 @@ * One set of samples read from the A/D converter */ struct ao_adc { - uint16_t tick; /* tick when the sample was read */ int16_t accel; /* accelerometer */ int16_t pres; /* pressure sensor */ int16_t pres_real; /* unclipped */ @@ -54,6 +54,8 @@ struct ao_adc { #define __code #define __reentrant +#include + #define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) #define to_fix32(x) ((int32_t) ((x) * 65536.0 + 0.5)) #define from_fix(x) ((x) >> 16) @@ -90,8 +92,8 @@ extern enum ao_flight_state ao_flight_state; #define FALSE 0 #define TRUE 1 -struct ao_adc ao_adc_ring[AO_ADC_RING]; -uint8_t ao_adc_head; +volatile struct ao_data ao_data_ring[AO_DATA_RING]; +volatile uint8_t ao_data_head; int ao_summary = 0; #define ao_led_on(l) @@ -110,7 +112,7 @@ enum ao_igniter { ao_igniter_main = 1 }; -struct ao_adc ao_adc_static; +struct ao_data ao_data_static; int drogue_height; double drogue_time; @@ -124,7 +126,7 @@ static int32_t ao_k_height; void ao_ignite(enum ao_igniter igniter) { - double time = (double) (ao_adc_static.tick + tick_offset) / 100; + double time = (double) (ao_data_static.tick + tick_offset) / 100; if (igniter == ao_igniter_drogue) { drogue_time = time; @@ -221,8 +223,8 @@ int ao_sample_prev_tick; uint16_t prev_tick; #include "ao_kalman.c" -#include "ao_sample.c" -#include "ao_flight.c" +#include "ao_sample_mm.c" +#include "ao_flight_mm.c" #define to_double(f) ((f) / 65536.0) @@ -282,19 +284,19 @@ ao_insert(void) { double time; - ao_adc_ring[ao_adc_head] = ao_adc_static; - ao_adc_head = ao_adc_ring_next(ao_adc_head); + ao_data_ring[ao_data_head] = ao_data_static; + ao_data_head = ao_data_ring_next(ao_data_head); if (ao_flight_state != ao_flight_startup) { - double height = ao_pres_to_altitude(ao_adc_static.pres_real) - ao_ground_height; - double accel = ((ao_flight_ground_accel - ao_adc_static.accel) * GRAVITY * 2.0) / + double height = ao_pres_to_altitude(ao_data_static.adc.pres_real) - ao_ground_height; + double accel = ((ao_flight_ground_accel - ao_data_static.adc.accel) * GRAVITY * 2.0) / (ao_config.accel_minus_g - ao_config.accel_plus_g); if (!tick_offset) - tick_offset = -ao_adc_static.tick; - if ((prev_tick - ao_adc_static.tick) > 0x400) + tick_offset = -ao_data_static.tick; + if ((prev_tick - ao_data_static.tick) > 0x400) tick_offset += 65536; - prev_tick = ao_adc_static.tick; - time = (double) (ao_adc_static.tick + tick_offset) / 100; + prev_tick = ao_data_static.tick; + time = (double) (ao_data_static.tick + tick_offset) / 100; if (ao_test_max_height < height) { ao_test_max_height = height; @@ -474,7 +476,7 @@ int16(uint8_t *bytes, int off) void ao_sleep(void *wchan) { - if (wchan == &ao_adc_head) { + if (wchan == &ao_data_head) { char type; uint16_t tick; uint16_t a, b; @@ -490,7 +492,7 @@ ao_sleep(void *wchan) for (;;) { if (ao_records_read > 2 && ao_flight_state == ao_flight_startup) { - ao_adc_static.accel = ao_flight_ground_accel; + ao_data_static.adc.accel = ao_flight_ground_accel; ao_insert(); return; } @@ -501,7 +503,7 @@ ao_sleep(void *wchan) printf ("no more data, exiting simulation\n"); ao_test_exit(); } - ao_adc_static.tick += 10; + ao_data_static.tick += 10; ao_insert(); return; } @@ -639,19 +641,19 @@ ao_sleep(void *wchan) case 'S': break; case 'A': - ao_adc_static.tick = tick; - ao_adc_static.accel = a; - ao_adc_static.pres_real = b; + ao_data_static.tick = tick; + ao_data_static.adc.accel = a; + ao_data_static.adc.pres_real = b; if (b < AO_MIN_BARO_VALUE) b = AO_MIN_BARO_VALUE; - ao_adc_static.pres = b; + ao_data_static.adc.pres = b; ao_records_read++; ao_insert(); return; case 'T': - ao_adc_static.tick = tick; - ao_adc_static.temp = a; - ao_adc_static.v_batt = b; + ao_data_static.tick = tick; + ao_data_static.adc.temp = a; + ao_data_static.adc.v_batt = b; break; case 'D': case 'G': -- cgit v1.2.3 From 5dd5e0284c8b26b0d4ce69c64bb7864e0ae83db7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 17:45:09 -0600 Subject: altos: Make telepyro-v0.1 build with new ao_data struct Signed-off-by: Keith Packard --- src/drivers/ao_pyro_slave.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/drivers/ao_pyro_slave.c b/src/drivers/ao_pyro_slave.c index 5a8ab922..70206a00 100644 --- a/src/drivers/ao_pyro_slave.c +++ b/src/drivers/ao_pyro_slave.c @@ -41,7 +41,7 @@ void ao_spi_slave(void) sizeof (ao_telepyro_setup)); break; case AO_COMPANION_FETCH: - ao_spi_slave_send((uint8_t *) &ao_adc_ring[ao_adc_ring_prev(ao_adc_head)].adc, + ao_spi_slave_send((uint8_t *) &ao_data_ring[ao_data_ring_prev(ao_data_head)].adc.adc, AO_TELEPYRO_NUM_ADC * sizeof (uint16_t)); break; case AO_COMPANION_NOTIFY: -- cgit v1.2.3 From 9f5e4cf7d8204016e023cf439d93de1203dc406e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 27 May 2012 18:23:39 -0600 Subject: altos: Make teleterra v0.2 compile with new ao_data struct Signed-off-by: Keith Packard --- src/teleterra-v0.2/ao_pins.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/teleterra-v0.2/ao_pins.h b/src/teleterra-v0.2/ao_pins.h index bcabdfee..1c12c437 100644 --- a/src/teleterra-v0.2/ao_pins.h +++ b/src/teleterra-v0.2/ao_pins.h @@ -21,6 +21,7 @@ #ifdef TELETERRA_V_0_2 #define HAS_FLIGHT 0 #define HAS_USB 1 + #define HAS_RADIO 1 #define HAS_BEEP 1 #define HAS_GPS 1 #define HAS_SERIAL_1 1 -- cgit v1.2.3 From 43e558738c76afd72fc01660884be3158f44470d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2012 11:44:07 -0600 Subject: altos: Try to get hmc5883 working No joy yet Signed-off-by: Keith Packard --- src/drivers/ao_hmc5883.c | 92 ++++++++++++++++++++++++++---------------------- src/drivers/ao_hmc5883.h | 7 ++++ 2 files changed, 57 insertions(+), 42 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c index 43d04f70..9551df71 100644 --- a/src/drivers/ao_hmc5883.c +++ b/src/drivers/ao_hmc5883.c @@ -19,55 +19,64 @@ #include #include -static uint8_t ao_hmc5883_wake; static uint8_t ao_hmc5883_configured; static void -ao_hmc5883_isr(void) +ao_hmc5883_reg_write(uint8_t addr, uint8_t data) { - ao_exti_disable(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); - ao_hmc5883_wake = 1; - ao_wakeup(&ao_hmc5883_wake); -} - -static uint8_t ao_hmc5883_addr_reg; + uint8_t d[2]; -static void -ao_hmc5883_update_addr (uint8_t len) -{ - ao_hmc5883_addr_reg += len; - if (ao_hmc5883_addr_reg == 9) - ao_hmc5883_addr_reg = 3; - else if (ao_hmc5883_addr_reg > 12) - ao_hmc5883_addr_reg = 0; - + d[0] = addr; + d[1] = data; + ao_i2c_get(AO_HMC5883_I2C_INDEX); + ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); + ao_i2c_send(d, 2, AO_HMC5883_I2C_INDEX, TRUE); + ao_i2c_put(AO_HMC5883_I2C_INDEX); } static void -ao_hmc5883_write(uint8_t addr, uint8_t *data, uint8_t len) +ao_hmc5883_read(uint8_t addr, uint8_t *data, uint8_t len) { ao_i2c_get(AO_HMC5883_I2C_INDEX); ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX, FALSE); - ao_hmc5883_addr_reg = addr; - ao_i2c_send(data, len, AO_HMC5883_I2C_INDEX, TRUE); - ao_hmc5883_update_addr(len); + ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_READ); + ao_i2c_recv(data, len, AO_HMC5883_I2C_INDEX, TRUE); ao_i2c_put(AO_HMC5883_I2C_INDEX); } +static uint8_t ao_hmc5883_done; + static void -ao_hmc5883_read(uint8_t addr, uint8_t *data, uint8_t len) +ao_hmc5883_isr(void) { - ao_i2c_get(AO_HMC5883_I2C_INDEX); - if (addr != ao_hmc5883_addr_reg) { - ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); - ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX, FALSE); - ao_hmc5883_addr_reg = addr; + ao_exti_disable(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); + ao_hmc5883_done = 1; + ao_wakeup(&ao_hmc5883_done); +} + +void +ao_hmc5883_sample(struct ao_hmc5883_sample *sample) +{ + uint16_t *d = (uint16_t *) sample; + int i = sizeof (*sample) / 2; + uint8_t single = HMC5883_MODE_SINGLE; + + ao_hmc5883_done = 0; + ao_exti_enable(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); + ao_hmc5883_reg_write(HMC5883_MODE, HMC5883_MODE_SINGLE); + cli(); + while (!ao_hmc5883_done) + ao_sleep(&ao_hmc5883_done); + sei(); + ao_hmc5883_read(HMC5883_X_MSB, (uint8_t *) sample, sizeof (struct ao_hmc5883_sample)); +#if __BYTE_ORDER == __LITTLE_ENDIAN + /* byte swap */ + while (i--) { + uint16_t t = *d; + *d++ = (t >> 8) | (t << 8); } - ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_READ); - ao_i2c_recv(data, len, AO_HMC5883_I2C_INDEX, TRUE); - ao_hmc5883_update_addr(len); - ao_i2c_put(AO_HMC5883_I2C_INDEX); +#endif } static uint8_t @@ -82,8 +91,6 @@ ao_hmc5883_setup(void) ao_exti_setup(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN, AO_EXTI_MODE_FALLING, ao_hmc5883_isr); - ao_hmc5883_addr_reg = 0xff; - ao_i2c_get(AO_HMC5883_I2C_INDEX); present = ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_READ); ao_i2c_recv(NULL, 0, AO_HMC5883_I2C_INDEX, TRUE); @@ -98,25 +105,21 @@ static void ao_hmc5883_show(void) { uint8_t addr, data; + struct ao_hmc5883_sample sample; - for (addr = 0x00; addr <= 0x7f; addr++) - { - ao_i2c_get(AO_HMC5883_I2C_INDEX); - data = ao_i2c_start(AO_HMC5883_I2C_INDEX, addr << 1); - ao_i2c_recv(NULL, 0, AO_HMC5883_I2C_INDEX, TRUE); - ao_i2c_put(AO_HMC5883_I2C_INDEX); - if (data) - printf("address %02x responds\n", addr << 1); - } if (!ao_hmc5883_setup()) { printf("hmc5883 not present\n"); return; } +#if 0 for (addr = 0; addr <= 12; addr++) { ao_hmc5883_read(addr, &data, 1); printf ("hmc5883 register %2d: %02x\n", addr, data); } +#endif + ao_hmc5883_sample(&sample); + printf ("X: %d Y: %d Z: %d\n", sample.x, sample.y, sample.z); } static const struct ao_cmds ao_hmc5883_cmds[] = { @@ -129,5 +132,10 @@ ao_hmc5883_init(void) { ao_hmc5883_configured = 0; + ao_exti_setup(&AO_HMC5883_INT_PORT, + AO_HMC5883_INT_PIN, + AO_EXTI_MODE_FALLING, + ao_hmc5883_isr); + ao_cmd_register(&ao_hmc5883_cmds[0]); } diff --git a/src/drivers/ao_hmc5883.h b/src/drivers/ao_hmc5883.h index 399ddcdd..2ec27dd9 100644 --- a/src/drivers/ao_hmc5883.h +++ b/src/drivers/ao_hmc5883.h @@ -24,6 +24,9 @@ #define HMC5883_CONFIG_A 0 #define HMC5883_CONFIG_B 1 #define HMC5883_MODE 2 +#define HMC5883_MODE_CONTINUOUS 0 +#define HMC5883_MODE_SINGLE 1 +#define HMC5883_MODE_IDLE 2 #define HMC5883_X_MSB 3 #define HMC5883_X_LSB 4 #define HMC5883_Y_MSB 5 @@ -35,6 +38,10 @@ #define HMC5883_ID_B 11 #define HMC5883_ID_C 12 +struct ao_hmc5883_sample { + int16_t x, y, z; +}; + void ao_hmc5883_init(void); -- cgit v1.2.3 From a53b8b84283eb62157b0f8ecd8061f61a4b6bd6f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2012 11:44:45 -0600 Subject: altos: Shrink telemetry generation code otherwise TM doesn't build anymore Signed-off-by: Keith Packard --- src/core/ao_telemetry.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 800adfcb..6e8fc02f 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -53,23 +53,23 @@ static __xdata union ao_telemetry_all telemetry; static void ao_send_sensor(void) { - uint8_t sample = ao_data_ring_prev(ao_sample_data); + __xdata struct ao_data *packet = &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; - telemetry.generic.tick = ao_data_ring[sample].tick; + telemetry.generic.tick = packet->tick; telemetry.generic.type = AO_TELEMETRY_SENSOR; telemetry.sensor.state = ao_flight_state; #if HAS_ACCEL - telemetry.sensor.accel = ao_data_ring[sample].adc.accel; + telemetry.sensor.accel = packet->adc.accel; #else telemetry.sensor.accel = 0; #endif - telemetry.sensor.pres = ao_data_ring[sample].adc.pres; - telemetry.sensor.temp = ao_data_ring[sample].adc.temp; - telemetry.sensor.v_batt = ao_data_ring[sample].adc.v_batt; + telemetry.sensor.pres = packet->adc.pres; + telemetry.sensor.temp = packet->adc.temp; + telemetry.sensor.v_batt = packet->adc.v_batt; #if HAS_IGNITE - telemetry.sensor.sense_d = ao_data_ring[sample].adc.sense_d; - telemetry.sensor.sense_m = ao_data_ring[sample].adc.sense_m; + telemetry.sensor.sense_d = packet->adc.sense_d; + telemetry.sensor.sense_m = packet->adc.sense_m; #else telemetry.sensor.sense_d = 0; telemetry.sensor.sense_m = 0; -- cgit v1.2.3 From 2df9113a22f4f67707d9ee777bd6b23ff671b105 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2012 11:45:30 -0600 Subject: altos: All cc1111 products have a radio Signed-off-by: Keith Packard --- src/cc1111/ao_pins.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 4f6edd37..5eef0de4 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -18,6 +18,8 @@ #ifndef _AO_PINS_H_ #define _AO_PINS_H_ +#define HAS_RADIO 1 + #if defined(TELEMETRUM_V_1_0) #define HAS_FLIGHT 1 #define HAS_USB 1 -- cgit v1.2.3 From ee61fb8ccb47f94b7c39e803f5a0248840d1eea6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2012 11:45:53 -0600 Subject: altos: Clean up ADC selection for cc1111 Depend directly on product defines instead of trying to guess Signed-off-by: Keith Packard --- src/cc1111/ao_adc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index f34bc042..95643956 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -52,7 +52,7 @@ ao_adc_isr(void) __interrupt 1 uint8_t __xdata *a; sequence = (ADCCON2 & ADCCON2_SCH_MASK) >> ADCCON2_SCH_SHIFT; -#if IGNITE_ON_P2 +#if TELEMETRUM_V_0_1 || TELEMETRUM_V_0_2 || TELEMETRUM_V_1_0 || TELEMETRUM_V_1_1 || TELEMETRUM_V_1_2 || TELELAUNCH_V_0_1 /* TeleMetrum readings */ #if HAS_ACCEL_REF if (sequence == 2) { @@ -81,10 +81,10 @@ ao_adc_isr(void) __interrupt 1 } #endif -#if IGNITE_ON_P0 +#if TELEMINI_V_1_0 || TELENANO_V_0_1 /* TeleMini readings */ a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.pres); -#ifdef TELEMINI_V_1_0 +#if TELEMINI_V_1_0 switch (sequence) { case 0: /* pressure */ @@ -138,7 +138,8 @@ ao_adc_isr(void) __interrupt 1 /* Start next conversion */ ADCCON3 = sequence; } -#endif +#endif /* telemini || telenano */ + #ifndef GOT_ADC #error No known ADC configuration set #endif -- cgit v1.2.3 From 8164cd95db62e4564b3a9ba5c06a74c870c03841 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2012 11:46:51 -0600 Subject: altos: Remove debug printf from accel auto-cal Otherwise, this goes way too slow Signed-off-by: Keith Packard --- src/core/ao_config.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 55ec9f40..76a8ed4a 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -256,8 +256,6 @@ ao_config_accel_calibrate_auto(char *orientation) __reentrant while (i) { ao_sleep(DATA_TO_XDATA(&ao_sample_data)); while (i && cal_data_ring != ao_sample_data) { - int16_t accel = ao_data_accel(&ao_data_ring[cal_data_ring]); - printf ("accel %d\n", accel); accel_total += (int32_t) ao_data_accel(&ao_data_ring[cal_data_ring]); cal_data_ring = ao_data_ring_next(cal_data_ring); i--; -- cgit v1.2.3 From 47bc9b2a39b7a8d3ef3fe8acc7fbf0512695e548 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 28 May 2012 11:47:28 -0600 Subject: altos: Clear stm i2c transfer timeout alarm Signed-off-by: Keith Packard --- src/stm/ao_i2c_stm.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index 763ae6cd..d82342db 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -250,10 +250,9 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) ao_alarm(1 + len); cli(); while (!ao_dma_done[tx_dma_index]) - if (ao_sleep(&ao_dma_done[tx_dma_index])) { - printf ("send timeout\n"); + if (ao_sleep(&ao_dma_done[tx_dma_index])) break; - } + ao_clear_alarm(); ao_dma_done_transfer(tx_dma_index); out_cr2("send enable isr", stm_i2c, AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN)); -- cgit v1.2.3 From e5aebfe0203de9e69712fac291c8cd0d3a96a385 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Jun 2012 19:33:18 -0700 Subject: altos: Mark full and mega logging correctly in 'v' command Make sure megametrum reports 'log format 5'. Signed-off-by: Keith Packard --- src/core/ao_log.c | 2 -- src/core/ao_log_big.c | 2 ++ src/core/ao_log_mega.c | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/ao_log.c b/src/core/ao_log.c index d696625e..7884ec3c 100644 --- a/src/core/ao_log.c +++ b/src/core/ao_log.c @@ -25,8 +25,6 @@ __xdata uint8_t ao_log_running; __pdata enum ao_flight_state ao_log_state; __xdata uint16_t ao_flight_number; -__code uint8_t ao_log_format = AO_LOG_FORMAT_FULL; - void ao_log_flush(void) { diff --git a/src/core/ao_log_big.c b/src/core/ao_log_big.c index 50eca069..db01f46c 100644 --- a/src/core/ao_log_big.c +++ b/src/core/ao_log_big.c @@ -20,6 +20,8 @@ static __xdata uint8_t ao_log_mutex; static __xdata struct ao_log_record log; +__code uint8_t ao_log_format = AO_LOG_FORMAT_FULL; + static uint8_t ao_log_csum(__xdata uint8_t *b) __reentrant { diff --git a/src/core/ao_log_mega.c b/src/core/ao_log_mega.c index 1763b9eb..404e6bf7 100644 --- a/src/core/ao_log_mega.c +++ b/src/core/ao_log_mega.c @@ -23,6 +23,8 @@ static __xdata uint8_t ao_log_mutex; static __xdata struct ao_log_mega log; +__code uint8_t ao_log_format = AO_LOG_FORMAT_MEGAMETRUM; + static uint8_t ao_log_csum(__xdata uint8_t *b) __reentrant { -- cgit v1.2.3 From 6806103bad98385c0ec122d400f981eb81c59dd3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Jun 2012 19:34:17 -0700 Subject: altos: add high-z accel and mag sensor to megametrum logging These nicely fill the 32-byte sensor log record Signed-off-by: Keith Packard --- src/core/ao_log.h | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/core/ao_log.h b/src/core/ao_log.h index e585750f..04abeb7e 100644 --- a/src/core/ao_log.h +++ b/src/core/ao_log.h @@ -216,13 +216,17 @@ struct ao_log_mega { int16_t gyro_x; /* 18 */ int16_t gyro_y; /* 20 */ int16_t gyro_z; /* 22 */ - } sensor; /* 24 */ + int16_t mag_x; /* 24 */ + int16_t mag_y; /* 26 */ + int16_t mag_z; /* 28 */ + int16_t accel; /* 30 */ + } sensor; /* 32 */ struct { int16_t v_batt; /* 4 */ - int16_t v_pbatt; /* 8 */ - int16_t n_sense; /* 10 */ - int16_t sense[10]; /* 12 */ - } volt; /* 32 */ + int16_t v_pbatt; /* 6 */ + int16_t n_sense; /* 8 */ + int16_t sense[10]; /* 10 */ + } volt; /* 30 */ struct { int32_t latitude; /* 4 */ int32_t longitude; /* 8 */ -- cgit v1.2.3 From ff4f3a56e09d595abbe32293cbdf1fe368633c49 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Jun 2012 19:35:01 -0700 Subject: altos: megametrum has logging This makes sure the various other subsystems know about it, like the 'v' command. Signed-off-by: Keith Packard --- src/megametrum-v0.1/ao_pins.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 2ae3cea8..ff0edaa9 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -98,6 +98,7 @@ #define HAS_FLIGHT 1 #define HAS_ADC 1 #define HAS_ACCEL 1 +#define HAS_LOG 1 #define AO_DATA_RING 32 #define AO_ADC_NUM_SENSE 6 -- cgit v1.2.3 From ab85337aa942cb73a08bd3b783771179773b9a67 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Jun 2012 19:35:33 -0700 Subject: altos: Timers clock base depends on perhipheral bus prescalers too For some weird reason, a non-unity perhipheral bus clock scaler affects the base of the various timers; this left the 100Hz tick running at 200Hz. Signed-off-by: Keith Packard --- src/stm/ao_timer.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 099a0ece..0c44f352 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -69,7 +69,19 @@ ao_timer_set_adc_interval(uint8_t interval) __critical } #endif -#define TIMER_10kHz (AO_PCLK1 / 10000) +/* + * According to the STM clock-configuration, timers run + * twice as fast as the APB1 clock *if* the APB1 prescaler + * is greater than 1. + */ + +#if AO_APB1_PRESCALER > 1 +#define TIMER_23467_SCALER 2 +#else +#define TIMER_23467_SCALER 1 +#endif + +#define TIMER_10kHz ((AO_PCLK1 * TIMER_23467_SCALER) / 10000) void ao_timer_init(void) -- cgit v1.2.3 From c04af7533bd3fd3f3260338c0753fde966131720 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Jun 2012 23:07:38 -0700 Subject: altos: Add support for MegaAccel daughter card. Switches all acceleration computation to using the MegaAccel accelerometer to ensure support for high-g flights. MPU6000 values continue to be logged as normal Signed-off-by: Keith Packard --- src/cc1111/ao_adc.c | 2 +- src/cc1111/ao_arch.h | 1 + src/core/ao_data.h | 7 ++----- src/megametrum-v0.1/ao_pins.h | 28 ++++++++++++++++++++++++---- src/stm/ao_adc_stm.c | 25 +++++++++++++++++++++++-- 5 files changed, 51 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index 95643956..ce827e25 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -56,7 +56,7 @@ ao_adc_isr(void) __interrupt 1 /* TeleMetrum readings */ #if HAS_ACCEL_REF if (sequence == 2) { - a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].accel_ref); + a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.accel_ref); sequence = 0; } else #endif diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 704ae4f9..44116b81 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -205,6 +205,7 @@ struct ao_adc { int16_t v_batt; /* battery voltage */ int16_t sense_d; /* drogue continuity sense */ int16_t sense_m; /* main continuity sense */ + int16_t accel_ref; /* acceleration reference */ }; #define AO_DATA_RING 32 diff --git a/src/core/ao_data.h b/src/core/ao_data.h index bb26c4c0..83f8df59 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -31,9 +31,6 @@ struct ao_data { #if HAS_ADC struct ao_adc adc; #endif -#if HAS_ACCEL_REF - uint16_t accel_ref; -#endif #if HAS_MS5607 struct ao_ms5607_sample ms5607; #endif @@ -82,7 +79,7 @@ typedef int16_t alt_t; * ao_data_accel_invert - flip rocket ends for positive acceleration */ -#if HAS_MPU6000 +#if HAS_MPU6000 && !HAS_HIGHG_ACCEL typedef int16_t accel_t; @@ -181,7 +178,7 @@ typedef int16_t accel_t; */ #if HAS_ACCEL_REF #define ao_data_accel_sample(packet) \ - ((uint16_t) ((((uint32_t) (packet)->adc.accel << 16) / ((packet)->accel_ref << 1))) >> 1) + ((uint16_t) ((((uint32_t) (packet)->adc.accel << 16) / ((packet)->adc.accel_ref << 1))) >> 1) #else #define ao_data_accel_sample(packet) ((packet)->adc.accel) #endif /* HAS_ACCEL_REF */ diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index ff0edaa9..75b22045 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -98,6 +98,7 @@ #define HAS_FLIGHT 1 #define HAS_ADC 1 #define HAS_ACCEL 1 +#define HAS_ACCEL_REF 1 #define HAS_LOG 1 #define AO_DATA_RING 32 @@ -107,6 +108,8 @@ struct ao_adc { int16_t sense[AO_ADC_NUM_SENSE]; int16_t v_batt; int16_t v_pbatt; + int16_t accel_ref; + int16_t accel; int16_t temp; }; @@ -142,13 +145,22 @@ struct ao_adc { #define AO_ADC_V_PBATT_PORT stm_gpiob #define AO_ADC_V_PBATT_PIN 1 +#define AO_ADC_ACCEL_REF 10 +#define AO_ADC_ACCEL_REF_PORT stm_gpioc +#define AO_ADC_ACCEL_REF_PIN 0 + +#define AO_ADC_ACCEL 11 +#define AO_ADC_ACCEL_PORT stm_gpioc +#define AO_ADC_ACCEL_PIN 1 + #define AO_ADC_TEMP 16 #define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN) | \ (1 << STM_RCC_AHBENR_GPIOEEN) | \ - (1 << STM_RCC_AHBENR_GPIOBEN)) + (1 << STM_RCC_AHBENR_GPIOBEN) | \ + (1 << STM_RCC_AHBENR_GPIOCEN)) -#define AO_NUM_ADC_PIN (AO_ADC_NUM_SENSE + 2) +#define AO_NUM_ADC_PIN (AO_ADC_NUM_SENSE + 4) #define AO_ADC_PIN0_PORT AO_ADC_SENSE_A_PORT #define AO_ADC_PIN0_PIN AO_ADC_SENSE_A_PIN @@ -166,8 +178,12 @@ struct ao_adc { #define AO_ADC_PIN6_PIN AO_ADC_V_BATT_PIN #define AO_ADC_PIN7_PORT AO_ADC_V_PBATT_PORT #define AO_ADC_PIN7_PIN AO_ADC_V_PBATT_PIN +#define AO_ADC_PIN8_PORT AO_ADC_ACCEL_REF_PORT +#define AO_ADC_PIN8_PIN AO_ADC_ACCEL_REF_PIN +#define AO_ADC_PIN9_PORT AO_ADC_ACCEL_PORT +#define AO_ADC_PIN9_PIN AO_ADC_ACCEL_PIN -#define AO_NUM_ADC (AO_ADC_NUM_SENSE + 3) +#define AO_NUM_ADC (AO_ADC_NUM_SENSE + 5) #define AO_ADC_SQ1 AO_ADC_SENSE_A #define AO_ADC_SQ2 AO_ADC_SENSE_B @@ -177,7 +193,9 @@ struct ao_adc { #define AO_ADC_SQ6 AO_ADC_SENSE_F #define AO_ADC_SQ7 AO_ADC_V_BATT #define AO_ADC_SQ8 AO_ADC_V_PBATT -#define AO_ADC_SQ9 AO_ADC_TEMP +#define AO_ADC_SQ9 AO_ADC_ACCEL_REF +#define AO_ADC_SQ10 AO_ADC_ACCEL +#define AO_ADC_SQ11 AO_ADC_TEMP /* * Pressure sensor settings @@ -230,4 +248,6 @@ struct ao_adc { #define AO_MPU6000_INT_PIN 13 #define AO_MPU6000_I2C_INDEX STM_I2C_INDEX(1) +#define HAS_HIGHG_ACCEL 1 + #endif /* _AO_PINS_H_ */ diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index ea9e25e4..24a1fdd0 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -82,7 +82,7 @@ ao_adc_poll(void) stm_adc.sr = 0; ao_dma_set_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1), &stm_adc.dr, - (void *) (&ao_data_ring[ao_data_head].tick + 1), + (void *) (&ao_data_ring[ao_data_head].adc), AO_NUM_ADC, (0 << STM_DMA_CCR_MEM2MEM) | (STM_DMA_CCR_PL_HIGH << STM_DMA_CCR_PL) | @@ -180,6 +180,15 @@ ao_adc_init(void) #ifdef AO_ADC_PIN9_PORT stm_moder_set(&AO_ADC_PIN9_PORT, AO_ADC_PIN9_PIN, STM_MODER_ANALOG); #endif +#ifdef AO_ADC_PIN10_PORT + stm_moder_set(&AO_ADC_PIN10_PORT, AO_ADC_PIN10_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN11_PORT + stm_moder_set(&AO_ADC_PIN11_PORT, AO_ADC_PIN11_PIN, STM_MODER_ANALOG); +#endif +#ifdef AO_ADC_PIN12_PORT + stm_moder_set(&AO_ADC_PIN12_PORT, AO_ADC_PIN12_PIN, STM_MODER_ANALOG); +#endif stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_ADC1EN); @@ -240,7 +249,19 @@ ao_adc_init(void) #if AO_NUM_ADC > 8 stm_adc.sqr4 |= (AO_ADC_SQ9 << 10); #endif - +#if AO_NUM_ADC > 9 + stm_adc.sqr4 |= (AO_ADC_SQ10 << 15); +#endif +#if AO_NUM_ADC > 10 + stm_adc.sqr4 |= (AO_ADC_SQ11 << 20); +#endif +#if AO_NUM_ADC > 11 + stm_adc.sqr4 |= (AO_ADC_SQ12 << 25); +#endif +#if AO_NUM_ADC > 12 +#error "need to finish stm_adc.sqr settings" +#endif + /* Turn ADC on */ stm_adc.cr2 = AO_ADC_CR2_VAL; -- cgit v1.2.3 From 1353b277f8314fbddef81c743bd6ea229364fd18 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Jun 2012 14:58:00 -0700 Subject: altos: Enable some debugging during flight mode on MM Until we've got the radio working, there's no way to see inside the MM state without using USB. Add a diagnostic command to dump out the internal flight state variables. Signed-off-by: Keith Packard --- src/core/ao_flight_mm.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_flight_mm.c b/src/core/ao_flight_mm.c index 27087e55..e812016e 100644 --- a/src/core/ao_flight_mm.c +++ b/src/core/ao_flight_mm.c @@ -108,7 +108,7 @@ ao_flight(void) { /* Set pad mode - we can fly! */ ao_flight_state = ao_flight_pad; -#if HAS_USB +#if HAS_USB && HAS_RADIO /* Disable the USB controller in flight mode * to save power */ @@ -352,11 +352,59 @@ ao_flight(void) } } +#if !HAS_RADIO +static inline int int_part(int16_t i) { return i >> 4; } +static inline int frac_part(int16_t i) { return ((i & 0xf) * 100 + 8) / 16; } + +static void +ao_flight_dump(void) +{ + int16_t accel; + + accel = ((ao_ground_accel - ao_sample_accel) * ao_accel_scale) >> 16; + + printf ("sample:\n"); + printf (" tick %d\n", ao_sample_tick); + printf (" raw pres %d\n", ao_sample_pres); +#if HAS_ACCEL + printf (" raw accel %d\n", ao_sample_accel); +#endif + printf (" ground pres %d\n", ao_ground_pres); +#if HAS_ACCEL + printf (" raw accel %d\n", ao_sample_accel); + printf (" groundaccel %d\n", ao_ground_accel); + printf (" accel_2g %d\n", ao_accel_2g); +#endif + + printf (" alt %d\n", ao_sample_alt); + printf (" height %d\n", ao_sample_height); + printf (" accel %d.%02d\n", int_part(accel), frac_part(accel)); + + + printf ("kalman:\n"); + printf (" height %d\n", ao_height); + printf (" speed %d.%02d\n", int_part(ao_speed), frac_part(ao_speed)); + printf (" accel %d.%02d\n", int_part(ao_accel), frac_part(ao_accel)); + printf (" max_height %d\n", ao_max_height); + printf (" avg_height %d\n", ao_avg_height); + printf (" error_h %d\n", ao_error_h); + printf (" error_avg %d\n", ao_error_h_sq_avg); +} + +__code struct ao_cmds ao_flight_cmds[] = { + { ao_flight_dump, "F\0Dump flight status" }, + { 0, NULL }, +}; +#endif + static __xdata struct ao_task flight_task; void ao_flight_init(void) { ao_flight_state = ao_flight_startup; +#if !HAS_RADIO + ao_cmd_register(&ao_flight_cmds[0]); +#endif ao_add_task(&flight_task, ao_flight, "flight"); } -- cgit v1.2.3 From 8d425ffba84ec6f632e8c0d44105de73242a86a9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Jun 2012 16:53:46 -0700 Subject: altos: Route correct GPIO line to interrupt controller Which GPIO a particular pin interrupt comes from is selected by the SYSCFG EXTICR registers; set these when an exti interrupt is configured. Signed-off-by: Keith Packard --- src/stm/ao_exti_stm.c | 6 +++++- src/stm/stm32l.h | 33 +++++++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c index 013d453b..2108e8b5 100644 --- a/src/stm/ao_exti_stm.c +++ b/src/stm/ao_exti_stm.c @@ -51,8 +51,12 @@ ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback uint32_t mask = 1 << pin; uint32_t pupdr; uint8_t irq; - + ao_exti_callback[pin] = callback; + + /* configure gpio to interrupt routing */ + stm_exticr_set(gpio, pin); + /* configure pin as input, setting selected pull-up/down mode */ stm_moder_set(gpio, pin, STM_MODER_INPUT); switch (mode & (AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_PULL_DOWN)) { diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 0bc7483e..cb66df6c 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -855,10 +855,7 @@ isr(tim7) struct stm_syscfg { vuint32_t memrmp; vuint32_t pmc; - vuint32_t exticr1; - vuint32_t exticr2; - vuint32_t exticr3; - vuint32_t exticr4; + vuint32_t exticr[4]; }; extern struct stm_syscfg stm_syscfg; @@ -871,6 +868,34 @@ extern struct stm_syscfg stm_syscfg; #define STM_SYSCFG_PMC_USB_PU 0 +#define STM_SYSCFG_EXTICR_PA 0 +#define STM_SYSCFG_EXTICR_PB 1 +#define STM_SYSCFG_EXTICR_PC 2 +#define STM_SYSCFG_EXTICR_PD 3 +#define STM_SYSCFG_EXTICR_PE 4 +#define STM_SYSCFG_EXTICR_PH 5 + +static inline void +stm_exticr_set(struct stm_gpio *gpio, int pin) { + uint8_t reg = pin >> 2; + uint8_t shift = (pin & 3) << 2; + uint8_t val = 0; + + if (gpio == &stm_gpioa) + val = STM_SYSCFG_EXTICR_PA; + else if (gpio == &stm_gpiob) + val = STM_SYSCFG_EXTICR_PB; + else if (gpio == &stm_gpioc) + val = STM_SYSCFG_EXTICR_PC; + else if (gpio == &stm_gpiod) + val = STM_SYSCFG_EXTICR_PD; + else if (gpio == &stm_gpioe) + val = STM_SYSCFG_EXTICR_PE; + + stm_syscfg.exticr[reg] = (stm_syscfg.exticr[reg] & ~(0xf << shift)) | val << shift; +} + + struct stm_dma_channel { vuint32_t ccr; vuint32_t cndtr; -- cgit v1.2.3 From 64e2e66a5239541b15f43172655cfb3560bec79b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Jun 2012 16:54:42 -0700 Subject: altos: Fix broken EXTI edge mode selections. Clear pending exti on enable Make sure the edge mode registers are set according to the requested mode. Clear any pending interrupt when enabling to avoid spurious isr call Signed-off-by: Keith Packard --- src/stm/ao_exti_stm.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c index 2108e8b5..0fa24188 100644 --- a/src/stm/ao_exti_stm.c +++ b/src/stm/ao_exti_stm.c @@ -75,11 +75,14 @@ ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback /* Set interrupt mask and rising/falling mode */ stm_exti.imr &= ~mask; - stm_exti.rtsr |= mask; if (mode & AO_EXTI_MODE_RISING) stm_exti.rtsr |= mask; + else + stm_exti.rtsr &= ~mask; if (mode & AO_EXTI_MODE_FALLING) stm_exti.ftsr |= mask; + else + stm_exti.ftsr &= ~mask; if (pin <= 4) irq = STM_ISR_EXTI0_POS + pin; @@ -93,12 +96,16 @@ ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback void ao_exti_enable(struct stm_gpio *gpio, uint8_t pin) { + uint32_t mask = (1 << pin); + stm_exti.pr = mask; stm_exti.imr |= (1 << pin); } void ao_exti_disable(struct stm_gpio *gpio, uint8_t pin) { - stm_exti.imr &= ~(1 << pin); + uint32_t mask = (1 << pin); + stm_exti.imr &= ~mask; + stm_exti.pr = mask; } void -- cgit v1.2.3 From 97317d332f21c42860747c4ecde633bd0228ef52 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Jun 2012 16:56:41 -0700 Subject: altos: Reset i2c controller at boot time In case it's wedged. Signed-off-by: Keith Packard --- src/stm/ao_i2c_stm.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index d82342db..c205706d 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -362,8 +362,12 @@ void ao_i2c_channel_init(uint8_t index) { struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + int i; /* Turn I2C off while configuring */ + stm_i2c->cr1 = (1 << STM_I2C_CR1_SWRST); + for (i = 0; i < 100; i++) + asm("nop"); stm_i2c->cr1 = 0; stm_i2c->cr2 = AO_STM_I2C_CR2; -- cgit v1.2.3 From 69a8907ecbb7ca0e8526aeea0dc7490a191a0f8b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Jun 2012 16:57:22 -0700 Subject: altos: Get HMC5883 driver limping along Not pushing data into the ring yet, but the chip appears to work now. Signed-off-by: Keith Packard --- src/drivers/ao_hmc5883.c | 37 +++++++++++++++++++++++++++---------- src/drivers/ao_hmc5883.h | 37 +++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c index 9551df71..f50376c8 100644 --- a/src/drivers/ao_hmc5883.c +++ b/src/drivers/ao_hmc5883.c @@ -21,6 +21,8 @@ static uint8_t ao_hmc5883_configured; +static uint8_t ao_hmc5883_addr; + static void ao_hmc5883_reg_write(uint8_t addr, uint8_t data) { @@ -32,17 +34,21 @@ ao_hmc5883_reg_write(uint8_t addr, uint8_t data) ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); ao_i2c_send(d, 2, AO_HMC5883_I2C_INDEX, TRUE); ao_i2c_put(AO_HMC5883_I2C_INDEX); + ao_hmc5883_addr = addr + 1; } static void ao_hmc5883_read(uint8_t addr, uint8_t *data, uint8_t len) { ao_i2c_get(AO_HMC5883_I2C_INDEX); - ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); - ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX, FALSE); + if (addr != ao_hmc5883_addr) { + ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_WRITE); + ao_i2c_send(&addr, 1, AO_HMC5883_I2C_INDEX, FALSE); + } ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_READ); ao_i2c_recv(data, len, AO_HMC5883_I2C_INDEX, TRUE); ao_i2c_put(AO_HMC5883_I2C_INDEX); + ao_hmc5883_addr = 0xff; } static uint8_t ao_hmc5883_done; @@ -51,7 +57,7 @@ static void ao_hmc5883_isr(void) { ao_exti_disable(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); - ao_hmc5883_done = 1; + ++ao_hmc5883_done; ao_wakeup(&ao_hmc5883_done); } @@ -65,10 +71,14 @@ ao_hmc5883_sample(struct ao_hmc5883_sample *sample) ao_hmc5883_done = 0; ao_exti_enable(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); ao_hmc5883_reg_write(HMC5883_MODE, HMC5883_MODE_SINGLE); + cli(); while (!ao_hmc5883_done) ao_sleep(&ao_hmc5883_done); sei(); + + printf ("done %d\n", ao_hmc5883_done); + ao_hmc5883_read(HMC5883_X_MSB, (uint8_t *) sample, sizeof (struct ao_hmc5883_sample)); #if __BYTE_ORDER == __LITTLE_ENDIAN /* byte swap */ @@ -82,21 +92,27 @@ ao_hmc5883_sample(struct ao_hmc5883_sample *sample) static uint8_t ao_hmc5883_setup(void) { + uint8_t d; uint8_t present; if (ao_hmc5883_configured) return 1; - /* Enable the EXTI interrupt for the appropriate pin */ - ao_enable_port(AO_HMC5883_INT_PORT); - ao_exti_setup(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN, - AO_EXTI_MODE_FALLING, ao_hmc5883_isr); - ao_i2c_get(AO_HMC5883_I2C_INDEX); present = ao_i2c_start(AO_HMC5883_I2C_INDEX, HMC5883_ADDR_READ); - ao_i2c_recv(NULL, 0, AO_HMC5883_I2C_INDEX, TRUE); + ao_i2c_recv(&d, 1, AO_HMC5883_I2C_INDEX, TRUE); ao_i2c_put(AO_HMC5883_I2C_INDEX); + if (!present) return 0; + + ao_hmc5883_reg_write(HMC5883_CONFIG_A, + (HMC5883_CONFIG_A_MA_8 << HMC5883_CONFIG_A_MA) | + (HMC5883_CONFIG_A_DO_15 << HMC5883_CONFIG_A_DO) | + (HMC5883_CONFIG_A_MS_NORMAL << HMC5883_CONFIG_A_MS)); + + ao_hmc5883_reg_write(HMC5883_CONFIG_B, + (HMC5883_CONFIG_B_GN_1_3 << HMC5883_CONFIG_B_GN)); + ao_hmc5883_configured = 1; return 1; } @@ -132,9 +148,10 @@ ao_hmc5883_init(void) { ao_hmc5883_configured = 0; + ao_enable_port(AO_HMC5883_INT_PORT); ao_exti_setup(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN, - AO_EXTI_MODE_FALLING, + AO_EXTI_MODE_FALLING | AO_EXTI_MODE_PULL_UP, ao_hmc5883_isr); ao_cmd_register(&ao_hmc5883_cmds[0]); diff --git a/src/drivers/ao_hmc5883.h b/src/drivers/ao_hmc5883.h index 2ec27dd9..55690978 100644 --- a/src/drivers/ao_hmc5883.h +++ b/src/drivers/ao_hmc5883.h @@ -22,11 +22,48 @@ #define HMC5883_ADDR_READ 0x3d #define HMC5883_CONFIG_A 0 + +#define HMC5883_CONFIG_A_MA 5 +#define HMC5883_CONFIG_A_MA_1 0 +#define HMC5883_CONFIG_A_MA_2 1 +#define HMC5883_CONFIG_A_MA_4 2 +#define HMC5883_CONFIG_A_MA_8 3 +#define HMC5883_CONFIG_A_MA_MASK 3 + +#define HMC5883_CONFIG_A_DO 2 +#define HMC5883_CONFIG_A_DO_0_75 0 +#define HMC5883_CONFIG_A_DO_1_5 1 +#define HMC5883_CONFIG_A_DO_3 2 +#define HMC5883_CONFIG_A_DO_7_5 3 +#define HMC5883_CONFIG_A_DO_15 4 +#define HMC5883_CONFIG_A_DO_30 5 +#define HMC5883_CONFIG_A_DO_75 6 +#define HMC5883_CONFIG_A_DO_MASK 7 + +#define HMC5883_CONFIG_A_MS 0 +#define HMC5883_CONFIG_A_MS_NORMAL 0 +#define HMC5883_CONFIG_A_MS_POSITIVE_BIAS 1 +#define HMC5883_CONFIG_A_MS_NEGATIVE_BIAS 2 +#define HMC5883_CONFIG_A_MS_MASK 3 + #define HMC5883_CONFIG_B 1 + +#define HMC5883_CONFIG_B_GN 5 +#define HMC5883_CONFIG_B_GN_0_88 0 +#define HMC5883_CONFIG_B_GN_1_3 1 +#define HMC5883_CONFIG_B_GN_1_9 2 +#define HMC5883_CONFIG_B_GN_2_5 3 +#define HMC5883_CONFIG_B_GN_4_0 4 +#define HMC5883_CONFIG_B_GN_4_7 5 +#define HMC5883_CONFIG_B_GN_5_6 6 +#define HMC5883_CONFIG_B_GN_8_1 7 +#define HMC5883_CONFIG_B_GN_MASK 7 + #define HMC5883_MODE 2 #define HMC5883_MODE_CONTINUOUS 0 #define HMC5883_MODE_SINGLE 1 #define HMC5883_MODE_IDLE 2 + #define HMC5883_X_MSB 3 #define HMC5883_X_LSB 4 #define HMC5883_Y_MSB 5 -- cgit v1.2.3 From 9aa7993ee31bdfd6890ad7262a0375c07464ee76 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 2 Jun 2012 17:09:00 -0700 Subject: altos: Intgrate hmc5883 sensor into adc ring Creates a task to poll the mag sensor and place the data into the sensor data ring. Signed-off-by: Keith Packard --- src/core/ao_data.h | 7 +++++++ src/core/ao_log_mega.c | 4 ++++ src/drivers/ao_hmc5883.c | 47 ++++++++++++++++++++++++++----------------- src/drivers/ao_hmc5883.h | 4 ++++ src/megametrum-v0.1/ao_pins.h | 1 + src/stm/ao_adc_stm.c | 5 +++++ 6 files changed, 50 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/core/ao_data.h b/src/core/ao_data.h index 83f8df59..502df6c9 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -26,6 +26,10 @@ #include #endif +#if HAS_HMC5883 +#include +#endif + struct ao_data { uint16_t tick; #if HAS_ADC @@ -37,6 +41,9 @@ struct ao_data { #if HAS_MPU6000 struct ao_mpu6000_sample mpu6000; #endif +#if HAS_HMC5883 + struct ao_hmc5883_sample hmc5883; +#endif }; #define ao_data_ring_next(n) (((n) + 1) & (AO_DATA_RING - 1)) diff --git a/src/core/ao_log_mega.c b/src/core/ao_log_mega.c index 404e6bf7..68e2af49 100644 --- a/src/core/ao_log_mega.c +++ b/src/core/ao_log_mega.c @@ -120,6 +120,10 @@ ao_log(void) log.u.sensor.gyro_x = ao_data_ring[ao_log_data_pos].mpu6000.gyro_x; log.u.sensor.gyro_y = ao_data_ring[ao_log_data_pos].mpu6000.gyro_y; log.u.sensor.gyro_z = ao_data_ring[ao_log_data_pos].mpu6000.gyro_z; + log.u.sensor.mag_x = ao_data_ring[ao_log_data_pos].hmc5883.x; + log.u.sensor.mag_y = ao_data_ring[ao_log_data_pos].hmc5883.y; + log.u.sensor.mag_z = ao_data_ring[ao_log_data_pos].hmc5883.z; + log.u.sensor.accel = ao_data_ring[ao_log_data_pos].adc.accel; ao_log_mega(&log); if (ao_log_state <= ao_flight_coast) next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c index f50376c8..1bc914e6 100644 --- a/src/drivers/ao_hmc5883.c +++ b/src/drivers/ao_hmc5883.c @@ -19,6 +19,8 @@ #include #include +uint8_t ao_hmc5883_valid; + static uint8_t ao_hmc5883_configured; static uint8_t ao_hmc5883_addr; @@ -57,7 +59,7 @@ static void ao_hmc5883_isr(void) { ao_exti_disable(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); - ++ao_hmc5883_done; + ao_hmc5883_done = 1; ao_wakeup(&ao_hmc5883_done); } @@ -77,8 +79,6 @@ ao_hmc5883_sample(struct ao_hmc5883_sample *sample) ao_sleep(&ao_hmc5883_done); sei(); - printf ("done %d\n", ao_hmc5883_done); - ao_hmc5883_read(HMC5883_X_MSB, (uint8_t *) sample, sizeof (struct ao_hmc5883_sample)); #if __BYTE_ORDER == __LITTLE_ENDIAN /* byte swap */ @@ -94,6 +94,7 @@ ao_hmc5883_setup(void) { uint8_t d; uint8_t present; + if (ao_hmc5883_configured) return 1; @@ -103,7 +104,7 @@ ao_hmc5883_setup(void) ao_i2c_put(AO_HMC5883_I2C_INDEX); if (!present) - return 0; + ao_panic(AO_PANIC_SELF_TEST); ao_hmc5883_reg_write(HMC5883_CONFIG_A, (HMC5883_CONFIG_A_MA_8 << HMC5883_CONFIG_A_MA) | @@ -117,24 +118,32 @@ ao_hmc5883_setup(void) return 1; } +struct ao_hmc5883_sample ao_hmc5883_current; + +static void +ao_hmc5883(void) +{ + ao_hmc5883_setup(); + for (;;) { + struct ao_hmc5883_sample ao_hmc5883_next; + + ao_hmc5883_sample(&ao_hmc5883_next); + ao_arch_critical( + ao_hmc5883_current = ao_hmc5883_next; + ao_hmc5883_valid = 1; + ); + ao_delay(0); + } +} + +static struct ao_task ao_hmc5883_task; + static void ao_hmc5883_show(void) { - uint8_t addr, data; - struct ao_hmc5883_sample sample; + struct ao_hmc5883_sample sample; - if (!ao_hmc5883_setup()) { - printf("hmc5883 not present\n"); - return; - } -#if 0 - for (addr = 0; addr <= 12; addr++) { - ao_hmc5883_read(addr, &data, 1); - printf ("hmc5883 register %2d: %02x\n", - addr, data); - } -#endif - ao_hmc5883_sample(&sample); + sample = ao_hmc5883_current; printf ("X: %d Y: %d Z: %d\n", sample.x, sample.y, sample.z); } @@ -147,6 +156,7 @@ void ao_hmc5883_init(void) { ao_hmc5883_configured = 0; + ao_hmc5883_valid = 0; ao_enable_port(AO_HMC5883_INT_PORT); ao_exti_setup(&AO_HMC5883_INT_PORT, @@ -154,5 +164,6 @@ ao_hmc5883_init(void) AO_EXTI_MODE_FALLING | AO_EXTI_MODE_PULL_UP, ao_hmc5883_isr); + ao_add_task(&ao_hmc5883_task, ao_hmc5883, "hmc5883"); ao_cmd_register(&ao_hmc5883_cmds[0]); } diff --git a/src/drivers/ao_hmc5883.h b/src/drivers/ao_hmc5883.h index 55690978..8d726510 100644 --- a/src/drivers/ao_hmc5883.h +++ b/src/drivers/ao_hmc5883.h @@ -75,10 +75,14 @@ #define HMC5883_ID_B 11 #define HMC5883_ID_C 12 +extern uint8_t ao_hmc5883_valid; + struct ao_hmc5883_sample { int16_t x, y, z; }; +extern struct ao_hmc5883_sample ao_hmc5883_current; + void ao_hmc5883_init(void); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 75b22045..d6394d9b 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -235,6 +235,7 @@ struct ao_adc { * Mag sensor (hmc5883) */ +#define HAS_HMC5883 1 #define AO_HMC5883_INT_PORT stm_gpioc #define AO_HMC5883_INT_PIN 12 #define AO_HMC5883_I2C_INDEX STM_I2C_INDEX(1) diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index 24a1fdd0..71299de9 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -62,6 +62,11 @@ static void ao_adc_done(int index) step = 0; ao_data_ring[ao_data_head].ms5607 = ao_ms5607_current; #endif +#if HAS_HMC5883 + if (!ao_hmc5883_valid) + step = 0; + ao_data_ring[ao_data_head].hmc5883 = ao_hmc5883_current; +#endif if (step) { ao_data_head = ao_data_ring_next(ao_data_head); ao_wakeup((void *) &ao_data_head); -- cgit v1.2.3 From 718a8affe1df98eacfd707b5c8c34f9456dcff14 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 20:47:14 -0700 Subject: altos: Remove accel_ref from pre v1.1 TM firmware V1.0 needs RAM space for flash buffer, leaving too little room for this extra data. Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 44116b81..cece09eb 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -205,7 +205,9 @@ struct ao_adc { int16_t v_batt; /* battery voltage */ int16_t sense_d; /* drogue continuity sense */ int16_t sense_m; /* main continuity sense */ +#if HAS_ACCEL_REF int16_t accel_ref; /* acceleration reference */ +#endif }; #define AO_DATA_RING 32 -- cgit v1.2.3 From f1b14932149153a096961fff94191778f88581d9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 20:49:15 -0700 Subject: altos: Remove unused AES code from teledongle and tidongle Leave this out as neither of these products need it. Signed-off-by: Keith Packard --- src/cc1111/ao_pins.h | 10 +++++----- src/product/Makefile.telebt | 4 ++-- src/product/Makefile.teledongle | 4 ++-- src/product/ao_teledongle.c | 2 -- src/product/ao_tidongle.c | 2 -- src/tidongle/Makefile | 2 -- 6 files changed, 9 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 5eef0de4..0923e75d 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -150,7 +150,7 @@ #define HAS_MONITOR 1 #define LEGACY_MONITOR 1 #define HAS_RSSI 1 - #define HAS_AES 1 + #define HAS_AES 0 #endif #if defined(TELEMINI_V_1_0) @@ -259,7 +259,7 @@ #define HAS_MONITOR 1 #define LEGACY_MONITOR 1 #define HAS_RSSI 1 - #define HAS_AES 1 + #define HAS_AES 0 #endif #if defined(TIDONGLE) @@ -286,7 +286,7 @@ #define HAS_MONITOR 1 #define LEGACY_MONITOR 1 #define HAS_RSSI 1 - #define HAS_AES 1 + #define HAS_AES 0 #endif #if defined(TELEBT_V_0_0) @@ -322,7 +322,7 @@ #define HAS_MONITOR 1 #define LEGACY_MONITOR 1 #define HAS_RSSI 0 - #define HAS_AES 1 + #define HAS_AES 0 #endif #if defined(TELEBT_V_0_1) @@ -365,7 +365,7 @@ #define HAS_MONITOR 1 #define LEGACY_MONITOR 1 #define HAS_RSSI 0 - #define HAS_AES 1 + #define HAS_AES 0 #endif #if defined(TELELAUNCH_V_0_1) diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index e53aa2c4..90525d63 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -15,6 +15,8 @@ endif INC = \ ao.h \ ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ cc1111.h \ ao_product.h \ $(TELEBT_INC) @@ -32,14 +34,12 @@ CORE_SRC = \ ao_freq.c CC1111_SRC = \ - ao_aes.c \ ao_dbg.c \ ao_dma.c \ ao_led.c \ ao_packet.c \ ao_packet_master.c \ ao_radio.c \ - ao_radio_cmac.c \ ao_romconfig.c \ ao_serial.c \ ao_string.c \ diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle index 27e7d24b..fbf14a04 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -18,6 +18,8 @@ endif INC = \ ao.h \ ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ cc1111.h \ ao_product.h @@ -35,14 +37,12 @@ CORE_SRC = \ ao_freq.c CC1111_SRC = \ - ao_aes.c \ ao_dbg.c \ ao_dma.c \ ao_led.c \ ao_packet.c \ ao_packet_master.c \ ao_radio.c \ - ao_radio_cmac.c \ ao_romconfig.c \ ao_string.c \ ao_timer.c \ diff --git a/src/product/ao_teledongle.c b/src/product/ao_teledongle.c index 49b80500..0c829e97 100644 --- a/src/product/ao_teledongle.c +++ b/src/product/ao_teledongle.c @@ -35,8 +35,6 @@ main(void) #if HAS_DBG ao_dbg_init(); #endif - ao_aes_init(); - ao_radio_cmac_init(); ao_config_init(); ao_start_scheduler(); } diff --git a/src/product/ao_tidongle.c b/src/product/ao_tidongle.c index a504a747..cba0b122 100644 --- a/src/product/ao_tidongle.c +++ b/src/product/ao_tidongle.c @@ -34,8 +34,6 @@ main(void) ao_rssi_init(AO_LED_RED); ao_radio_init(); ao_dbg_init(); - ao_aes_init(); - ao_radio_cmac_init(); ao_config_init(); /* Bring up the USB link */ P1DIR |= 1; diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile index 149b00c5..0bb2ce32 100644 --- a/src/tidongle/Makefile +++ b/src/tidongle/Makefile @@ -30,14 +30,12 @@ CORE_SRC = \ ao_freq.c CC1111_SRC = \ - ao_aes.c \ ao_dbg.c \ ao_dma.c \ ao_led.c \ ao_packet.c \ ao_packet_master.c \ ao_radio.c \ - ao_radio_cmac.c \ ao_romconfig.c \ ao_string.c \ ao_timer.c \ -- cgit v1.2.3 From 06afa2c3e78ea5bc9f1eb4913ee35c0eab0ac1bf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 20:50:10 -0700 Subject: altos: Legacy telemetry needs original ADC record The legacy telemetry packets included the raw ADC structure directly, so make sure that doesn't change further, allowing teledongle firmware to remain compatible with old TM firmware. Signed-off-by: Keith Packard --- src/core/ao.h | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index da1fd67b..a4136a9b 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -574,6 +574,16 @@ ao_gps_report_init(void); * ao_telemetry_orig.c */ +struct ao_adc_orig { + uint16_t tick; /* tick when the sample was read */ + int16_t accel; /* accelerometer */ + int16_t pres; /* pressure sensor */ + int16_t temp; /* temperature sensor */ + int16_t v_batt; /* battery voltage */ + int16_t sense_d; /* drogue continuity sense */ + int16_t sense_m; /* main continuity sense */ +}; + struct ao_telemetry_orig { uint16_t serial; uint16_t flight; @@ -591,7 +601,7 @@ struct ao_telemetry_orig { int16_t ground_pres; int16_t accel_plus_g; int16_t accel_minus_g; - struct ao_adc adc; + struct ao_adc_orig adc; struct ao_gps_orig gps; char callsign[AO_MAX_CALLSIGN]; struct ao_gps_tracking_orig gps_tracking; -- cgit v1.2.3 From 1832e2f76c844e97a2bd11226b003fb2af8057db Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 20:51:35 -0700 Subject: altos: fix test builds of non-accel flight code Remove references to accel variables when building baro-only flight test code. Signed-off-by: Keith Packard --- src/core/ao_flight_mm.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/core/ao_flight_mm.c b/src/core/ao_flight_mm.c index e812016e..2bc5c36a 100644 --- a/src/core/ao_flight_mm.c +++ b/src/core/ao_flight_mm.c @@ -359,9 +359,11 @@ static inline int frac_part(int16_t i) { return ((i & 0xf) * 100 + 8) / 16; } static void ao_flight_dump(void) { +#if HAS_ACCEL int16_t accel; accel = ((ao_ground_accel - ao_sample_accel) * ao_accel_scale) >> 16; +#endif printf ("sample:\n"); printf (" tick %d\n", ao_sample_tick); @@ -378,7 +380,9 @@ ao_flight_dump(void) printf (" alt %d\n", ao_sample_alt); printf (" height %d\n", ao_sample_height); +#if HAS_ACCEL printf (" accel %d.%02d\n", int_part(accel), frac_part(accel)); +#endif printf ("kalman:\n"); -- cgit v1.2.3 From e687a9bafc696998b47fd0300fbc89dece09509c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 20:52:38 -0700 Subject: altos: Make 'v' command dump pressure sensor ROM values Avoids needing a new command Signed-off-by: Keith Packard --- src/core/ao_cmd.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index fdc70007..40bb476c 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -251,6 +251,9 @@ version(void) printf("serial-number %u\n", ao_serial_number); #if HAS_LOG printf("log-format %u\n", ao_log_format); +#endif +#if HAS_MS5607 + ao_ms5607_info(); #endif printf("software-version %s\n", ao_version); } -- cgit v1.2.3 From dec5cbee22f13c47690b0c6bf7ca724ef132fe5e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 20:53:06 -0700 Subject: altos: typo in ao_monitor prevented ground station from including code This created ground station software that couldn't actually receive and report telemetry packets. Signed-off-by: Keith Packard --- src/core/ao_monitor.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 830464d8..4ca641b7 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -17,6 +17,7 @@ #include "ao.h" #include "ao_telem.h" +#include "ao_flight.h" #if !HAS_MONITOR #error Must define HAS_MONITOR to 1 @@ -27,7 +28,7 @@ #endif #ifndef HAS_MONITOR_PUT -#define HAS_MONIOTOR_PUT 1 +#define HAS_MONITOR_PUT 1 #endif #ifndef AO_MONITOR_LED -- cgit v1.2.3 From a9ad342ae4c34626df4f2891da4c7f6d2c14d73e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 20:53:53 -0700 Subject: altos: Other half of the ms5607 prom reporting patch Signed-off-by: Keith Packard --- src/drivers/ao_ms5607.c | 16 ++++++++++------ src/drivers/ao_ms5607.h | 3 +++ 2 files changed, 13 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 7db7022f..0f0625d0 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -215,12 +215,9 @@ ao_ms5607(void) __xdata struct ao_task ao_ms5607_task; -static void -ao_ms5607_dump(void) +void +ao_ms5607_info(void) { - struct ao_ms5607_sample sample; - struct ao_ms5607_value value; - printf ("ms5607 reserved: %u\n", ms5607_prom.reserved); printf ("ms5607 sens: %u\n", ms5607_prom.sens); printf ("ms5607 off: %u\n", ms5607_prom.off); @@ -229,6 +226,13 @@ ao_ms5607_dump(void) printf ("ms5607 tref: %u\n", ms5607_prom.tref); printf ("ms5607 tempsens: %u\n", ms5607_prom.tempsens); printf ("ms5607 crc: %u\n", ms5607_prom.crc); +} + +static void +ao_ms5607_dump(void) +{ + struct ao_ms5607_sample sample; + struct ao_ms5607_value value; sample = ao_ms5607_current; ao_ms5607_convert(&sample, &value); @@ -238,7 +242,7 @@ ao_ms5607_dump(void) } __code struct ao_cmds ao_ms5607_cmds[] = { - { ao_ms5607_dump, "p\0Display MS5607 data" }, + { ao_ms5607_dump, "B\0Display MS5607 data" }, { 0, NULL }, }; diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h index 1384d3a2..fa3b1c5b 100644 --- a/src/drivers/ao_ms5607.h +++ b/src/drivers/ao_ms5607.h @@ -62,6 +62,9 @@ struct ao_ms5607_value { void ao_ms5607_init(void); +void +ao_ms5607_info(void); + void ao_ms5607_sample(struct ao_ms5607_sample *sample); -- cgit v1.2.3 From 705891be53e298ac6ced4ba02b87d2f6d1085b34 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 4 Jun 2012 20:54:36 -0700 Subject: altos: Make cc1111 products all depend on ao_arch.h and ao_arch_func.h Ensures that files get recompiled as needed Signed-off-by: Keith Packard --- src/product/Makefile.telelaunch | 2 ++ src/product/Makefile.telemetrum | 2 ++ src/product/Makefile.telemini | 2 ++ src/product/Makefile.telenano | 2 ++ 4 files changed, 8 insertions(+) (limited to 'src') diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch index 688ac5f3..3753f3c9 100644 --- a/src/product/Makefile.telelaunch +++ b/src/product/Makefile.telelaunch @@ -15,6 +15,8 @@ endif INC = \ ao.h \ ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ cc1111.h \ ao_product.h diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index b1111053..fba2c19a 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -18,6 +18,8 @@ endif INC = \ ao.h \ ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ cc1111.h \ altitude.h \ ao_kalman.h \ diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini index 9506eb65..f0ab2b14 100644 --- a/src/product/Makefile.telemini +++ b/src/product/Makefile.telemini @@ -15,6 +15,8 @@ endif INC = \ ao.h \ ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ cc1111.h \ ao_product.h diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index 56db1c2c..a55bcf95 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -15,6 +15,8 @@ endif INC = \ ao.h \ ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ cc1111.h \ ao_product.h -- cgit v1.2.3 From baf1be1def01266512e67068948bf19b04ead6aa Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jun 2012 22:23:10 -0700 Subject: Allow product to override maximum number of command lists (NUM_CMDS) Just in case some product wants to save memory, or have more. Signed-off-by: Keith Packard --- src/core/ao_cmd.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 40bb476c..fbf0c347 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -258,7 +258,9 @@ version(void) printf("software-version %s\n", ao_version); } +#ifndef NUM_CMDS #define NUM_CMDS 11 +#endif static __code struct ao_cmds *__xdata (ao_cmds[NUM_CMDS]); static __pdata uint8_t ao_ncmds; -- cgit v1.2.3 From a5a7df405c242593cbc828d5b66bbfc141a35947 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jun 2012 22:26:06 -0700 Subject: Temporarily disable packet and telem on MM While work on the radio code progresses Signed-off-by: Keith Packard --- src/core/ao_flight_mm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/core/ao_flight_mm.c b/src/core/ao_flight_mm.c index 2bc5c36a..c2a7cd64 100644 --- a/src/core/ao_flight_mm.c +++ b/src/core/ao_flight_mm.c @@ -94,7 +94,7 @@ ao_flight(void) */ ao_flight_state = ao_flight_invalid; -#if HAS_RADIO +#if HAS_RADIO && PACKET_HAS_SLAVE /* Turn on packet system in invalid mode on TeleMetrum */ ao_packet_slave_start(); #endif @@ -120,7 +120,7 @@ ao_flight(void) ao_packet_slave_stop(); #endif -#if HAS_RADIO +#if HAS_RADIO && !defined (MEGAMETRUM) /* Turn on telemetry system */ ao_rdf_set(1); ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); @@ -131,7 +131,7 @@ ao_flight(void) /* Set idle mode */ ao_flight_state = ao_flight_idle; -#if HAS_ACCEL && HAS_RADIO +#if HAS_ACCEL && HAS_RADIO && PACKET_HAS_SLAVE /* Turn on packet system in idle mode on TeleMetrum */ ao_packet_slave_start(); #endif @@ -171,7 +171,7 @@ ao_flight(void) /* start logging data */ ao_log_start(); -#if HAS_RADIO +#if HAS_RADIO && !defined(MEGAMETRUM) /* Increase telemetry rate */ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); @@ -259,7 +259,7 @@ ao_flight(void) ao_ignite(ao_igniter_drogue); #endif -#if HAS_RADIO +#if HAS_RADIO && !defined(MEGAMETRUM) /* slow down the telemetry system */ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); -- cgit v1.2.3 From 97d163c88ed8c8f64a9714018863d0b6eedab38f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jun 2012 22:27:48 -0700 Subject: altos: Configure cc1120 frequency Set default conversion value, and pull the selected frequency calibration data out of the config block. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 95b21170..5156b7b2 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -25,7 +25,7 @@ uint8_t ao_radio_abort; #define CC1120_DEBUG 1 -uint32_t ao_radio_cal = 1186611; +uint32_t ao_radio_cal = 0x6ca333; #define FOSC 32000000 @@ -492,6 +492,9 @@ ao_radio_get(uint8_t len) ao_mutex_get(&ao_radio_mutex); if (!ao_radio_configured) ao_radio_setup(); + ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16); + ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8); + ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting); ao_radio_reg_write(CC1120_PKT_LEN, len); } -- cgit v1.2.3 From c96e60bedeb00d28c36436c12b803fd8cbadce26 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jun 2012 22:28:55 -0700 Subject: altos: Actually write cc1120 register values Helps to not use 'read' mode when writing. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 5156b7b2..d2820e51 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -77,13 +77,13 @@ ao_radio_reg_write(uint16_t addr, uint8_t value) printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value); #endif if (CC1120_IS_EXTENDED(addr)) { - data[0] = ((1 << CC1120_READ) | + data[0] = ((0 << CC1120_READ) | (0 << CC1120_BURST) | CC1120_EXTENDED); data[1] = addr; d = 2; } else { - data[0] = ((1 << CC1120_READ) | + data[0] = ((0 << CC1120_READ) | (0 << CC1120_BURST) | addr); d = 1; -- cgit v1.2.3 From 93e6d0a2c0b60e7bedd34f06ba63b468dcc8e013 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jun 2012 22:30:03 -0700 Subject: altos: Fix RDF mode data rate and PKT_CFG0 value Changes tone to the desired 1kHz frequency and ensures the PKT_CFG0 has the right value. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index d2820e51..37dc67db 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -197,8 +197,8 @@ ao_radio_recv_abort(void) * * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes */ -#define RDF_DRATE_E 6 -#define RDF_DRATE_M 511705 +#define RDF_DRATE_E 5 +#define RDF_DRATE_M 25166 #define RDF_PACKET_LEN 50 static const uint16_t rdf_setup[] = { @@ -216,6 +216,11 @@ static const uint16_t rdf_setup[] = { (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) | (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) | (0 << CC1120_PKT_CFG1_APPEND_STATUS)), + CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) | + (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | + (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | + (0 << CC1120_PKT_CFG0_UART_MODE_EN) | + (0 << CC1120_PKT_CFG0_UART_SWAP_EN)), }; #define int_pin(w) printf("\t%s: %d\n", \ -- cgit v1.2.3 From 27c95adf35e646840b9bd562497eea0dc96bb9bb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jun 2012 22:31:36 -0700 Subject: altos: use 'b' command for radio beep 'B' is used by the baro data dumper. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 37dc67db..5fe314c9 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -725,7 +725,7 @@ static const struct ao_cmds ao_radio_cmds[] = { { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" }, #if CC1120_DEBUG { ao_radio_show, "R\0Show CC1120 status" }, - { ao_radio_beep, "B\0Emit an RDF beacon" }, + { ao_radio_beep, "b\0Emit an RDF beacon" }, #endif { 0, NULL } }; -- cgit v1.2.3 From 1b7e4c29bf9608bfc972ae28b53cc823f4c37f92 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jun 2012 22:32:10 -0700 Subject: altos: Make sure cc1120 is initialized correctly at startup time Check to make sure it pulls down MISO when CS is enabled. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 5fe314c9..63f7cd89 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -733,8 +733,18 @@ static const struct ao_cmds ao_radio_cmds[] = { void ao_radio_init(void) { + int i; + ao_radio_configured = 0; ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN)); + AO_CC1120_SPI_CS_PORT.bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN)); + for (i = 0; i < 10000; i++) { + if ((SPI_2_GPIO.idr & (1 << SPI_2_MISO)) == 0) + break; + } + AO_CC1120_SPI_CS_PORT.bsrr = (1 << AO_CC1120_SPI_CS_PIN); + if (i == 10000) + ao_panic(AO_PANIC_SELF_TEST); ao_cmd_register(&ao_radio_cmds[0]); } -- cgit v1.2.3 From c2949ea15c59215834fedac7646f50c8a09f716f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jun 2012 22:38:37 -0700 Subject: altos: Fix cc1120 packet mode datarate and config Was using the wrong function Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 63f7cd89..68f7e736 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -406,17 +406,16 @@ ao_radio_recv(__xdata void *d, uint8_t size) /* * For our packet data, set the symbol rate to 38360 Baud * - * (2**20 - DATARATE_M) * 2 ** DATARATE_E + * (2**20 + DATARATE_M) * 2 ** DATARATE_E * Rdata = -------------------------------------- * fosc * 2 ** 39 * - * DATARATE_M = 405002 - * DATARATE_E = 10 * - * To make the tone last for 200ms, we need 2000 * .2 = 400 bits or 50 bytes + * DATARATE_M = 239914 + * DATARATE_E = 9 */ -#define PACKET_DRATE_E 10 -#define PACKET_DRATE_M 405002 +#define PACKET_DRATE_E 9 +#define PACKET_DRATE_M 239914 static const uint16_t packet_setup[] = { CC1120_DEVIATION_M, PACKET_DEV_M, @@ -433,6 +432,11 @@ static const uint16_t packet_setup[] = { (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) | (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) | (1 << CC1120_PKT_CFG1_APPEND_STATUS)), + CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) | + (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | + (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | + (0 << CC1120_PKT_CFG0_UART_MODE_EN) | + (0 << CC1120_PKT_CFG0_UART_SWAP_EN)), }; void -- cgit v1.2.3 From e09e35471e788b88909ff01037fb8e0e4eabcd7d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jun 2012 22:40:30 -0700 Subject: altos: Start making cc1120 radio work RDF tones and radio calibration work now. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 31 ++++++++++++++++++++++++++----- src/drivers/ao_cc1120.h | 1 + src/drivers/ao_cc1120_CC1120.h | 5 +---- src/megametrum-v0.1/Makefile | 2 +- src/megametrum-v0.1/ao_megametrum.c | 18 +----------------- src/megametrum-v0.1/ao_pins.h | 9 ++++++++- 6 files changed, 38 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 68f7e736..a1d78d9c 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -106,7 +106,7 @@ ao_radio_strobe(uint8_t addr) ao_radio_duplex(&addr, &in, 1); ao_radio_deselect(); #if CC1120_DEBUG - printf("%02x\n", in); + printf("%02x\n", in); flush(); #endif return in; } @@ -254,15 +254,33 @@ ao_radio_rdf(uint8_t len) ao_radio_abort = 0; for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]); - ao_radio_reg_write(CC1120_PKT_LEN, len); + +#if 0 int_pin ("Before CFG"); ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); int_pin ("After CFG"); +#endif + + ao_radio_fifo_write_fixed(ao_radio_rdf_value, len); + + ao_radio_reg_write(CC1120_PKT_LEN, len); + + printf ("packet length: %d\n", ao_radio_reg_read(CC1120_PKT_LEN)); + ao_radio_strobe(CC1120_STX); + + for (i = 0; i < 20; i++) { + printf ("%d ", i); flush(); + printf ("Status %02x ", ao_radio_status()); flush(); + printf ("num_tx_bytes %d ", ao_radio_reg_read(CC1120_NUM_TXBYTES)); flush(); + printf ("marc status %x\n", ao_radio_marc_status()); flush(); + ao_delay(AO_MS_TO_TICKS(50)); + } + +#if 0 ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); int_pin ("After strobe"); ao_delay(AO_MS_TO_TICKS(100)); - ao_radio_fifo_write_fixed(ao_radio_rdf_value, len); int_pin ("After delay"); cli(); for (i = 0; i < 20; i++) { @@ -278,11 +296,14 @@ ao_radio_rdf(uint8_t len) #endif } sei(); +#endif printf ("num_tx_bytes %d marc status %x\n", ao_radio_reg_read(CC1120_NUM_TXBYTES), ao_radio_marc_status()); +#if 0 if (!ao_radio_tx_done()) ao_radio_idle(); +#endif ao_radio_set_packet(); ao_radio_put(); } @@ -488,8 +509,8 @@ ao_radio_setup(void) ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP); /* Enable the EXTI interrupt for the appropriate pin */ - ao_enable_port(AO_CC1120_INT_PORT); - ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_isr); +// ao_enable_port(AO_CC1120_INT_PORT); +// ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_isr); ao_radio_set_packet(); ao_radio_configured = 1; diff --git a/src/drivers/ao_cc1120.h b/src/drivers/ao_cc1120.h index 0f03f2c7..5822a21a 100644 --- a/src/drivers/ao_cc1120.h +++ b/src/drivers/ao_cc1120.h @@ -281,6 +281,7 @@ #define CC1120_PKT_CFG1_APPEND_STATUS 0 #define CC1120_PKT_CFG0 0x28 +#define CC1120_PKT_CFG0_RESERVED7 7 #define CC1120_PKT_CFG0_LENGTH_CONFIG 5 #define CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED 0 #define CC1120_PKT_CFG0_LENGTH_CONFIG_VARIABLE 1 diff --git a/src/drivers/ao_cc1120_CC1120.h b/src/drivers/ao_cc1120_CC1120.h index 1799c274..f86fd384 100644 --- a/src/drivers/ao_cc1120_CC1120.h +++ b/src/drivers/ao_cc1120_CC1120.h @@ -68,7 +68,7 @@ CC1120_PKT_CFG2, 0x04, /* Packet Configuration, Reg 2 */ CC1120_PKT_CFG1, 0x45, /* Packet Configuration, Reg 1 */ #endif - CC1120_PKT_CFG0, 0x20, /* Packet Configuration, Reg 0 */ + CC1120_PKT_CFG0, 0x00, /* Packet Configuration, Reg 0 */ CC1120_RFEND_CFG1, 0x0f, /* RFEND Configuration, Reg 1 */ CC1120_RFEND_CFG0, 0x00, /* RFEND Configuration, Reg 0 */ CC1120_PA_CFG2, 0x3f, /* Power Amplifier Configuration, Reg 2 */ @@ -87,9 +87,6 @@ CC1120_RCCAL_OFFSET, 0x00, /* RC Oscillator Calibration Clock Offset */ CC1120_FREQOFF1, 0x00, /* Frequency Offset (MSB) */ CC1120_FREQOFF0, 0x00, /* Frequency Offset (LSB) */ - CC1120_FREQ2, 0x6c, /* Frequency Configuration [23:16] */ - CC1120_FREQ1, 0xa3, /* Frequency Configuration [15:8] */ - CC1120_FREQ0, 0x33, /* Frequency Configuration [7:0] */ CC1120_IF_ADC2, 0x02, /* Analog to Digital Converter Configuration, Reg 2 */ CC1120_IF_ADC1, 0xa6, /* Analog to Digital Converter Configuration, Reg 1 */ CC1120_IF_ADC0, 0x04, /* Analog to Digital Converter Configuration, Reg 0 */ diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index a07b25ee..5761fed7 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -24,7 +24,6 @@ INC = \ # Common AltOS sources # -# ao_cc1120.c \ # ao_packet.c \ # ao_packet_slave.c \ @@ -45,6 +44,7 @@ ALTOS_SRC = \ ao_freq.c \ ao_dma_stm.c \ ao_spi_stm.c \ + ao_cc1120.c \ ao_ms5607.c \ ao_adc_stm.c \ ao_beep_stm.c \ diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 19746d37..628c5538 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -21,21 +21,6 @@ #include #include -void -beep(void) -{ - ao_beep(AO_BEEP_MID); - printf ("Hit a character to stop..."); flush(); - getchar(); - putchar('\n'); - ao_beep(0); -} - -const struct ao_cmds ao_mm_cmds[] = { - { beep, "b\0Beep" }, - { 0, NULL }, -}; - int main(void) { @@ -55,7 +40,7 @@ main(void) ao_storage_init(); ao_usb_init(); ao_exti_init(); -// ao_radio_init(); + ao_radio_init(); ao_i2c_init(); ao_hmc5883_init(); ao_mpu6000_init(); @@ -64,7 +49,6 @@ main(void) ao_report_init(); ao_config_init(); - ao_cmd_register(&ao_mm_cmds[0]); ao_start_scheduler(); return 0; } diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index d6394d9b..5121ad58 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -65,6 +65,7 @@ #define USE_INTERNAL_FLASH 0 #define HAS_USB 1 #define HAS_BEEP 1 +#define HAS_RADIO 1 #define HAS_SPI_1 1 #define SPI_1_PA5_PA6_PA7 1 @@ -74,6 +75,10 @@ #define HAS_SPI_2 1 #define SPI_2_PB13_PB14_PB15 1 #define SPI_2_PD1_PD3_PD4 0 +#define SPI_2_GPIO stm_gpiob +#define SPI_2_SCK 13 +#define SPI_2_MISO 14 +#define SPI_2_MOSI 15 #define HAS_I2C_1 1 #define I2C_1_PB8_PB9 1 @@ -81,7 +86,7 @@ #define HAS_I2C_2 1 #define I2C_2_PB10_PB11 1 -#define PACKET_HAS_SLAVE 1 +#define PACKET_HAS_SLAVE 0 #define LOW_LEVEL_DEBUG 1 @@ -251,4 +256,6 @@ struct ao_adc { #define HAS_HIGHG_ACCEL 1 +#define NUM_CMDS 16 + #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From e856df474c386b8df3d2bd9e87b766ae0439efbf Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 15 Jun 2012 22:41:17 -0700 Subject: altos: Reduce STM SPI data rate to 4MHz cc1120 doesn't want more than 6.1MHz, otherwise it gets very angry. Signed-off-by: Keith Packard --- src/stm/ao_spi_stm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index 8bb0d8e8..8784d985 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -282,7 +282,7 @@ ao_spi_get(uint8_t spi_index) (1 << STM_SPI_CR1_SSI) | /* ... */ (0 << STM_SPI_CR1_LSBFIRST) | /* Big endian */ (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */ - (STM_SPI_CR1_BR_PCLK_4 << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ + (STM_SPI_CR1_BR_PCLK_8 << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ (1 << STM_SPI_CR1_MSTR) | (0 << STM_SPI_CR1_CPOL) | /* Format 0 */ (0 << STM_SPI_CR1_CPHA)); -- cgit v1.2.3 From 5df94f74522357e062f4ec2786ff825381b2fb10 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 12:42:32 -0700 Subject: altos: Crank cc1120 power down to 0dBm to avoid crashing CPU Looks like RFI from the transmitter is confusing the CPU; lower the 1120 power output from +14dBm to +0dBm to keep the CPU happy. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120_CC1120.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/drivers/ao_cc1120_CC1120.h b/src/drivers/ao_cc1120_CC1120.h index f86fd384..c900b7f9 100644 --- a/src/drivers/ao_cc1120_CC1120.h +++ b/src/drivers/ao_cc1120_CC1120.h @@ -71,7 +71,8 @@ CC1120_PKT_CFG0, 0x00, /* Packet Configuration, Reg 0 */ CC1120_RFEND_CFG1, 0x0f, /* RFEND Configuration, Reg 1 */ CC1120_RFEND_CFG0, 0x00, /* RFEND Configuration, Reg 0 */ - CC1120_PA_CFG2, 0x3f, /* Power Amplifier Configuration, Reg 2 */ + // CC1120_PA_CFG2, 0x3f, /* Power Amplifier Configuration, Reg 2 */ + CC1120_PA_CFG2, 0x23, /* Power Amplifier Configuration, Reg 2 */ CC1120_PA_CFG1, 0x56, /* Power Amplifier Configuration, Reg 1 */ CC1120_PA_CFG0, 0x7b, /* Power Amplifier Configuration, Reg 0 */ CC1120_PKT_LEN, 0xff, /* Packet Length Configuration */ -- cgit v1.2.3 From 58e005375ca29dec6091d87159055004e7f19605 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 12:43:43 -0700 Subject: altos: Use interrupts to wake up after RDF transmission. Also clean up the debug output Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 72 ++++++++++++++----------------------------------- 1 file changed, 20 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index a1d78d9c..f06d52ca 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -24,6 +24,7 @@ uint8_t ao_radio_mutex; uint8_t ao_radio_abort; #define CC1120_DEBUG 1 +#define CC1120_TRACE 0 uint32_t ao_radio_cal = 0x6ca333; @@ -42,7 +43,7 @@ ao_radio_reg_read(uint16_t addr) uint8_t data[2]; uint8_t d; -#if CC1120_DEBUG +#if CC1120_TRACE printf("\t\tao_radio_reg_read (%04x): ", addr); flush(); #endif if (CC1120_IS_EXTENDED(addr)) { @@ -61,7 +62,7 @@ ao_radio_reg_read(uint16_t addr) ao_radio_spi_send(data, d); ao_radio_spi_recv(data, 1); ao_radio_deselect(); -#if CC1120_DEBUG +#if CC1120_TRACE printf (" %02x\n", data[0]); #endif return data[0]; @@ -73,7 +74,7 @@ ao_radio_reg_write(uint16_t addr, uint8_t value) uint8_t data[3]; uint8_t d; -#if CC1120_DEBUG +#if CC1120_TRACE printf("\t\tao_radio_reg_write (%04x): %02x\n", addr, value); #endif if (CC1120_IS_EXTENDED(addr)) { @@ -99,13 +100,13 @@ ao_radio_strobe(uint8_t addr) { uint8_t in; -#if CC1120_DEBUG +#if CC1120_TRACE printf("\t\tao_radio_strobe (%02x): ", addr); flush(); #endif ao_radio_select(); ao_radio_duplex(&addr, &in, 1); ao_radio_deselect(); -#if CC1120_DEBUG +#if CC1120_TRACE printf("%02x\n", in); flush(); #endif return in; @@ -149,12 +150,10 @@ ao_radio_fifo_write_fixed(uint8_t data, uint8_t len) CC1120_FIFO); uint8_t status; - printf ("num tx bytes: %d\n", ao_radio_reg_read(CC1120_NUM_TXBYTES)); ao_radio_select(); ao_radio_duplex(&addr, &status, 1); ao_radio_spi_send_fixed(data, len); ao_radio_deselect(); - printf ("num tx bytes: %d\n", ao_radio_reg_read(CC1120_NUM_TXBYTES)); return status; } @@ -223,10 +222,6 @@ static const uint16_t rdf_setup[] = { (0 << CC1120_PKT_CFG0_UART_SWAP_EN)), }; -#define int_pin(w) printf("\t%s: %d\n", \ - w,\ - (AO_CC1120_INT_PORT.idr >> AO_CC1120_INT_PIN) & 1) - static uint8_t ao_radio_marc_status(void) { @@ -252,58 +247,27 @@ ao_radio_rdf(uint8_t len) ao_radio_get(len); ao_radio_abort = 0; + ao_radio_wake = 0; for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]); -#if 0 - int_pin ("Before CFG"); ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); - int_pin ("After CFG"); -#endif ao_radio_fifo_write_fixed(ao_radio_rdf_value, len); ao_radio_reg_write(CC1120_PKT_LEN, len); - printf ("packet length: %d\n", ao_radio_reg_read(CC1120_PKT_LEN)); + ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); ao_radio_strobe(CC1120_STX); - for (i = 0; i < 20; i++) { - printf ("%d ", i); flush(); - printf ("Status %02x ", ao_radio_status()); flush(); - printf ("num_tx_bytes %d ", ao_radio_reg_read(CC1120_NUM_TXBYTES)); flush(); - printf ("marc status %x\n", ao_radio_marc_status()); flush(); - ao_delay(AO_MS_TO_TICKS(50)); - } - -#if 0 - ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - int_pin ("After strobe"); - ao_delay(AO_MS_TO_TICKS(100)); - int_pin ("After delay"); cli(); - for (i = 0; i < 20; i++) { -#if CC1120_DEBUG - ao_delay(AO_MS_TO_TICKS(50)); - int_pin ("Waited"); - printf ("Status %02x num_tx_bytes %d marc status %x\n", - ao_radio_status(), - ao_radio_reg_read(CC1120_NUM_TXBYTES), - ao_radio_marc_status()); -#else + while (!ao_radio_wake && !ao_radio_abort) ao_sleep(&ao_radio_wake); -#endif - } + sei(); -#endif - printf ("num_tx_bytes %d marc status %x\n", - ao_radio_reg_read(CC1120_NUM_TXBYTES), - ao_radio_marc_status()); -#if 0 if (!ao_radio_tx_done()) ao_radio_idle(); -#endif ao_radio_set_packet(); ao_radio_put(); } @@ -335,7 +299,7 @@ ao_radio_test(void) #endif ao_radio_get(0xff); ao_radio_strobe(CC1120_STX); -#if CC1120_DEBUG +#if CC1120_TRACE { int t; for (t = 0; t < 10; t++) { printf ("status: %02x\n", ao_radio_status()); @@ -508,11 +472,10 @@ ao_radio_setup(void) /* Enable marc status interrupt on gpio 2 pin */ ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP); - /* Enable the EXTI interrupt for the appropriate pin */ -// ao_enable_port(AO_CC1120_INT_PORT); -// ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_isr); - ao_radio_set_packet(); + + ao_config_get(); + ao_radio_configured = 1; } @@ -741,7 +704,7 @@ static void ao_radio_show(void) { } static void ao_radio_beep(void) { - ao_radio_rdf(120); + ao_radio_rdf(RDF_PACKET_LEN); } #endif @@ -771,5 +734,10 @@ ao_radio_init(void) AO_CC1120_SPI_CS_PORT.bsrr = (1 << AO_CC1120_SPI_CS_PIN); if (i == 10000) ao_panic(AO_PANIC_SELF_TEST); + + /* Enable the EXTI interrupt for the appropriate pin */ + ao_enable_port(AO_CC1120_INT_PORT); + ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_isr); + ao_cmd_register(&ao_radio_cmds[0]); } -- cgit v1.2.3 From 4e6d96816e6604ee8d9bb49345a1c1211699a655 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 16:11:23 -0700 Subject: altos: ao_storage_read already calls ao_storage_setup No need to call twice. Signed-off-by: Keith Packard --- src/core/ao_config.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 76a8ed4a..a4877b06 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -81,7 +81,6 @@ _ao_config_get(void) if (ao_config_loaded) return; #if HAS_EEPROM - ao_storage_setup(); ao_storage_read(ao_storage_config, &ao_config, sizeof (ao_config)); #endif if (ao_config.major != AO_CONFIG_MAJOR) { -- cgit v1.2.3 From 9d3fe2a80d0925e3eded6d738d05c5b4ea61504c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 16:12:18 -0700 Subject: altos: Don't lose IRQ disabled state in ao_sleep Using ao_arch_critical around the wchan setting will force interrupts to be re-enabled before ao_yield records the state of that bit, potentially causing problems with functions not atomically testing and sleeping. Tasks that need to set wchan with interrupts disabled should have interrupts disabled when entering ao_sleep already. Signed-off-by: Keith Packard --- src/core/ao_task.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src') diff --git a/src/core/ao_task.c b/src/core/ao_task.c index d7d0e8a2..910f1587 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -103,9 +103,7 @@ ao_yield(void) ao_arch_naked_define uint8_t ao_sleep(__xdata void *wchan) { - ao_arch_critical( - ao_cur_task->wchan = wchan; - ); + ao_cur_task->wchan = wchan; ao_yield(); if (ao_cur_task->wchan) { ao_cur_task->wchan = NULL; -- cgit v1.2.3 From 1a294852b3607947f0f86bf236785456d8719e5f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 16:14:33 -0700 Subject: altos: Be more careful about register save/restore in ao_yield Make sure the general registers are all saved before messing with any of them. Then, explicitly use r0 to save/restore apsr and primask. Signed-off-by: Keith Packard --- src/stm/ao_arch.h | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 62af86f7..bbd1b3b1 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -74,12 +74,6 @@ extern const uint16_t ao_serial_number; uint32_t a = (uint32_t) start; \ int i; \ \ - /* APSR */ \ - ARM_PUSH32(sp, 0); \ - \ - /* PRIMASK with interrupts enabled */ \ - ARM_PUSH32(sp, 0); \ - \ /* Return address (goes into LR) */ \ ARM_PUSH32(sp, a); \ \ @@ -88,23 +82,29 @@ extern const uint16_t ao_serial_number; while (i--) \ ARM_PUSH32(sp, 0); \ \ + /* APSR */ \ + ARM_PUSH32(sp, 0); \ + \ + /* PRIMASK with interrupts enabled */ \ + ARM_PUSH32(sp, 0); \ + \ task->sp = sp; \ } while (0); #define ao_arch_save_regs() do { \ - uint32_t apsr; \ - uint32_t primask; \ + /* Save general registers */ \ + asm("push {r0-r12,lr}\n"); \ \ /* Save APSR */ \ - asm("mrs %0,apsr" : "=&r" (apsr)); \ - asm("push {%0}" : : "r" (apsr)); \ + asm("mrs r0,apsr"); \ + asm("push {r0}"); \ \ /* Save PRIMASK */ \ - asm("mrs %0,primask" : "=&r" (primask)); \ - asm("push {%0}" : : "r" (primask)); \ + asm("mrs r0,primask"); \ + asm("push {r0}"); \ \ - /* Save general registers */ \ - asm("push {r0-r12,lr}\n"); \ + /* Enable interrupts */ \ + sei(); \ } while (0) #define ao_arch_save_stack() do { \ @@ -123,23 +123,21 @@ extern const uint16_t ao_serial_number; #define ao_arch_restore_stack() do { \ uint32_t sp; \ - uint32_t primask; \ - uint32_t apsr; \ sp = (uint32_t) ao_cur_task->sp; \ \ /* Switch stacks */ \ asm("mov sp, %0" : : "r" (sp) ); \ \ - /* Restore general registers */ \ - asm("pop {r0-r12,lr}\n"); \ - \ /* Restore PRIMASK */ \ - asm("pop {%0}" : "=&r" (primask) ); \ - asm("msr primask,%0" : : "r" (primask) ); \ + asm("pop {r0}"); \ + asm("msr primask,r0"); \ \ /* Restore APSR */ \ - asm("pop {%0}" : "=&r" (apsr) ); \ - asm("msr apsr,%0" : : "r" (apsr) ); \ + asm("pop {r0}"); \ + asm("msr apsr,r0"); \ + \ + /* Restore general registers */ \ + asm("pop {r0-r12,lr}\n"); \ \ /* Return to calling function */ \ asm("bx lr"); \ -- cgit v1.2.3 From e6d236fdc615625fbbf28377453f920729e49b0f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 16:17:00 -0700 Subject: altos: Software implemenation of CC1111 radio encoding Add CRC, whitening, FEC and interleaving routines for transmission path to allow cc1120 to send telem packets to cc1111. Signed-off-by: Keith Packard --- src/.gitignore | 1 + src/Makefile | 6 +- src/drivers/ao_cc1120.c | 87 ++++++++++++++++++-------- src/drivers/ao_cc1120_CC1120.h | 28 ++++----- src/drivers/ao_fec.h | 60 ++++++++++++++++++ src/drivers/ao_fec_tx.c | 139 +++++++++++++++++++++++++++++++++++++++++ src/megametrum-v0.1/Makefile | 3 + src/test/Makefile | 7 ++- src/test/ao_fec_tx_test.c | 47 ++++++++++++++ src/util/make-whiten | 37 +++++++++++ 10 files changed, 372 insertions(+), 43 deletions(-) create mode 100644 src/drivers/ao_fec.h create mode 100644 src/drivers/ao_fec_tx.c create mode 100644 src/test/ao_fec_tx_test.c create mode 100644 src/util/make-whiten (limited to 'src') diff --git a/src/.gitignore b/src/.gitignore index c6e1e353..cae36ae6 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,2 +1,3 @@ altitude.h altitude-pa.h +ao_whiten.h diff --git a/src/Makefile b/src/Makefile index c2e324c4..3fca2ab2 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,6 +6,7 @@ vpath make-altitude util vpath make-altitude-pa util vpath make-kalman util +vpath make-whiten util vpath kalman.5c kalman vpath kalman_filter.5c kalman vpath load_csv.5c kalman @@ -46,7 +47,7 @@ uninstall: all-recursive: all-local -all-local: altitude.h altitude-pa.h ao_kalman.h +all-local: altitude.h altitude-pa.h ao_kalman.h ao_whiten.h altitude.h: make-altitude nickle $< > $@ @@ -57,5 +58,8 @@ altitude-pa.h: make-altitude-pa ao_kalman.h: make-kalman kalman.5c kalman_filter.5c load_csv.5c matrix.5c bash $< kalman > $@ +ao_whiten.h: make-whiten + nickle $< > $@ + clean-local: rm -f altitude.h ao_kalman.h diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index f06d52ca..231d14d4 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -18,6 +18,7 @@ #include #include #include +#include uint8_t ao_radio_wake; uint8_t ao_radio_mutex; @@ -240,26 +241,27 @@ ao_radio_rx_done(void) return ao_radio_marc_status() == CC1120_MARC_STATUS1_RX_FINISHED; } +static void +ao_radio_start_tx(void) +{ + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); + ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_strobe(CC1120_STX); +} + void ao_radio_rdf(uint8_t len) { int i; ao_radio_get(len); - ao_radio_abort = 0; ao_radio_wake = 0; for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]); - ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); - ao_radio_fifo_write_fixed(ao_radio_rdf_value, len); - ao_radio_reg_write(CC1120_PKT_LEN, len); - - ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - - ao_radio_strobe(CC1120_STX); + ao_radio_start_tx(); cli(); while (!ao_radio_wake && !ao_radio_abort) @@ -327,24 +329,45 @@ ao_radio_test(void) void ao_radio_send(void *d, uint8_t size) { - uint8_t marc_status; - + uint8_t marc_status; + static uint8_t prepare[128]; + uint8_t prepare_len; + static uint8_t encode[256]; + uint8_t encode_len; + static uint8_t interleave[256]; + uint8_t interleave_len; + + ao_fec_dump_bytes(d, size, "Input"); + +#if 1 + prepare_len = ao_fec_prepare(d, size, prepare); + ao_fec_dump_bytes(prepare, prepare_len, "Prepare"); + + ao_fec_whiten(prepare, prepare_len, prepare); + ao_fec_dump_bytes(prepare, prepare_len, "Whiten"); + + encode_len = ao_fec_encode(prepare, prepare_len, encode); + ao_fec_dump_bytes(encode, encode_len, "Encode"); + + interleave_len = ao_fec_interleave(encode, encode_len, interleave); + ao_fec_dump_bytes(interleave, interleave_len, "Interleave"); + ao_radio_get(interleave_len); + ao_radio_fifo_write(interleave, interleave_len); +#else ao_radio_get(size); - ao_radio_wake = 0; ao_radio_fifo_write(d, size); - ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - ao_radio_strobe(CC1120_STX); +#endif + + ao_radio_wake = 0; + + ao_radio_start_tx(); + cli(); - for (;;) { - if (ao_radio_wake) { - marc_status = ao_radio_marc_status(); - if (marc_status != CC1120_MARC_STATUS1_NO_FAILURE) - break; - ao_radio_wake = 0; - } + while (!ao_radio_wake && !ao_radio_abort) ao_sleep(&ao_radio_wake); - } sei(); + if (!ao_radio_tx_done()) + ao_radio_idle(); ao_radio_put(); } @@ -361,6 +384,7 @@ ao_radio_recv(__xdata void *d, uint8_t size) cli(); for (;;) { if (ao_radio_abort) + break; if (ao_radio_wake) { marc_status = ao_radio_marc_status(); @@ -413,7 +437,7 @@ static const uint16_t packet_setup[] = { CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff), CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)), - CC1120_PKT_CFG1, ((1 << CC1120_PKT_CFG1_WHITE_DATA) | + CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) | (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) | (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) | (1 << CC1120_PKT_CFG1_APPEND_STATUS)), @@ -469,9 +493,6 @@ ao_radio_setup(void) for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2) ao_radio_reg_write(radio_setup[i], radio_setup[i+1]); - /* Enable marc status interrupt on gpio 2 pin */ - ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_MARC_MCU_WAKEUP); - ao_radio_set_packet(); ao_config_get(); @@ -707,6 +728,21 @@ static void ao_radio_beep(void) { ao_radio_rdf(RDF_PACKET_LEN); } +static void ao_radio_packet(void) { + static uint8_t packet[] = { +#if 1 + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, +#else + 3, 1, 2, 3 +#endif + }; + + ao_radio_send(packet, sizeof (packet)); +} + #endif static const struct ao_cmds ao_radio_cmds[] = { @@ -714,6 +750,7 @@ static const struct ao_cmds ao_radio_cmds[] = { #if CC1120_DEBUG { ao_radio_show, "R\0Show CC1120 status" }, { ao_radio_beep, "b\0Emit an RDF beacon" }, + { ao_radio_packet, "p\0Send a test packet" }, #endif { 0, NULL } }; diff --git a/src/drivers/ao_cc1120_CC1120.h b/src/drivers/ao_cc1120_CC1120.h index c900b7f9..c0f35a23 100644 --- a/src/drivers/ao_cc1120_CC1120.h +++ b/src/drivers/ao_cc1120_CC1120.h @@ -21,29 +21,27 @@ * ***************************************************************/ - CC1120_SYNC3, 0x93, /* Sync Word Configuration [31:24] */ - CC1120_SYNC2, 0x0b, /* Sync Word Configuration [23:16] */ - CC1120_SYNC1, 0x51, /* Sync Word Configuration [15:8] */ - CC1120_SYNC0, 0xde, /* Sync Word Configuration [7:0] */ + CC1120_SYNC3, 0xD3, /* Sync Word Configuration [31:24] */ + CC1120_SYNC2, 0x91, /* Sync Word Configuration [23:16] */ + CC1120_SYNC1, 0xD3, /* Sync Word Configuration [15:8] */ + CC1120_SYNC0, 0x91, /* Sync Word Configuration [7:0] */ + CC1120_SYNC_CFG1, 0x08, /* Sync Word Detection Configuration */ - CC1120_SYNC_CFG0, 0x17, /* Sync Word Length Configuration */ -#if 0 - CC1120_DEVIATION_M, 0x50, /* Frequency Deviation Configuration */ - CC1120_MODCFG_DEV_E, 0x0d, /* Modulation Format and Frequency Deviation Configuration */ -#endif + CC1120_SYNC_CFG0, + (CC1120_SYNC_CFG0_SYNC_MODE_16_BITS << CC1120_SYNC_CFG0_SYNC_MODE) | + (CC1120_SYNC_CFG0_SYNC_NUM_ERROR_2 << CC1120_SYNC_CFG0_SYNC_NUM_ERROR), CC1120_DCFILT_CFG, 0x1c, /* Digital DC Removal Configuration */ - CC1120_PREAMBLE_CFG1, 0x18, /* Preamble Length Configuration */ + CC1120_PREAMBLE_CFG1, /* Preamble Length Configuration */ + (CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) | + (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD), CC1120_PREAMBLE_CFG0, 0x2a, /* */ CC1120_FREQ_IF_CFG, 0x40, /* RX Mixer Frequency Configuration */ CC1120_IQIC, 0x46, /* Digital Image Channel Compensation Configuration */ CC1120_CHAN_BW, 0x02, /* Channel Filter Configuration */ + CC1120_MDMCFG1, 0x46, /* General Modem Parameter Configuration */ CC1120_MDMCFG0, 0x05, /* General Modem Parameter Configuration */ -#if 0 - CC1120_DRATE2, 0x93, /* Data Rate Configuration Exponent and Mantissa [19:16] */ - CC1120_DRATE1, 0xa4, /* Data Rate Configuration Mantissa [15:8] */ - CC1120_DRATE0, 0x00, /* Data Rate Configuration Mantissa [7:0] */ -#endif + CC1120_AGC_REF, 0x20, /* AGC Reference Level Configuration */ CC1120_AGC_CS_THR, 0x19, /* Carrier Sense Threshold Configuration */ CC1120_AGC_GAIN_ADJUST, 0x00, /* RSSI Offset Configuration */ diff --git a/src/drivers/ao_fec.h b/src/drivers/ao_fec.h new file mode 100644 index 00000000..db5523a3 --- /dev/null +++ b/src/drivers/ao_fec.h @@ -0,0 +1,60 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_FEC_H_ +#define _AO_FEC_H_ + +#include + +#define AO_FEC_CRC_INIT 0xffff +#define AO_FEC_TRELLIS_TERMINATOR 0x0b +#define AO_FEC_PREPARE_EXTRA 4 + +void +ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name); + +uint16_t +ao_fec_crc(uint8_t *bytes, uint8_t len); + +/* + * Append CRC and terminator bytes, returns resulting length. + * 'out' must be at least len + AO_FEC_PREPARE_EXTRA bytes long + */ +uint8_t +ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out); + +/* + * Whiten data using the cc1111 PN9 sequence. 'out' + * must be 'len' bytes long. 'out' and 'in' can be + * the same array + */ +uint8_t +ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out); + +/* + * Encode data. 'out' must be len*2 bytes long + */ +uint8_t +ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); + +/* + * Interleave data. 'out' must be 'len' bytes long + */ +uint8_t +ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out); + +#endif /* _AO_FEC_H_ */ diff --git a/src/drivers/ao_fec_tx.c b/src/drivers/ao_fec_tx.c new file mode 100644 index 00000000..b8933956 --- /dev/null +++ b/src/drivers/ao_fec_tx.c @@ -0,0 +1,139 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +void +ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name) +{ + uint8_t i; + + printf ("%s (%d):", name, len); + for (i = 0; i < len; i++) { + if ((i & 7) == 0) + printf ("\n\t%02x:", i); + printf(" %02x", bytes[i]); + } + printf ("\n"); +} + +static uint16_t inline +crc_byte(uint8_t byte, uint16_t crc) +{ + uint8_t bit; + + for (bit = 0; bit < 8; bit++) { + if (((crc & 0x8000) >> 8) ^ (byte & 0x80)) + crc = (crc << 1) ^ 0x8005; + else + crc = (crc << 1); + byte <<= 1; + } + return crc; +} + +uint16_t +ao_fec_crc(uint8_t *bytes, uint8_t len) +{ + uint16_t crc = AO_FEC_CRC_INIT; + + while (len--) + crc = crc_byte(*bytes++, crc); + return crc; +} + +uint8_t +ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out) +{ + uint16_t crc = ao_fec_crc (in, len); + uint8_t i; + uint8_t num_fec; + + /* Copy data */ + for (i = 0; i < len; i++) + out[i] = in[i]; + + /* Append CRC */ + out[i++] = crc >> 8; + out[i++] = crc; + + /* Append FEC -- 1 byte if odd, two bytes if even */ + num_fec = 2 - (i & 1); + while (num_fec--) + out[i++] = AO_FEC_TRELLIS_TERMINATOR; + return i; +} + +static const uint8_t whiten[] = { +#include "ao_whiten.h" +}; + +uint8_t +ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out) +{ + const uint8_t *w = whiten; + + while (len--) + *out++ = *in++ ^ *w++; +} + +static const uint8_t ao_fec_encode_table[16] = { + 0, 3, 1, 2, + 3, 0, 2, 1, + 3, 0, 2, 1, + 0, 3, 1, 2 +}; + +uint8_t +ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out) +{ + uint16_t fec = 0, output; + uint8_t byte, bit; + + for (byte = 0; byte < len; byte++) { + fec = (fec & 0x700) | in[byte]; + output = 0; + for (bit = 0; bit < 8; bit++) { + output = output << 2 | ao_fec_encode_table[fec >> 7]; + fec = (fec << 1) & 0x7ff; + } + out[byte * 2] = output >> 8; + out[byte * 2 + 1] = output; + } + return len * 2; +} + +uint8_t +ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out) +{ + uint8_t i, j; + + for (i = 0; i < len; i += 4) { + uint32_t interleaved = 0; + + for (j = 0; j < 4 * 4; j++) { + interleaved <<= 2; + interleaved |= (in[i + (~j & 0x3)] >> (2 * ((j & 0xc) >> 2))) & 0x03; + } + out[i+0] = interleaved >> 24; + out[i+1] = interleaved >> 16; + out[i+2] = interleaved >> 8; + out[i+3] = interleaved; + } + return len; +} diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 5761fed7..054855ba 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -18,6 +18,8 @@ INC = \ ao_ms5607.h \ ao_hmc5883.h \ ao_mpu6000.h \ + ao_cc1120_CC1120.h \ + ao_whiten.h \ stm32l.h # @@ -45,6 +47,7 @@ ALTOS_SRC = \ ao_dma_stm.c \ ao_spi_stm.c \ ao_cc1120.c \ + ao_fec_tx.c \ ao_ms5607.c \ ao_adc_stm.c \ ao_beep_stm.c \ diff --git a/src/test/Makefile b/src/test/Makefile index 1e54f5e0..3e308dd7 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,6 +1,6 @@ vpath % ..:../core:../drivers:../util -PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_gps_test ao_gps_test_skytraq ao_convert_test ao_convert_pa_test +PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_gps_test ao_gps_test_skytraq ao_convert_test ao_convert_pa_test ao_fec_tx_test KALMAN=make-kalman @@ -38,4 +38,7 @@ ao_convert_pa_test: ao_convert_pa_test.c ao_convert_pa.c altitude-pa.h cc $(CFLAGS) -o $@ $< ao_kalman.h: $(KALMAN) - (cd .. && make ao_kalman.h) \ No newline at end of file + (cd .. && make ao_kalman.h) + +ao_fec_tx_test: ao_fec_tx_test.c ao_fec_tx.c + cc $(CFLAGS) -o $@ ao_fec_tx_test.c ../drivers/ao_fec_tx.c diff --git a/src/test/ao_fec_tx_test.c b/src/test/ao_fec_tx_test.c new file mode 100644 index 00000000..b8dc9308 --- /dev/null +++ b/src/test/ao_fec_tx_test.c @@ -0,0 +1,47 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include + +int +main(int argc, char **argv) +{ + uint8_t input[4] = { 3, 1, 2, 3 }; + uint8_t prepare[sizeof(input) + AO_FEC_PREPARE_EXTRA]; + uint8_t encode[sizeof(prepare) * 2]; + uint8_t interleave[sizeof(encode)]; + uint8_t prepare_len; + uint8_t encode_len; + uint8_t interleave_len; + + ao_fec_dump_bytes(input, sizeof(input), "Input"); + + prepare_len = ao_fec_prepare(input, sizeof (input), prepare); + + ao_fec_dump_bytes(prepare, prepare_len, "Prepare"); + + encode_len = ao_fec_encode(prepare, prepare_len, encode); + + ao_fec_dump_bytes(encode, encode_len, "Encode"); + + interleave_len = ao_fec_interleave(encode, encode_len, interleave); + + ao_fec_dump_bytes(interleave, interleave_len, "Interleave"); +} + diff --git a/src/util/make-whiten b/src/util/make-whiten new file mode 100644 index 00000000..d68a02af --- /dev/null +++ b/src/util/make-whiten @@ -0,0 +1,37 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +/* Generate the data whitening array used by the CC11* radios */ + +int pn9 = 0x1ff; + +void +pn9_step() { + pn9 = (pn9 >> 1) | (((pn9 ^ (pn9 >> 5)) & 1) << 8); +} + +int val() +{ + int ret = pn9 & 0xff; + + for (int i = 0; i < 8; i++) + pn9_step(); + return ret; +} + +for (int i = 0; i < 128; i++) + printf (" /* %3d */ 0x%02x,\n", i + 1, val()); -- cgit v1.2.3 From 629f43e7c7abbff33e14b168a08a4b6a9c88b937 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 19:04:22 -0700 Subject: altos: Add telemetry to megametrum Now that the radio works Signed-off-by: Keith Packard --- src/core/ao.h | 1 + src/core/ao_flight_mm.c | 16 ++++++++++------ src/core/ao_telemetry.c | 8 ++++++-- src/megametrum-v0.1/Makefile | 5 +++-- src/megametrum-v0.1/ao_megametrum.c | 1 + src/megametrum-v0.1/ao_pins.h | 1 + 6 files changed, 22 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index a4136a9b..3dae8b40 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -347,6 +347,7 @@ struct ao_telemetry_generic { #define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 #define AO_TELEMETRY_SENSOR_TELEMINI 0x02 #define AO_TELEMETRY_SENSOR_TELENANO 0x03 +#define AO_TELEMETRY_SENSOR_MEGAMETRUM 0x08 struct ao_telemetry_sensor { uint16_t serial; /* 0 */ diff --git a/src/core/ao_flight_mm.c b/src/core/ao_flight_mm.c index c2a7cd64..28b9869f 100644 --- a/src/core/ao_flight_mm.c +++ b/src/core/ao_flight_mm.c @@ -32,6 +32,10 @@ #error Please define HAS_USB #endif +#ifndef HAS_TELEMETRY +#define HAS_TELEMETRY HAS_RADIO +#endif + /* Main flight thread. */ __pdata enum ao_flight_state ao_flight_state; /* current flight state */ @@ -83,7 +87,7 @@ ao_flight(void) * - pad mode if we're upright, * - idle mode otherwise */ -#if HAS_ACCEL +#if HAS_ACCEL && 0 if (ao_config.accel_plus_g == 0 || ao_config.accel_minus_g == 0 || ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || @@ -101,14 +105,14 @@ ao_flight(void) } else #endif if (!ao_flight_force_idle -#if HAS_ACCEL +#if HAS_ACCEL && 0 && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP #endif ) { /* Set pad mode - we can fly! */ ao_flight_state = ao_flight_pad; -#if HAS_USB && HAS_RADIO +#if HAS_USB && HAS_RADIO && 0 /* Disable the USB controller in flight mode * to save power */ @@ -120,7 +124,7 @@ ao_flight(void) ao_packet_slave_stop(); #endif -#if HAS_RADIO && !defined (MEGAMETRUM) +#if HAS_TELEMETRY /* Turn on telemetry system */ ao_rdf_set(1); ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); @@ -171,7 +175,7 @@ ao_flight(void) /* start logging data */ ao_log_start(); -#if HAS_RADIO && !defined(MEGAMETRUM) +#if HAS_TELEMETRY /* Increase telemetry rate */ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); @@ -259,7 +263,7 @@ ao_flight(void) ao_ignite(ao_igniter_drogue); #endif -#if HAS_RADIO && !defined(MEGAMETRUM) +#if HAS_TELEMETRY /* slow down the telemetry system */ ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 6e8fc02f..5857c44d 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -35,6 +35,10 @@ static __pdata uint16_t ao_rdf_time; #define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) #define AO_RDF_LENGTH_MS 500 +#if defined(MEGAMETRUM) +#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_MEGAMETRUM +#endif + #if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) || defined(TELEBALLOON_V_1_1) || defined(TELEMETRUM_V_1_2) #define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_TELEMETRUM #endif @@ -53,7 +57,7 @@ static __xdata union ao_telemetry_all telemetry; static void ao_send_sensor(void) { - __xdata struct ao_data *packet = &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; + __xdata struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; telemetry.generic.tick = packet->tick; telemetry.generic.type = AO_TELEMETRY_SENSOR; @@ -64,7 +68,7 @@ ao_send_sensor(void) #else telemetry.sensor.accel = 0; #endif - telemetry.sensor.pres = packet->adc.pres; + telemetry.sensor.pres = ao_data_pres(packet); telemetry.sensor.temp = packet->adc.temp; telemetry.sensor.v_batt = packet->adc.v_batt; #if HAS_IGNITE diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 054855ba..5c641e9a 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -64,12 +64,13 @@ ALTOS_SRC = \ ao_log_mega.c \ ao_sample_mm.c \ ao_kalman.c \ - ao_flight_mm.c + ao_flight_mm.c \ + ao_telemetry.c PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM -IDPRODUCT=0x000a +IDPRODUCT=0x0023 CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -Os -g diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 628c5538..dc9c0d19 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -47,6 +47,7 @@ main(void) ao_flight_init(); ao_log_init(); ao_report_init(); + ao_telemetry_init(); ao_config_init(); ao_start_scheduler(); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 5121ad58..5c5c5972 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -66,6 +66,7 @@ #define HAS_USB 1 #define HAS_BEEP 1 #define HAS_RADIO 1 +#define HAS_TELEMETRY 1 #define HAS_SPI_1 1 #define SPI_1_PA5_PA6_PA7 1 -- cgit v1.2.3 From 976a8375932ddb46ca3100863b0a892732c0923e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 19:04:53 -0700 Subject: altos: make cc1120 ao_radio_send re-entrant It gets called from multiple tasks, so put local data on the stack. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 231d14d4..67a36c5c 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -27,6 +27,12 @@ uint8_t ao_radio_abort; #define CC1120_DEBUG 1 #define CC1120_TRACE 0 +#if CC1120_TRACE +#define fec_dump_bytes(b,l,n) ao_fec_dump_bytes(b,l,n) +#else +#define fec_dump_bytes(b,l,n) +#endif + uint32_t ao_radio_cal = 0x6ca333; #define FOSC 32000000 @@ -330,33 +336,29 @@ void ao_radio_send(void *d, uint8_t size) { uint8_t marc_status; - static uint8_t prepare[128]; + uint8_t prepare[size + AO_FEC_PREPARE_EXTRA]; uint8_t prepare_len; - static uint8_t encode[256]; + uint8_t encode[sizeof(prepare) * 2]; uint8_t encode_len; - static uint8_t interleave[256]; + uint8_t interleave[sizeof(encode)]; uint8_t interleave_len; - ao_fec_dump_bytes(d, size, "Input"); + fec_dump_bytes(d, size, "Input"); -#if 1 prepare_len = ao_fec_prepare(d, size, prepare); - ao_fec_dump_bytes(prepare, prepare_len, "Prepare"); + fec_dump_bytes(prepare, prepare_len, "Prepare"); ao_fec_whiten(prepare, prepare_len, prepare); - ao_fec_dump_bytes(prepare, prepare_len, "Whiten"); + fec_dump_bytes(prepare, prepare_len, "Whiten"); encode_len = ao_fec_encode(prepare, prepare_len, encode); - ao_fec_dump_bytes(encode, encode_len, "Encode"); + fec_dump_bytes(encode, encode_len, "Encode"); interleave_len = ao_fec_interleave(encode, encode_len, interleave); - ao_fec_dump_bytes(interleave, interleave_len, "Interleave"); + fec_dump_bytes(interleave, interleave_len, "Interleave"); + ao_radio_get(interleave_len); ao_radio_fifo_write(interleave, interleave_len); -#else - ao_radio_get(size); - ao_radio_fifo_write(d, size); -#endif ao_radio_wake = 0; -- cgit v1.2.3 From ae3662c56effda9f0516c7d6ffd2d5f56b859593 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 19:06:08 -0700 Subject: altos: hack STM serial number to 58 otherwise altosui won't record telemetry Signed-off-by: Keith Packard --- src/stm/ao_romconfig.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/ao_romconfig.c b/src/stm/ao_romconfig.c index bbb677e2..84317458 100644 --- a/src/stm/ao_romconfig.c +++ b/src/stm/ao_romconfig.c @@ -17,4 +17,4 @@ #include "ao.h" -const uint16_t ao_serial_number = 0; +const uint16_t ao_serial_number = 58; -- cgit v1.2.3 From 611f37607fadcdc9908d67456f844a452ad4a87a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 17 Jun 2012 19:11:35 -0700 Subject: altos: Make sure ao_storage_config is set before reading config block ao_storage_read does in fact call ao_storage_setup, but we need the value of ao_storage_config *before* calling ao_storage_read, so call ao_storage_setup first. Signed-off-by: Keith Packard --- src/core/ao_config.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/core/ao_config.c b/src/core/ao_config.c index a4877b06..cc580d66 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -81,6 +81,11 @@ _ao_config_get(void) if (ao_config_loaded) return; #if HAS_EEPROM + /* Yes, I know ao_storage_read calls ao_storage_setup, + * but ao_storage_setup *also* sets ao_storage_config, which we + * need before calling ao_storage_read here + */ + ao_storage_setup(); ao_storage_read(ao_storage_config, &ao_config, sizeof (ao_config)); #endif if (ao_config.major != AO_CONFIG_MAJOR) { -- cgit v1.2.3 From 419a801131c1034f1fa149a67850290431cbda72 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Jun 2012 09:39:10 -0700 Subject: altos: Configure STM LCD driver for giant LCD digits These devices require static mode. Signed-off-by: Keith Packard --- src/stm-demo/ao_demo.c | 2 +- src/stm/ao_lcd_stm.c | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 232c2313..73ace558 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -166,7 +166,7 @@ main(void) ao_timer_init(); ao_dma_init(); ao_cmd_init(); -// ao_lcd_stm_init(); + ao_lcd_stm_init(); // ao_lcd_font_init(); ao_spi_init(); ao_i2c_init(); diff --git a/src/stm/ao_lcd_stm.c b/src/stm/ao_lcd_stm.c index f68cf165..b1909444 100644 --- a/src/stm/ao_lcd_stm.c +++ b/src/stm/ao_lcd_stm.c @@ -328,10 +328,14 @@ ao_lcd_stm_init(void) } } + /* Disable the LCD */ + stm_lcd.cr = 0; + /* duty cycle 1/3, radio 352, frame rate about 33Hz */ - stm_lcd.fcr = ((STM_LCD_FCR_PS_1 << STM_LCD_FCR_PS) | - (STM_LCD_FCR_DIV_31 << STM_LCD_FCR_DIV) | + stm_lcd.fcr = ((STM_LCD_FCR_PS_16 << STM_LCD_FCR_PS) | + (STM_LCD_FCR_DIV_20 << STM_LCD_FCR_DIV) | (4 << STM_LCD_FCR_CC) | + (0 << STM_LCD_FCR_DEAD) | (4 << STM_LCD_FCR_PON) | (0 << STM_LCD_FCR_UDDIE) | (0 << STM_LCD_FCR_SOFIE) | @@ -343,8 +347,8 @@ ao_lcd_stm_init(void) /* Program desired BIAS in LCD_CR */ /* Enable mux seg */ /* Internal voltage source */ - stm_lcd.cr = ((STM_LCD_CR_DUTY_1_4 << STM_LCD_CR_DUTY) | - (STM_LCD_CR_BIAS_1_3 << STM_LCD_CR_BIAS) | + stm_lcd.cr = ((STM_LCD_CR_DUTY_STATIC << STM_LCD_CR_DUTY) | + (STM_LCD_CR_BIAS_1_2 << STM_LCD_CR_BIAS) | (0 << STM_LCD_CR_VSEL) | (1 << STM_LCD_CR_MUX_SEG)); -- cgit v1.2.3 From d2bd95edb6f77daeb1e8f043c4a239c248728e0c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Jun 2012 09:45:42 -0700 Subject: altos: Add full MM telemetry Create two new telemetry packets to hold all of the MM data. This patch also splits the telemetry structures out of ao.h Signed-off-by: Keith Packard --- src/core/ao.h | 177 +----------------------------------------------- src/core/ao_data.h | 33 +++++---- src/core/ao_log_mega.c | 4 +- src/core/ao_sample_mm.c | 5 +- src/core/ao_telemetry.c | 135 +++++++++++++++++++++++++++++------- src/stm/ao_adc_stm.c | 2 +- 6 files changed, 138 insertions(+), 218 deletions(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 3dae8b40..204c8530 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -325,182 +325,7 @@ ao_spi_slave_init(void); void ao_spi_slave(void); -/* - * ao_telemetry.c - */ -#define AO_MAX_CALLSIGN 8 -#define AO_MAX_VERSION 8 -#if LEGACY_MONITOR -#define AO_MAX_TELEMETRY 128 -#else -#define AO_MAX_TELEMETRY 32 -#endif - -struct ao_telemetry_generic { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t payload[27]; /* 5 */ - /* 32 */ -}; - -#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 -#define AO_TELEMETRY_SENSOR_TELEMINI 0x02 -#define AO_TELEMETRY_SENSOR_TELENANO 0x03 -#define AO_TELEMETRY_SENSOR_MEGAMETRUM 0x08 - -struct ao_telemetry_sensor { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t state; /* 5 flight state */ - int16_t accel; /* 6 accelerometer (TM only) */ - int16_t pres; /* 8 pressure sensor */ - int16_t temp; /* 10 temperature sensor */ - int16_t v_batt; /* 12 battery voltage */ - int16_t sense_d; /* 14 drogue continuity sense (TM/Tm) */ - int16_t sense_m; /* 16 main continuity sense (TM/Tm) */ - - int16_t acceleration; /* 18 m/s² * 16 */ - int16_t speed; /* 20 m/s * 16 */ - int16_t height; /* 22 m */ - - int16_t ground_pres; /* 24 average pres on pad */ - int16_t ground_accel; /* 26 average accel on pad */ - int16_t accel_plus_g; /* 28 accel calibration at +1g */ - int16_t accel_minus_g; /* 30 accel calibration at -1g */ - /* 32 */ -}; - -#define AO_TELEMETRY_CONFIGURATION 0x04 - -struct ao_telemetry_configuration { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t device; /* 5 device type */ - uint16_t flight; /* 6 flight number */ - uint8_t config_major; /* 8 Config major version */ - uint8_t config_minor; /* 9 Config minor version */ - uint16_t apogee_delay; /* 10 Apogee deploy delay in seconds */ - uint16_t main_deploy; /* 12 Main deploy alt in meters */ - uint16_t flight_log_max; /* 14 Maximum flight log size in kB */ - char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ - char version[AO_MAX_VERSION]; /* 24 Software version */ - /* 32 */ -}; - -#define AO_TELEMETRY_LOCATION 0x05 - -#define AO_GPS_MODE_NOT_VALID 'N' -#define AO_GPS_MODE_AUTONOMOUS 'A' -#define AO_GPS_MODE_DIFFERENTIAL 'D' -#define AO_GPS_MODE_ESTIMATED 'E' -#define AO_GPS_MODE_MANUAL 'M' -#define AO_GPS_MODE_SIMULATED 'S' - -struct ao_telemetry_location { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - - uint8_t flags; /* 5 Number of sats and other flags */ - int16_t altitude; /* 6 GPS reported altitude (m) */ - int32_t latitude; /* 8 latitude (degrees * 10⁷) */ - int32_t longitude; /* 12 longitude (degrees * 10⁷) */ - uint8_t year; /* 16 (- 2000) */ - uint8_t month; /* 17 (1-12) */ - uint8_t day; /* 18 (1-31) */ - uint8_t hour; /* 19 (0-23) */ - uint8_t minute; /* 20 (0-59) */ - uint8_t second; /* 21 (0-59) */ - uint8_t pdop; /* 22 (m * 5) */ - uint8_t hdop; /* 23 (m * 5) */ - uint8_t vdop; /* 24 (m * 5) */ - uint8_t mode; /* 25 */ - uint16_t ground_speed; /* 26 cm/s */ - int16_t climb_rate; /* 28 cm/s */ - uint8_t course; /* 30 degrees / 2 */ - uint8_t unused[1]; /* 31 */ - /* 32 */ -}; - -#define AO_TELEMETRY_SATELLITE 0x06 - -struct ao_telemetry_satellite_info { - uint8_t svid; - uint8_t c_n_1; -}; - -struct ao_telemetry_satellite { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t channels; /* 5 number of reported sats */ - - struct ao_telemetry_satellite_info sats[12]; /* 6 */ - uint8_t unused[2]; /* 30 */ - /* 32 */ -}; - -#define AO_TELEMETRY_COMPANION 0x07 - -#define AO_COMPANION_MAX_CHANNELS 12 - -struct ao_telemetry_companion { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t board_id; /* 5 */ - - uint8_t update_period; /* 6 */ - uint8_t channels; /* 7 */ - uint16_t companion_data[AO_COMPANION_MAX_CHANNELS]; /* 8 */ - /* 32 */ -}; - -/* #define AO_SEND_ALL_BARO */ - -#define AO_TELEMETRY_BARO 0x80 - -/* - * This packet allows the full sampling rate baro - * data to be captured over the RF link so that the - * flight software can be tested using 'real' data. - * - * Along with this telemetry packet, the flight - * code is modified to send full-rate telemetry all the time - * and never send an RDF tone; this ensure that the full radio - * link is available. - */ -struct ao_telemetry_baro { - uint16_t serial; /* 0 */ - uint16_t tick; /* 2 */ - uint8_t type; /* 4 */ - uint8_t samples; /* 5 number samples */ - - int16_t baro[12]; /* 6 samples */ - /* 32 */ -}; - -union ao_telemetry_all { - struct ao_telemetry_generic generic; - struct ao_telemetry_sensor sensor; - struct ao_telemetry_configuration configuration; - struct ao_telemetry_location location; - struct ao_telemetry_satellite satellite; - struct ao_telemetry_companion companion; - struct ao_telemetry_baro baro; -}; - -struct ao_telemetry_all_recv { - union ao_telemetry_all telemetry; - int8_t rssi; - uint8_t status; -}; - +#include /* * ao_gps.c */ diff --git a/src/core/ao_data.h b/src/core/ao_data.h index 502df6c9..fdc49ca2 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -36,7 +36,8 @@ struct ao_data { struct ao_adc adc; #endif #if HAS_MS5607 - struct ao_ms5607_sample ms5607; + struct ao_ms5607_sample ms5607_raw; + struct ao_ms5607_value ms5607_cooked; #endif #if HAS_MPU6000 struct ao_mpu6000_sample mpu6000; @@ -57,25 +58,24 @@ extern volatile __data uint8_t ao_data_head; typedef int32_t pres_t; typedef int32_t alt_t; -static inline pres_t ao_data_pres(struct ao_data *packet) -{ - struct ao_ms5607_value value; +#define ao_data_pres_cook(packet) ao_ms5607_convert(&packet->ms5607_raw, &packet->ms5607_cooked) - ao_ms5607_convert(&packet->ms5607, &value); - return value.pres; -} +#define ao_data_pres(packet) ((packet)->ms5607_cooked.pres) +#define ao_data_temp(packet) ((packet)->ms5607_cooked.temp) #define pres_to_altitude(p) ao_pa_to_altitude(p) -#else +#else /* HAS_MS5607 */ typedef int16_t pres_t; typedef int16_t alt_t; #define ao_data_pres(packet) ((packet)->adc.pres) +#define ao_data_temp(packet) ((packet)->adc.temp) #define pres_to_altitude(p) ao_pres_to_altitude(p) +#define ao_data_pres_cook(p) -#endif +#endif /* else HAS_MS5607 */ /* * Need a few macros to pull data from the sensors: @@ -92,11 +92,11 @@ typedef int16_t accel_t; /* MPU6000 is hooked up so that positive y is positive acceleration */ #define ao_data_accel(packet) ((packet)->mpu6000.accel_y) -#define ao_data_accel_sample(packet) (-ao_data_accel(packet)) +#define ao_data_accel_cook(packet) (-(packet)->mpu6000.accel_y) #define ao_data_set_accel(packet, accel) ((packet)->mpu6000.accel_y = (accel)) #define ao_data_accel_invert(a) (-(a)) -#else +#else /* HAS_MPU6000 && !HAS_HIGHG_ACCEL */ typedef int16_t accel_t; #define ao_data_accel(packet) ((packet)->adc.accel) @@ -183,13 +183,18 @@ typedef int16_t accel_t; * provides 11 bits of data, we haven't actually lost any precision, * just dropped a bit of noise off the low end. */ + #if HAS_ACCEL_REF -#define ao_data_accel_sample(packet) \ + +#define ao_data_accel_cook(packet) \ ((uint16_t) ((((uint32_t) (packet)->adc.accel << 16) / ((packet)->adc.accel_ref << 1))) >> 1) + #else -#define ao_data_accel_sample(packet) ((packet)->adc.accel) + +#define ao_data_accel_cook(packet) ((packet)->adc.accel) + #endif /* HAS_ACCEL_REF */ -#endif /* else some other pressure sensor */ +#endif /* else some other accel sensor */ #endif /* _AO_DATA_H_ */ diff --git a/src/core/ao_log_mega.c b/src/core/ao_log_mega.c index 68e2af49..e7c2b0d9 100644 --- a/src/core/ao_log_mega.c +++ b/src/core/ao_log_mega.c @@ -112,8 +112,8 @@ ao_log(void) log.tick = ao_data_ring[ao_log_data_pos].tick; if ((int16_t) (log.tick - next_sensor) >= 0) { log.type = AO_LOG_SENSOR; - log.u.sensor.pres = ao_data_ring[ao_log_data_pos].ms5607.pres; - log.u.sensor.temp = ao_data_ring[ao_log_data_pos].ms5607.temp; + log.u.sensor.pres = ao_data_ring[ao_log_data_pos].ms5607_raw.pres; + log.u.sensor.temp = ao_data_ring[ao_log_data_pos].ms5607_raw.temp; log.u.sensor.accel_x = ao_data_ring[ao_log_data_pos].mpu6000.accel_x; log.u.sensor.accel_y = ao_data_ring[ao_log_data_pos].mpu6000.accel_y; log.u.sensor.accel_z = ao_data_ring[ao_log_data_pos].mpu6000.accel_z; diff --git a/src/core/ao_sample_mm.c b/src/core/ao_sample_mm.c index 8cfadc40..ac11eef0 100644 --- a/src/core/ao_sample_mm.c +++ b/src/core/ao_sample_mm.c @@ -101,11 +101,14 @@ ao_sample(void) /* Capture a sample */ ao_data = (struct ao_data *) &ao_data_ring[ao_sample_data]; ao_sample_tick = ao_data->tick; + + ao_data_pres_cook(ao_data); ao_sample_pres = ao_data_pres(ao_data); ao_sample_alt = pres_to_altitude(ao_sample_pres); ao_sample_height = ao_sample_alt - ao_ground_height; + #if HAS_ACCEL - ao_sample_accel = ao_data_accel_sample(ao_data); + ao_sample_accel = ao_data_accel_cook(ao_data); if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) ao_sample_accel = ao_data_accel_invert(ao_sample_accel); ao_data_set_accel(ao_data, ao_sample_accel); diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 5857c44d..9000a149 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -19,16 +19,6 @@ #include "ao_product.h" static __pdata uint16_t ao_telemetry_interval; -static __pdata int8_t ao_telemetry_config_max; -static __pdata int8_t ao_telemetry_config_cur; -#if HAS_GPS -static __pdata int8_t ao_telemetry_loc_cur; -static __pdata int8_t ao_telemetry_sat_cur; -#endif -#if HAS_COMPANION -static __pdata int8_t ao_telemetry_companion_max; -static __pdata int8_t ao_telemetry_companion_cur; -#endif static __pdata uint8_t ao_rdf = 0; static __pdata uint16_t ao_rdf_time; @@ -36,7 +26,7 @@ static __pdata uint16_t ao_rdf_time; #define AO_RDF_LENGTH_MS 500 #if defined(MEGAMETRUM) -#define AO_TELEMETRY_SENSOR AO_TELEMETRY_SENSOR_MEGAMETRUM +#define AO_SEND_MEGA 1 #endif #if defined(TELEMETRUM_V_0_1) || defined(TELEMETRUM_V_0_2) || defined(TELEMETRUM_V_1_0) || defined(TELEMETRUM_V_1_1) || defined(TELEBALLOON_V_1_1) || defined(TELEMETRUM_V_1_2) @@ -53,6 +43,7 @@ static __pdata uint16_t ao_rdf_time; static __xdata union ao_telemetry_all telemetry; +#if defined AO_TELEMETRY_SENSOR /* Send sensor packet */ static void ao_send_sensor(void) @@ -96,10 +87,78 @@ ao_send_sensor(void) ao_radio_send(&telemetry, sizeof (telemetry)); } +#endif -static uint8_t ao_baro_sample; + +#ifdef AO_SEND_MEGA +/* Send mega sensor packet */ +static void +ao_send_mega_sensor(void) +{ + __xdata struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; + + telemetry.generic.tick = packet->tick; + telemetry.generic.type = AO_TELEMETRY_MEGA_SENSOR; + + telemetry.mega_sensor.accel = ao_data_accel(packet); + telemetry.mega_sensor.pres = ao_data_pres(packet); + telemetry.mega_sensor.temp = ao_data_temp(packet); + + telemetry.mega_sensor.accel_x = packet->mpu6000.accel_x; + telemetry.mega_sensor.accel_y = packet->mpu6000.accel_y; + telemetry.mega_sensor.accel_z = packet->mpu6000.accel_z; + + telemetry.mega_sensor.gyro_x = packet->mpu6000.gyro_x; + telemetry.mega_sensor.gyro_y = packet->mpu6000.gyro_y; + telemetry.mega_sensor.gyro_z = packet->mpu6000.gyro_z; + + telemetry.mega_sensor.mag_x = packet->hmc5883.x; + telemetry.mega_sensor.mag_y = packet->hmc5883.y; + telemetry.mega_sensor.mag_z = packet->hmc5883.z; + + ao_radio_send(&telemetry, sizeof (telemetry)); +} + +static __pdata int8_t ao_telemetry_mega_data_max; +static __pdata int8_t ao_telemetry_mega_data_cur; + +/* Send mega data packet */ +static void +ao_send_mega_data(void) +{ + if (--ao_telemetry_mega_data_cur <= 0) { + __xdata struct ao_data *packet = (__xdata struct ao_data *) &ao_data_ring[ao_data_ring_prev(ao_sample_data)]; + uint8_t i; + + telemetry.generic.tick = packet->tick; + telemetry.generic.type = AO_TELEMETRY_MEGA_DATA; + + telemetry.mega_data.state = ao_flight_state; + telemetry.mega_data.v_batt = packet->adc.v_batt; + telemetry.mega_data.v_pyro = packet->adc.v_pbatt; + + /* XXX figure out right shift value; 4 might suffice */ + for (i = 0; i < AO_ADC_NUM_SENSE; i++) + telemetry.mega_data.sense[i] = packet->adc.sense[i] >> 8; + + telemetry.mega_data.ground_pres = ao_ground_pres; + telemetry.mega_data.ground_accel = ao_ground_accel; + telemetry.mega_data.accel_plus_g = ao_config.accel_plus_g; + telemetry.mega_data.accel_minus_g = ao_config.accel_minus_g; + + telemetry.mega_data.acceleration = ao_accel; + telemetry.mega_data.speed = ao_speed; + telemetry.mega_data.height = ao_height; + + ao_radio_send(&telemetry, sizeof (telemetry)); + ao_telemetry_mega_data_cur = ao_telemetry_mega_data_max; + } +} +#endif /* AO_SEND_MEGA */ #ifdef AO_SEND_ALL_BARO +static uint8_t ao_baro_sample; + static void ao_send_baro(void) { @@ -121,6 +180,9 @@ ao_send_baro(void) } #endif +static __pdata int8_t ao_telemetry_config_max; +static __pdata int8_t ao_telemetry_config_cur; + static void ao_send_configuration(void) { @@ -146,6 +208,10 @@ ao_send_configuration(void) } #if HAS_GPS + +static __pdata int8_t ao_telemetry_loc_cur; +static __pdata int8_t ao_telemetry_sat_cur; + static void ao_send_location(void) { @@ -181,6 +247,10 @@ ao_send_satellite(void) #endif #if HAS_COMPANION + +static __pdata int8_t ao_telemetry_companion_max; +static __pdata int8_t ao_telemetry_companion_cur; + static void ao_send_companion(void) { @@ -223,7 +293,13 @@ ao_telemetry(void) #ifdef AO_SEND_ALL_BARO ao_send_baro(); #endif +#ifdef AO_SEND_MEGA + ao_send_mega_sensor(); + ao_send_mega_data(); +#else ao_send_sensor(); +#endif + #if HAS_COMPANION if (ao_companion_running) ao_send_companion(); @@ -257,31 +333,42 @@ ao_telemetry(void) void ao_telemetry_set_interval(uint16_t interval) { + uint8_t cur = 0; ao_telemetry_interval = interval; + +#if AO_SEND_MEGA + if (interval > 1) + ao_telemetry_mega_data_max = 1; + else + ao_telemetry_mega_data_max = 2; + if (ao_telemetry_mega_data_max > cur) + cur++; + ao_telemetry_mega_data_cur = cur; +#endif #if HAS_COMPANION if (!ao_companion_setup.update_period) ao_companion_setup.update_period = AO_SEC_TO_TICKS(1); ao_telemetry_companion_max = ao_companion_setup.update_period / interval; - ao_telemetry_companion_cur = 1; + if (ao_telemetry_companion_max > cur) + cur++; + ao_telemetry_companion_cur = cur; #endif ao_telemetry_config_max = AO_SEC_TO_TICKS(1) / interval; #if HAS_COMPANION - ao_telemetry_config_cur = ao_telemetry_companion_cur; - if (ao_telemetry_config_max > ao_telemetry_config_cur) - ao_telemetry_config_cur++; -#else - ao_telemetry_config_cur = 1; + if (ao_telemetry_config_max > cur) + cur++; + ao_telemetry_config_cur = cur; #endif #if HAS_GPS - ao_telemetry_loc_cur = ao_telemetry_config_cur; - if (ao_telemetry_config_max > ao_telemetry_loc_cur) - ao_telemetry_loc_cur++; - ao_telemetry_sat_cur = ao_telemetry_loc_cur; - if (ao_telemetry_config_max > ao_telemetry_sat_cur) - ao_telemetry_sat_cur++; + if (ao_telemetry_config_max > cur) + cur++; + ao_telemetry_loc_cur = cur; + if (ao_telemetry_config_max > cur) + cur++; + ao_telemetry_sat_cur = cur; #endif ao_wakeup(&telemetry); } diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index 71299de9..ed1d20c9 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -60,7 +60,7 @@ static void ao_adc_done(int index) #if HAS_MS5607 if (!ao_ms5607_valid) step = 0; - ao_data_ring[ao_data_head].ms5607 = ao_ms5607_current; + ao_data_ring[ao_data_head].ms5607_raw = ao_ms5607_current; #endif #if HAS_HMC5883 if (!ao_hmc5883_valid) -- cgit v1.2.3 From ff5b0ba90e73a83360a2e8a7e9969ed2c3ce1514 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Jun 2012 09:46:50 -0700 Subject: altos: Crank down STM SPI speed for MM The cc1120 is noisy enough to break SPI data transfers at 4MHz, so crank things down to 1MHz. It's "stable" now, but clearly needs a filter and shorter traces. Signed-off-by: Keith Packard --- src/stm/ao_spi_stm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index 8784d985..d3378648 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -282,7 +282,7 @@ ao_spi_get(uint8_t spi_index) (1 << STM_SPI_CR1_SSI) | /* ... */ (0 << STM_SPI_CR1_LSBFIRST) | /* Big endian */ (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */ - (STM_SPI_CR1_BR_PCLK_8 << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ + (STM_SPI_CR1_BR_PCLK_16 << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ (1 << STM_SPI_CR1_MSTR) | (0 << STM_SPI_CR1_CPOL) | /* Format 0 */ (0 << STM_SPI_CR1_CPHA)); -- cgit v1.2.3 From 75e4521ec42a368cebc67a07f8713d7a854ea265 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Jun 2012 09:52:37 -0700 Subject: altos: Move FEC code to core It's not a driver as it's not specific to the 1120 chip Signed-off-by: Keith Packard --- src/core/ao_fec.h | 60 ++++++++++++++++++++ src/core/ao_fec_tx.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_fec.h | 60 -------------------- src/drivers/ao_fec_tx.c | 139 ---------------------------------------------- 4 files changed, 204 insertions(+), 199 deletions(-) create mode 100644 src/core/ao_fec.h create mode 100644 src/core/ao_fec_tx.c delete mode 100644 src/drivers/ao_fec.h delete mode 100644 src/drivers/ao_fec_tx.c (limited to 'src') diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h new file mode 100644 index 00000000..db5523a3 --- /dev/null +++ b/src/core/ao_fec.h @@ -0,0 +1,60 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_FEC_H_ +#define _AO_FEC_H_ + +#include + +#define AO_FEC_CRC_INIT 0xffff +#define AO_FEC_TRELLIS_TERMINATOR 0x0b +#define AO_FEC_PREPARE_EXTRA 4 + +void +ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name); + +uint16_t +ao_fec_crc(uint8_t *bytes, uint8_t len); + +/* + * Append CRC and terminator bytes, returns resulting length. + * 'out' must be at least len + AO_FEC_PREPARE_EXTRA bytes long + */ +uint8_t +ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out); + +/* + * Whiten data using the cc1111 PN9 sequence. 'out' + * must be 'len' bytes long. 'out' and 'in' can be + * the same array + */ +uint8_t +ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out); + +/* + * Encode data. 'out' must be len*2 bytes long + */ +uint8_t +ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); + +/* + * Interleave data. 'out' must be 'len' bytes long + */ +uint8_t +ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out); + +#endif /* _AO_FEC_H_ */ diff --git a/src/core/ao_fec_tx.c b/src/core/ao_fec_tx.c new file mode 100644 index 00000000..bf32c506 --- /dev/null +++ b/src/core/ao_fec_tx.c @@ -0,0 +1,144 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +void +ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name) +{ + uint8_t i; + + printf ("%s (%d):", name, len); + for (i = 0; i < len; i++) { + if ((i & 7) == 0) + printf ("\n\t%02x:", i); + printf(" %02x", bytes[i]); + } + printf ("\n"); +} + +static uint16_t inline +crc_byte(uint8_t byte, uint16_t crc) +{ + uint8_t bit; + + for (bit = 0; bit < 8; bit++) { + if (((crc & 0x8000) >> 8) ^ (byte & 0x80)) + crc = (crc << 1) ^ 0x8005; + else + crc = (crc << 1); + byte <<= 1; + } + return crc; +} + +uint16_t +ao_fec_crc(uint8_t *bytes, uint8_t len) +{ + uint16_t crc = AO_FEC_CRC_INIT; + + while (len--) + crc = crc_byte(*bytes++, crc); + return crc; +} + +uint8_t +ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out) +{ + uint16_t crc = ao_fec_crc (in, len); + uint8_t i; + uint8_t num_fec; + + /* Copy data */ + for (i = 0; i < len; i++) + out[i] = in[i]; + + /* Append CRC */ + out[i++] = crc >> 8; + out[i++] = crc; + + /* Append FEC -- 1 byte if odd, two bytes if even */ + num_fec = 2 - (i & 1); + while (num_fec--) + out[i++] = AO_FEC_TRELLIS_TERMINATOR; + return i; +} + +static const uint8_t whiten[] = { +#include "ao_whiten.h" +}; + +uint8_t +ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out) +{ + const uint8_t *w = whiten; + + while (len--) + *out++ = *in++ ^ *w++; +} + +static const uint8_t ao_fec_encode_table[16] = { +/* next 0 1 state */ + 0, 3, /* 000 */ + 1, 2, /* 001 */ + 3, 0, /* 010 */ + 2, 1, /* 011 */ + 3, 0, /* 100 */ + 2, 1, /* 101 */ + 0, 3, /* 110 */ + 1, 2 /* 111 */ +}; + +uint8_t +ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out) +{ + uint16_t fec = 0, output; + uint8_t byte, bit; + + for (byte = 0; byte < len; byte++) { + fec = (fec & 0x700) | in[byte]; + output = 0; + for (bit = 0; bit < 8; bit++) { + output = output << 2 | ao_fec_encode_table[fec >> 7]; + fec = (fec << 1) & 0x7ff; + } + out[byte * 2] = output >> 8; + out[byte * 2 + 1] = output; + } + return len * 2; +} + +uint8_t +ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out) +{ + uint8_t i, j; + + for (i = 0; i < len; i += 4) { + uint32_t interleaved = 0; + + for (j = 0; j < 4 * 4; j++) { + interleaved <<= 2; + interleaved |= (in[i + (~j & 0x3)] >> (2 * ((j & 0xc) >> 2))) & 0x03; + } + out[i+0] = interleaved >> 24; + out[i+1] = interleaved >> 16; + out[i+2] = interleaved >> 8; + out[i+3] = interleaved; + } + return len; +} diff --git a/src/drivers/ao_fec.h b/src/drivers/ao_fec.h deleted file mode 100644 index db5523a3..00000000 --- a/src/drivers/ao_fec.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_FEC_H_ -#define _AO_FEC_H_ - -#include - -#define AO_FEC_CRC_INIT 0xffff -#define AO_FEC_TRELLIS_TERMINATOR 0x0b -#define AO_FEC_PREPARE_EXTRA 4 - -void -ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name); - -uint16_t -ao_fec_crc(uint8_t *bytes, uint8_t len); - -/* - * Append CRC and terminator bytes, returns resulting length. - * 'out' must be at least len + AO_FEC_PREPARE_EXTRA bytes long - */ -uint8_t -ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out); - -/* - * Whiten data using the cc1111 PN9 sequence. 'out' - * must be 'len' bytes long. 'out' and 'in' can be - * the same array - */ -uint8_t -ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out); - -/* - * Encode data. 'out' must be len*2 bytes long - */ -uint8_t -ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); - -/* - * Interleave data. 'out' must be 'len' bytes long - */ -uint8_t -ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out); - -#endif /* _AO_FEC_H_ */ diff --git a/src/drivers/ao_fec_tx.c b/src/drivers/ao_fec_tx.c deleted file mode 100644 index b8933956..00000000 --- a/src/drivers/ao_fec_tx.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include -#include - -void -ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name) -{ - uint8_t i; - - printf ("%s (%d):", name, len); - for (i = 0; i < len; i++) { - if ((i & 7) == 0) - printf ("\n\t%02x:", i); - printf(" %02x", bytes[i]); - } - printf ("\n"); -} - -static uint16_t inline -crc_byte(uint8_t byte, uint16_t crc) -{ - uint8_t bit; - - for (bit = 0; bit < 8; bit++) { - if (((crc & 0x8000) >> 8) ^ (byte & 0x80)) - crc = (crc << 1) ^ 0x8005; - else - crc = (crc << 1); - byte <<= 1; - } - return crc; -} - -uint16_t -ao_fec_crc(uint8_t *bytes, uint8_t len) -{ - uint16_t crc = AO_FEC_CRC_INIT; - - while (len--) - crc = crc_byte(*bytes++, crc); - return crc; -} - -uint8_t -ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out) -{ - uint16_t crc = ao_fec_crc (in, len); - uint8_t i; - uint8_t num_fec; - - /* Copy data */ - for (i = 0; i < len; i++) - out[i] = in[i]; - - /* Append CRC */ - out[i++] = crc >> 8; - out[i++] = crc; - - /* Append FEC -- 1 byte if odd, two bytes if even */ - num_fec = 2 - (i & 1); - while (num_fec--) - out[i++] = AO_FEC_TRELLIS_TERMINATOR; - return i; -} - -static const uint8_t whiten[] = { -#include "ao_whiten.h" -}; - -uint8_t -ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out) -{ - const uint8_t *w = whiten; - - while (len--) - *out++ = *in++ ^ *w++; -} - -static const uint8_t ao_fec_encode_table[16] = { - 0, 3, 1, 2, - 3, 0, 2, 1, - 3, 0, 2, 1, - 0, 3, 1, 2 -}; - -uint8_t -ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out) -{ - uint16_t fec = 0, output; - uint8_t byte, bit; - - for (byte = 0; byte < len; byte++) { - fec = (fec & 0x700) | in[byte]; - output = 0; - for (bit = 0; bit < 8; bit++) { - output = output << 2 | ao_fec_encode_table[fec >> 7]; - fec = (fec << 1) & 0x7ff; - } - out[byte * 2] = output >> 8; - out[byte * 2 + 1] = output; - } - return len * 2; -} - -uint8_t -ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out) -{ - uint8_t i, j; - - for (i = 0; i < len; i += 4) { - uint32_t interleaved = 0; - - for (j = 0; j < 4 * 4; j++) { - interleaved <<= 2; - interleaved |= (in[i + (~j & 0x3)] >> (2 * ((j & 0xc) >> 2))) & 0x03; - } - out[i+0] = interleaved >> 24; - out[i+1] = interleaved >> 16; - out[i+2] = interleaved >> 8; - out[i+3] = interleaved; - } - return len; -} -- cgit v1.2.3 From cbf79a0f9cb859d04e8e03d627219cb2bf49611f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 22 Jun 2012 23:12:02 -0700 Subject: altos: Add the simplest possible viterbi decoder I think I understand how it works now. It's not exactly speedy, and it uses a lot of memory. Signed-off-by: Keith Packard --- src/core/ao_fec.h | 9 +++ src/core/ao_viterbi.c | 143 ++++++++++++++++++++++++++++++++++++++++ src/test/Makefile | 4 +- src/test/ao_fec_tx_test.c | 163 +++++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 307 insertions(+), 12 deletions(-) create mode 100644 src/core/ao_viterbi.c (limited to 'src') diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index db5523a3..985352dd 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -57,4 +57,13 @@ ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); uint8_t ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out); + +/* + * Decode data. 'in' is one byte per bit, soft decision + * 'out' must be len/8 bytes long + */ + +uint8_t +ao_fec_decode(uint8_t *in, int in_len, uint8_t *out); + #endif /* _AO_FEC_H_ */ diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c new file mode 100644 index 00000000..2d441f4b --- /dev/null +++ b/src/core/ao_viterbi.c @@ -0,0 +1,143 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +/* + * 'input' is 8-bits per symbol soft decision data + * 'len' is output byte length + */ + +static const uint8_t ao_fec_encode_table[16] = { +/* next 0 1 state */ + 0, 3, /* 000 */ + 1, 2, /* 001 */ + 3, 0, /* 010 */ + 2, 1, /* 011 */ + 3, 0, /* 100 */ + 2, 1, /* 101 */ + 0, 3, /* 110 */ + 1, 2 /* 111 */ +}; + +struct ao_soft_sym { + uint8_t a, b; +}; + +struct ao_soft_sym +ao_soft_sym(uint8_t bits) +{ + struct ao_soft_sym s; + + s.a = ((bits & 2) >> 1) * 0xff; + s.b = (bits & 1) * 0xff; + return s; +} + +uint8_t +ao_next_state(uint8_t state, uint8_t bit) +{ + return ((state << 1) | bit) & 0x7; +} + +static inline abs(int x) { return x < 0 ? -x : x; } + +int +ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) +{ + return abs(a.a - b.a) + abs(a.b - b.b); +} + +uint8_t +ao_fec_decode(uint8_t *in, int len, uint8_t *out) +{ + int cost[len/2 + 1][8]; + uint8_t prev[len/2 + 1][8]; + int c; + int i, b; + uint8_t state = 0, min_state; + uint8_t bits[len/2]; + + for (c = 0; c < 8; c++) + cost[0][c] = 10000; + cost[0][0] = 0; + + for (i = 0; i < len; i += 2) { + b = i/2; + struct ao_soft_sym s = { .a = in[i], .b = in[i+1] }; + + for (state = 0; state < 8; state++) + cost[b+1][state] = 10000; + + for (state = 0; state < 8; state++) { + struct ao_soft_sym zero = ao_soft_sym(ao_fec_encode_table[state * 2 + 0]); + struct ao_soft_sym one = ao_soft_sym(ao_fec_encode_table[state * 2 + 1]); + uint8_t zero_state = ao_next_state(state, 0); + uint8_t one_state = ao_next_state(state, 1); + int zero_cost = ao_cost(s, zero); + int one_cost = ao_cost(s, one); + +#if 0 + printf ("saw %02x %02x expected %02x %02x (%d) or %02x %02x (%d)\n", + s.a, s.b, zero.a, zero.b, zero_cost, one.a, one.b, one_cost); +#endif + zero_cost += cost[b][state]; + one_cost += cost[b][state]; + if (zero_cost < cost[b+1][zero_state]) { + prev[b+1][zero_state] = state; + cost[b+1][zero_state] = zero_cost; + } + + if (one_cost < cost[b+1][one_state]) { + prev[b+1][one_state] = state; + cost[b+1][one_state] = one_cost; + } + } + + printf ("bit %3d symbol %2x %2x:", i/2, s.a, s.b); + for (state = 0; state < 8; state++) { + printf (" %5d", cost[b+1][state]); + } + printf ("\n"); + } + + b = len / 2; + c = cost[b][0]; + min_state = 0; + for (state = 1; state < 8; state++) { + if (cost[b][state] < c) { + c = cost[b][state]; + min_state = state; + } + } + + for (b = len/2; b > 0; b--) { + bits[b-1] = min_state & 1; + min_state = prev[b][min_state]; + } + + for (i = 0; i < len/2; i += 8) { + uint8_t byte; + + byte = 0; + for (b = 0; b < 8; b++) + byte = (byte << 1) | bits[i + b]; + out[i/8] = byte; + } + return len/16; +} diff --git a/src/test/Makefile b/src/test/Makefile index 3e308dd7..024a54c1 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -40,5 +40,5 @@ ao_convert_pa_test: ao_convert_pa_test.c ao_convert_pa.c altitude-pa.h ao_kalman.h: $(KALMAN) (cd .. && make ao_kalman.h) -ao_fec_tx_test: ao_fec_tx_test.c ao_fec_tx.c - cc $(CFLAGS) -o $@ ao_fec_tx_test.c ../drivers/ao_fec_tx.c +ao_fec_tx_test: ao_fec_tx_test.c ao_fec_tx.c ao_viterbi.c + cc $(CFLAGS) -o $@ ao_fec_tx_test.c ../core/ao_fec_tx.c ../core/ao_viterbi.c -lm diff --git a/src/test/ao_fec_tx_test.c b/src/test/ao_fec_tx_test.c index b8dc9308..d01eadc5 100644 --- a/src/test/ao_fec_tx_test.c +++ b/src/test/ao_fec_tx_test.c @@ -18,21 +18,73 @@ #include #include #include +#include +#include -int -main(int argc, char **argv) +#ifndef RANDOM_MAX +#define RANDOM_MAX 0x7fffffff +#endif + +static double +rand_real(void) { + return (double) random() / (double) RANDOM_MAX; +} + +static double +gaussian_random(double mean, double dev) { - uint8_t input[4] = { 3, 1, 2, 3 }; - uint8_t prepare[sizeof(input) + AO_FEC_PREPARE_EXTRA]; - uint8_t encode[sizeof(prepare) * 2]; - uint8_t interleave[sizeof(encode)]; + static int save_x_valid = 0; + static double save_x; + double x; + + if (save_x_valid) + { + x = save_x; + save_x_valid = 0; + } + else + { + double w; + double normal_x1, normal_x2; + + do { + normal_x1 = 2 * rand_real () - 1; + normal_x2 = 2 * rand_real () - 1; + w = normal_x1*normal_x1 + normal_x2*normal_x2; + } while (w >= 1 || w < 1E-30); + + w = sqrt(log(w)*(-2./w)); + + /* + * normal_x1 and normal_x2 are independent normally + * distributed variates + */ + + x = normal_x1 * w; + /* save normal_x2 for next call */ + save_x = normal_x2 * w; + save_x_valid = 1; + } + return x * dev + mean; +} + +#define PREPARE_LEN(input_len) ((input_len) + AO_FEC_PREPARE_EXTRA) +#define ENCODE_LEN(input_len) (PREPARE_LEN(input_len) * 2) +#define INTERLEAVE_LEN(input_len) ENCODE_LEN(input_len) + +static int +ao_encode(uint8_t *input, int input_len, uint8_t *output) +{ + uint8_t prepare[PREPARE_LEN(input_len)]; + uint8_t encode[ENCODE_LEN(input_len)]; + uint8_t interleave[INTERLEAVE_LEN(input_len)]; uint8_t prepare_len; uint8_t encode_len; uint8_t interleave_len; - ao_fec_dump_bytes(input, sizeof(input), "Input"); + ao_fec_dump_bytes(input, input_len, "Input"); - prepare_len = ao_fec_prepare(input, sizeof (input), prepare); + prepare_len = ao_fec_prepare(input, input_len, prepare); ao_fec_dump_bytes(prepare, prepare_len, "Prepare"); @@ -40,8 +92,99 @@ main(int argc, char **argv) ao_fec_dump_bytes(encode, encode_len, "Encode"); - interleave_len = ao_fec_interleave(encode, encode_len, interleave); + interleave_len = ao_fec_interleave(encode, encode_len, output); + + ao_fec_dump_bytes(output, interleave_len, "Interleave"); + + return interleave_len; +} + +#define RADIO_LEN(input_len) (INTERLEAVE_LEN(input_len) * 8) + +static int +ao_radio(uint8_t *bits, int bits_len, uint8_t *bytes) +{ + uint8_t b, *bytes_orig = bytes; + uint8_t interleave[bits_len]; + int i, bit; + + ao_fec_interleave(bits, bits_len, interleave); + + ao_fec_dump_bytes(interleave, bits_len, "De-interleave"); + + for (i = 0; i < bits_len; i++) { + b = interleave[i]; + for (bit = 7; bit >= 0; bit--) + *bytes++ = ((b >> bit) & 1) * 0xff; + } + + ao_fec_dump_bytes(bytes_orig, bits_len * 8, "Bytes"); - ao_fec_dump_bytes(interleave, interleave_len, "Interleave"); + return bits_len * 8; } +static int +ao_fuzz (uint8_t *in, int in_len, uint8_t *out, double dev) +{ + int i; + int errors = 0; + + for (i = 0; i < in_len; i++) { + double error = gaussian_random(0, dev); + uint8_t byte = in[i]; + + if (error > 0) { + if (error > 0xff) + error = 0xff; + if (error >= 0x80) + errors++; + if (byte < 0x80) + byte += error; + else + byte -= error; + } + out[i] = byte; + } + + printf ("Introduced %d errors\n", errors); + ao_fec_dump_bytes(out, in_len, "Fuzz"); + return in_len; +} + +static int +ao_decode(uint8_t *bytes, int bytes_len, uint8_t *bits) +{ + int bits_len; + + bits_len = ao_fec_decode(bytes, bytes_len, bits); + + ao_fec_dump_bytes(bits, bits_len, "Decode"); +} + +int +main(int argc, char **argv) +{ + uint8_t original[4] = { 3, 1, 2, 3 }; + uint8_t encode[INTERLEAVE_LEN(sizeof(original))]; + int encode_len; + + uint8_t transmit[RADIO_LEN(sizeof(original))]; + int transmit_len; + + uint8_t receive[RADIO_LEN(sizeof(original))]; + int receive_len; + + uint8_t decode[INTERLEAVE_LEN(sizeof(original))]; + int decode_len; + + encode_len = ao_encode(original, sizeof(original), encode); + + transmit_len = ao_radio(encode, encode_len, transmit); + + /* apply gaussian noise to test viterbi code against errors */ + receive_len = ao_fuzz(transmit, transmit_len, receive, 0x80); + + decode_len = ao_decode(receive, receive_len, decode); +} + + -- cgit v1.2.3 From 047e95421c87c5d056038797b48f759bedabf245 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 22 Jun 2012 23:31:11 -0700 Subject: altos: Start optimizing viterbi decoder Only need two cost arrays (previous and next). Create constant full-width decoder table instead of expanding bits into bytes for each decode step. Signed-off-by: Keith Packard --- src/core/ao_viterbi.c | 94 +++++++++++++++++++++++++-------------------------- 1 file changed, 47 insertions(+), 47 deletions(-) (limited to 'src') diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index 2d441f4b..916c4d7c 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -23,22 +23,22 @@ * 'len' is output byte length */ -static const uint8_t ao_fec_encode_table[16] = { -/* next 0 1 state */ - 0, 3, /* 000 */ - 1, 2, /* 001 */ - 3, 0, /* 010 */ - 2, 1, /* 011 */ - 3, 0, /* 100 */ - 2, 1, /* 101 */ - 0, 3, /* 110 */ - 1, 2 /* 111 */ -}; - struct ao_soft_sym { uint8_t a, b; }; +static const struct ao_soft_sym ao_fec_decode_table[16] = { +/* next 0 1 state */ + { 0x00, 0x00 }, { 0xff, 0xff }, /* 000 */ + { 0x00, 0xff }, { 0xff, 0x00 }, /* 001 */ + { 0xff, 0xff }, { 0x00, 0x00 }, /* 010 */ + { 0xff, 0x00 }, { 0x00, 0xff }, /* 011 */ + { 0xff, 0xff }, { 0x00, 0x00 }, /* 100 */ + { 0xff, 0x00 }, { 0x00, 0xff }, /* 101 */ + { 0x00, 0x00 }, { 0xff, 0xff }, /* 110 */ + { 0x00, 0xff }, { 0xff, 0x00 } /* 111 */ +}; + struct ao_soft_sym ao_soft_sym(uint8_t bits) { @@ -57,71 +57,71 @@ ao_next_state(uint8_t state, uint8_t bit) static inline abs(int x) { return x < 0 ? -x : x; } -int +static inline uint16_t ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) { return abs(a.a - b.a) + abs(a.b - b.b); } +#define NUM_STATE 8 + uint8_t ao_fec_decode(uint8_t *in, int len, uint8_t *out) { - int cost[len/2 + 1][8]; - uint8_t prev[len/2 + 1][8]; - int c; - int i, b; - uint8_t state = 0, min_state; - uint8_t bits[len/2]; - - for (c = 0; c < 8; c++) - cost[0][c] = 10000; + uint16_t cost[2][NUM_STATE]; + uint8_t prev[len/2 + 1][NUM_STATE]; + int c; + int i, b; + uint8_t p, n; + uint8_t state = 0, min_state; + uint8_t bits[len/2]; + + p = 0; + for (c = 0; c < NUM_STATE; c++) + cost[0][c] = 0xffff; cost[0][0] = 0; for (i = 0; i < len; i += 2) { b = i/2; + n = p ^ 1; struct ao_soft_sym s = { .a = in[i], .b = in[i+1] }; - for (state = 0; state < 8; state++) - cost[b+1][state] = 10000; + for (state = 0; state < NUM_STATE; state++) + cost[n][state] = 0xffff; + + for (state = 0; state < NUM_STATE; state++) { + int zero_cost = ao_cost(s, ao_fec_decode_table[state * 2 + 0]); + int one_cost = ao_cost(s, ao_fec_decode_table[state * 2 + 1]); - for (state = 0; state < 8; state++) { - struct ao_soft_sym zero = ao_soft_sym(ao_fec_encode_table[state * 2 + 0]); - struct ao_soft_sym one = ao_soft_sym(ao_fec_encode_table[state * 2 + 1]); uint8_t zero_state = ao_next_state(state, 0); uint8_t one_state = ao_next_state(state, 1); - int zero_cost = ao_cost(s, zero); - int one_cost = ao_cost(s, one); - -#if 0 - printf ("saw %02x %02x expected %02x %02x (%d) or %02x %02x (%d)\n", - s.a, s.b, zero.a, zero.b, zero_cost, one.a, one.b, one_cost); -#endif - zero_cost += cost[b][state]; - one_cost += cost[b][state]; - if (zero_cost < cost[b+1][zero_state]) { + + zero_cost += cost[p][state]; + one_cost += cost[p][state]; + if (zero_cost < cost[n][zero_state]) { prev[b+1][zero_state] = state; - cost[b+1][zero_state] = zero_cost; + cost[n][zero_state] = zero_cost; } - if (one_cost < cost[b+1][one_state]) { + if (one_cost < cost[n][one_state]) { prev[b+1][one_state] = state; - cost[b+1][one_state] = one_cost; + cost[n][one_state] = one_cost; } } printf ("bit %3d symbol %2x %2x:", i/2, s.a, s.b); - for (state = 0; state < 8; state++) { - printf (" %5d", cost[b+1][state]); + for (state = 0; state < NUM_STATE; state++) { + printf (" %5d", cost[n][state]); } printf ("\n"); + p = n; } - b = len / 2; - c = cost[b][0]; + c = cost[p][0]; min_state = 0; - for (state = 1; state < 8; state++) { - if (cost[b][state] < c) { - c = cost[b][state]; + for (state = 1; state < NUM_STATE; state++) { + if (cost[p][state] < c) { + c = cost[p][state]; min_state = state; } } -- cgit v1.2.3 From ff8de3af193839de4bacfd07ade7a5f9ac0bf5b3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Jun 2012 00:54:42 -0700 Subject: altos: incremental viterbi decode Decode bits incrementally. Don't bother decoding the last byte; it's always a pad byte. Signed-off-by: Keith Packard --- src/core/ao_viterbi.c | 70 +++++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 30 deletions(-) (limited to 'src') diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index 916c4d7c..df95e979 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -49,18 +49,18 @@ ao_soft_sym(uint8_t bits) return s; } -uint8_t +static inline uint8_t ao_next_state(uint8_t state, uint8_t bit) { return ((state << 1) | bit) & 0x7; } -static inline abs(int x) { return x < 0 ? -x : x; } +static inline uint16_t ao_abs(int16_t x) { return x < 0 ? -x : x; } static inline uint16_t ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) { - return abs(a.a - b.a) + abs(a.b - b.b); + return ao_abs(a.a - b.a) + ao_abs(a.b - b.b); } #define NUM_STATE 8 @@ -68,19 +68,23 @@ ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) uint8_t ao_fec_decode(uint8_t *in, int len, uint8_t *out) { - uint16_t cost[2][NUM_STATE]; + uint16_t cost[2][NUM_STATE], min_cost; uint8_t prev[len/2 + 1][NUM_STATE]; - int c; - int i, b; + uint16_t prev_bits[2][NUM_STATE]; + int i, b, dump; uint8_t p, n; uint8_t state = 0, min_state; - uint8_t bits[len/2]; p = 0; - for (c = 0; c < NUM_STATE; c++) - cost[0][c] = 0xffff; + for (state = 0; state < NUM_STATE; state++) { + cost[0][state] = 0xffff; + prev_bits[0][state] = 0; + } cost[0][0] = 0; + min_state = 0; + min_cost = 0; + dump = 0; for (i = 0; i < len; i += 2) { b = i/2; n = p ^ 1; @@ -101,43 +105,49 @@ ao_fec_decode(uint8_t *in, int len, uint8_t *out) if (zero_cost < cost[n][zero_state]) { prev[b+1][zero_state] = state; cost[n][zero_state] = zero_cost; + prev_bits[n][zero_state] = (prev_bits[p][state] << 1) | (state & 1); } if (one_cost < cost[n][one_state]) { prev[b+1][one_state] = state; cost[n][one_state] = one_cost; + prev_bits[n][one_state] = (prev_bits[p][state] << 1) | (state & 1); } } +#if 0 printf ("bit %3d symbol %2x %2x:", i/2, s.a, s.b); for (state = 0; state < NUM_STATE; state++) { - printf (" %5d", cost[n][state]); + printf (" %5d(%04x)", cost[n][state], prev_bits[n][state]); } printf ("\n"); +#endif p = n; - } - c = cost[p][0]; - min_state = 0; - for (state = 1; state < NUM_STATE; state++) { - if (cost[p][state] < c) { - c = cost[p][state]; - min_state = state; + b++; + if ((b - dump) > 16 || i + 2 >= len) { + uint8_t dist = b - (dump + 9); + uint8_t rev; + min_cost = cost[p][0]; + min_state = 0; + for (state = 1; state < NUM_STATE; state++) { + if (cost[p][state] < min_cost) { + min_cost = cost[p][state]; + min_state = state; + } + } + for (rev = 0; rev < dist; rev++) { + min_state = prev[b][min_state]; + b--; + } +#if 0 + printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x\n", + i/2, min_cost, b-1, min_state, (prev_bits[p][min_state] >> dist) & 0xff); +#endif + out[dump/8] = prev_bits[p][min_state] >> dist; + dump = b - 1; } - } - - for (b = len/2; b > 0; b--) { - bits[b-1] = min_state & 1; - min_state = prev[b][min_state]; - } - - for (i = 0; i < len/2; i += 8) { - uint8_t byte; - byte = 0; - for (b = 0; b < 8; b++) - byte = (byte << 1) | bits[i + b]; - out[i/8] = byte; } return len/16; } -- cgit v1.2.3 From f7bf07dfdad260c1f219064957ef08fb480bf20f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Jun 2012 02:12:58 -0700 Subject: altos: optimize Viterbi implementation Minimize data usage, make data arrays static Signed-off-by: Keith Packard --- src/core/ao_fec.h | 5 +- src/core/ao_fec_tx.c | 2 +- src/core/ao_viterbi.c | 149 ++++++++++++++++++++++++++++---------------------- 3 files changed, 86 insertions(+), 70 deletions(-) (limited to 'src') diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index 985352dd..d4f64b74 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -42,7 +42,7 @@ ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out); * must be 'len' bytes long. 'out' and 'in' can be * the same array */ -uint8_t +void ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out); /* @@ -57,13 +57,12 @@ ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); uint8_t ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out); - /* * Decode data. 'in' is one byte per bit, soft decision * 'out' must be len/8 bytes long */ uint8_t -ao_fec_decode(uint8_t *in, int in_len, uint8_t *out); +ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out); #endif /* _AO_FEC_H_ */ diff --git a/src/core/ao_fec_tx.c b/src/core/ao_fec_tx.c index bf32c506..c5f410b8 100644 --- a/src/core/ao_fec_tx.c +++ b/src/core/ao_fec_tx.c @@ -83,7 +83,7 @@ static const uint8_t whiten[] = { #include "ao_whiten.h" }; -uint8_t +void ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out) { const uint8_t *w = whiten; diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index df95e979..1b1784b3 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -18,37 +18,26 @@ #include #include -/* - * 'input' is 8-bits per symbol soft decision data - * 'len' is output byte length - */ - struct ao_soft_sym { uint8_t a, b; }; -static const struct ao_soft_sym ao_fec_decode_table[16] = { +#define NUM_STATE 8 +#define NUM_HIST 8 +#define MOD_HIST(b) ((b) & 7) + +static const struct ao_soft_sym ao_fec_decode_table[NUM_STATE][2] = { /* next 0 1 state */ - { 0x00, 0x00 }, { 0xff, 0xff }, /* 000 */ - { 0x00, 0xff }, { 0xff, 0x00 }, /* 001 */ - { 0xff, 0xff }, { 0x00, 0x00 }, /* 010 */ - { 0xff, 0x00 }, { 0x00, 0xff }, /* 011 */ - { 0xff, 0xff }, { 0x00, 0x00 }, /* 100 */ - { 0xff, 0x00 }, { 0x00, 0xff }, /* 101 */ - { 0x00, 0x00 }, { 0xff, 0xff }, /* 110 */ - { 0x00, 0xff }, { 0xff, 0x00 } /* 111 */ + { { 0x00, 0x00 }, { 0xff, 0xff } } , /* 000 */ + { { 0x00, 0xff }, { 0xff, 0x00 } }, /* 001 */ + { { 0xff, 0xff }, { 0x00, 0x00 } }, /* 010 */ + { { 0xff, 0x00 }, { 0x00, 0xff } }, /* 011 */ + { { 0xff, 0xff }, { 0x00, 0x00 } }, /* 100 */ + { { 0xff, 0x00 }, { 0x00, 0xff } }, /* 101 */ + { { 0x00, 0x00 }, { 0xff, 0xff } }, /* 110 */ + { { 0x00, 0xff }, { 0xff, 0x00 } } /* 111 */ }; -struct ao_soft_sym -ao_soft_sym(uint8_t bits) -{ - struct ao_soft_sym s; - - s.a = ((bits & 2) >> 1) * 0xff; - s.b = (bits & 1) * 0xff; - return s; -} - static inline uint8_t ao_next_state(uint8_t state, uint8_t bit) { @@ -63,71 +52,93 @@ ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) return ao_abs(a.a - b.a) + ao_abs(a.b - b.b); } -#define NUM_STATE 8 +/* + * 'in' is 8-bits per symbol soft decision data + * 'len' is input byte length. 'out' must be + * 'len'/16 bytes long + */ uint8_t -ao_fec_decode(uint8_t *in, int len, uint8_t *out) +ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out) { - uint16_t cost[2][NUM_STATE], min_cost; - uint8_t prev[len/2 + 1][NUM_STATE]; - uint16_t prev_bits[2][NUM_STATE]; - int i, b, dump; - uint8_t p, n; - uint8_t state = 0, min_state; + static uint16_t cost[2][NUM_STATE]; /* path cost */ + static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */ + uint16_t i; /* input byte index */ + uint16_t b; /* encoded symbol index (bytes/2) */ + uint16_t o; /* output bit index */ + uint8_t p; /* previous cost/bits index */ + uint8_t n; /* next cost/bits index */ + uint8_t state; /* state index */ + uint8_t bit; /* original encoded bit index */ p = 0; for (state = 0; state < NUM_STATE; state++) { cost[0][state] = 0xffff; - prev_bits[0][state] = 0; + bits[0][state] = 0; } cost[0][0] = 0; - min_state = 0; - min_cost = 0; - dump = 0; + o = 0; for (i = 0; i < len; i += 2) { b = i/2; n = p ^ 1; struct ao_soft_sym s = { .a = in[i], .b = in[i+1] }; + /* Reset next costs to 'impossibly high' values so that + * the first path through this state is cheaper than this + */ for (state = 0; state < NUM_STATE; state++) cost[n][state] = 0xffff; + /* Compute path costs and accumulate output bit path + * for each state and encoded bit value + */ for (state = 0; state < NUM_STATE; state++) { - int zero_cost = ao_cost(s, ao_fec_decode_table[state * 2 + 0]); - int one_cost = ao_cost(s, ao_fec_decode_table[state * 2 + 1]); - - uint8_t zero_state = ao_next_state(state, 0); - uint8_t one_state = ao_next_state(state, 1); - - zero_cost += cost[p][state]; - one_cost += cost[p][state]; - if (zero_cost < cost[n][zero_state]) { - prev[b+1][zero_state] = state; - cost[n][zero_state] = zero_cost; - prev_bits[n][zero_state] = (prev_bits[p][state] << 1) | (state & 1); - } - - if (one_cost < cost[n][one_state]) { - prev[b+1][one_state] = state; - cost[n][one_state] = one_cost; - prev_bits[n][one_state] = (prev_bits[p][state] << 1) | (state & 1); + for (bit = 0; bit < 2; bit++) { + int bit_cost = cost[p][state] + ao_cost(s, ao_fec_decode_table[state][bit]); + uint8_t bit_state = ao_next_state(state, bit); + + /* Only track the minimal cost to reach + * this state; the best path can never + * go through the higher cost paths as + * total path cost is cumulative + */ + if (bit_cost < cost[n][bit_state]) { + cost[n][bit_state] = bit_cost; + bits[n][bit_state] = (bits[p][state] << 1) | (state & 1); + } } } #if 0 printf ("bit %3d symbol %2x %2x:", i/2, s.a, s.b); for (state = 0; state < NUM_STATE; state++) { - printf (" %5d(%04x)", cost[n][state], prev_bits[n][state]); + printf (" %5d(%04x)", cost[n][state], bits[n][state]); } printf ("\n"); #endif p = n; - b++; - if ((b - dump) > 16 || i + 2 >= len) { - uint8_t dist = b - (dump + 9); - uint8_t rev; + /* A loop is needed to handle the last output byte. It + * won't have a full NUM_HIST bits of future data to + * perform full error correction, but we might as well + * give the best possible answer anyways. + */ + while ((b - o) >= (8 + NUM_HIST) || (i + 2 >= len && b > o)) { + + /* Compute number of bits to the end of the + * last full byte of data. This is generally + * NUM_HIST, unless we've reached + * the end of the input, in which case + * it will be seven. + */ + int8_t dist = b - (o + 8); /* distance to last ready-for-writing bit */ + uint16_t min_cost; /* lowest cost */ + uint8_t min_state; /* lowest cost state */ + + /* Find the best fit at the current point + * of the decode. + */ min_cost = cost[p][0]; min_state = 0; for (state = 1; state < NUM_STATE; state++) { @@ -136,18 +147,24 @@ ao_fec_decode(uint8_t *in, int len, uint8_t *out) min_state = state; } } - for (rev = 0; rev < dist; rev++) { - min_state = prev[b][min_state]; - b--; + + /* The very last byte of data has the very last bit + * of data left in the state value; just smash the + * bits value in place and reset the 'dist' from + * -1 to 0 so that the full byte is read out + */ + if (dist < 0) { + bits[p][min_state] = (bits[p][min_state] << 1) | (min_state & 1); + dist = 0; } + #if 0 printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x\n", - i/2, min_cost, b-1, min_state, (prev_bits[p][min_state] >> dist) & 0xff); + i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff); #endif - out[dump/8] = prev_bits[p][min_state] >> dist; - dump = b - 1; + out[o >> 3] = bits[p][min_state] >> dist; + o += 8; } - } return len/16; } -- cgit v1.2.3 From 83549f8bde42c3fddbdc817540c869dc8aefd013 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Jun 2012 02:13:52 -0700 Subject: altos: Make ao_fec_tx_test build cleanly with -Wall Signed-off-by: Keith Packard --- src/test/Makefile | 2 +- src/test/ao_fec_tx_test.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/test/Makefile b/src/test/Makefile index 024a54c1..7bcf24e1 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -4,7 +4,7 @@ PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noi KALMAN=make-kalman -CFLAGS=-I.. -I. -I../core -I../drivers -O0 -g +CFLAGS=-I.. -I. -I../core -I../drivers -O0 -g -Wall all: $(PROGS) diff --git a/src/test/ao_fec_tx_test.c b/src/test/ao_fec_tx_test.c index d01eadc5..1b1fd56d 100644 --- a/src/test/ao_fec_tx_test.c +++ b/src/test/ao_fec_tx_test.c @@ -77,7 +77,6 @@ ao_encode(uint8_t *input, int input_len, uint8_t *output) { uint8_t prepare[PREPARE_LEN(input_len)]; uint8_t encode[ENCODE_LEN(input_len)]; - uint8_t interleave[INTERLEAVE_LEN(input_len)]; uint8_t prepare_len; uint8_t encode_len; uint8_t interleave_len; @@ -159,6 +158,7 @@ ao_decode(uint8_t *bytes, int bytes_len, uint8_t *bits) bits_len = ao_fec_decode(bytes, bytes_len, bits); ao_fec_dump_bytes(bits, bits_len, "Decode"); + return bits_len; } int @@ -182,9 +182,11 @@ main(int argc, char **argv) transmit_len = ao_radio(encode, encode_len, transmit); /* apply gaussian noise to test viterbi code against errors */ - receive_len = ao_fuzz(transmit, transmit_len, receive, 0x80); + receive_len = ao_fuzz(transmit, transmit_len, receive, 0x70); decode_len = ao_decode(receive, receive_len, decode); + + return decode_len >= sizeof(original); } -- cgit v1.2.3 From 566a0c277de01963922cabc80db8ec3a129923bd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Jun 2012 02:23:08 -0700 Subject: altos: fix comment about decoding last byte of FEC data There aren't *any* forward bits to use when decoding the last byte. Signed-off-by: Keith Packard --- src/core/ao_viterbi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index 1b1784b3..17464cd1 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -120,9 +120,9 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out) p = n; /* A loop is needed to handle the last output byte. It - * won't have a full NUM_HIST bits of future data to - * perform full error correction, but we might as well - * give the best possible answer anyways. + * won't have any bits of future data to perform full + * error correction, but we might as well give the + * best possible answer anyways. */ while ((b - o) >= (8 + NUM_HIST) || (i + 2 >= len && b > o)) { -- cgit v1.2.3 From 74f6a1a8c8fa9d5bb8d74c99782310b431dd4727 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Jun 2012 02:24:30 -0700 Subject: altos: Add ao_viterbi.c to megametrum build It's not used yet, just wanted to see how big the resulting object file was (492 bytes). Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 5c641e9a..857667b0 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -48,6 +48,7 @@ ALTOS_SRC = \ ao_spi_stm.c \ ao_cc1120.c \ ao_fec_tx.c \ + ao_viterbi.c \ ao_ms5607.c \ ao_adc_stm.c \ ao_beep_stm.c \ -- cgit v1.2.3 From b292c14790fc225029cba3f80ce8ad6c5652bc4e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 23 Jun 2012 16:05:42 -0700 Subject: altos: improve FEC apis to reduce data copying Integrate interleaving and whitening into encode and decode steps. Add CRC checking function for receive. Make ao_fec_test program round-trip the data and verify correctness. Signed-off-by: Keith Packard --- src/core/ao_fec.h | 26 ++++-- src/core/ao_fec_tx.c | 118 +++++++++++++++++---------- src/core/ao_viterbi.c | 46 ++++++++++- src/test/Makefile | 6 +- src/test/ao_fec_test.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++ src/test/ao_fec_tx_test.c | 192 -------------------------------------------- 6 files changed, 337 insertions(+), 249 deletions(-) create mode 100644 src/test/ao_fec_test.c delete mode 100644 src/test/ao_fec_tx_test.c (limited to 'src') diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index d4f64b74..f3f55fa8 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -24,12 +24,22 @@ #define AO_FEC_TRELLIS_TERMINATOR 0x0b #define AO_FEC_PREPARE_EXTRA 4 +extern const uint8_t ao_fec_whiten_table[]; + void -ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name); +ao_fec_dump_bytes(uint8_t *bytes, uint16_t len, char *name); uint16_t ao_fec_crc(uint8_t *bytes, uint8_t len); +/* + * 'len' is the length of the original data; 'bytes' + * must be four bytes longer than that, and the first + * two after 'len' must be the received crc + */ +uint8_t +ao_fec_check_crc(uint8_t *bytes, uint8_t len); + /* * Append CRC and terminator bytes, returns resulting length. * 'out' must be at least len + AO_FEC_PREPARE_EXTRA bytes long @@ -46,17 +56,11 @@ void ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out); /* - * Encode data. 'out' must be len*2 bytes long + * Encode and interleave data. 'out' must be len*2 bytes long */ uint8_t ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); -/* - * Interleave data. 'out' must be 'len' bytes long - */ -uint8_t -ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out); - /* * Decode data. 'in' is one byte per bit, soft decision * 'out' must be len/8 bytes long @@ -65,4 +69,10 @@ ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out); uint8_t ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out); +/* + * Interleave data packed in bytes. 'out' must be 'len' bytes long. + */ +uint16_t +ao_fec_interleave_bytes(uint8_t *in, uint16_t len, uint8_t *out); + #endif /* _AO_FEC_H_ */ diff --git a/src/core/ao_fec_tx.c b/src/core/ao_fec_tx.c index c5f410b8..c9c0a3d6 100644 --- a/src/core/ao_fec_tx.c +++ b/src/core/ao_fec_tx.c @@ -19,9 +19,9 @@ #include void -ao_fec_dump_bytes(uint8_t *bytes, uint8_t len, char *name) +ao_fec_dump_bytes(uint8_t *bytes, uint16_t len, char *name) { - uint8_t i; + uint16_t i; printf ("%s (%d):", name, len); for (i = 0; i < len; i++) { @@ -57,41 +57,76 @@ ao_fec_crc(uint8_t *bytes, uint8_t len) return crc; } +/* + * len is the length of the data; the crc will be + * the fist two bytes after that + */ + uint8_t -ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out) +ao_fec_check_crc(uint8_t *bytes, uint8_t len) +{ + uint16_t computed_crc = ao_fec_crc(bytes, len); + uint16_t received_crc = (bytes[len] << 8) | (bytes[len+1]); + + return computed_crc == received_crc; +} + +uint8_t +ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *extra) { uint16_t crc = ao_fec_crc (in, len); - uint8_t i; + uint8_t i = 0; uint8_t num_fec; - /* Copy data */ - for (i = 0; i < len; i++) - out[i] = in[i]; - /* Append CRC */ - out[i++] = crc >> 8; - out[i++] = crc; + extra[i++] = crc >> 8; + extra[i++] = crc; /* Append FEC -- 1 byte if odd, two bytes if even */ num_fec = 2 - (i & 1); while (num_fec--) - out[i++] = AO_FEC_TRELLIS_TERMINATOR; + extra[i++] = AO_FEC_TRELLIS_TERMINATOR; return i; } -static const uint8_t whiten[] = { +const uint8_t ao_fec_whiten_table[] = { #include "ao_whiten.h" }; +#if 0 void ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out) { - const uint8_t *w = whiten; + const uint8_t *w = ao_fec_whiten_table; while (len--) *out++ = *in++ ^ *w++; } +/* + * Unused as interleaving is now built in to ao_fec_encode + */ + +static void +ao_fec_interleave(uint8_t *d, uint8_t len) +{ + uint8_t i, j; + + for (i = 0; i < len; i += 4) { + uint32_t interleaved = 0; + + for (j = 0; j < 4 * 4; j++) { + interleaved <<= 2; + interleaved |= (d[i + (~j & 0x3)] >> (2 * ((j & 0xc) >> 2))) & 0x03; + } + d[i+0] = interleaved >> 24; + d[i+1] = interleaved >> 16; + d[i+2] = interleaved >> 8; + d[i+3] = interleaved; + } +} +#endif + static const uint8_t ao_fec_encode_table[16] = { /* next 0 1 state */ 0, 3, /* 000 */ @@ -107,38 +142,37 @@ static const uint8_t ao_fec_encode_table[16] = { uint8_t ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out) { - uint16_t fec = 0, output; - uint8_t byte, bit; - - for (byte = 0; byte < len; byte++) { - fec = (fec & 0x700) | in[byte]; - output = 0; - for (bit = 0; bit < 8; bit++) { - output = output << 2 | ao_fec_encode_table[fec >> 7]; - fec = (fec << 1) & 0x7ff; + uint8_t extra[AO_FEC_PREPARE_EXTRA]; + uint8_t extra_len; + uint32_t encode, interleave; + uint8_t pair, byte, bit; + uint16_t fec = 0; + const uint8_t *whiten = ao_fec_whiten_table; + + extra_len = ao_fec_prepare(in, len, extra); + for (pair = 0; pair < len + extra_len; pair += 2) { + encode = 0; + for (byte = 0; byte < 2; byte++) { + if (pair + byte == len) + in = extra; + fec |= *in++ ^ *whiten++; + for (bit = 0; bit < 8; bit++) { + encode = encode << 2 | ao_fec_encode_table[fec >> 7]; + fec = (fec << 1) & 0x7ff; + } } - out[byte * 2] = output >> 8; - out[byte * 2 + 1] = output; - } - return len * 2; -} -uint8_t -ao_fec_interleave(uint8_t *in, uint8_t len, uint8_t *out) -{ - uint8_t i, j; - - for (i = 0; i < len; i += 4) { - uint32_t interleaved = 0; + interleave = 0; + for (bit = 0; bit < 4 * 4; bit++) { + uint8_t byte_shift = (bit & 0x3) << 3; + uint8_t bit_shift = (bit & 0xc) >> 1; - for (j = 0; j < 4 * 4; j++) { - interleaved <<= 2; - interleaved |= (in[i + (~j & 0x3)] >> (2 * ((j & 0xc) >> 2))) & 0x03; + interleave = (interleave << 2) | ((encode >> (byte_shift + bit_shift)) & 0x3); } - out[i+0] = interleaved >> 24; - out[i+1] = interleaved >> 16; - out[i+2] = interleaved >> 8; - out[i+3] = interleaved; + *out++ = interleave >> 24; + *out++ = interleave >> 16; + *out++ = interleave >> 8; + *out++ = interleave >> 0; } - return len; + return (len + extra_len) * 2; } diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index 17464cd1..bb93bc83 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -18,6 +18,35 @@ #include #include +/* + * byte order repeats through 3 2 1 0 + * + * bit-pair order repeats through + * + * 1/0 3/2 5/4 7/6 + * + * So, the over all order is: + * + * 3,1/0 2,1/0 1,1/0 0,1/0 + * 3,3/2 2,3/2 1,3/2 0,3/2 + * 3,5/4 2,5/4 1,5/4 0,5/4 + * 3,7/6 2,7/6 1,7/6 0,7/6 + * + * The raw bit order is thus + * + * 1e/1f 16/17 0e/0f 06/07 + * 1c/1d 14/15 0c/0d 04/05 + * 1a/1b 12/13 0a/0b 02/03 + * 18/19 10/11 08/09 00/01 + */ + +static inline uint16_t ao_interleave_index(uint16_t i) { + uint8_t l = i & 0x1e; + uint16_t h = i & ~0x1e; + uint8_t o = 0x1e ^ (((l >> 2) & 0x6) | ((l << 2) & 0x18)); + return h | o; +} + struct ao_soft_sym { uint8_t a, b; }; @@ -70,6 +99,9 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out) uint8_t n; /* next cost/bits index */ uint8_t state; /* state index */ uint8_t bit; /* original encoded bit index */ + const uint8_t *whiten = ao_fec_whiten_table; + uint16_t interleave; /* input byte array index */ + struct ao_soft_sym s; /* input symbol pair */ p = 0; for (state = 0; state < NUM_STATE; state++) { @@ -82,7 +114,13 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out) for (i = 0; i < len; i += 2) { b = i/2; n = p ^ 1; - struct ao_soft_sym s = { .a = in[i], .b = in[i+1] }; + + /* Fetch one pair of input bytes, de-interleaving + * the input. + */ + interleave = ao_interleave_index(i); + s.a = in[interleave]; + s.b = in[interleave+1]; /* Reset next costs to 'impossibly high' values so that * the first path through this state is cheaper than this @@ -159,10 +197,10 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out) } #if 0 - printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x\n", - i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff); + printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x whiten %0x\n", + i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff, *whiten); #endif - out[o >> 3] = bits[p][min_state] >> dist; + *out++ = (bits[p][min_state] >> dist) ^ *whiten++; o += 8; } } diff --git a/src/test/Makefile b/src/test/Makefile index 7bcf24e1..cdcecd51 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -1,6 +1,6 @@ vpath % ..:../core:../drivers:../util -PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_gps_test ao_gps_test_skytraq ao_convert_test ao_convert_pa_test ao_fec_tx_test +PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noisy_accel ao_gps_test ao_gps_test_skytraq ao_convert_test ao_convert_pa_test ao_fec_test KALMAN=make-kalman @@ -40,5 +40,5 @@ ao_convert_pa_test: ao_convert_pa_test.c ao_convert_pa.c altitude-pa.h ao_kalman.h: $(KALMAN) (cd .. && make ao_kalman.h) -ao_fec_tx_test: ao_fec_tx_test.c ao_fec_tx.c ao_viterbi.c - cc $(CFLAGS) -o $@ ao_fec_tx_test.c ../core/ao_fec_tx.c ../core/ao_viterbi.c -lm +ao_fec_test: ao_fec_test.c ao_fec_tx.c ao_viterbi.c + cc $(CFLAGS) -o $@ ao_fec_test.c ../core/ao_fec_tx.c ../core/ao_viterbi.c -lm diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c new file mode 100644 index 00000000..c7509728 --- /dev/null +++ b/src/test/ao_fec_test.c @@ -0,0 +1,198 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include +#include +#include + +#ifndef RANDOM_MAX +#define RANDOM_MAX 0x7fffffff +#endif + +static double +rand_real(void) { + return (double) random() / (double) RANDOM_MAX; +} + +static double +gaussian_random(double mean, double dev) +{ + static int save_x_valid = 0; + static double save_x; + double x; + + if (save_x_valid) + { + x = save_x; + save_x_valid = 0; + } + else + { + double w; + double normal_x1, normal_x2; + + do { + normal_x1 = 2 * rand_real () - 1; + normal_x2 = 2 * rand_real () - 1; + w = normal_x1*normal_x1 + normal_x2*normal_x2; + } while (w >= 1 || w < 1E-30); + + w = sqrt(log(w)*(-2./w)); + + /* + * normal_x1 and normal_x2 are independent normally + * distributed variates + */ + + x = normal_x1 * w; + /* save normal_x2 for next call */ + save_x = normal_x2 * w; + save_x_valid = 1; + } + return x * dev + mean; +} + +#define PREPARE_LEN(input_len) ((input_len) + AO_FEC_PREPARE_EXTRA) +#define ENCODE_LEN(input_len) (PREPARE_LEN(input_len) * 2) +#define DECODE_LEN(input_len) ((input_len) + AO_FEC_PREPARE_EXTRA) +#define EXPAND_LEN(input_len) (ENCODE_LEN(input_len) * 8) + +static int +ao_expand(uint8_t *bits, int bits_len, uint8_t *bytes) +{ + int i, bit; + uint8_t b; + + for (i = 0; i < bits_len; i++) { + b = bits[i]; + for (bit = 7; bit >= 0; bit--) + *bytes++ = ((b >> bit) & 1) * 0xff; + } + + return bits_len * 8; +} + +static int +ao_fuzz (uint8_t *in, int in_len, uint8_t *out, double dev) +{ + int i; + int errors = 0; + + for (i = 0; i < in_len; i++) { + double error = gaussian_random(0, dev); + uint8_t byte = in[i]; + + if (error > 0) { + if (error > 0xff) + error = 0xff; + if (error >= 0x80) + errors++; + if (byte < 0x80) + byte += error; + else + byte -= error; + } + out[i] = byte; + } + return errors; +} + +static uint8_t +ao_random_data(uint8_t *out, uint8_t out_len) +{ + uint8_t len = random() % (out_len + 1); + uint8_t i; + + for (i = 0; i < len; i++) + out[i] = random(); + return len; +} + + +int +main(int argc, char **argv) +{ + int trial; + + uint8_t original[120]; + uint8_t original_len; + + uint8_t encode[ENCODE_LEN(sizeof(original))]; + int encode_len; + + uint8_t transmit[EXPAND_LEN(sizeof(original))]; + int transmit_len; + + uint8_t receive[EXPAND_LEN(sizeof(original))]; + int receive_len, receive_errors; + + uint8_t decode[DECODE_LEN(sizeof(original))]; + int decode_len; + + int errors = 0; + int error; + + srandom(0); + for (trial = 0; trial < 10000; trial++) { + + /* Compute some random data */ + original_len = ao_random_data(original, sizeof(original)); + + /* Encode it */ + encode_len = ao_fec_encode(original, original_len, encode); + + /* Expand from 1-bit-per-symbol to 1-byte-per-symbol */ + transmit_len = ao_expand(encode, encode_len, transmit); + + /* Add gaussian noise to the signal */ + receive_errors = ao_fuzz(transmit, transmit_len, receive, 0x30); + receive_len = transmit_len; + + /* Decode it */ + decode_len = ao_fec_decode(receive, receive_len, decode); + + /* Check to see if we received the right data */ + error = 0; + + if (decode_len < original_len + 2) { + printf ("len mis-match\n"); + error++; + } + + if (!ao_fec_check_crc(decode, original_len)) { + printf ("crc mis-match\n"); + error++; + } + + if (memcmp(original, decode, original_len) != 0) { + printf ("data mis-match\n"); + error++; + } + if (error) { + printf ("Errors: %d\n", receive_errors); + ao_fec_dump_bytes(original, original_len, "Input"); + ao_fec_dump_bytes(decode, original_len, "Decode"); + errors += error; + } + } + return errors; +} + + diff --git a/src/test/ao_fec_tx_test.c b/src/test/ao_fec_tx_test.c deleted file mode 100644 index 1b1fd56d..00000000 --- a/src/test/ao_fec_tx_test.c +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include -#include -#include -#include -#include - -#ifndef RANDOM_MAX -#define RANDOM_MAX 0x7fffffff -#endif - -static double -rand_real(void) { - return (double) random() / (double) RANDOM_MAX; -} - -static double -gaussian_random(double mean, double dev) -{ - static int save_x_valid = 0; - static double save_x; - double x; - - if (save_x_valid) - { - x = save_x; - save_x_valid = 0; - } - else - { - double w; - double normal_x1, normal_x2; - - do { - normal_x1 = 2 * rand_real () - 1; - normal_x2 = 2 * rand_real () - 1; - w = normal_x1*normal_x1 + normal_x2*normal_x2; - } while (w >= 1 || w < 1E-30); - - w = sqrt(log(w)*(-2./w)); - - /* - * normal_x1 and normal_x2 are independent normally - * distributed variates - */ - - x = normal_x1 * w; - /* save normal_x2 for next call */ - save_x = normal_x2 * w; - save_x_valid = 1; - } - return x * dev + mean; -} - -#define PREPARE_LEN(input_len) ((input_len) + AO_FEC_PREPARE_EXTRA) -#define ENCODE_LEN(input_len) (PREPARE_LEN(input_len) * 2) -#define INTERLEAVE_LEN(input_len) ENCODE_LEN(input_len) - -static int -ao_encode(uint8_t *input, int input_len, uint8_t *output) -{ - uint8_t prepare[PREPARE_LEN(input_len)]; - uint8_t encode[ENCODE_LEN(input_len)]; - uint8_t prepare_len; - uint8_t encode_len; - uint8_t interleave_len; - - ao_fec_dump_bytes(input, input_len, "Input"); - - prepare_len = ao_fec_prepare(input, input_len, prepare); - - ao_fec_dump_bytes(prepare, prepare_len, "Prepare"); - - encode_len = ao_fec_encode(prepare, prepare_len, encode); - - ao_fec_dump_bytes(encode, encode_len, "Encode"); - - interleave_len = ao_fec_interleave(encode, encode_len, output); - - ao_fec_dump_bytes(output, interleave_len, "Interleave"); - - return interleave_len; -} - -#define RADIO_LEN(input_len) (INTERLEAVE_LEN(input_len) * 8) - -static int -ao_radio(uint8_t *bits, int bits_len, uint8_t *bytes) -{ - uint8_t b, *bytes_orig = bytes; - uint8_t interleave[bits_len]; - int i, bit; - - ao_fec_interleave(bits, bits_len, interleave); - - ao_fec_dump_bytes(interleave, bits_len, "De-interleave"); - - for (i = 0; i < bits_len; i++) { - b = interleave[i]; - for (bit = 7; bit >= 0; bit--) - *bytes++ = ((b >> bit) & 1) * 0xff; - } - - ao_fec_dump_bytes(bytes_orig, bits_len * 8, "Bytes"); - - return bits_len * 8; -} - -static int -ao_fuzz (uint8_t *in, int in_len, uint8_t *out, double dev) -{ - int i; - int errors = 0; - - for (i = 0; i < in_len; i++) { - double error = gaussian_random(0, dev); - uint8_t byte = in[i]; - - if (error > 0) { - if (error > 0xff) - error = 0xff; - if (error >= 0x80) - errors++; - if (byte < 0x80) - byte += error; - else - byte -= error; - } - out[i] = byte; - } - - printf ("Introduced %d errors\n", errors); - ao_fec_dump_bytes(out, in_len, "Fuzz"); - return in_len; -} - -static int -ao_decode(uint8_t *bytes, int bytes_len, uint8_t *bits) -{ - int bits_len; - - bits_len = ao_fec_decode(bytes, bytes_len, bits); - - ao_fec_dump_bytes(bits, bits_len, "Decode"); - return bits_len; -} - -int -main(int argc, char **argv) -{ - uint8_t original[4] = { 3, 1, 2, 3 }; - uint8_t encode[INTERLEAVE_LEN(sizeof(original))]; - int encode_len; - - uint8_t transmit[RADIO_LEN(sizeof(original))]; - int transmit_len; - - uint8_t receive[RADIO_LEN(sizeof(original))]; - int receive_len; - - uint8_t decode[INTERLEAVE_LEN(sizeof(original))]; - int decode_len; - - encode_len = ao_encode(original, sizeof(original), encode); - - transmit_len = ao_radio(encode, encode_len, transmit); - - /* apply gaussian noise to test viterbi code against errors */ - receive_len = ao_fuzz(transmit, transmit_len, receive, 0x70); - - decode_len = ao_decode(receive, receive_len, decode); - - return decode_len >= sizeof(original); -} - - -- cgit v1.2.3 From 246174b32bb6cf827d240c32d6a51c3513a08c37 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Jun 2012 05:03:16 -0700 Subject: altos: Forgot ao_telemetry.h Not much builds without this... Signed-off-by: Keith Packard --- src/core/ao_telemetry.h | 250 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 src/core/ao_telemetry.h (limited to 'src') diff --git a/src/core/ao_telemetry.h b/src/core/ao_telemetry.h new file mode 100644 index 00000000..32a1668c --- /dev/null +++ b/src/core/ao_telemetry.h @@ -0,0 +1,250 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_TELEMETRY_H_ +#define _AO_TELEMETRY_H_ + +/* + * ao_telemetry.c + */ +#define AO_MAX_CALLSIGN 8 +#define AO_MAX_VERSION 8 +#if LEGACY_MONITOR +#define AO_MAX_TELEMETRY 128 +#else +#define AO_MAX_TELEMETRY 32 +#endif + +struct ao_telemetry_generic { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t payload[27]; /* 5 */ + /* 32 */ +}; + +#define AO_TELEMETRY_SENSOR_TELEMETRUM 0x01 +#define AO_TELEMETRY_SENSOR_TELEMINI 0x02 +#define AO_TELEMETRY_SENSOR_TELENANO 0x03 + +struct ao_telemetry_sensor { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t state; /* 5 flight state */ + int16_t accel; /* 6 accelerometer (TM only) */ + int16_t pres; /* 8 pressure sensor */ + int16_t temp; /* 10 temperature sensor */ + int16_t v_batt; /* 12 battery voltage */ + int16_t sense_d; /* 14 drogue continuity sense (TM/Tm) */ + int16_t sense_m; /* 16 main continuity sense (TM/Tm) */ + + int16_t acceleration; /* 18 m/s² * 16 */ + int16_t speed; /* 20 m/s * 16 */ + int16_t height; /* 22 m */ + + int16_t ground_pres; /* 24 average pres on pad */ + int16_t ground_accel; /* 26 average accel on pad */ + int16_t accel_plus_g; /* 28 accel calibration at +1g */ + int16_t accel_minus_g; /* 30 accel calibration at -1g */ + /* 32 */ +}; + +#define AO_TELEMETRY_CONFIGURATION 0x04 + +struct ao_telemetry_configuration { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t device; /* 5 device type */ + uint16_t flight; /* 6 flight number */ + uint8_t config_major; /* 8 Config major version */ + uint8_t config_minor; /* 9 Config minor version */ + uint16_t apogee_delay; /* 10 Apogee deploy delay in seconds */ + uint16_t main_deploy; /* 12 Main deploy alt in meters */ + uint16_t flight_log_max; /* 14 Maximum flight log size in kB */ + char callsign[AO_MAX_CALLSIGN]; /* 16 Radio operator identity */ + char version[AO_MAX_VERSION]; /* 24 Software version */ + /* 32 */ +}; + +#define AO_TELEMETRY_LOCATION 0x05 + +#define AO_GPS_MODE_NOT_VALID 'N' +#define AO_GPS_MODE_AUTONOMOUS 'A' +#define AO_GPS_MODE_DIFFERENTIAL 'D' +#define AO_GPS_MODE_ESTIMATED 'E' +#define AO_GPS_MODE_MANUAL 'M' +#define AO_GPS_MODE_SIMULATED 'S' + +struct ao_telemetry_location { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t flags; /* 5 Number of sats and other flags */ + int16_t altitude; /* 6 GPS reported altitude (m) */ + int32_t latitude; /* 8 latitude (degrees * 10⁷) */ + int32_t longitude; /* 12 longitude (degrees * 10⁷) */ + uint8_t year; /* 16 (- 2000) */ + uint8_t month; /* 17 (1-12) */ + uint8_t day; /* 18 (1-31) */ + uint8_t hour; /* 19 (0-23) */ + uint8_t minute; /* 20 (0-59) */ + uint8_t second; /* 21 (0-59) */ + uint8_t pdop; /* 22 (m * 5) */ + uint8_t hdop; /* 23 (m * 5) */ + uint8_t vdop; /* 24 (m * 5) */ + uint8_t mode; /* 25 */ + uint16_t ground_speed; /* 26 cm/s */ + int16_t climb_rate; /* 28 cm/s */ + uint8_t course; /* 30 degrees / 2 */ + uint8_t unused[1]; /* 31 */ + /* 32 */ +}; + +#define AO_TELEMETRY_SATELLITE 0x06 + +struct ao_telemetry_satellite_info { + uint8_t svid; + uint8_t c_n_1; +}; + +struct ao_telemetry_satellite { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t channels; /* 5 number of reported sats */ + + struct ao_telemetry_satellite_info sats[12]; /* 6 */ + uint8_t unused[2]; /* 30 */ + /* 32 */ +}; + +#define AO_TELEMETRY_COMPANION 0x07 + +#define AO_COMPANION_MAX_CHANNELS 12 + +struct ao_telemetry_companion { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t board_id; /* 5 */ + + uint8_t update_period; /* 6 */ + uint8_t channels; /* 7 */ + uint16_t companion_data[AO_COMPANION_MAX_CHANNELS]; /* 8 */ + /* 32 */ +}; + +#define AO_TELEMETRY_MEGA_SENSOR 0x08 + +struct ao_telemetry_mega_sensor { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t pad5; /* 5 */ + int16_t accel; /* 6 Z axis */ + + int32_t pres; /* 8 Pa * 10 */ + int16_t temp; /* 12 °C * 100 */ + + int16_t accel_x; /* 14 */ + int16_t accel_y; /* 16 */ + int16_t accel_z; /* 18 */ + + int16_t gyro_x; /* 20 */ + int16_t gyro_y; /* 22 */ + int16_t gyro_z; /* 24 */ + + int16_t mag_x; /* 26 */ + int16_t mag_y; /* 28 */ + int16_t mag_z; /* 30 */ + /* 32 */ +}; + +#define AO_TELEMETRY_MEGA_DATA 0x09 + +struct ao_telemetry_mega_data { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + + uint8_t state; /* 5 flight state */ + + int16_t v_batt; /* 6 battery voltage */ + int16_t v_pyro; /* 8 pyro battery voltage */ + int8_t sense[6]; /* 10 continuity sense */ + + int32_t ground_pres; /* 16 average pres on pad */ + int16_t ground_accel; /* 20 average accel on pad */ + int16_t accel_plus_g; /* 22 accel calibration at +1g */ + int16_t accel_minus_g; /* 24 accel calibration at -1g */ + + int16_t acceleration; /* 26 m/s² * 16 */ + int16_t speed; /* 28 m/s * 16 */ + int16_t height; /* 30 m */ + /* 32 */ +}; + + +/* #define AO_SEND_ALL_BARO */ + +#define AO_TELEMETRY_BARO 0x80 + +/* + * This packet allows the full sampling rate baro + * data to be captured over the RF link so that the + * flight software can be tested using 'real' data. + * + * Along with this telemetry packet, the flight + * code is modified to send full-rate telemetry all the time + * and never send an RDF tone; this ensure that the full radio + * link is available. + */ +struct ao_telemetry_baro { + uint16_t serial; /* 0 */ + uint16_t tick; /* 2 */ + uint8_t type; /* 4 */ + uint8_t samples; /* 5 number samples */ + + int16_t baro[12]; /* 6 samples */ + /* 32 */ +}; + +union ao_telemetry_all { + struct ao_telemetry_generic generic; + struct ao_telemetry_sensor sensor; + struct ao_telemetry_configuration configuration; + struct ao_telemetry_location location; + struct ao_telemetry_satellite satellite; + struct ao_telemetry_companion companion; + struct ao_telemetry_mega_sensor mega_sensor; + struct ao_telemetry_mega_data mega_data; + struct ao_telemetry_baro baro; +}; + +struct ao_telemetry_all_recv { + union ao_telemetry_all telemetry; + int8_t rssi; + uint8_t status; +}; + +#endif /* _AO_TELEMETRY_H_ */ -- cgit v1.2.3 From 70cf32e89df19bde5185339fc703532c8a5b8be6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Jun 2012 05:03:34 -0700 Subject: altos: Get cc1120 packet reception working Interrupt-per-bit, but it seems to work Signed-off-by: Keith Packard --- src/core/ao_viterbi.c | 19 ++-- src/drivers/ao_cc1120.c | 169 ++++++++++++++++++++++++++---------- src/megametrum-v0.1/ao_megametrum.c | 6 +- src/megametrum-v0.1/ao_pins.h | 2 +- src/stm/ao_exti.h | 3 + src/stm/ao_exti_stm.c | 5 ++ src/test/ao_fec_test.c | 151 ++++++++++++++++++++++++++++++++ 7 files changed, 299 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index bb93bc83..594c0d91 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -55,16 +55,19 @@ struct ao_soft_sym { #define NUM_HIST 8 #define MOD_HIST(b) ((b) & 7) +#define V_0 0xc0 +#define V_1 0x40 + static const struct ao_soft_sym ao_fec_decode_table[NUM_STATE][2] = { /* next 0 1 state */ - { { 0x00, 0x00 }, { 0xff, 0xff } } , /* 000 */ - { { 0x00, 0xff }, { 0xff, 0x00 } }, /* 001 */ - { { 0xff, 0xff }, { 0x00, 0x00 } }, /* 010 */ - { { 0xff, 0x00 }, { 0x00, 0xff } }, /* 011 */ - { { 0xff, 0xff }, { 0x00, 0x00 } }, /* 100 */ - { { 0xff, 0x00 }, { 0x00, 0xff } }, /* 101 */ - { { 0x00, 0x00 }, { 0xff, 0xff } }, /* 110 */ - { { 0x00, 0xff }, { 0xff, 0x00 } } /* 111 */ + { { V_0, V_0 }, { V_1, V_1 } } , /* 000 */ + { { V_0, V_1 }, { V_1, V_0 } }, /* 001 */ + { { V_1, V_1 }, { V_0, V_0 } }, /* 010 */ + { { V_1, V_0 }, { V_0, V_1 } }, /* 011 */ + { { V_1, V_1 }, { V_0, V_0 } }, /* 100 */ + { { V_1, V_0 }, { V_0, V_1 } }, /* 101 */ + { { V_0, V_0 }, { V_1, V_1 } }, /* 110 */ + { { V_0, V_1 }, { V_1, V_0 } } /* 111 */ }; static inline uint8_t diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 67a36c5c..4378716d 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -19,6 +19,7 @@ #include #include #include +#include uint8_t ao_radio_wake; uint8_t ao_radio_mutex; @@ -102,6 +103,35 @@ ao_radio_reg_write(uint16_t addr, uint8_t value) ao_radio_deselect(); } +static void +ao_radio_burst_read_start (uint16_t addr) +{ + uint8_t data[2]; + uint8_t d; + + if (CC1120_IS_EXTENDED(addr)) { + data[0] = ((1 << CC1120_READ) | + (1 << CC1120_BURST) | + CC1120_EXTENDED); + data[1] = addr; + d = 2; + } else { + data[0] = ((1 << CC1120_READ) | + (1 << CC1120_BURST) | + addr); + d = 1; + } + ao_radio_select(); + ao_radio_spi_send(data, d); +} + +static void +ao_radio_burst_read_stop (void) +{ + ao_radio_deselect(); +} + + static uint8_t ao_radio_strobe(uint8_t addr) { @@ -247,10 +277,19 @@ ao_radio_rx_done(void) return ao_radio_marc_status() == CC1120_MARC_STATUS1_RX_FINISHED; } +static void +ao_radio_tx_isr(void) +{ + ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_wake = 1; + ao_wakeup(&ao_radio_wake); +} + static void ao_radio_start_tx(void) { ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); + ao_exti_set_callback(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_tx_isr); ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); ao_radio_strobe(CC1120_STX); } @@ -336,29 +375,13 @@ void ao_radio_send(void *d, uint8_t size) { uint8_t marc_status; - uint8_t prepare[size + AO_FEC_PREPARE_EXTRA]; - uint8_t prepare_len; - uint8_t encode[sizeof(prepare) * 2]; + uint8_t encode[size + AO_FEC_PREPARE_EXTRA]; uint8_t encode_len; - uint8_t interleave[sizeof(encode)]; - uint8_t interleave_len; - fec_dump_bytes(d, size, "Input"); + encode_len = ao_fec_encode(d, size, encode); - prepare_len = ao_fec_prepare(d, size, prepare); - fec_dump_bytes(prepare, prepare_len, "Prepare"); - - ao_fec_whiten(prepare, prepare_len, prepare); - fec_dump_bytes(prepare, prepare_len, "Whiten"); - - encode_len = ao_fec_encode(prepare, prepare_len, encode); - fec_dump_bytes(encode, encode_len, "Encode"); - - interleave_len = ao_fec_interleave(encode, encode_len, interleave); - fec_dump_bytes(interleave, interleave_len, "Interleave"); - - ao_radio_get(interleave_len); - ao_radio_fifo_write(interleave, interleave_len); + ao_radio_get(encode_len); + ao_radio_fifo_write(encode, encode_len); ao_radio_wake = 0; @@ -373,34 +396,92 @@ ao_radio_send(void *d, uint8_t size) ao_radio_put(); } +#define AO_RADIO_MAX_RECV 90 + +static uint8_t rx_data[2048]; +static uint16_t rx_data_count; +static uint16_t rx_data_cur; +static uint8_t rx_started; + +static void +ao_radio_rx_isr(void) +{ + if (rx_started) { + rx_data[rx_data_cur++] = stm_spi2.dr; + if (rx_data_cur >= rx_data_count) { + ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_wake = 1; + ao_wakeup(&ao_radio_wake); + } + } else { + (void) stm_spi2.dr; + rx_started = 1; + } + stm_spi2.dr = 0x00; +} + uint8_t ao_radio_recv(__xdata void *d, uint8_t size) { - uint8_t marc_status = CC1120_MARC_STATUS1_NO_FAILURE; + uint8_t len = ((size - 2) + 4) * 2; /* two bytes for status */ + uint16_t i; + + rx_data_count = sizeof (rx_data); + rx_data_cur = 0; + rx_started = 0; + + printf ("len %d rx_data_count %d\n", len, rx_data_count); /* configure interrupt pin */ - ao_radio_get(size); + ao_radio_get(len); ao_radio_wake = 0; + ao_radio_abort = 0; + + ao_radio_reg_write(CC1120_PKT_CFG2, + (CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | + (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)); + + ao_radio_reg_write(CC1120_EXT_CTRL, 0); + + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT); + + stm_spi2.cr2 = 0; + + /* clear any RXNE */ + (void) stm_spi2.dr; + + ao_exti_set_callback(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr); ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_strobe(CC1120_SRX); - cli(); - for (;;) { - if (ao_radio_abort) - break; - if (ao_radio_wake) { - marc_status = ao_radio_marc_status(); - if (marc_status != CC1120_MARC_STATUS1_NO_FAILURE) - break; - ao_radio_wake = 0; - } + ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT); +#if 1 + cli(); + while (!ao_radio_wake && !ao_radio_abort) ao_sleep(&ao_radio_wake); - } sei(); - if (marc_status != CC1120_MARC_STATUS1_RX_FINISHED) - ao_radio_fifo_read(d, size); + +#else + printf ("Hit a character to stop..."); flush(); + getchar(); + putchar('\n'); + ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); +#endif + ao_radio_burst_read_stop(); + + ao_radio_strobe(CC1120_SIDLE); + ao_radio_put(); - return marc_status == CC1120_MARC_STATUS1_RX_FINISHED; + + printf ("Received data:"); + for (i = 0; i < rx_data_cur; i++) { + if ((i & 15) == 0) + printf ("\n"); + printf (" %02x", rx_data[i]); + } + printf ("\n"); + return 1; } /* @@ -477,13 +558,6 @@ static const uint16_t radio_setup[] = { static uint8_t ao_radio_configured = 0; -static void -ao_radio_isr(void) -{ - ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - ao_radio_wake = 1; - ao_wakeup(&ao_radio_wake); -} static void ao_radio_setup(void) @@ -745,6 +819,12 @@ static void ao_radio_packet(void) { ao_radio_send(packet, sizeof (packet)); } +void +ao_radio_test_recv() +{ + ao_radio_recv(0, 34); +} + #endif static const struct ao_cmds ao_radio_cmds[] = { @@ -753,6 +833,7 @@ static const struct ao_cmds ao_radio_cmds[] = { { ao_radio_show, "R\0Show CC1120 status" }, { ao_radio_beep, "b\0Emit an RDF beacon" }, { ao_radio_packet, "p\0Send a test packet" }, + { ao_radio_test_recv, "q\0Recv a test packet" }, #endif { 0, NULL } }; @@ -776,7 +857,7 @@ ao_radio_init(void) /* Enable the EXTI interrupt for the appropriate pin */ ao_enable_port(AO_CC1120_INT_PORT); - ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_isr); + ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_tx_isr); ao_cmd_register(&ao_radio_cmds[0]); } diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index dc9c0d19..a2ac186b 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -44,9 +44,9 @@ main(void) ao_i2c_init(); ao_hmc5883_init(); ao_mpu6000_init(); - ao_flight_init(); - ao_log_init(); - ao_report_init(); +// ao_flight_init(); +// ao_log_init(); +// ao_report_init(); ao_telemetry_init(); ao_config_init(); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 5c5c5972..9d9113c8 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -255,7 +255,7 @@ struct ao_adc { #define AO_MPU6000_INT_PIN 13 #define AO_MPU6000_I2C_INDEX STM_I2C_INDEX(1) -#define HAS_HIGHG_ACCEL 1 +#define HAS_HIGHG_ACCEL 0 #define NUM_CMDS 16 diff --git a/src/stm/ao_exti.h b/src/stm/ao_exti.h index 43eaa52f..87a072e7 100644 --- a/src/stm/ao_exti.h +++ b/src/stm/ao_exti.h @@ -26,6 +26,9 @@ void ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)()); +void +ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)()); + void ao_exti_enable(struct stm_gpio *gpio, uint8_t pin); diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c index 0fa24188..683a91b3 100644 --- a/src/stm/ao_exti_stm.c +++ b/src/stm/ao_exti_stm.c @@ -94,6 +94,11 @@ ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback stm_nvic_set_enable(irq); } +void +ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)()) { + ao_exti_callback[pin] = callback; +} + void ao_exti_enable(struct stm_gpio *gpio, uint8_t pin) { uint32_t mask = (1 << pin); diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c index c7509728..98067486 100644 --- a/src/test/ao_fec_test.c +++ b/src/test/ao_fec_test.c @@ -126,6 +126,156 @@ ao_random_data(uint8_t *out, uint8_t out_len) } +static uint8_t real_packet[] = { + 0x00, 0x40, 0x38, 0xcd, 0x38, 0x3d, 0x34, 0xca, 0x31, 0xc3, 0xc1, 0xc6, 0x35, 0xcc, 0x3a, 0x3c, + 0x3c, 0x3d, 0x3c, 0x37, 0xc5, 0xc1, 0xc0, 0xc1, 0xc1, 0xc3, 0xc0, 0xc1, 0xc6, 0x38, 0x3b, 0xc6, + 0xc0, 0xc6, 0x32, 0xc9, 0xc9, 0x34, 0xcf, 0x35, 0xcf, 0x3a, 0x3b, 0xc6, 0xc7, 0x35, 0xcf, 0x36, + 0xce, 0x37, 0xc8, 0xc8, 0x3a, 0x3c, 0xc9, 0xc8, 0x3a, 0x3c, 0xcc, 0x32, 0xcd, 0x32, 0xce, 0x32, + 0xc9, 0xc6, 0x37, 0x3e, 0x3d, 0xc8, 0xc3, 0xc6, 0x38, 0x3d, 0xcf, 0x34, 0x3d, 0x3b, 0xcb, 0x31, + 0xca, 0x35, 0x38, 0xcb, 0x31, 0xcc, 0x31, 0x3b, 0xc7, 0xbf, 0xbe, 0xbe, 0xc3, 0x35, 0x38, 0xcb, + 0x2f, 0xc9, 0xc2, 0x34, 0x3c, 0xcc, 0x31, 0xca, 0xc1, 0xc0, 0xc3, 0x33, 0x3f, 0x3f, 0x3e, 0x3c, + 0xcc, 0x31, 0xcc, 0xc3, 0xc4, 0x32, 0xd1, 0x34, 0x3f, 0x3c, 0xcc, 0x31, 0xcc, 0xc3, 0x33, 0xd0, + 0x31, 0xd1, 0x35, 0x3f, 0x3e, 0x3c, 0xca, 0xc5, 0x34, 0xcc, 0xc2, 0xc3, 0xc3, 0xc5, 0x36, 0x40, + 0x3e, 0x41, 0x3e, 0x41, 0x3e, 0x3f, 0x41, 0x40, 0xce, 0xc5, 0x33, 0xcf, 0xc7, 0x36, 0xd2, 0x32, + 0xd1, 0xc5, 0xc6, 0x35, 0xd4, 0x32, 0xd1, 0xc6, 0x34, 0x41, 0xd2, 0x30, 0xd0, 0xc2, 0xc2, 0xc5, + 0x31, 0xd3, 0x31, 0xd1, 0xc7, 0x33, 0xd4, 0xc6, 0x34, 0x42, 0x40, 0x40, 0x40, 0x41, 0x41, 0xd2, + 0xc4, 0xc4, 0x39, 0x3e, 0xce, 0x35, 0x3c, 0xcd, 0x31, 0x3d, 0xc8, 0xc3, 0x32, 0x3d, 0xcc, 0x2f, + 0xce, 0x30, 0xd0, 0x2e, 0xcf, 0x30, 0x3d, 0x3c, 0x3c, 0x3a, 0xcb, 0xbf, 0xbf, 0xc1, 0x31, 0x3d, + 0x3d, 0x3c, 0x3c, 0x3c, 0x3d, 0x3b, 0xcf, 0x2e, 0xd2, 0x2e, 0xd0, 0x2c, 0x3b, 0xd1, 0x2a, 0xcf, + 0xbe, 0xc0, 0xc0, 0xbf, 0xc1, 0xc1, 0x2c, 0x3f, 0xd0, 0xc0, 0x2e, 0xd0, 0x31, 0xd2, 0xc2, 0x2f, + 0x3e, 0x3e, 0x3d, 0xcf, 0x31, 0xcb, 0xc3, 0x32, 0xd1, 0xc4, 0x37, 0x3f, 0xce, 0xc4, 0x35, 0xd0, + 0x33, 0x3f, 0xce, 0x31, 0x3c, 0x3b, 0xcc, 0x31, 0xcd, 0x2f, 0xd1, 0x32, 0x3a, 0x3b, 0xcb, 0xc1, + 0xc0, 0x32, 0x3e, 0x3e, 0x3c, 0x3d, 0x3d, 0xce, 0x2d, 0xcd, 0xc3, 0xc2, 0x30, 0x3d, 0xcf, 0xc1, + 0xc2, 0x30, 0xd0, 0xc4, 0x31, 0xd4, 0x30, 0x40, 0x3e, 0xd0, 0x2f, 0xd0, 0x2f, 0xd1, 0xc2, 0x2e, + 0xd4, 0x2e, 0x3f, 0xce, 0xc2, 0x34, 0x3e, 0x3f, 0xd0, 0x30, 0xcf, 0x31, 0x3d, 0x3d, 0xcc, 0x2d, + 0xcf, 0x2f, 0xcf, 0x2e, 0x3b, 0xcf, 0x2c, 0x3b, 0x3b, 0x3a, 0x3d, 0x38, 0xcc, 0x2d, 0x3b, 0xcc, + 0xbe, 0x2d, 0xd1, 0x2c, 0x3c, 0x3d, 0xce, 0xc0, 0x2d, 0xd1, 0x2f, 0x3f, 0x3f, 0x3c, 0x3f, 0x3e, + 0x3e, 0x3c, 0xd3, 0x2a, 0xd1, 0xc2, 0x2e, 0x3c, 0xd1, 0x2f, 0x3d, 0xd1, 0xbe, 0xc1, 0x2d, 0xd2, + 0x2d, 0x3d, 0x3d, 0x3b, 0xcd, 0x31, 0xcc, 0x31, 0xce, 0x2e, 0x3d, 0x3e, 0x3a, 0xcd, 0x2d, 0xcc, + 0xc1, 0xc1, 0xc3, 0x2e, 0x3f, 0x3f, 0x3c, 0xcf, 0xc0, 0x31, 0xd1, 0xc2, 0xc3, 0x33, 0xd2, 0xc7, + 0x32, 0x40, 0xd3, 0xc4, 0xc4, 0x33, 0x40, 0x40, 0xd2, 0x2f, 0xd0, 0x2f, 0x3c, 0xd1, 0x2c, 0x3a, + 0x3d, 0xd0, 0x2a, 0xd0, 0x28, 0xcf, 0xc3, 0x2c, 0xd2, 0x2d, 0xd3, 0xc3, 0xc3, 0x2e, 0x3e, 0x41, + 0xd2, 0xc3, 0xc2, 0xc2, 0xc2, 0xc2, 0xc4, 0x32, 0xd2, 0x34, 0x3e, 0x3e, 0x3c, 0xd1, 0x30, 0x3d, + 0x3c, 0xce, 0x2e, 0x3b, 0x38, 0xcb, 0xbe, 0xc1, 0x2e, 0x3e, 0x3c, 0x3d, 0xd1, 0x2c, 0x3b, 0x3b, + 0xcd, 0xbf, 0x2d, 0xd0, 0x2f, 0xd0, 0x2d, 0xd1, 0x2d, 0x3d, 0xd0, 0x2b, 0x3b, 0xcf, 0x2b, 0x3a, + 0xcc, 0xbc, 0xc1, 0x2a, 0x3c, 0xce, 0x28, 0xd1, 0x2a, 0x3c, 0x3a, 0xcf, 0xbf, 0x2b, 0x3e, 0x3c, + 0xd2, 0x2b, 0x3d, 0x3a, 0x3a, 0xcf, 0x2c, 0xcc, 0xbe, 0xc1, 0xc0, 0xbf, 0xc1, 0x31, 0x3c, 0xce, + 0xc0, 0xc1, 0xc0, 0xc1, 0x31, 0x3c, 0xd1, 0xc2, 0x2e, 0xd1, 0xc3, 0xc4, 0x30, 0x3f, 0xd3, 0x2c, + 0xd3, 0xc2, 0x30, 0xd5, 0xc3, 0xc5, 0x30, 0xd5, 0xc4, 0xc5, 0xc5, 0x31, 0x41, 0xd4, 0xc4, 0x31, + 0x40, 0xd4, 0x2d, 0xd5, 0xc0, 0xc3, 0x2c, 0x3f, 0x3e, 0x3f, 0x3f, 0x3f, 0xd6, 0x2c, 0x3e, 0xd2, + 0x27, 0x37, 0xde, 0xc9, 0xe9, 0x2e, 0xc7, 0x3c, 0xd9, 0x07, 0xf3, 0x28, 0x8d, 0xa5, 0xc9, 0xca, + 0xe7, 0xcb, 0xfc, 0xb3, 0x3c, 0xd4, 0xd3, 0x9a, 0xe7, 0x2c, 0xc8, 0xf8, 0x44, 0xb3, 0xb0, 0xfa, + 0x1c, 0xbf, 0xc9, 0xff, 0xbb, 0x1d, 0x02, 0xdb, 0x45, 0xc1, 0x40, 0x1c, 0xec, 0x48, 0xda, 0x21, + 0x4c, 0xe3, 0x38, 0xdf, 0x34, 0xd8, 0x35, 0xd8, 0x31, 0xd7, 0x30, 0xd4, 0x2f, 0xd6, 0x2d, 0xd5, + 0x2b, 0xd5, 0x33, 0xce, 0x33, 0xce, 0x33, 0xd0, 0x34, 0xcf, 0x31, 0xcf, 0x30, 0xce, 0x30, 0xcf, + 0x30, 0x3d, 0xce, 0x2f, 0xcf, 0xc2, 0x30, 0x3f, 0x3d, 0xcf, 0xc1, 0x31, 0xd0, 0xc5, 0xc4, 0x33, + 0x41, 0x3e, 0xd1, 0x30, 0x3c, 0x3d, 0xce, 0x2f, 0xce, 0xc1, 0xc3, 0x2e, 0xd3, 0x30, 0x3e, 0x3e, + 0x3c, 0x3f, 0x3c, 0xd1, 0xc0, 0xc0, 0xc0, 0xc1, 0xc2, 0xc0, 0xc1, 0xc3, 0x2c, 0x3f, 0xd2, 0xbe, + 0xc1, 0x2e, 0xcf, 0xc4, 0x33, 0xd3, 0x34, 0xd0, 0x33, 0x3d, 0xcf, 0xc3, 0x32, 0xce, 0x33, 0xd2, + 0x32, 0xce, 0xc5, 0x34, 0x40, 0xce, 0xc5, 0x32, 0x3e, 0xd0, 0x31, 0xd0, 0x2f, 0xd2, 0x30, 0xce, + 0xc2, 0x33, 0x40, 0x3e, 0xd0, 0xc3, 0xc2, 0x2e, 0xd3, 0x31, 0xd0, 0xc7, 0x32, 0x40, 0x3e, 0xd3, + 0x2f, 0xd3, 0x2e, 0xd0, 0x2d, 0xd3, 0x2d, 0xd3, 0x2f, 0x3c, 0x3d, 0xd1, 0x2a, 0x3b, 0xd1, 0x28, + 0x3b, 0x3b, 0xc8, 0x31, 0x39, 0x3b, 0x38, 0xc6, 0xbf, 0x31, 0x3d, 0x3a, 0xca, 0xc0, 0x33, 0x3c, + 0xca, 0xc0, 0xc1, 0xc1, 0xc2, 0x35, 0x3e, 0x3c, 0x3d, 0x3f, 0xcc, 0xc0, 0xc3, 0x31, 0xce, 0xc5, + 0x33, 0xd0, 0xc4, 0x35, 0xd3, 0x33, 0xd3, 0x32, 0xd1, 0xc4, 0xc3, 0x35, 0xd3, 0xc6, 0xc4, 0x35, + 0xd2, 0xc6, 0x35, 0x41, 0x41, 0xd4, 0x33, 0xd1, 0xc4, 0x30, 0x41, 0xd2, 0x30, 0x3e, 0xce, 0xc1, + 0xc3, 0xc0, 0x31, 0xce, 0xc5, 0x34, 0x40, 0x3d, 0xd1, 0xc4, 0x32, 0x3e, 0xcf, 0xc2, 0xc3, 0x30, + 0xd4, 0x32, 0x3e, 0x3f, 0x3e, 0x3f, 0x3e, 0xd0, 0xc2, 0x31, 0x3e, 0x3f, 0x3f, 0xd1, 0xc2, 0x2f, + 0xd5, 0x2e, 0xd3, 0xc3, 0x2f, 0xd7, 0x30, 0x3e, 0xd2, 0x2c, 0x3e, 0x3c, 0xd0, 0xc1, 0xc1, 0xc3, + 0xc0, 0xc3, 0x2c, 0xd4, 0xc2, 0x2e, 0x40, 0xd2, 0xc3, 0x2d, 0xd5, 0xc3, 0x2f, 0x42, 0x40, 0xd6, + 0x2d, 0xd4, 0xc2, 0xc2, 0xc2, 0x32, 0xd4, 0xc3, 0xc5, 0xc4, 0x32, 0x40, 0xd3, 0x30, 0xd0, 0xc3, + 0xc4, 0x30, 0xd3, 0xc5, 0xc5, 0xc4, 0xc4, 0x33, 0x40, 0x40, 0xd4, 0x2f, 0xd2, 0x2d, 0x3d, 0xd1, + 0xc1, 0xc2, 0x2c, 0xd4, 0x2e, 0xd4, 0x2d, 0x3d, 0xd3, 0xc1, 0xc1, 0xc1, 0x2d, 0xd5, 0xc2, 0xc2, + 0xc2, 0x2d, 0xd9, 0xc4, 0xc5, 0x2f, 0x43, 0x40, 0xd6, 0xd7, 0xd7, 0x2b, 0x3e, 0xd5, 0x29, 0x3d, + 0xd4, 0x24, 0x3b, 0x3a, 0x3b, 0xce, 0x2a, 0x3a, 0xcc, 0xbe, 0x2d, 0x3b, 0x3b, 0x3d, 0x3b, 0x3b, + 0xce, 0x2b, 0x3a, 0xcc, 0x2b, 0xd0, 0x2b, 0x3b, 0x3b, 0x39, 0xcf, 0xbf, 0x2a, 0xd1, 0xc0, 0x2f, + 0x3e, 0xd0, 0x2d, 0x3a, 0xd1, 0xbe, 0x2b, 0xd2, 0xc3, 0xc2, 0xc0, 0x2d, 0xd7, 0x2c, 0xd7, 0xc2, + 0xc3, 0x2f, 0x43, 0x41, 0x40, 0xd4, 0xc3, 0xc3, 0xc3, 0xc2, 0x2c, 0x40, 0xd7, 0x2a, 0x3d, 0xd3, + 0x26, 0xd5, 0x2f, 0x3a, 0x3c, 0xca, 0xc3, 0x2c, 0xd3, 0x2e, 0x3c, 0x3d, 0x3d, 0x3d, 0xd0, 0xc2, + 0x2e, 0xd3, 0x2e, 0xd1, 0xc5, 0x2e, 0x3f, 0xd3, 0x2e, 0x3c, 0xd1, 0xc0, 0xc2, 0x2a, 0xd2, 0xc2, + 0xc4, 0x2e, 0xd7, 0x2e, 0x3e, 0xd3, 0xc1, 0xc3, 0xc1, 0x2d, 0x3f, 0xd3, 0xc2, 0x2c, 0x3f, 0xd3, + 0x2b, 0x3b, 0xd1, 0xbf, 0xc1, 0xbe, 0x29, 0x3f, 0xd4, 0x29, 0xd5, 0xbf, 0x29, 0xd7, 0xc0, 0x2d, + 0xd8, 0xc2, 0x33, 0x41, 0xd3, 0x30, 0x3d, 0xd0, 0x2c, 0xcf, 0xc1, 0xc1, 0xc2, 0x2e, 0x3f, 0xd3, + 0x2b, 0xcf, 0xc3, 0x2f, 0x40, 0x3f, 0x3e, 0xd3, 0x2a, 0x3d, 0x3d, 0xce, 0xc1, 0x2b, 0x3d, 0xd0, + 0x2b, 0xd3, 0x2b, 0x3b, 0x3d, 0xce, 0x29, 0x3b, 0x3b, 0x3b, 0xd1, 0xbe, 0x2b, 0xd2, 0x29, 0x3d, + 0x3a, 0xd3, 0x29, 0x3a, 0x3b, 0x3b, 0xd2, 0x26, 0x3b, 0xd0, 0xbf, 0xbe, 0xbc, 0xbf, 0xbe, 0xbc, + 0x27, 0x3d, 0x3a, 0x3c, 0xce, 0xc1, 0x2c, 0xd2, 0xc2, 0xc2, 0x2f, 0x40, 0xd2, 0xc2, 0xc2, 0x2e, + 0x40, 0xd4, 0x2a, 0x3b, 0xcf, 0x2b, 0xd2, 0x2a, 0x3c, 0xd0, 0xc1, 0x2a, 0x3d, 0xd0, 0xc1, 0xc0, + 0xbe, 0x2b, 0x3f, 0x3e, 0xd2, 0xc1, 0xc0, 0xc1, 0xc0, 0xc2, 0x2a, 0xd6, 0xc2, 0xc3, 0xc3, 0xc3, + 0x2c, 0x3e, 0x41, 0xd6, 0xc0, 0xc3, 0xc2, 0xc2, 0x2a, 0xd9, 0x28, 0x3f, 0xd5, 0xc1, 0xc2, 0xc0, + 0xc3, 0x28, 0xd5, 0xc2, 0xc5, 0x30, 0xd6, 0xc4, 0xc5, 0xc5, 0x31, 0x43, 0xd4, 0xc3, 0xc5, 0xc2, + 0xc2, 0x2f, 0xd6, 0xc5, 0xc2, 0x2d, 0x41, 0x41, 0x43, 0x40, 0x41, 0xd8, 0x2a, 0x3f, 0x3f, 0x3e, + 0x2c, 0x0a, 0x0d, 0x2a, 0xbb, 0x91, 0x5e, 0x2a, 0xca, 0x23, 0xf0, 0x0f, 0xbe, 0xd6, 0xfb, 0xc0, + 0x2c, 0x34, 0x7f, 0xd1, 0xc9, 0xc1, 0x1c, 0x06, 0x97, 0x1f, 0x21, 0xa8, 0x04, 0x5d, 0x07, 0xb0, + 0x49, 0xaf, 0x10, 0x60, 0xd1, 0xf1, 0xf3, 0xcb, 0x72, 0x16, 0x24, 0xe9, 0xd4, 0x28, 0xb2, 0x8c, + 0xf3, 0x3b, 0xe8, 0x06, 0xeb, 0x09, 0xec, 0x0a, 0xec, 0x0b, 0xee, 0x0b, 0xee, 0x0b, 0xf0, 0x0b, + 0xf0, 0x0a, 0xf3, 0x0b, 0xf2, 0x0a, 0xf5, 0x08, 0xf5, 0x0a, 0xf4, 0x08, 0xf5, 0x08, 0xf5, 0x09, + 0xf4, 0x07, 0x3f, 0xf5, 0x05, 0xf6, 0xbf, 0x06, 0x3f, 0x3f, 0xf8, 0xbe, 0x07, 0xf8, 0xc3, 0xc3, + 0x06, 0x41, 0x40, 0xf0, 0x0f, 0x3c, 0x3d, 0xef, 0x0e, 0xee, 0xbe, 0xbf, 0x11, 0xf2, 0x0e, 0x3e, + 0x3c, 0x3f, 0x3e, 0x3e, 0xf0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc3, 0xc0, 0xc1, 0xc1, 0x0b, 0x3f, 0xf5, + 0xc0, 0xc0, 0x08, 0xf7, 0xc2, 0x0c, 0xf6, 0x0d, 0xf9, 0x0a, 0x3f, 0xf9, 0xc0, 0x0b, 0xf6, 0x06, + 0xf8, 0x06, 0xf9, 0xc3, 0x08, 0x40, 0xfa, 0xc2, 0x09, 0x3e, 0xf7, 0x05, 0xf6, 0x04, 0xf7, 0x05, + 0xf8, 0xc1, 0xc3, 0xc1, 0x0a, 0x3e, 0x41, 0xf6, 0x07, 0xf7, 0x08, 0xf6, 0x07, 0x3e, 0x3c, 0x3f, + 0xf4, 0xbf, 0xbe, 0x06, 0xf8, 0x07, 0xf8, 0x05, 0xfb, 0xc0, 0xc1, 0x02, 0x40, 0x40, 0x3e, 0xfb, + 0x02, 0x3e, 0x3e, 0xf6, 0x01, 0xf9, 0x00, 0x3f, 0xf8, 0xbd, 0x02, 0xfc, 0xc1, 0xc0, 0x03, 0xfe, + 0xc5, 0xc4, 0xc2, 0xc5, 0xc2, 0x02, 0x41, 0x40, 0x40, 0x41, 0x40, 0xff, 0xff, 0x40, 0xfd, 0xfd, + 0xfc, 0xfd, 0x3e, 0xfc, 0xbe, 0xbf, 0xfe, 0xfc, 0xc1, 0xc0, 0xc1, 0xc1, 0x00, 0x01, 0x01, 0x02, + 0xc0, 0x00, 0x02, 0xc3, 0xc5, 0x02, 0x07, 0xc4, 0xc6, 0xc4, 0x02, 0x06, 0xc3, 0x01, 0x43, 0x43, + 0x42, 0x05, 0xfc, 0x04, 0xfd, 0x41, 0x3e, 0x05, 0xbf, 0xfb, 0x41, 0x3e, 0x3e, 0x3f, 0x3f, 0x40, + 0x02, 0xf9, 0x3e, 0x03, 0xbf, 0xbe, 0xf6, 0x3f, 0x05, 0xf6, 0x3c, 0x05, 0xbd, 0xbf, 0xbe, 0xf2, + 0x3f, 0x3c, 0x3d, 0x3e, 0x08, 0xee, 0x3d, 0x3b, 0x07, 0xbd, 0xf3, 0x0e, 0xc0, 0xc0, 0xf2, 0x0f, + 0xf2, 0x40, 0x0d, 0xef, 0x3f, 0x3e, 0x0a, 0xbf, 0xf0, 0x0e, 0xf1, 0x40, 0x0a, 0xef, 0x0e, 0xc1, + 0xc0, 0xc1, 0xc2, 0xc0, 0xee, 0x13, 0xc1, 0xee, 0x43, 0x10, 0xea, 0x15, 0xc0, 0xc0, 0xc0, 0xc3, + 0xc0, 0xec, 0x15, 0xc2, 0xf0, 0x16, 0xc2, 0xef, 0x1b, 0xc2, 0xf1, 0x44, 0x42, 0x19, 0xc2, 0xc3, + 0xed, 0x17, 0xe7, 0x21, 0xe4, 0x40, 0x3f, 0x20, 0xc0, 0xe2, 0x40, 0x3e, 0x1d, 0xc1, 0xc2, 0xc0, + 0xe2, 0x20, 0xe2, 0x3f, 0x3f, 0x3e, 0x1c, 0xdf, 0x3c, 0x3f, 0x1e, 0xbf, 0xc1, 0xbe, 0xdf, 0x3e, + 0x3d, 0x1f, 0xdc, 0x3c, 0x3b, 0x3d, 0x3a, 0x3d, 0x1f, 0xdb, 0x1e, 0xda, 0x20, 0xda, 0x21, 0xc1, + 0xc0, 0xc1, 0xdc, 0x3e, 0x23, 0xda, 0x3e, 0x20, 0xbf, 0xbd, 0xdb, 0x23, 0xbf, 0xdf, 0x26, 0xdc, + 0x26, 0xdc, 0x2e, 0xc2, 0xc3, 0xc3, 0xd4, 0x40, 0x2f, 0xc2, 0xd2, 0x3f, 0x3f, 0x3f, 0x2e, 0xd1, + 0x2d, 0xd3, 0x2c, 0xc3, 0xc3, 0xc3, 0xc2, 0xc3, 0xc2, 0xd3, 0x3e, 0x31, 0xd0, 0x2d, 0xc3, 0xc0, + 0xc1, 0xd1, 0x2f, 0xd3, 0x3f, 0x3f, 0x31, 0xc1, 0xcf, 0x31, 0xd2, 0x3e, 0x3f, 0x3c, 0x41, 0x3e, + 0x3e, 0x3f, 0x31, 0xd1, 0x30, 0xc0, 0xcf, 0x33, 0xd1, 0x3d, 0x41, 0x32, 0xc0, 0xc3, 0xce, 0x3e, + 0x32, 0xc3, 0xc3, 0xc2, 0xc0, 0xc3, 0xca, 0x3c, 0x37, 0xc5, 0xc3, 0xca, 0x34, 0xcf, 0x35, 0xc6, + 0xca, 0x3c, 0x39, 0xce, 0x3c, 0x37, 0xc2, 0xc8, 0x3c, 0x36, 0xcc, 0x30, 0xcb, 0x33, 0xc6, 0xc3, + 0xc8, 0x34, 0xcc, 0x3d, 0x37, 0xc5, 0xc9, 0x38, 0xc6, 0xca, 0x3b, 0x40, 0x40, 0x40, 0x3a, 0xc5, + 0xc8, 0x3f, 0x3e, 0x3b, 0xce, 0x3a, 0x3e, 0x38, 0xca, 0x39, 0x3c, 0x3c, 0x36, 0xcb, 0x36, 0x3b, + 0x37, 0xc8, 0x35, 0x3a, 0x36, 0xc8, 0x2f, 0xc4, 0xc5, 0x36, 0x38, 0xc7, 0xc0, 0xc7, 0x33, 0xc8, + 0xc3, 0xc5, 0x39, 0x3b, 0xc9, 0xc7, 0x34, 0xd1, 0x34, 0xcf, 0x35, 0xca, 0xc9, 0x36, 0xd0, 0x36, + 0xcc, 0xc7, 0x39, 0x41, 0x42, 0x42, 0x3e, 0xca, 0xc1, 0xc3, 0xc3, 0xc2, 0xc3, 0xc2, 0xc4, 0xc6, + 0x34, 0xd1, 0x35, 0xcf, 0x37, 0x3c, 0xce, 0x35, 0x3b, 0xcc, 0x30, 0xca, 0x33, 0x39, 0xc9, 0xbf, + 0xbf, 0xbf, 0xc3, 0x34, 0x3c, 0x3f, 0x3a, 0xcc, 0x2f, 0xcd, 0x32, 0x3c, 0x3a, 0xc8, 0xc2, 0x34, + 0x3a, 0xcb, 0xc0, 0xc0, 0x35, 0x3c, 0xce, 0x32, 0x3c, 0x3c, 0x3d, 0x3a, 0xcd, 0x2e, 0x3b, 0x39, + 0xc9, 0xbc, 0xbf, 0x30, 0xcc, 0xc0, 0xc3, 0x33, 0xce, 0xc5, 0xc2, 0xc4, 0x36, 0x3e, 0xd1, 0xc3, + 0xc2, 0xc3, 0xc5, 0x33, 0xd0, 0xc5, 0xc4, 0x35, 0x40, 0x40, 0x3e, 0x41, 0x3e, 0xd2, 0x30, 0x3f, + 0x3e, 0x3d, 0x21, 0xc8, 0x0d, 0x23, 0xec, 0xb1, 0x1a, 0xf0, 0xf3, 0x10, 0xc6, 0xbd, 0x5b, 0x0d, + 0xff, 0xe2, 0xe6, 0xd4, 0x72, 0xe2, 0xda, 0x0c, 0xf8, 0x1b, 0x04, 0x0b, 0xf7, 0xb4, 0xf0, 0x44, + 0xcd, 0xaf, 0x12, 0x1f, 0x11, 0xa1, 0x29, 0xb8, 0x1a, 0xdb, 0x09, 0x69, 0xf7, 0x20, 0xc4, 0x1c, + 0xc0, 0xc8, 0x1d, 0x45, 0xd9, 0x30, 0xd8, 0x2e, 0xd8, 0x2e, 0xd6, 0x2c, 0xd5, 0x2d, 0xd4, 0x2b, + 0xd5, 0x2b, 0xd1, 0x31, 0xd0, 0x32, 0xd2, 0x30, 0xd0, 0x31, 0xd0, 0x31, 0xce, 0x2f, 0xd3, 0x2e, + 0xce, 0x2f, 0xd1, 0x31, 0x3c, 0xd1, 0x2d, 0xd0, 0xc0, 0x2e, 0x3c, 0x3d, 0xd1, 0xc3, 0x2c, 0xd2, + 0xc3, 0xc5, 0x31, 0x40, 0x40, 0xd5, 0x2c, 0x3a, 0x3d, 0xd0, 0x2b, 0xd3, 0xc0, 0xc0, 0x2d, 0xd4, + 0x2c, 0x3f, 0x3e, 0x3c, 0x3f, 0x3c, 0xd2, 0xc1, 0xc2, 0xc0, 0xc1, 0xc1, 0xc1, 0xc1, 0xc1, 0x2a, +}; + + +void +ao_real_packet(void) +{ + uint8_t decode[64]; + uint8_t decode_len; + int off; + + for (off = 0; off < sizeof (real_packet) - 576; off++) { + decode_len = ao_fec_decode(real_packet+off, 576, decode); + + if (ao_fec_check_crc(decode, 32)) { + printf ("match at %d\n", off); + + ao_fec_dump_bytes(decode, decode_len, "Decode"); + } + } +} + int main(int argc, char **argv) { @@ -149,6 +299,7 @@ main(int argc, char **argv) int errors = 0; int error; + ao_real_packet(); exit(0); srandom(0); for (trial = 0; trial < 10000; trial++) { -- cgit v1.2.3 From 628076aa90e7bc9a894646e417dd8e1fe149b60d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Jun 2012 06:38:34 -0700 Subject: altos: decode cc1120 received packets Call the fec decode function, compute RSSI and check CRC Signed-off-by: Keith Packard --- src/core/ao_fec.h | 2 +- src/core/ao_viterbi.c | 7 +++++-- src/drivers/ao_cc1120.c | 47 ++++++++++++++++++++++++++--------------------- 3 files changed, 32 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index f3f55fa8..e3c55d6e 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -67,7 +67,7 @@ ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); */ uint8_t -ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out); +ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len); /* * Interleave data packed in bytes. 'out' must be 'len' bytes long. diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index 594c0d91..77681556 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -91,7 +91,7 @@ ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) */ uint8_t -ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out) +ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len) { static uint16_t cost[2][NUM_STATE]; /* path cost */ static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */ @@ -203,7 +203,10 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out) printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x whiten %0x\n", i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff, *whiten); #endif - *out++ = (bits[p][min_state] >> dist) ^ *whiten++; + if (out_len) { + *out++ = (bits[p][min_state] >> dist) ^ *whiten++; + --out_len; + } o += 8; } } diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 4378716d..b42ca54c 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -401,12 +401,12 @@ ao_radio_send(void *d, uint8_t size) static uint8_t rx_data[2048]; static uint16_t rx_data_count; static uint16_t rx_data_cur; -static uint8_t rx_started; +static uint8_t rx_ignore; static void ao_radio_rx_isr(void) { - if (rx_started) { + if (rx_ignore == 0) { rx_data[rx_data_cur++] = stm_spi2.dr; if (rx_data_cur >= rx_data_count) { ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); @@ -415,7 +415,7 @@ ao_radio_rx_isr(void) } } else { (void) stm_spi2.dr; - rx_started = 1; + --rx_ignore; } stm_spi2.dr = 0x00; } @@ -423,12 +423,17 @@ ao_radio_rx_isr(void) uint8_t ao_radio_recv(__xdata void *d, uint8_t size) { - uint8_t len = ((size - 2) + 4) * 2; /* two bytes for status */ + uint8_t len; uint16_t i; + uint8_t rssi; - rx_data_count = sizeof (rx_data); + size -= 2; /* status bytes */ + len = size + 2; /* CRC bytes */ + len += 1 + ~(len & 1); /* 1 or two pad bytes */ + len *= 2; /* 1/2 rate convolution */ + rx_data_count = len * 8; /* bytes to bits */ rx_data_cur = 0; - rx_started = 0; + rx_ignore = 2; printf ("len %d rx_data_count %d\n", len, rx_data_count); @@ -456,31 +461,31 @@ ao_radio_recv(__xdata void *d, uint8_t size) ao_radio_strobe(CC1120_SRX); ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT); -#if 1 cli(); while (!ao_radio_wake && !ao_radio_abort) ao_sleep(&ao_radio_wake); sei(); - -#else - printf ("Hit a character to stop..."); flush(); - getchar(); - putchar('\n'); - ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); -#endif ao_radio_burst_read_stop(); + /* Convert from 'real' rssi to cc1111-style values */ + + rssi = (((int8_t) ao_radio_reg_read(CC1120_RSSI1)) + 74) * 2; + ao_radio_strobe(CC1120_SIDLE); ao_radio_put(); - printf ("Received data:"); - for (i = 0; i < rx_data_cur; i++) { - if ((i & 15) == 0) - printf ("\n"); - printf (" %02x", rx_data[i]); - } - printf ("\n"); + /* Construct final packet */ + + ao_fec_decode(rx_data, rx_data_cur, d, size + 2); + + if (ao_fec_check_crc(d, size)) + ((uint8_t *) d)[size + 1] = 0x80; + else + ((uint8_t *) d)[size + 1] = 0x00; + + ((uint8_t *) d)[size] = (uint8_t) rssi; + return 1; } -- cgit v1.2.3 From 09761fe0f6ed40ff74317fbb47d6a74068fb4ce4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 Jun 2012 06:51:36 -0700 Subject: altos: Incremental viterbi decode Decode radio input one interleave block at a time. This overlaps the decode computation with the packet reception, leading to lower latency in an attempt to keep up with the transmitter. Signed-off-by: Keith Packard --- src/core/ao_fec.h | 4 +++- src/core/ao_viterbi.c | 14 +++++++++++++- src/drivers/ao_cc1120.c | 28 +++++++++++++++++++++------- src/test/ao_fec_test.c | 4 ++-- 4 files changed, 39 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index e3c55d6e..4fd398eb 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -66,8 +66,10 @@ ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); * 'out' must be len/8 bytes long */ +#define AO_FEC_DECODE_BLOCK (8 * 32) /* callback must return multiples of this many bits */ + uint8_t -ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len); +ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()); /* * Interleave data packed in bytes. 'out' must be 'len' bytes long. diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c index 77681556..69e9c1f5 100644 --- a/src/core/ao_viterbi.c +++ b/src/core/ao_viterbi.c @@ -91,7 +91,7 @@ ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) */ uint8_t -ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len) +ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()) { static uint16_t cost[2][NUM_STATE]; /* path cost */ static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */ @@ -105,6 +105,7 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len) const uint8_t *whiten = ao_fec_whiten_table; uint16_t interleave; /* input byte array index */ struct ao_soft_sym s; /* input symbol pair */ + uint16_t avail; p = 0; for (state = 0; state < NUM_STATE; state++) { @@ -113,11 +114,22 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len) } cost[0][0] = 0; + if (callback) + avail = 0; + else + avail = len; + o = 0; for (i = 0; i < len; i += 2) { b = i/2; n = p ^ 1; + if (!avail) { + avail = callback(); + if (!avail) + break; + } + /* Fetch one pair of input bytes, de-interleaving * the input. */ diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index b42ca54c..394cf7c5 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -400,6 +400,7 @@ ao_radio_send(void *d, uint8_t size) static uint8_t rx_data[2048]; static uint16_t rx_data_count; +static uint16_t rx_data_consumed; static uint16_t rx_data_cur; static uint8_t rx_ignore; @@ -408,9 +409,9 @@ ao_radio_rx_isr(void) { if (rx_ignore == 0) { rx_data[rx_data_cur++] = stm_spi2.dr; - if (rx_data_cur >= rx_data_count) { + if (rx_data_cur >= rx_data_count) ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - ao_radio_wake = 1; + if (rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) { ao_wakeup(&ao_radio_wake); } } else { @@ -420,6 +421,19 @@ ao_radio_rx_isr(void) stm_spi2.dr = 0x00; } +static uint16_t +ao_radio_rx_wait(void) +{ + cli(); + while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK && + !ao_radio_abort) + ao_sleep(&ao_radio_wake); + sei(); + if (ao_radio_abort) + return 0; + return AO_FEC_DECODE_BLOCK; +} + uint8_t ao_radio_recv(__xdata void *d, uint8_t size) { @@ -433,6 +447,7 @@ ao_radio_recv(__xdata void *d, uint8_t size) len *= 2; /* 1/2 rate convolution */ rx_data_count = len * 8; /* bytes to bits */ rx_data_cur = 0; + rx_data_consumed = 0; rx_ignore = 2; printf ("len %d rx_data_count %d\n", len, rx_data_count); @@ -461,10 +476,9 @@ ao_radio_recv(__xdata void *d, uint8_t size) ao_radio_strobe(CC1120_SRX); ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT); - cli(); - while (!ao_radio_wake && !ao_radio_abort) - ao_sleep(&ao_radio_wake); - sei(); + + ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait); + ao_radio_burst_read_stop(); /* Convert from 'real' rssi to cc1111-style values */ @@ -477,7 +491,7 @@ ao_radio_recv(__xdata void *d, uint8_t size) /* Construct final packet */ - ao_fec_decode(rx_data, rx_data_cur, d, size + 2); + ao_fec_decode(rx_data, rx_data_cur, d, size + 2, 0); if (ao_fec_check_crc(d, size)) ((uint8_t *) d)[size + 1] = 0x80; diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c index 98067486..e8d3d8b1 100644 --- a/src/test/ao_fec_test.c +++ b/src/test/ao_fec_test.c @@ -266,7 +266,7 @@ ao_real_packet(void) int off; for (off = 0; off < sizeof (real_packet) - 576; off++) { - decode_len = ao_fec_decode(real_packet+off, 576, decode); + decode_len = ao_fec_decode(real_packet+off, 576, decode, 34, NULL); if (ao_fec_check_crc(decode, 32)) { printf ("match at %d\n", off); @@ -317,7 +317,7 @@ main(int argc, char **argv) receive_len = transmit_len; /* Decode it */ - decode_len = ao_fec_decode(receive, receive_len, decode); + decode_len = ao_fec_decode(receive, receive_len, decode, original_len + 2, NULL); /* Check to see if we received the right data */ error = 0; -- cgit v1.2.3 From eab18714ed9eabbcef0ff81b07427da042a58ccc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 22:16:44 -0700 Subject: altos: rename ao_viterbi.c to ao_fec_rx.c Keep it parallel with ao_fec_tx.c Signed-off-by: Keith Packard --- src/core/ao_fec_rx.c | 226 +++++++++++++++++++++++++++++++++++++++++++ src/core/ao_viterbi.c | 226 ------------------------------------------- src/megametrum-v0.1/Makefile | 2 +- src/test/Makefile | 4 +- 4 files changed, 229 insertions(+), 229 deletions(-) create mode 100644 src/core/ao_fec_rx.c delete mode 100644 src/core/ao_viterbi.c (limited to 'src') diff --git a/src/core/ao_fec_rx.c b/src/core/ao_fec_rx.c new file mode 100644 index 00000000..69e9c1f5 --- /dev/null +++ b/src/core/ao_fec_rx.c @@ -0,0 +1,226 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +/* + * byte order repeats through 3 2 1 0 + * + * bit-pair order repeats through + * + * 1/0 3/2 5/4 7/6 + * + * So, the over all order is: + * + * 3,1/0 2,1/0 1,1/0 0,1/0 + * 3,3/2 2,3/2 1,3/2 0,3/2 + * 3,5/4 2,5/4 1,5/4 0,5/4 + * 3,7/6 2,7/6 1,7/6 0,7/6 + * + * The raw bit order is thus + * + * 1e/1f 16/17 0e/0f 06/07 + * 1c/1d 14/15 0c/0d 04/05 + * 1a/1b 12/13 0a/0b 02/03 + * 18/19 10/11 08/09 00/01 + */ + +static inline uint16_t ao_interleave_index(uint16_t i) { + uint8_t l = i & 0x1e; + uint16_t h = i & ~0x1e; + uint8_t o = 0x1e ^ (((l >> 2) & 0x6) | ((l << 2) & 0x18)); + return h | o; +} + +struct ao_soft_sym { + uint8_t a, b; +}; + +#define NUM_STATE 8 +#define NUM_HIST 8 +#define MOD_HIST(b) ((b) & 7) + +#define V_0 0xc0 +#define V_1 0x40 + +static const struct ao_soft_sym ao_fec_decode_table[NUM_STATE][2] = { +/* next 0 1 state */ + { { V_0, V_0 }, { V_1, V_1 } } , /* 000 */ + { { V_0, V_1 }, { V_1, V_0 } }, /* 001 */ + { { V_1, V_1 }, { V_0, V_0 } }, /* 010 */ + { { V_1, V_0 }, { V_0, V_1 } }, /* 011 */ + { { V_1, V_1 }, { V_0, V_0 } }, /* 100 */ + { { V_1, V_0 }, { V_0, V_1 } }, /* 101 */ + { { V_0, V_0 }, { V_1, V_1 } }, /* 110 */ + { { V_0, V_1 }, { V_1, V_0 } } /* 111 */ +}; + +static inline uint8_t +ao_next_state(uint8_t state, uint8_t bit) +{ + return ((state << 1) | bit) & 0x7; +} + +static inline uint16_t ao_abs(int16_t x) { return x < 0 ? -x : x; } + +static inline uint16_t +ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) +{ + return ao_abs(a.a - b.a) + ao_abs(a.b - b.b); +} + +/* + * 'in' is 8-bits per symbol soft decision data + * 'len' is input byte length. 'out' must be + * 'len'/16 bytes long + */ + +uint8_t +ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()) +{ + static uint16_t cost[2][NUM_STATE]; /* path cost */ + static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */ + uint16_t i; /* input byte index */ + uint16_t b; /* encoded symbol index (bytes/2) */ + uint16_t o; /* output bit index */ + uint8_t p; /* previous cost/bits index */ + uint8_t n; /* next cost/bits index */ + uint8_t state; /* state index */ + uint8_t bit; /* original encoded bit index */ + const uint8_t *whiten = ao_fec_whiten_table; + uint16_t interleave; /* input byte array index */ + struct ao_soft_sym s; /* input symbol pair */ + uint16_t avail; + + p = 0; + for (state = 0; state < NUM_STATE; state++) { + cost[0][state] = 0xffff; + bits[0][state] = 0; + } + cost[0][0] = 0; + + if (callback) + avail = 0; + else + avail = len; + + o = 0; + for (i = 0; i < len; i += 2) { + b = i/2; + n = p ^ 1; + + if (!avail) { + avail = callback(); + if (!avail) + break; + } + + /* Fetch one pair of input bytes, de-interleaving + * the input. + */ + interleave = ao_interleave_index(i); + s.a = in[interleave]; + s.b = in[interleave+1]; + + /* Reset next costs to 'impossibly high' values so that + * the first path through this state is cheaper than this + */ + for (state = 0; state < NUM_STATE; state++) + cost[n][state] = 0xffff; + + /* Compute path costs and accumulate output bit path + * for each state and encoded bit value + */ + for (state = 0; state < NUM_STATE; state++) { + for (bit = 0; bit < 2; bit++) { + int bit_cost = cost[p][state] + ao_cost(s, ao_fec_decode_table[state][bit]); + uint8_t bit_state = ao_next_state(state, bit); + + /* Only track the minimal cost to reach + * this state; the best path can never + * go through the higher cost paths as + * total path cost is cumulative + */ + if (bit_cost < cost[n][bit_state]) { + cost[n][bit_state] = bit_cost; + bits[n][bit_state] = (bits[p][state] << 1) | (state & 1); + } + } + } + +#if 0 + printf ("bit %3d symbol %2x %2x:", i/2, s.a, s.b); + for (state = 0; state < NUM_STATE; state++) { + printf (" %5d(%04x)", cost[n][state], bits[n][state]); + } + printf ("\n"); +#endif + p = n; + + /* A loop is needed to handle the last output byte. It + * won't have any bits of future data to perform full + * error correction, but we might as well give the + * best possible answer anyways. + */ + while ((b - o) >= (8 + NUM_HIST) || (i + 2 >= len && b > o)) { + + /* Compute number of bits to the end of the + * last full byte of data. This is generally + * NUM_HIST, unless we've reached + * the end of the input, in which case + * it will be seven. + */ + int8_t dist = b - (o + 8); /* distance to last ready-for-writing bit */ + uint16_t min_cost; /* lowest cost */ + uint8_t min_state; /* lowest cost state */ + + /* Find the best fit at the current point + * of the decode. + */ + min_cost = cost[p][0]; + min_state = 0; + for (state = 1; state < NUM_STATE; state++) { + if (cost[p][state] < min_cost) { + min_cost = cost[p][state]; + min_state = state; + } + } + + /* The very last byte of data has the very last bit + * of data left in the state value; just smash the + * bits value in place and reset the 'dist' from + * -1 to 0 so that the full byte is read out + */ + if (dist < 0) { + bits[p][min_state] = (bits[p][min_state] << 1) | (min_state & 1); + dist = 0; + } + +#if 0 + printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x whiten %0x\n", + i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff, *whiten); +#endif + if (out_len) { + *out++ = (bits[p][min_state] >> dist) ^ *whiten++; + --out_len; + } + o += 8; + } + } + return len/16; +} diff --git a/src/core/ao_viterbi.c b/src/core/ao_viterbi.c deleted file mode 100644 index 69e9c1f5..00000000 --- a/src/core/ao_viterbi.c +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include -#include - -/* - * byte order repeats through 3 2 1 0 - * - * bit-pair order repeats through - * - * 1/0 3/2 5/4 7/6 - * - * So, the over all order is: - * - * 3,1/0 2,1/0 1,1/0 0,1/0 - * 3,3/2 2,3/2 1,3/2 0,3/2 - * 3,5/4 2,5/4 1,5/4 0,5/4 - * 3,7/6 2,7/6 1,7/6 0,7/6 - * - * The raw bit order is thus - * - * 1e/1f 16/17 0e/0f 06/07 - * 1c/1d 14/15 0c/0d 04/05 - * 1a/1b 12/13 0a/0b 02/03 - * 18/19 10/11 08/09 00/01 - */ - -static inline uint16_t ao_interleave_index(uint16_t i) { - uint8_t l = i & 0x1e; - uint16_t h = i & ~0x1e; - uint8_t o = 0x1e ^ (((l >> 2) & 0x6) | ((l << 2) & 0x18)); - return h | o; -} - -struct ao_soft_sym { - uint8_t a, b; -}; - -#define NUM_STATE 8 -#define NUM_HIST 8 -#define MOD_HIST(b) ((b) & 7) - -#define V_0 0xc0 -#define V_1 0x40 - -static const struct ao_soft_sym ao_fec_decode_table[NUM_STATE][2] = { -/* next 0 1 state */ - { { V_0, V_0 }, { V_1, V_1 } } , /* 000 */ - { { V_0, V_1 }, { V_1, V_0 } }, /* 001 */ - { { V_1, V_1 }, { V_0, V_0 } }, /* 010 */ - { { V_1, V_0 }, { V_0, V_1 } }, /* 011 */ - { { V_1, V_1 }, { V_0, V_0 } }, /* 100 */ - { { V_1, V_0 }, { V_0, V_1 } }, /* 101 */ - { { V_0, V_0 }, { V_1, V_1 } }, /* 110 */ - { { V_0, V_1 }, { V_1, V_0 } } /* 111 */ -}; - -static inline uint8_t -ao_next_state(uint8_t state, uint8_t bit) -{ - return ((state << 1) | bit) & 0x7; -} - -static inline uint16_t ao_abs(int16_t x) { return x < 0 ? -x : x; } - -static inline uint16_t -ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) -{ - return ao_abs(a.a - b.a) + ao_abs(a.b - b.b); -} - -/* - * 'in' is 8-bits per symbol soft decision data - * 'len' is input byte length. 'out' must be - * 'len'/16 bytes long - */ - -uint8_t -ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()) -{ - static uint16_t cost[2][NUM_STATE]; /* path cost */ - static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */ - uint16_t i; /* input byte index */ - uint16_t b; /* encoded symbol index (bytes/2) */ - uint16_t o; /* output bit index */ - uint8_t p; /* previous cost/bits index */ - uint8_t n; /* next cost/bits index */ - uint8_t state; /* state index */ - uint8_t bit; /* original encoded bit index */ - const uint8_t *whiten = ao_fec_whiten_table; - uint16_t interleave; /* input byte array index */ - struct ao_soft_sym s; /* input symbol pair */ - uint16_t avail; - - p = 0; - for (state = 0; state < NUM_STATE; state++) { - cost[0][state] = 0xffff; - bits[0][state] = 0; - } - cost[0][0] = 0; - - if (callback) - avail = 0; - else - avail = len; - - o = 0; - for (i = 0; i < len; i += 2) { - b = i/2; - n = p ^ 1; - - if (!avail) { - avail = callback(); - if (!avail) - break; - } - - /* Fetch one pair of input bytes, de-interleaving - * the input. - */ - interleave = ao_interleave_index(i); - s.a = in[interleave]; - s.b = in[interleave+1]; - - /* Reset next costs to 'impossibly high' values so that - * the first path through this state is cheaper than this - */ - for (state = 0; state < NUM_STATE; state++) - cost[n][state] = 0xffff; - - /* Compute path costs and accumulate output bit path - * for each state and encoded bit value - */ - for (state = 0; state < NUM_STATE; state++) { - for (bit = 0; bit < 2; bit++) { - int bit_cost = cost[p][state] + ao_cost(s, ao_fec_decode_table[state][bit]); - uint8_t bit_state = ao_next_state(state, bit); - - /* Only track the minimal cost to reach - * this state; the best path can never - * go through the higher cost paths as - * total path cost is cumulative - */ - if (bit_cost < cost[n][bit_state]) { - cost[n][bit_state] = bit_cost; - bits[n][bit_state] = (bits[p][state] << 1) | (state & 1); - } - } - } - -#if 0 - printf ("bit %3d symbol %2x %2x:", i/2, s.a, s.b); - for (state = 0; state < NUM_STATE; state++) { - printf (" %5d(%04x)", cost[n][state], bits[n][state]); - } - printf ("\n"); -#endif - p = n; - - /* A loop is needed to handle the last output byte. It - * won't have any bits of future data to perform full - * error correction, but we might as well give the - * best possible answer anyways. - */ - while ((b - o) >= (8 + NUM_HIST) || (i + 2 >= len && b > o)) { - - /* Compute number of bits to the end of the - * last full byte of data. This is generally - * NUM_HIST, unless we've reached - * the end of the input, in which case - * it will be seven. - */ - int8_t dist = b - (o + 8); /* distance to last ready-for-writing bit */ - uint16_t min_cost; /* lowest cost */ - uint8_t min_state; /* lowest cost state */ - - /* Find the best fit at the current point - * of the decode. - */ - min_cost = cost[p][0]; - min_state = 0; - for (state = 1; state < NUM_STATE; state++) { - if (cost[p][state] < min_cost) { - min_cost = cost[p][state]; - min_state = state; - } - } - - /* The very last byte of data has the very last bit - * of data left in the state value; just smash the - * bits value in place and reset the 'dist' from - * -1 to 0 so that the full byte is read out - */ - if (dist < 0) { - bits[p][min_state] = (bits[p][min_state] << 1) | (min_state & 1); - dist = 0; - } - -#if 0 - printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x whiten %0x\n", - i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff, *whiten); -#endif - if (out_len) { - *out++ = (bits[p][min_state] >> dist) ^ *whiten++; - --out_len; - } - o += 8; - } - } - return len/16; -} diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 857667b0..22a58ff4 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -48,7 +48,7 @@ ALTOS_SRC = \ ao_spi_stm.c \ ao_cc1120.c \ ao_fec_tx.c \ - ao_viterbi.c \ + ao_fec_rx.c \ ao_ms5607.c \ ao_adc_stm.c \ ao_beep_stm.c \ diff --git a/src/test/Makefile b/src/test/Makefile index cdcecd51..4631fb78 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -40,5 +40,5 @@ ao_convert_pa_test: ao_convert_pa_test.c ao_convert_pa.c altitude-pa.h ao_kalman.h: $(KALMAN) (cd .. && make ao_kalman.h) -ao_fec_test: ao_fec_test.c ao_fec_tx.c ao_viterbi.c - cc $(CFLAGS) -o $@ ao_fec_test.c ../core/ao_fec_tx.c ../core/ao_viterbi.c -lm +ao_fec_test: ao_fec_test.c ao_fec_tx.c ao_fec_rx.c + cc $(CFLAGS) -DAO_FEC_DEBUG=1 -o $@ ao_fec_test.c ../core/ao_fec_tx.c ../core/ao_fec_rx.c -lm -- cgit v1.2.3 From 03dc80d15a2f8fe9d7340351226dadd8bc3cfdb9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:01:58 -0700 Subject: altos: Clean up usage of port parameters Make stm port parameters always be pointers; this avoids the confusion where some macros took '&port' and others took a bare 'port', and also unifies code to run on other processors in a consistent fashion. Signed-off-by: Keith Packard --- src/cc1111/ao_arch_funcs.h | 24 ++++++--- src/cc1111/ao_pins.h | 27 +++++++--- src/drivers/ao_25lc1024.c | 11 ++--- src/drivers/ao_at45db161d.c | 4 +- src/drivers/ao_companion.c | 49 ++++++++++++------- src/drivers/ao_hmc5883.c | 6 +-- src/drivers/ao_ms5607.c | 14 +++--- src/megametrum-v0.1/ao_pins.h | 111 ++++++++++++++++++++++++++++++++++-------- src/stm-demo/ao_pins.h | 4 +- src/stm/ao_adc_stm.c | 30 ++++++------ src/stm/ao_arch_funcs.h | 36 ++++++++++---- src/stm/ao_led.c | 17 ++++--- 12 files changed, 230 insertions(+), 103 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_arch_funcs.h b/src/cc1111/ao_arch_funcs.h index d9f5955a..728f1f76 100644 --- a/src/cc1111/ao_arch_funcs.h +++ b/src/cc1111/ao_arch_funcs.h @@ -31,14 +31,14 @@ extern __xdata uint8_t ao_spi_mutex; ao_mutex_put(&ao_spi_mutex); \ } while (0) -#define ao_spi_get_bit(bit,bus) do { \ - ao_mutex_get(&ao_spi_mutex); \ - (bit) = 0; \ +#define ao_spi_get_bit(reg,bit,pin,bus) do { \ + ao_mutex_get(&ao_spi_mutex); \ + pin = 0; \ } while (0) -#define ao_spi_put_bit(bit,bus) do { \ - (bit) = 1; \ - ao_mutex_put(&ao_spi_mutex); \ +#define ao_spi_put_bit(reg,bit,pin,bus) do { \ + pin = 1; \ + ao_mutex_put(&ao_spi_mutex); \ } while (0) @@ -65,3 +65,15 @@ ao_spi_init(void); SPI_CS_DIR |= mask; \ SPI_CS_SEL &= ~mask; \ } while (0) + +#define cc1111_enable_output(port,dir,sel,mask,v) do { \ + port = port & ~(mask) | v; \ + dir |= mask; \ + sel &= ~mask; \ +} while (0) + +#define disable_unreachable _Pragma("disable_warning 126") + +#define token_paster(x,y) x ## y +#define token_evaluator(x,y) token_paster(x,y) +#define ao_enable_output(port,pin,v) cc1111_enable_output(port,token_evaluator(port,DIR), token_evaluator(port,SEL), 1 << pin, 1 << v) diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index 0923e75d..e28a7b65 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -41,8 +41,9 @@ #define HAS_COMPANION 1 #define COMPANION_CS_ON_P1 1 - #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ - #define COMPANION_CS P1_2 + #define AO_COMPANION_CS_PORT P1 + #define AO_COMPANION_CS_PIN 2 + #define AO_COMPANION_CS P1_2 #define AO_LED_RED 1 #define LEDS_AVAILABLE (AO_LED_RED) @@ -72,9 +73,9 @@ #define PACKET_HAS_SLAVE 1 #define HAS_COMPANION 1 - #define COMPANION_CS_ON_P1 1 - #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ - #define COMPANION_CS P1_2 + #define AO_COMPANION_CS_PORT P1 + #define AO_COMPANION_CS_PIN 2 + #define AO_COMPANION_CS P1_2 #define AO_LED_RED 1 #define LEDS_AVAILABLE (AO_LED_RED) @@ -108,9 +109,9 @@ #define PACKET_HAS_SLAVE 1 #define HAS_COMPANION 1 - #define COMPANION_CS_ON_P1 1 - #define COMPANION_CS_MASK 0x4 /* CS1 is P1_2 */ - #define COMPANION_CS P1_2 + #define AO_COMPANION_CS_PORT P1 + #define AO_COMPANION_CS_PIN 2 + #define AO_COMPANION_CS P1_2 #define AO_LED_RED 1 #define LEDS_AVAILABLE (AO_LED_RED) @@ -527,21 +528,31 @@ #endif /* HAS_ADC */ #if IGNITE_ON_P2 +#define AO_IGNITER_PORT P2 +#define AO_IGNITER_DROGUE_PORT AO_IGNITER_PORT #define AO_IGNITER_DROGUE P2_3 #define AO_IGNITER_MAIN P2_4 #define AO_IGNITER_DIR P2DIR #define AO_IGNITER_DROGUE_BIT (1 << 3) #define AO_IGNITER_MAIN_BIT (1 << 4) +#define AO_IGNITER_DROGUE_PIN 3 +#define AO_IGNITER_MAIN_PIN 4 #endif #if IGNITE_ON_P0 +#define AO_IGNITER_PORT P0 #define AO_IGNITER_DROGUE P0_5 #define AO_IGNITER_MAIN P0_4 #define AO_IGNITER_DIR P0DIR #define AO_IGNITER_DROGUE_BIT (1 << 5) #define AO_IGNITER_MAIN_BIT (1 << 4) +#define AO_IGNITER_DROGUE_PIN 5 +#define AO_IGNITER_MAIN_PIN 4 #endif +#define AO_IGNITER_DROGUE_PORT AO_IGNITER_PORT +#define AO_IGNITER_MAIN_PORT AO_IGNITER_PORT + /* test these values with real igniters */ #define AO_IGNITER_OPEN 1000 #define AO_IGNITER_CLOSED 7000 diff --git a/src/drivers/ao_25lc1024.c b/src/drivers/ao_25lc1024.c index f0fb13c9..b25d52c4 100644 --- a/src/drivers/ao_25lc1024.c +++ b/src/drivers/ao_25lc1024.c @@ -38,8 +38,9 @@ __pdata uint16_t ao_storage_unit; * Using SPI on USART 0, with P1_2 as the chip select */ +#define EE_CS_PORT P1 #define EE_CS P1_2 -#define EE_CS_INDEX 2 +#define EE_CS_PIN 2 static __xdata uint8_t ao_ee_mutex; @@ -49,9 +50,9 @@ static __xdata uint8_t ao_ee_mutex; _asm nop _endasm; \ } while(0) -#define ao_ee_cs_low() ao_spi_get_bit(EE_CS, AO_EE_SPI_BUS) +#define ao_ee_cs_low() ao_spi_get_bit(EE_CS_PORT, EE_CS_PIN, EE_CS, AO_EE_SPI_BUS) -#define ao_ee_cs_high() ao_spi_put_bit(EE_CS, AO_EE_SPI_BUS) +#define ao_ee_cs_high() ao_spi_put_bit(EE_CS_PORT, EE_CS_PIN, EE_CS, AO_EE_SPI_BUS) struct ao_ee_instruction { uint8_t instruction; @@ -235,7 +236,5 @@ void ao_storage_device_init(void) { /* set up CS */ - EE_CS = 1; - P1DIR |= (1 << EE_CS_INDEX); - P1SEL &= ~(1 << EE_CS_INDEX); + ao_enable_output(EE_CS_PORT, EE_CS_PIN,1); } diff --git a/src/drivers/ao_at45db161d.c b/src/drivers/ao_at45db161d.c index afe0080b..5eb25acf 100644 --- a/src/drivers/ao_at45db161d.c +++ b/src/drivers/ao_at45db161d.c @@ -43,9 +43,9 @@ __xdata uint8_t ao_flash_mutex; _asm nop _endasm; \ } while(0) -#define ao_flash_cs_low() ao_spi_get_bit(FLASH_CS, AO_FLASH_SPI_BUS) +#define ao_flash_cs_low() ao_spi_get_bit(FLASH_CS_PORT, FLASH_CS_PIN, FLASH_CS, AO_FLASH_SPI_BUS) -#define ao_flash_cs_high() ao_spi_put_bit(FLASH_CS, AO_FLASH_SPI_BUS) +#define ao_flash_cs_high() ao_spi_put_bit(FLASH_CS_PORT, FLASH_CS_PIN, FLASH_CS, AO_FLASH_SPI_BUS) struct ao_flash_instruction { uint8_t instruction; diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index fe88e998..a31cc2ea 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -15,20 +15,36 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" - -#define ao_spi_slow() (U0GCR = (UxGCR_CPOL_NEGATIVE | \ - UxGCR_CPHA_FIRST_EDGE | \ - UxGCR_ORDER_MSB | \ - (13 << UxGCR_BAUD_E_SHIFT))) - -#define ao_spi_fast() (U0GCR = (UxGCR_CPOL_NEGATIVE | \ - UxGCR_CPHA_FIRST_EDGE | \ - UxGCR_ORDER_MSB | \ - (17 << UxGCR_BAUD_E_SHIFT))) - -#define COMPANION_SELECT() do { ao_spi_get_bit(COMPANION_CS, AO_COMPANION_BUS); ao_spi_slow(); } while (0) -#define COMPANION_DESELECT() do { ao_spi_fast(); ao_spi_put_bit(COMPANION_CS, AO_COMPANION_BUS); } while (0) +#include +#include + +#ifndef ao_spi_slow +#define ao_spi_slow(bus) (U0GCR = (UxGCR_CPOL_NEGATIVE | \ + UxGCR_CPHA_FIRST_EDGE | \ + UxGCR_ORDER_MSB | \ + (13 << UxGCR_BAUD_E_SHIFT))) + +#define ao_spi_fast(bus) (U0GCR = (UxGCR_CPOL_NEGATIVE | \ + UxGCR_CPHA_FIRST_EDGE | \ + UxGCR_ORDER_MSB | \ + (17 << UxGCR_BAUD_E_SHIFT))) +#endif + +#define COMPANION_SELECT() do { \ + ao_spi_get_bit(AO_COMPANION_CS_PORT, \ + AO_COMPANION_CS_PIN, \ + AO_COMPANION_CS, \ + AO_COMPANION_SPI_BUS); \ + ao_spi_slow(AO_COMPANION_SPI_BUS); \ + } while (0) + +#define COMPANION_DESELECT() do { \ + ao_spi_fast(AO_COMPANION_SPI_BUS); \ + ao_spi_put_bit(AO_COMPANION_CS_PORT, \ + AO_COMPANION_CS_PIN, \ + AO_COMPANION_CS, \ + AO_COMPANION_SPI_BUS); \ + } while (0) __xdata struct ao_companion_command ao_companion_command; __xdata struct ao_companion_setup ao_companion_setup; @@ -123,10 +139,7 @@ static __xdata struct ao_task ao_companion_task; void ao_companion_init(void) { - COMPANION_CS_PORT |= COMPANION_CS_MASK; /* raise all CS pins */ - COMPANION_CS_DIR |= COMPANION_CS_MASK; /* set CS pins as outputs */ - COMPANION_CS_SEL &= ~COMPANION_CS_MASK; /* set CS pins as GPIO */ - + ao_enable_output(AO_COMPANION_CS_PORT, AO_COMPANION_CS_PIN, 1); ao_cmd_register(&ao_companion_cmds[0]); ao_add_task(&ao_companion_task, ao_companion, "companion"); } diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c index 1bc914e6..64663ea6 100644 --- a/src/drivers/ao_hmc5883.c +++ b/src/drivers/ao_hmc5883.c @@ -58,7 +58,7 @@ static uint8_t ao_hmc5883_done; static void ao_hmc5883_isr(void) { - ao_exti_disable(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); + ao_exti_disable(AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); ao_hmc5883_done = 1; ao_wakeup(&ao_hmc5883_done); } @@ -71,7 +71,7 @@ ao_hmc5883_sample(struct ao_hmc5883_sample *sample) uint8_t single = HMC5883_MODE_SINGLE; ao_hmc5883_done = 0; - ao_exti_enable(&AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); + ao_exti_enable(AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); ao_hmc5883_reg_write(HMC5883_MODE, HMC5883_MODE_SINGLE); cli(); @@ -159,7 +159,7 @@ ao_hmc5883_init(void) ao_hmc5883_valid = 0; ao_enable_port(AO_HMC5883_INT_PORT); - ao_exti_setup(&AO_HMC5883_INT_PORT, + ao_exti_setup(AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN, AO_EXTI_MODE_FALLING | AO_EXTI_MODE_PULL_UP, ao_hmc5883_isr); diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 0f0625d0..e08f4d40 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -25,12 +25,12 @@ static uint8_t ms5607_configured; static void ao_ms5607_start(void) { ao_spi_get(AO_MS5607_SPI_INDEX); - stm_gpio_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, 0); + stm_gpio_set(AO_MS5607_CS_GPIO, AO_MS5607_CS, 0); } static void ao_ms5607_stop(void) { - stm_gpio_set(&AO_MS5607_CS_GPIO, AO_MS5607_CS, 1); + stm_gpio_set(AO_MS5607_CS_GPIO, AO_MS5607_CS, 1); ao_spi_put(AO_MS5607_SPI_INDEX); } @@ -132,12 +132,12 @@ ao_ms5607_get_sample(uint8_t cmd) { ao_ms5607_start(); ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); - ao_exti_enable(&AO_MS5607_MISO_GPIO, AO_MS5607_MISO); + ao_exti_enable(AO_MS5607_MISO_GPIO, AO_MS5607_MISO); cli(); while (!ao_ms5607_done) ao_sleep(&ao_ms5607_done); sei(); - ao_exti_disable(&AO_MS5607_MISO_GPIO, AO_MS5607_MISO); + ao_exti_disable(AO_MS5607_MISO_GPIO, AO_MS5607_MISO); ao_ms5607_stop(); ao_ms5607_start(); @@ -203,7 +203,7 @@ ao_ms5607(void) ao_ms5607_setup(); for (;;) { - struct ao_ms5607_sample ao_ms5607_next; + static struct ao_ms5607_sample ao_ms5607_next; ao_ms5607_sample(&ao_ms5607_next); ao_arch_critical( ao_ms5607_current = ao_ms5607_next; @@ -260,7 +260,7 @@ ao_ms5607_init(void) * conversion is complete, the MS5607 will raise this * pin as a signal */ - ao_exti_setup(&AO_MS5607_MISO_GPIO, + ao_exti_setup(AO_MS5607_MISO_GPIO, AO_MS5607_MISO, AO_EXTI_MODE_RISING, ao_ms5607_isr); @@ -268,7 +268,7 @@ ao_ms5607_init(void) /* Reset the pin from INPUT to ALTERNATE so that SPI works * This needs an abstraction at some point... */ - stm_moder_set(&AO_MS5607_MISO_GPIO, + stm_moder_set(AO_MS5607_MISO_GPIO, AO_MS5607_MISO, STM_MODER_ALTERNATE); } diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 9d9113c8..f5bd3e0d 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -76,7 +76,7 @@ #define HAS_SPI_2 1 #define SPI_2_PB13_PB14_PB15 1 #define SPI_2_PD1_PD3_PD4 0 -#define SPI_2_GPIO stm_gpiob +#define SPI_2_GPIO (&stm_gpiob) #define SPI_2_SCK 13 #define SPI_2_MISO 14 #define SPI_2_MOSI 15 @@ -87,12 +87,13 @@ #define HAS_I2C_2 1 #define I2C_2_PB10_PB11 1 -#define PACKET_HAS_SLAVE 0 +#define PACKET_HAS_SLAVE 1 +#define PACKET_HAS_MASTER 0 -#define LOW_LEVEL_DEBUG 1 +#define LOW_LEVEL_DEBUG 0 #define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOCEN -#define LED_PORT stm_gpioc +#define LED_PORT (&stm_gpioc) #define LED_PIN_RED 8 #define LED_PIN_GREEN 9 #define AO_LED_RED (1 << LED_PIN_RED) @@ -107,6 +108,48 @@ #define HAS_ACCEL_REF 1 #define HAS_LOG 1 +/* + * Igniter + */ + +#define HAS_IGNITE 1 +#define HAS_IGNITE_REPORT 1 + +#define AO_SENSE_DROGUE(p) ((p)->adc.sense[0]) +#define AO_SENSE_MAIN(p) ((p)->adc.sense[1]) +#define AO_IGNITER_CLOSED 400 +#define AO_IGNITER_OPEN 60 + +#define AO_IGNITER_PORT_A (&stm_gpiod) +#define AO_IGNITER_PIN_A 6 + +#define AO_IGNITER_PORT_B (&stm_gpiod) +#define AO_IGNITER_PIN_B 7 + +#define AO_IGNITER_PORT_C (&stm_gpiob) +#define AO_IGNITER_PIN_C 5 + +#define AO_IGNITER_PORT_D (&stm_gpioe) +#define AO_IGNITER_PIN_D 4 + +#define AO_IGNITER_PORT_E (&stm_gpioe) +#define AO_IGNITER_PIN_E 6 + +#define AO_IGNITER_PORT_F (&stm_gpioe) +#define AO_IGNITER_PIN_F 5 + +#define AO_IGNITER_DROGUE_PORT AO_IGNITER_PORT_A +#define AO_IGNITER_DROGUE_PIN AO_IGNITER_PIN_A + +#define AO_IGNITER_MAIN_PORT AO_IGNITER_PORT_B +#define AO_IGNITER_MAIN_PIN AO_IGNITER_PIN_B + +#define AO_IGNITER_SET_DROGUE(v) stm_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, v) +#define AO_IGNITER_SET_MAIN(v) stm_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, v) + +/* + * ADC + */ #define AO_DATA_RING 32 #define AO_ADC_NUM_SENSE 6 @@ -120,43 +163,43 @@ struct ao_adc { }; #define AO_ADC_SENSE_A 0 -#define AO_ADC_SENSE_A_PORT stm_gpioa +#define AO_ADC_SENSE_A_PORT (&stm_gpioa) #define AO_ADC_SENSE_A_PIN 0 #define AO_ADC_SENSE_B 1 -#define AO_ADC_SENSE_B_PORT stm_gpioa +#define AO_ADC_SENSE_B_PORT (&stm_gpioa) #define AO_ADC_SENSE_B_PIN 1 #define AO_ADC_SENSE_C 2 -#define AO_ADC_SENSE_C_PORT stm_gpioa +#define AO_ADC_SENSE_C_PORT (&stm_gpioa) #define AO_ADC_SENSE_C_PIN 2 #define AO_ADC_SENSE_D 3 -#define AO_ADC_SENSE_D_PORT stm_gpioa +#define AO_ADC_SENSE_D_PORT (&stm_gpioa) #define AO_ADC_SENSE_D_PIN 3 #define AO_ADC_SENSE_E 4 -#define AO_ADC_SENSE_E_PORT stm_gpioa +#define AO_ADC_SENSE_E_PORT (&stm_gpioa) #define AO_ADC_SENSE_E_PIN 4 #define AO_ADC_SENSE_F 22 -#define AO_ADC_SENSE_F_PORT stm_gpioe +#define AO_ADC_SENSE_F_PORT (&stm_gpioe) #define AO_ADC_SENSE_F_PIN 7 #define AO_ADC_V_BATT 8 -#define AO_ADC_V_BATT_PORT stm_gpiob +#define AO_ADC_V_BATT_PORT (&stm_gpiob) #define AO_ADC_V_BATT_PIN 0 #define AO_ADC_V_PBATT 9 -#define AO_ADC_V_PBATT_PORT stm_gpiob +#define AO_ADC_V_PBATT_PORT (&stm_gpiob) #define AO_ADC_V_PBATT_PIN 1 #define AO_ADC_ACCEL_REF 10 -#define AO_ADC_ACCEL_REF_PORT stm_gpioc +#define AO_ADC_ACCEL_REF_PORT (&stm_gpioc) #define AO_ADC_ACCEL_REF_PIN 0 #define AO_ADC_ACCEL 11 -#define AO_ADC_ACCEL_PORT stm_gpioc +#define AO_ADC_ACCEL_PORT (&stm_gpioc) #define AO_ADC_ACCEL_PIN 1 #define AO_ADC_TEMP 16 @@ -207,10 +250,10 @@ struct ao_adc { * Pressure sensor settings */ #define HAS_MS5607 1 -#define AO_MS5607_CS_GPIO stm_gpioc +#define AO_MS5607_CS_GPIO (&stm_gpioc) #define AO_MS5607_CS 4 #define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) -#define AO_MS5607_MISO_GPIO stm_gpioa +#define AO_MS5607_MISO_GPIO (&stm_gpioa) #define AO_MS5607_MISO 6 #define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO) #define AO_MS5607_SPI_INDEX (STM_SPI_INDEX(1)) @@ -220,7 +263,7 @@ struct ao_adc { */ #define M25_MAX_CHIPS 1 -#define AO_M25_SPI_CS_PORT stm_gpiod +#define AO_M25_SPI_CS_PORT (&stm_gpiod) #define AO_M25_SPI_CS_MASK (1 << 3) #define AO_M25_SPI_BUS STM_SPI_INDEX(2) @@ -228,21 +271,23 @@ struct ao_adc { * Radio (cc1120) */ -#define AO_CC1120_SPI_CS_PORT stm_gpioc +#define AO_FEC_DEBUG 1 +#define AO_CC1120_SPI_CS_PORT (&stm_gpioc) #define AO_CC1120_SPI_CS_PIN 5 #define AO_CC1120_SPI_BUS STM_SPI_INDEX(2) -#define AO_CC1120_INT_PORT stm_gpioc +#define AO_CC1120_INT_PORT (&stm_gpioc) #define AO_CC1120_INT_PIN 14 #define AO_CC1120_INT_GPIO 2 +#define HAS_BOOT_RADIO 1 /* * Mag sensor (hmc5883) */ #define HAS_HMC5883 1 -#define AO_HMC5883_INT_PORT stm_gpioc +#define AO_HMC5883_INT_PORT (&stm_gpioc) #define AO_HMC5883_INT_PIN 12 #define AO_HMC5883_I2C_INDEX STM_I2C_INDEX(1) @@ -251,7 +296,7 @@ struct ao_adc { */ #define HAS_MPU6000 1 -#define AO_MPU6000_INT_PORT stm_gpioc +#define AO_MPU6000_INT_PORT (&stm_gpioc) #define AO_MPU6000_INT_PIN 13 #define AO_MPU6000_I2C_INDEX STM_I2C_INDEX(1) @@ -259,4 +304,28 @@ struct ao_adc { #define NUM_CMDS 16 +/* + * Companion + */ + +#define AO_COMPANION_CS_PORT (&stm_gpiod) +#define AO_COMPANION_CS_PIN (0) +#define AO_COMPANION_SPI_BUS STM_SPI_INDEX(2) + +/* + * Monitor + */ + +#define HAS_MONITOR 0 +#define LEGACY_MONITOR 0 +#define HAS_MONITOR_PUT 1 +#define AO_MONITOR_LED 0 +#define HAS_RSSI 0 + +/* + * Profiling Viterbi decoding + */ + +#define AO_PROFILE 0 + #endif /* _AO_PINS_H_ */ diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index d02c071c..7e222122 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -70,7 +70,7 @@ #define LOW_LEVEL_DEBUG 1 #define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOBEN -#define LED_PORT stm_gpiob +#define LED_PORT (&stm_gpiob) #define LED_PIN_GREEN 7 #define LED_PIN_BLUE 6 #define AO_LED_GREEN (1 << LED_PIN_GREEN) @@ -147,7 +147,7 @@ struct ao_adc { }; #define AO_ADC_IDD 4 -#define AO_ADC_PIN0_PORT stm_gpioa +#define AO_ADC_PIN0_PORT (&stm_gpioa) #define AO_ADC_PIN0_PIN 4 #define AO_ADC_RCC_AHBENR ((1 << STM_RCC_AHBENR_GPIOAEN)) diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index ed1d20c9..7564c7fa 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -156,43 +156,43 @@ ao_adc_init(void) #endif #ifdef AO_ADC_PIN0_PORT - stm_moder_set(&AO_ADC_PIN0_PORT, AO_ADC_PIN0_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN0_PORT, AO_ADC_PIN0_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN1_PORT - stm_moder_set(&AO_ADC_PIN1_PORT, AO_ADC_PIN1_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN1_PORT, AO_ADC_PIN1_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN2_PORT - stm_moder_set(&AO_ADC_PIN2_PORT, AO_ADC_PIN2_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN2_PORT, AO_ADC_PIN2_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN3_PORT - stm_moder_set(&AO_ADC_PIN3_PORT, AO_ADC_PIN3_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN3_PORT, AO_ADC_PIN3_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN4_PORT - stm_moder_set(&AO_ADC_PIN4_PORT, AO_ADC_PIN4_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN4_PORT, AO_ADC_PIN4_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN5_PORT - stm_moder_set(&AO_ADC_PIN5_PORT, AO_ADC_PIN5_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN5_PORT, AO_ADC_PIN5_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN6_PORT - stm_moder_set(&AO_ADC_PIN6_PORT, AO_ADC_PIN6_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN6_PORT, AO_ADC_PIN6_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN7_PORT - stm_moder_set(&AO_ADC_PIN7_PORT, AO_ADC_PIN7_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN7_PORT, AO_ADC_PIN7_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN8_PORT - stm_moder_set(&AO_ADC_PIN8_PORT, AO_ADC_PIN8_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN8_PORT, AO_ADC_PIN8_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN9_PORT - stm_moder_set(&AO_ADC_PIN9_PORT, AO_ADC_PIN9_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN9_PORT, AO_ADC_PIN9_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN10_PORT - stm_moder_set(&AO_ADC_PIN10_PORT, AO_ADC_PIN10_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN10_PORT, AO_ADC_PIN10_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN11_PORT - stm_moder_set(&AO_ADC_PIN11_PORT, AO_ADC_PIN11_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN11_PORT, AO_ADC_PIN11_PIN, STM_MODER_ANALOG); #endif #ifdef AO_ADC_PIN12_PORT - stm_moder_set(&AO_ADC_PIN12_PORT, AO_ADC_PIN12_PIN, STM_MODER_ANALOG); + stm_moder_set(AO_ADC_PIN12_PORT, AO_ADC_PIN12_PIN, STM_MODER_ANALOG); #endif stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_ADC1EN); @@ -281,8 +281,10 @@ ao_adc_init(void) #endif /* Clear any stale status bits */ stm_adc.sr = 0; - ao_adc_ready = 1; ao_dma_alloc(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1)); + ao_cmd_register(&ao_adc_cmds[0]); + + ao_adc_ready = 1; } diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 447042dd..62b10063 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -40,36 +40,54 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); void ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index); +#define AO_SPI_SPEED_FAST STM_SPI_CR1_BR_PCLK_16 +#define AO_SPI_SPEED_200kHz STM_SPI_CR1_BR_PCLK_256 + +extern uint16_t ao_spi_speed[STM_NUM_SPI]; + +#define ao_spi_slow(bus) (ao_spi_speed[bus] = AO_SPI_SPEED_200kHz) + +#define ao_spi_fast(bus) (ao_spi_speed[bus] = AO_SPI_SPEED_FAST) + void ao_spi_init(void); #define ao_spi_get_mask(reg,mask,bus) do { \ ao_spi_get(bus); \ - (reg).bsrr = ((uint32_t) mask) << 16; \ + (reg)->bsrr = ((uint32_t) mask) << 16; \ } while (0) #define ao_spi_put_mask(reg,mask,bus) do { \ - (reg).bsrr = mask; \ + (reg)->bsrr = mask; \ ao_spi_put(bus); \ } while (0) +#define ao_spi_get_bit(reg,bit,pin,bus) ao_spi_get_mask(reg,(1<bsrr = (colors & ao_led_enable); } void ao_led_off(uint16_t colors) { - LED_PORT.odr &= ~(colors & ao_led_enable); + LED_PORT->bsrr = (uint32_t) (colors & ao_led_enable) << 16; } void ao_led_set(uint16_t colors) { - LED_PORT.odr = (LED_PORT.odr & ~(ao_led_enable)) | (colors & ao_led_enable); + uint16_t on = colors & ao_led_enable; + uint16_t off = ~colors & ao_led_enable; + + LED_PORT->bsrr = off << 16 | on; } void ao_led_toggle(uint16_t colors) { - LED_PORT.odr ^= (colors & ao_led_enable); + LED_PORT->odr ^= (colors & ao_led_enable); } void @@ -58,11 +61,11 @@ ao_led_init(uint16_t enable) stm_rcc.ahbenr |= (1 << LED_PORT_ENABLE); ao_led_enable = enable; - LED_PORT.odr &= ~enable; + LED_PORT->odr &= ~enable; for (bit = 0; bit < 16; bit++) { if (enable & (1 << bit)) { - stm_moder_set(&LED_PORT, bit, STM_MODER_OUTPUT); - stm_otyper_set(&LED_PORT, bit, STM_OTYPER_PUSH_PULL); + stm_moder_set(LED_PORT, bit, STM_MODER_OUTPUT); + stm_otyper_set(LED_PORT, bit, STM_OTYPER_PUSH_PULL); } } } -- cgit v1.2.3 From 33f8f7add27a02d24b0671da353b59762224c1ee Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:05:42 -0700 Subject: altos: Make cc1111 radio control functions static No need to publish these; they're all private to cc1111 Signed-off-by: Keith Packard --- src/cc1111/ao_radio.c | 8 +++++--- src/core/ao.h | 13 +------------ 2 files changed, 6 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index 51ed369b..2c4a661e 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -260,7 +260,7 @@ ao_radio_general_isr(void) __interrupt 16 } } -void +static void ao_radio_set_packet(void) { uint8_t i; @@ -268,7 +268,7 @@ ao_radio_set_packet(void) RF[fixed_pkt_setup[i]] = fixed_pkt_setup[i+1]; } -void +static void ao_radio_idle(void) { if (RF_MARCSTATE != RF_MARCSTATE_IDLE) @@ -280,7 +280,9 @@ ao_radio_idle(void) } } -void +#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) + +static void ao_radio_get(uint8_t len) { ao_config_get(); diff --git a/src/core/ao.h b/src/core/ao.h index 204c8530..c13029bf 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -505,15 +505,7 @@ void ao_radio_general_isr(void) ao_arch_interrupt(16); void -ao_radio_get(uint8_t len); - -#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) - -void -ao_radio_set_packet(void); - -void -ao_radio_send(__xdata void *d, uint8_t size) __reentrant; +ao_radio_send(const __xdata void *d, uint8_t size) __reentrant; uint8_t ao_radio_recv(__xdata void *d, uint8_t size) __reentrant; @@ -537,9 +529,6 @@ ao_radio_rdf(uint8_t pkt_len); void ao_radio_rdf_abort(void); -void -ao_radio_idle(void); - void ao_radio_init(void); -- cgit v1.2.3 From 936ecad62596f34773afb7460b10f63df7d0896d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:07:38 -0700 Subject: altos: Add GPS logging code for MegaMetrum MM uses a different logging format with larger log blocks, so restructure the GPS logging code to fill them up Signed-off-by: Keith Packard --- src/core/ao.h | 10 +++++ src/core/ao_gps_report_mega.c | 95 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 src/core/ao_gps_report_mega.c (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index c13029bf..62eb488e 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -396,6 +396,16 @@ ao_gps_report(void); void ao_gps_report_init(void); +/* + * ao_gps_report_mega.c + */ + +void +ao_gps_report_mega(void); + +void +ao_gps_report_mega_init(void); + /* * ao_telemetry_orig.c */ diff --git a/src/core/ao_gps_report_mega.c b/src/core/ao_gps_report_mega.c new file mode 100644 index 00000000..47891cab --- /dev/null +++ b/src/core/ao_gps_report_mega.c @@ -0,0 +1,95 @@ +/* + * 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_report_mega(void) +{ + static __xdata struct ao_log_mega gps_log; + static __xdata struct ao_telemetry_location gps_data; + uint8_t date_reported = 0; + + for (;;) { + ao_sleep(&ao_gps_data); + ao_mutex_get(&ao_gps_mutex); + ao_xmemcpy(&gps_data, &ao_gps_data, sizeof (ao_gps_data)); + ao_mutex_put(&ao_gps_mutex); + + if (!(gps_data.flags & AO_GPS_VALID)) + continue; + + gps_log.tick = ao_gps_tick; + gps_log.type = AO_LOG_GPS_TIME; + gps_log.u.gps.latitude = gps_data.latitude; + gps_log.u.gps.longitude = gps_data.longitude; + gps_log.u.gps.altitude = gps_data.altitude; + + gps_log.u.gps.hour = gps_data.hour; + gps_log.u.gps.minute = gps_data.minute; + gps_log.u.gps.second = gps_data.second; + gps_log.u.gps.flags = gps_data.flags; + gps_log.u.gps.year = gps_data.year; + gps_log.u.gps.month = gps_data.month; + gps_log.u.gps.day = gps_data.day; + ao_log_mega(&gps_log); + } +} + +void +ao_gps_tracking_report_mega(void) +{ + static __xdata struct ao_log_mega gps_log; + static __xdata struct ao_telemetry_satellite gps_tracking_data; + uint8_t c, n, i; + + for (;;) { + ao_sleep(&ao_gps_tracking_data); + ao_mutex_get(&ao_gps_mutex); + ao_xmemcpy(&gps_tracking_data, &ao_gps_tracking_data, sizeof (ao_gps_tracking_data)); + ao_mutex_put(&ao_gps_mutex); + + if (!(n = gps_tracking_data.channels)) + continue; + + gps_log.type = AO_LOG_GPS_SAT; + gps_log.tick = ao_gps_tick; + i = 0; + for (c = 0; c < n; c++) + if ((gps_log.u.gps_sat.sats[i].svid = gps_tracking_data.sats[c].svid)) + { + gps_log.u.gps_sat.sats[i].c_n = gps_tracking_data.sats[c].c_n_1; + i++; + } + gps_log.u.gps_sat.channels = i; + ao_log_mega(&gps_log); + } +} + +__xdata struct ao_task ao_gps_report_mega_task; +__xdata struct ao_task ao_gps_tracking_report_mega_task; + +void +ao_gps_report_mega_init(void) +{ + ao_add_task(&ao_gps_report_mega_task, + ao_gps_report_mega, + "gps_report"); + ao_add_task(&ao_gps_tracking_report_mega_task, + ao_gps_tracking_report_mega, + "gps_tracking_report"); +} -- cgit v1.2.3 From f1ae622eff60e05c1f5d8f822a3cf6a85750c6cc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:11:10 -0700 Subject: altos: Optimize FEC encode and decode Integrate interleaving, CRC and padding within the decode/encode functions. Provide for ISR priorities so that the 1120 RX interrupt takes precedence over the other interrupts or we risk losing bits. Optimize the viterbi decoder a bit (goes from 10ms per packet to 7ms per packet). Signed-off-by: Keith Packard --- src/core/ao_fec.h | 46 ++-- src/core/ao_fec_rx.c | 145 ++++++++----- src/core/ao_fec_tx.c | 68 +----- src/drivers/ao_cc1120.c | 483 ++++++++++++++++++++++++++--------------- src/drivers/ao_cc1120.h | 9 + src/drivers/ao_cc1120_CC1120.h | 27 ++- src/stm/ao_arch.h | 23 +- src/stm/ao_exti.h | 3 + src/stm/ao_exti_stm.c | 73 ++++--- src/stm/ao_spi_stm.c | 6 +- src/stm/ao_timer.c | 2 +- src/test/ao_fec_test.c | 39 ++-- 12 files changed, 560 insertions(+), 364 deletions(-) (limited to 'src') diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index 4fd398eb..f1192b62 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -26,11 +26,28 @@ extern const uint8_t ao_fec_whiten_table[]; +#if AO_FEC_DEBUG void -ao_fec_dump_bytes(uint8_t *bytes, uint16_t len, char *name); +ao_fec_dump_bytes(const uint8_t *bytes, uint16_t len, const char *name); +#endif + +static uint16_t inline +ao_fec_crc_byte(uint8_t byte, uint16_t crc) +{ + uint8_t bit; + + for (bit = 0; bit < 8; bit++) { + if (((crc & 0x8000) >> 8) ^ (byte & 0x80)) + crc = (crc << 1) ^ 0x8005; + else + crc = (crc << 1); + byte <<= 1; + } + return crc; +} uint16_t -ao_fec_crc(uint8_t *bytes, uint8_t len); +ao_fec_crc(const uint8_t *bytes, uint8_t len); /* * 'len' is the length of the original data; 'bytes' @@ -38,38 +55,23 @@ ao_fec_crc(uint8_t *bytes, uint8_t len); * two after 'len' must be the received crc */ uint8_t -ao_fec_check_crc(uint8_t *bytes, uint8_t len); - -/* - * Append CRC and terminator bytes, returns resulting length. - * 'out' must be at least len + AO_FEC_PREPARE_EXTRA bytes long - */ -uint8_t -ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *out); - -/* - * Whiten data using the cc1111 PN9 sequence. 'out' - * must be 'len' bytes long. 'out' and 'in' can be - * the same array - */ -void -ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out); +ao_fec_check_crc(const uint8_t *bytes, uint8_t len); /* - * Encode and interleave data. 'out' must be len*2 bytes long + * Compute CRC, whiten, convolve and interleave data. 'out' must be (len + 4) * 2 bytes long */ uint8_t -ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out); +ao_fec_encode(const uint8_t *in, uint8_t len, uint8_t *out); /* * Decode data. 'in' is one byte per bit, soft decision * 'out' must be len/8 bytes long */ -#define AO_FEC_DECODE_BLOCK (8 * 32) /* callback must return multiples of this many bits */ +#define AO_FEC_DECODE_BLOCK (32) /* callback must return multiples of this many bits */ uint8_t -ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()); +ao_fec_decode(const uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()); /* * Interleave data packed in bytes. 'out' must be 'len' bytes long. diff --git a/src/core/ao_fec_rx.c b/src/core/ao_fec_rx.c index 69e9c1f5..0d400bb0 100644 --- a/src/core/ao_fec_rx.c +++ b/src/core/ao_fec_rx.c @@ -18,6 +18,16 @@ #include #include +#ifdef MEGAMETRUM +#include +#endif + +#if AO_PROFILE +#include + +uint32_t ao_fec_decode_start, ao_fec_decode_end; +#endif + /* * byte order repeats through 3 2 1 0 * @@ -40,34 +50,35 @@ * 18/19 10/11 08/09 00/01 */ +static const uint8_t ao_interleave_order[] = { + 0x1e, 0x16, 0x0e, 0x06, + 0x1c, 0x14, 0x0c, 0x04, + 0x1a, 0x12, 0x0a, 0x02, + 0x18, 0x10, 0x08, 0x00 +}; + static inline uint16_t ao_interleave_index(uint16_t i) { - uint8_t l = i & 0x1e; - uint16_t h = i & ~0x1e; - uint8_t o = 0x1e ^ (((l >> 2) & 0x6) | ((l << 2) & 0x18)); - return h | o; + return (i & ~0x1e) | ao_interleave_order[(i & 0x1e) >> 1]; } -struct ao_soft_sym { - uint8_t a, b; -}; - #define NUM_STATE 8 #define NUM_HIST 8 -#define MOD_HIST(b) ((b) & 7) - -#define V_0 0xc0 -#define V_1 0x40 - -static const struct ao_soft_sym ao_fec_decode_table[NUM_STATE][2] = { -/* next 0 1 state */ - { { V_0, V_0 }, { V_1, V_1 } } , /* 000 */ - { { V_0, V_1 }, { V_1, V_0 } }, /* 001 */ - { { V_1, V_1 }, { V_0, V_0 } }, /* 010 */ - { { V_1, V_0 }, { V_0, V_1 } }, /* 011 */ - { { V_1, V_1 }, { V_0, V_0 } }, /* 100 */ - { { V_1, V_0 }, { V_0, V_1 } }, /* 101 */ - { { V_0, V_0 }, { V_1, V_1 } }, /* 110 */ - { { V_0, V_1 }, { V_1, V_0 } } /* 111 */ + +#define V_0 0xff +#define V_1 0x00 + +/* + * These are just the 'zero' states; the 'one' states mirror them + */ +static const uint8_t ao_fec_decode_table[NUM_STATE*2] = { + V_0, V_0, /* 000 */ + V_0, V_1, /* 001 */ + V_1, V_1, /* 010 */ + V_1, V_0, /* 011 */ + V_1, V_1, /* 100 */ + V_1, V_0, /* 101 */ + V_0, V_0, /* 110 */ + V_0, V_1 /* 111 */ }; static inline uint8_t @@ -76,14 +87,6 @@ ao_next_state(uint8_t state, uint8_t bit) return ((state << 1) | bit) & 0x7; } -static inline uint16_t ao_abs(int16_t x) { return x < 0 ? -x : x; } - -static inline uint16_t -ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) -{ - return ao_abs(a.a - b.a) + ao_abs(a.b - b.b); -} - /* * 'in' is 8-bits per symbol soft decision data * 'len' is input byte length. 'out' must be @@ -91,25 +94,29 @@ ao_cost(struct ao_soft_sym a, struct ao_soft_sym b) */ uint8_t -ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()) +ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()) { - static uint16_t cost[2][NUM_STATE]; /* path cost */ + static uint32_t cost[2][NUM_STATE]; /* path cost */ static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */ + uint16_t i; /* input byte index */ uint16_t b; /* encoded symbol index (bytes/2) */ uint16_t o; /* output bit index */ uint8_t p; /* previous cost/bits index */ uint8_t n; /* next cost/bits index */ uint8_t state; /* state index */ - uint8_t bit; /* original encoded bit index */ const uint8_t *whiten = ao_fec_whiten_table; uint16_t interleave; /* input byte array index */ - struct ao_soft_sym s; /* input symbol pair */ + uint8_t s0, s1; uint16_t avail; + uint16_t crc = AO_FEC_CRC_INIT; +#if AO_PROFILE + uint32_t start_tick; +#endif p = 0; for (state = 0; state < NUM_STATE; state++) { - cost[0][state] = 0xffff; + cost[0][state] = 0x7fffffff; bits[0][state] = 0; } cost[0][0] = 0; @@ -119,6 +126,14 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t else avail = len; +#if AO_PROFILE + if (!avail) { + avail = callback(); + if (!avail) + return 0; + } + start_tick = ao_profile_tick(); +#endif o = 0; for (i = 0; i < len; i += 2) { b = i/2; @@ -127,44 +142,52 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t if (!avail) { avail = callback(); if (!avail) - break; + return 0; } /* Fetch one pair of input bytes, de-interleaving * the input. */ interleave = ao_interleave_index(i); - s.a = in[interleave]; - s.b = in[interleave+1]; + s0 = in[interleave]; + s1 = in[interleave+1]; + + avail -= 2; /* Reset next costs to 'impossibly high' values so that * the first path through this state is cheaper than this */ for (state = 0; state < NUM_STATE; state++) - cost[n][state] = 0xffff; + cost[n][state] = 0x7fffffff; /* Compute path costs and accumulate output bit path * for each state and encoded bit value */ for (state = 0; state < NUM_STATE; state++) { - for (bit = 0; bit < 2; bit++) { - int bit_cost = cost[p][state] + ao_cost(s, ao_fec_decode_table[state][bit]); - uint8_t bit_state = ao_next_state(state, bit); - - /* Only track the minimal cost to reach - * this state; the best path can never - * go through the higher cost paths as - * total path cost is cumulative - */ - if (bit_cost < cost[n][bit_state]) { - cost[n][bit_state] = bit_cost; - bits[n][bit_state] = (bits[p][state] << 1) | (state & 1); + uint32_t bitcost = ((uint32_t) (s0 ^ ao_fec_decode_table[(state<<1)]) + + (uint32_t) (s1 ^ ao_fec_decode_table[(state<<1)+1])); + { + uint32_t cost0 = cost[p][state] + bitcost; + uint8_t state0 = ao_next_state(state, 0); + + if (cost0 < cost[n][state0]) { + cost[n][state0] = cost0; + bits[n][state0] = (bits[p][state] << 1) | (state & 1); + } + } + { + uint32_t cost1 = cost[p][state] + 510 - bitcost; + uint8_t state1 = ao_next_state(state, 1); + + if (cost1 < cost[n][state1]) { + cost[n][state1] = cost1; + bits[n][state1] = (bits[p][state] << 1) | (state & 1); } } } #if 0 - printf ("bit %3d symbol %2x %2x:", i/2, s.a, s.b); + printf ("bit %3d symbol %2x %2x:", i/2, s0, s1); for (state = 0; state < NUM_STATE; state++) { printf (" %5d(%04x)", cost[n][state], bits[n][state]); } @@ -186,7 +209,7 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t * it will be seven. */ int8_t dist = b - (o + 8); /* distance to last ready-for-writing bit */ - uint16_t min_cost; /* lowest cost */ + uint32_t min_cost; /* lowest cost */ uint8_t min_state; /* lowest cost state */ /* Find the best fit at the current point @@ -216,11 +239,23 @@ ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff, *whiten); #endif if (out_len) { - *out++ = (bits[p][min_state] >> dist) ^ *whiten++; + uint8_t byte = (bits[p][min_state] >> dist) ^ *whiten++; + + if (out_len > 2) { + crc = ao_fec_crc_byte(byte, crc); + *out++ = byte; + } else { + *out++ = byte ^ (crc >> 8); + crc <<= 8; + } --out_len; } o += 8; } } +#if AO_PROFILE + ao_fec_decode_start = start_tick; + ao_fec_decode_end = ao_profile_tick(); +#endif return len/16; } diff --git a/src/core/ao_fec_tx.c b/src/core/ao_fec_tx.c index c9c0a3d6..4941d745 100644 --- a/src/core/ao_fec_tx.c +++ b/src/core/ao_fec_tx.c @@ -18,8 +18,9 @@ #include #include +#if AO_FEC_DEBUG void -ao_fec_dump_bytes(uint8_t *bytes, uint16_t len, char *name) +ao_fec_dump_bytes(const uint8_t *bytes, uint16_t len, const char *name) { uint16_t i; @@ -31,29 +32,15 @@ ao_fec_dump_bytes(uint8_t *bytes, uint16_t len, char *name) } printf ("\n"); } - -static uint16_t inline -crc_byte(uint8_t byte, uint16_t crc) -{ - uint8_t bit; - - for (bit = 0; bit < 8; bit++) { - if (((crc & 0x8000) >> 8) ^ (byte & 0x80)) - crc = (crc << 1) ^ 0x8005; - else - crc = (crc << 1); - byte <<= 1; - } - return crc; -} +#endif uint16_t -ao_fec_crc(uint8_t *bytes, uint8_t len) +ao_fec_crc(const uint8_t *bytes, uint8_t len) { uint16_t crc = AO_FEC_CRC_INIT; while (len--) - crc = crc_byte(*bytes++, crc); + crc = ao_fec_crc_byte(*bytes++, crc); return crc; } @@ -63,7 +50,7 @@ ao_fec_crc(uint8_t *bytes, uint8_t len) */ uint8_t -ao_fec_check_crc(uint8_t *bytes, uint8_t len) +ao_fec_check_crc(const uint8_t *bytes, uint8_t len) { uint16_t computed_crc = ao_fec_crc(bytes, len); uint16_t received_crc = (bytes[len] << 8) | (bytes[len+1]); @@ -71,8 +58,11 @@ ao_fec_check_crc(uint8_t *bytes, uint8_t len) return computed_crc == received_crc; } -uint8_t -ao_fec_prepare(uint8_t *in, uint8_t len, uint8_t *extra) +/* + * Compute CRC and trellis-terminator/interleave-pad bytes + */ +static uint8_t +ao_fec_prepare(const uint8_t *in, uint8_t len, uint8_t *extra) { uint16_t crc = ao_fec_crc (in, len); uint8_t i = 0; @@ -93,40 +83,6 @@ const uint8_t ao_fec_whiten_table[] = { #include "ao_whiten.h" }; -#if 0 -void -ao_fec_whiten(uint8_t *in, uint8_t len, uint8_t *out) -{ - const uint8_t *w = ao_fec_whiten_table; - - while (len--) - *out++ = *in++ ^ *w++; -} - -/* - * Unused as interleaving is now built in to ao_fec_encode - */ - -static void -ao_fec_interleave(uint8_t *d, uint8_t len) -{ - uint8_t i, j; - - for (i = 0; i < len; i += 4) { - uint32_t interleaved = 0; - - for (j = 0; j < 4 * 4; j++) { - interleaved <<= 2; - interleaved |= (d[i + (~j & 0x3)] >> (2 * ((j & 0xc) >> 2))) & 0x03; - } - d[i+0] = interleaved >> 24; - d[i+1] = interleaved >> 16; - d[i+2] = interleaved >> 8; - d[i+3] = interleaved; - } -} -#endif - static const uint8_t ao_fec_encode_table[16] = { /* next 0 1 state */ 0, 3, /* 000 */ @@ -140,7 +96,7 @@ static const uint8_t ao_fec_encode_table[16] = { }; uint8_t -ao_fec_encode(uint8_t *in, uint8_t len, uint8_t *out) +ao_fec_encode(const uint8_t *in, uint8_t len, uint8_t *out) { uint8_t extra[AO_FEC_PREPARE_EXTRA]; uint8_t extra_len; diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 394cf7c5..501b9370 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -24,8 +24,9 @@ uint8_t ao_radio_wake; uint8_t ao_radio_mutex; uint8_t ao_radio_abort; +uint8_t ao_radio_in_recv; -#define CC1120_DEBUG 1 +#define CC1120_DEBUG AO_FEC_DEBUG #define CC1120_TRACE 0 #if CC1120_TRACE @@ -34,7 +35,7 @@ uint8_t ao_radio_abort; #define fec_dump_bytes(b,l,n) #endif -uint32_t ao_radio_cal = 0x6ca333; +const uint32_t ao_radio_cal = 0x6ca333; #define FOSC 32000000 @@ -194,6 +195,12 @@ ao_radio_fifo_write_fixed(uint8_t data, uint8_t len) return status; } +static uint8_t +ao_radio_tx_fifo_space(void) +{ + return CC1120_FIFO_SIZE - ao_radio_reg_read(CC1120_NUM_TXBYTES); +} + static uint8_t ao_radio_status(void) { @@ -209,6 +216,97 @@ ao_radio_recv_abort(void) #define ao_radio_rdf_value 0x55 +static uint8_t +ao_radio_marc_status(void) +{ + return ao_radio_reg_read(CC1120_MARC_STATUS1); +} + +static void +ao_radio_tx_isr(void) +{ + ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_wake = 1; + ao_wakeup(&ao_radio_wake); +} + +static void +ao_radio_start_tx(void) +{ + ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_tx_isr); + ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_radio_strobe(CC1120_STX); +} + +static void +ao_radio_idle(void) +{ + for (;;) { + uint8_t state = ao_radio_strobe(CC1120_SIDLE); + if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE) + break; + } +} + +/* + * Packet deviation is 20.5kHz + * + * fdev = fosc >> 24 * (256 + dev_m) << dev_e + * + * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz + */ + +#define PACKET_DEV_E 5 +#define PACKET_DEV_M 80 + +/* + * For our packet data, set the symbol rate to 38360 Baud + * + * (2**20 + DATARATE_M) * 2 ** DATARATE_E + * Rdata = -------------------------------------- * fosc + * 2 ** 39 + * + * + * DATARATE_M = 239914 + * DATARATE_E = 9 + */ +#define PACKET_DRATE_E 9 +#define PACKET_DRATE_M 239914 + +static const uint16_t packet_setup[] = { + CC1120_DEVIATION_M, PACKET_DEV_M, + CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) | + (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) | + (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)), + CC1120_DRATE2, ((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) | + (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)), + CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff), + CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff), + CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | + (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)), + CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) | + (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) | + (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) | + (0 << CC1120_PKT_CFG1_APPEND_STATUS)), + CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) | + (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | + (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | + (0 << CC1120_PKT_CFG0_UART_MODE_EN) | + (0 << CC1120_PKT_CFG0_UART_SWAP_EN)), +}; + +static const uint16_t packet_tx_setup[] = { + CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | + (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)), + CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG, +}; + +static const uint16_t packet_rx_setup[] = { + CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | + (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)), + CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT, +}; + /* * RDF deviation is 5kHz * @@ -259,50 +357,111 @@ static const uint16_t rdf_setup[] = { (0 << CC1120_PKT_CFG0_UART_SWAP_EN)), }; -static uint8_t -ao_radio_marc_status(void) -{ - return ao_radio_reg_read(CC1120_MARC_STATUS1); -} +static uint8_t ao_radio_mode; -static uint8_t -ao_radio_tx_done(void) -{ - return ao_radio_marc_status() == CC1120_MARC_STATUS1_TX_FINISHED; -} +#define AO_RADIO_MODE_BITS_PACKET 1 +#define AO_RADIO_MODE_BITS_PACKET_TX 2 +#define AO_RADIO_MODE_BITS_TX_BUF 4 +#define AO_RADIO_MODE_BITS_TX_FINISH 8 +#define AO_RADIO_MODE_BITS_PACKET_RX 16 +#define AO_RADIO_MODE_BITS_RDF 32 -static uint8_t -ao_radio_rx_done(void) +#define AO_RADIO_MODE_NONE 0 +#define AO_RADIO_MODE_PACKET_TX_BUF (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_BUF) +#define AO_RADIO_MODE_PACKET_TX_FINISH (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_TX | AO_RADIO_MODE_BITS_TX_FINISH) +#define AO_RADIO_MODE_PACKET_RX (AO_RADIO_MODE_BITS_PACKET | AO_RADIO_MODE_BITS_PACKET_RX) +#define AO_RADIO_MODE_RDF (AO_RADIO_MODE_BITS_RDF | AO_RADIO_MODE_BITS_TX_FINISH) + +static void +ao_radio_set_mode(uint8_t new_mode) { - return ao_radio_marc_status() == CC1120_MARC_STATUS1_RX_FINISHED; + uint8_t changes; + int i; + + if (new_mode == ao_radio_mode) + return; + + changes = new_mode & (~ao_radio_mode); + if (changes & AO_RADIO_MODE_BITS_PACKET) + for (i = 0; i < sizeof (packet_setup) / sizeof (packet_setup[0]); i += 2) + ao_radio_reg_write(packet_setup[i], packet_setup[i+1]); + + if (changes & AO_RADIO_MODE_BITS_PACKET_TX) + for (i = 0; i < sizeof (packet_tx_setup) / sizeof (packet_tx_setup[0]); i += 2) + ao_radio_reg_write(packet_tx_setup[i], packet_tx_setup[i+1]); + + if (changes & AO_RADIO_MODE_BITS_TX_BUF) + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_TXFIFO_THR); + + if (changes & AO_RADIO_MODE_BITS_TX_FINISH) + ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); + + if (changes & AO_RADIO_MODE_BITS_PACKET_RX) + for (i = 0; i < sizeof (packet_rx_setup) / sizeof (packet_rx_setup[0]); i += 2) + ao_radio_reg_write(packet_rx_setup[i], packet_rx_setup[i+1]); + + if (changes & AO_RADIO_MODE_BITS_RDF) + for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) + ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]); + ao_radio_mode = new_mode; } +static const uint16_t radio_setup[] = { +#include "ao_cc1120_CC1120.h" +}; + +static uint8_t ao_radio_configured = 0; + static void -ao_radio_tx_isr(void) +ao_radio_setup(void) { - ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - ao_radio_wake = 1; - ao_wakeup(&ao_radio_wake); + int i; + + ao_radio_strobe(CC1120_SRES); + + for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2) + ao_radio_reg_write(radio_setup[i], radio_setup[i+1]); + + ao_radio_mode = 0; + + ao_config_get(); + + ao_radio_configured = 1; } static void -ao_radio_start_tx(void) +ao_radio_get(uint8_t len) { - ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_RX0TX1_CFG); - ao_exti_set_callback(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_tx_isr); - ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - ao_radio_strobe(CC1120_STX); + static uint32_t last_radio_setting; + static uint8_t last_len; + + ao_mutex_get(&ao_radio_mutex); + if (!ao_radio_configured) + ao_radio_setup(); + if (ao_config.radio_setting != last_radio_setting) { + ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16); + ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8); + ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting); + last_radio_setting = ao_config.radio_setting; + } + if (len != last_len) { + ao_radio_reg_write(CC1120_PKT_LEN, len); + last_len = len; + } } +#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) + void ao_radio_rdf(uint8_t len) { int i; + ao_radio_abort = 0; ao_radio_get(len); + + ao_radio_set_mode(AO_RADIO_MODE_RDF); ao_radio_wake = 0; - for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) - ao_radio_reg_write(rdf_setup[i], rdf_setup[i+1]); ao_radio_fifo_write_fixed(ao_radio_rdf_value, len); @@ -311,11 +470,9 @@ ao_radio_rdf(uint8_t len) cli(); while (!ao_radio_wake && !ao_radio_abort) ao_sleep(&ao_radio_wake); - sei(); - if (!ao_radio_tx_done()) + if (!ao_radio_wake) ao_radio_idle(); - ao_radio_set_packet(); ao_radio_put(); } @@ -372,65 +529,113 @@ ao_radio_test(void) } void -ao_radio_send(void *d, uint8_t size) +ao_radio_send(const void *d, uint8_t size) { uint8_t marc_status; - uint8_t encode[size + AO_FEC_PREPARE_EXTRA]; + static uint8_t encode[256]; + uint8_t *e = encode; uint8_t encode_len; + uint8_t this_len; + uint8_t started = 0; + uint8_t fifo_space; encode_len = ao_fec_encode(d, size, encode); ao_radio_get(encode_len); - ao_radio_fifo_write(encode, encode_len); - ao_radio_wake = 0; + started = 0; + fifo_space = CC1120_FIFO_SIZE; + while (encode_len) { + this_len = encode_len; - ao_radio_start_tx(); + if (this_len > fifo_space) { + this_len = fifo_space; + ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_BUF); + } else { + ao_radio_set_mode(AO_RADIO_MODE_PACKET_TX_FINISH); + } - cli(); - while (!ao_radio_wake && !ao_radio_abort) - ao_sleep(&ao_radio_wake); - sei(); - if (!ao_radio_tx_done()) - ao_radio_idle(); + ao_radio_fifo_write(e, this_len); + e += this_len; + encode_len -= this_len; + + if (!started) { + ao_radio_start_tx(); + started = 1; + } else { + ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + } + + do { + ao_radio_wake = 0; + cli(); + while (!ao_radio_wake) + ao_sleep(&ao_radio_wake); + sei(); + if (!encode_len) + break; + fifo_space = ao_radio_tx_fifo_space(); + } while (!fifo_space); + } ao_radio_put(); } #define AO_RADIO_MAX_RECV 90 -static uint8_t rx_data[2048]; -static uint16_t rx_data_count; -static uint16_t rx_data_consumed; -static uint16_t rx_data_cur; -static uint8_t rx_ignore; +uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8]; +uint16_t rx_data_count; +uint16_t rx_data_consumed; +uint16_t rx_data_cur; +uint8_t rx_ignore; +uint8_t rx_waiting; + +#if AO_PROFILE +static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick; + +uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick; + +#include +#endif static void ao_radio_rx_isr(void) { + uint8_t d; + + d = stm_spi2.dr; + stm_spi2.dr = 0; if (rx_ignore == 0) { - rx_data[rx_data_cur++] = stm_spi2.dr; if (rx_data_cur >= rx_data_count) - ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); - if (rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) { + ao_exti_disable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + else + rx_data[rx_data_cur++] = d; + if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) { +#if AO_PROFILE + if (rx_data_consumed == 0) + rx_packet_tick = ao_profile_tick(); +#endif + rx_waiting = 0; ao_wakeup(&ao_radio_wake); } } else { - (void) stm_spi2.dr; --rx_ignore; } - stm_spi2.dr = 0x00; } static uint16_t ao_radio_rx_wait(void) { cli(); + rx_waiting = 1; while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK && - !ao_radio_abort) + !ao_radio_abort) { ao_sleep(&ao_radio_wake); + } + rx_waiting = 0; sei(); if (ao_radio_abort) return 0; + rx_data_consumed += AO_FEC_DECODE_BLOCK; return AO_FEC_DECODE_BLOCK; } @@ -440,8 +645,17 @@ ao_radio_recv(__xdata void *d, uint8_t size) uint8_t len; uint16_t i; uint8_t rssi; + uint8_t ret; + static int been_here = 0; size -= 2; /* status bytes */ + if (size > AO_RADIO_MAX_RECV) { + ao_delay(AO_SEC_TO_TICKS(1)); + return 0; + } +#if AO_PROFILE + rx_start_tick = ao_profile_tick(); +#endif len = size + 2; /* CRC bytes */ len += 1 + ~(len & 1); /* 1 or two pad bytes */ len *= 2; /* 1/2 rate convolution */ @@ -450,162 +664,65 @@ ao_radio_recv(__xdata void *d, uint8_t size) rx_data_consumed = 0; rx_ignore = 2; - printf ("len %d rx_data_count %d\n", len, rx_data_count); - + ao_radio_abort = 0; + ao_radio_in_recv = 1; /* configure interrupt pin */ ao_radio_get(len); - ao_radio_wake = 0; - ao_radio_abort = 0; - - ao_radio_reg_write(CC1120_PKT_CFG2, - (CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | - (CC1120_PKT_CFG2_PKT_FORMAT_SYNCHRONOUS_SERIAL << CC1120_PKT_CFG2_PKT_FORMAT)); + ao_radio_set_mode(AO_RADIO_MODE_PACKET_RX); - ao_radio_reg_write(CC1120_EXT_CTRL, 0); - - ao_radio_reg_write(CC1120_IOCFG2, CC1120_IOCFG_GPIO_CFG_CLKEN_SOFT); + ao_radio_wake = 0; stm_spi2.cr2 = 0; /* clear any RXNE */ (void) stm_spi2.dr; - ao_exti_set_callback(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr); - ao_exti_enable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); + ao_exti_set_callback(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, ao_radio_rx_isr); + ao_exti_enable(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN); ao_radio_strobe(CC1120_SRX); ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT); - ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait); + ret = ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait); ao_radio_burst_read_stop(); + ao_radio_strobe(CC1120_SIDLE); + /* Convert from 'real' rssi to cc1111-style values */ rssi = (((int8_t) ao_radio_reg_read(CC1120_RSSI1)) + 74) * 2; - ao_radio_strobe(CC1120_SIDLE); - ao_radio_put(); /* Construct final packet */ - ao_fec_decode(rx_data, rx_data_cur, d, size + 2, 0); - - if (ao_fec_check_crc(d, size)) + if (ret && ((uint8_t *) d)[size] == 0 && ((uint8_t *)d)[size+1] == 0) ((uint8_t *) d)[size + 1] = 0x80; else ((uint8_t *) d)[size + 1] = 0x00; ((uint8_t *) d)[size] = (uint8_t) rssi; - return 1; -} - -/* - * Packet deviation is 20.5kHz - * - * fdev = fosc >> 24 * (256 + dev_m) << dev_e - * - * 32e6Hz / (2 ** 24) * (256 + 80) * (2 ** 5) = 20508Hz - */ - -#define PACKET_DEV_E 5 -#define PACKET_DEV_M 80 - -/* - * For our packet data, set the symbol rate to 38360 Baud - * - * (2**20 + DATARATE_M) * 2 ** DATARATE_E - * Rdata = -------------------------------------- * fosc - * 2 ** 39 - * - * - * DATARATE_M = 239914 - * DATARATE_E = 9 - */ -#define PACKET_DRATE_E 9 -#define PACKET_DRATE_M 239914 + ao_radio_in_recv = 0; -static const uint16_t packet_setup[] = { - CC1120_DEVIATION_M, PACKET_DEV_M, - CC1120_MODCFG_DEV_E, ((CC1120_MODCFG_DEV_E_MODEM_MODE_NORMAL << CC1120_MODCFG_DEV_E_MODEM_MODE) | - (CC1120_MODCFG_DEV_E_MOD_FORMAT_2_GFSK << CC1120_MODCFG_DEV_E_MOD_FORMAT) | - (PACKET_DEV_E << CC1120_MODCFG_DEV_E_DEV_E)), - CC1120_DRATE2, ((PACKET_DRATE_E << CC1120_DRATE2_DATARATE_E) | - (((PACKET_DRATE_M >> 16) & CC1120_DRATE2_DATARATE_M_19_16_MASK) << CC1120_DRATE2_DATARATE_M_19_16)), - CC1120_DRATE1, ((PACKET_DRATE_M >> 8) & 0xff), - CC1120_DRATE0, ((PACKET_DRATE_M >> 0) & 0xff), - CC1120_PKT_CFG2, ((CC1120_PKT_CFG2_CCA_MODE_ALWAYS_CLEAR << CC1120_PKT_CFG2_CCA_MODE) | - (CC1120_PKT_CFG2_PKT_FORMAT_NORMAL << CC1120_PKT_CFG2_PKT_FORMAT)), - CC1120_PKT_CFG1, ((0 << CC1120_PKT_CFG1_WHITE_DATA) | - (CC1120_PKT_CFG1_ADDR_CHECK_CFG_NONE << CC1120_PKT_CFG1_ADDR_CHECK_CFG) | - (CC1120_PKT_CFG1_CRC_CFG_DISABLED << CC1120_PKT_CFG1_CRC_CFG) | - (1 << CC1120_PKT_CFG1_APPEND_STATUS)), - CC1120_PKT_CFG0, ((0 << CC1120_PKT_CFG0_RESERVED7) | - (CC1120_PKT_CFG0_LENGTH_CONFIG_FIXED << CC1120_PKT_CFG0_LENGTH_CONFIG) | - (0 << CC1120_PKT_CFG0_PKG_BIT_LEN) | - (0 << CC1120_PKT_CFG0_UART_MODE_EN) | - (0 << CC1120_PKT_CFG0_UART_SWAP_EN)), -}; - -void -ao_radio_set_packet(void) -{ - int i; - - for (i = 0; i < sizeof (rdf_setup) / sizeof (rdf_setup[0]); i += 2) - ao_radio_reg_write(packet_setup[i], packet_setup[i+1]); -} - -void -ao_radio_idle(void) -{ - for (;;) { - uint8_t state = ao_radio_strobe(CC1120_SIDLE); - if ((state >> CC1120_STATUS_STATE) == CC1120_STATUS_STATE_IDLE) - break; - } - ao_radio_strobe(CC1120_SFTX); - ao_radio_strobe(CC1120_SFRX); -} - -static const uint16_t radio_setup[] = { -#include "ao_cc1120_CC1120.h" -}; - -static uint8_t ao_radio_configured = 0; - - -static void -ao_radio_setup(void) -{ - int i; - - ao_radio_strobe(CC1120_SRES); - - for (i = 0; i < sizeof (radio_setup) / sizeof (radio_setup[0]); i += 2) - ao_radio_reg_write(radio_setup[i], radio_setup[i+1]); + if (ao_radio_abort) + ao_delay(1); - ao_radio_set_packet(); +#if AO_PROFILE + rx_last_done_tick = rx_done_tick; + rx_done_tick = ao_profile_tick(); - ao_config_get(); + ao_rx_start_tick = rx_start_tick; + ao_rx_packet_tick = rx_packet_tick; + ao_rx_done_tick = rx_done_tick; + ao_rx_last_done_tick = rx_last_done_tick; +#endif - ao_radio_configured = 1; + return ret; } -void -ao_radio_get(uint8_t len) -{ - ao_mutex_get(&ao_radio_mutex); - if (!ao_radio_configured) - ao_radio_setup(); - ao_radio_reg_write(CC1120_FREQ2, ao_config.radio_setting >> 16); - ao_radio_reg_write(CC1120_FREQ1, ao_config.radio_setting >> 8); - ao_radio_reg_write(CC1120_FREQ0, ao_config.radio_setting); - ao_radio_reg_write(CC1120_PKT_LEN, len); -} #if CC1120_DEBUG static char *cc1120_state_name[] = { @@ -824,7 +941,7 @@ static void ao_radio_beep(void) { } static void ao_radio_packet(void) { - static uint8_t packet[] = { + static const uint8_t packet[] = { #if 1 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, @@ -841,7 +958,19 @@ static void ao_radio_packet(void) { void ao_radio_test_recv() { - ao_radio_recv(0, 34); + uint8_t bytes[34]; + uint8_t b; + + if (ao_radio_recv(bytes, 34)) { + if (bytes[33] & 0x80) + printf ("CRC OK"); + else + printf ("CRC BAD"); + printf (" RSSI %d", (int16_t) ((int8_t) bytes[32] >> 1) - 74); + for (b = 0; b < 32; b++) + printf (" %02x", bytes[b]); + printf ("\n"); + } } #endif @@ -865,18 +994,20 @@ ao_radio_init(void) ao_radio_configured = 0; ao_spi_init_cs (AO_CC1120_SPI_CS_PORT, (1 << AO_CC1120_SPI_CS_PIN)); - AO_CC1120_SPI_CS_PORT.bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN)); + AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN)); for (i = 0; i < 10000; i++) { - if ((SPI_2_GPIO.idr & (1 << SPI_2_MISO)) == 0) + if ((SPI_2_GPIO->idr & (1 << SPI_2_MISO)) == 0) break; } - AO_CC1120_SPI_CS_PORT.bsrr = (1 << AO_CC1120_SPI_CS_PIN); + AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN); if (i == 10000) ao_panic(AO_PANIC_SELF_TEST); /* Enable the EXTI interrupt for the appropriate pin */ ao_enable_port(AO_CC1120_INT_PORT); - ao_exti_setup(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, AO_EXTI_MODE_FALLING, ao_radio_tx_isr); + ao_exti_setup(AO_CC1120_INT_PORT, AO_CC1120_INT_PIN, + AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_HIGH, + ao_radio_tx_isr); ao_cmd_register(&ao_radio_cmds[0]); } diff --git a/src/drivers/ao_cc1120.h b/src/drivers/ao_cc1120.h index 5822a21a..60b9621e 100644 --- a/src/drivers/ao_cc1120.h +++ b/src/drivers/ao_cc1120.h @@ -181,6 +181,11 @@ #define CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_MASK 3 #define CC1120_PREAMBLE_CFG0 0x0e +#define CC1120_PREAMBLE_CFG0_PQT_EN 5 +#define CC1120_PREAMBLE_CFG0_PQT_VALID_TIMEOUT 4 +#define CC1120_PREAMBLE_CFG0_PQT 0 +#define CC1120_PREAMBLE_CFG0_PQT_MASK 0xf + #define CC1120_FREQ_IF_CFG 0x0f #define CC1120_IQIC 0x10 #define CC1120_CHAN_BW 0x11 @@ -215,6 +220,8 @@ #define CC1120_AGC_CFG1 0x1c #define CC1120_AGC_CFG0 0x1d #define CC1120_FIFO_CFG 0x1e +#define CC1120_FIFO_CFG_CRC_AUTOFLUSH 7 +#define CC1120_FIFO_CFG_FIFO_THR 0 #define CC1120_DEV_ADDR 0x1f #define CC1120_SETTLING_CFG 0x20 #define CC1120_SETTLING_CFG_FS_AUTOCAL 3 @@ -321,6 +328,8 @@ #define CC1120_DIRECT_FIFO 0x3e #define CC1120_FIFO 0x3f +#define CC1120_FIFO_SIZE 128 + /* Extended register space */ #define CC1120_EXTENDED_BIT 0x8000 diff --git a/src/drivers/ao_cc1120_CC1120.h b/src/drivers/ao_cc1120_CC1120.h index c0f35a23..5376afd5 100644 --- a/src/drivers/ao_cc1120_CC1120.h +++ b/src/drivers/ao_cc1120_CC1120.h @@ -26,7 +26,9 @@ CC1120_SYNC1, 0xD3, /* Sync Word Configuration [15:8] */ CC1120_SYNC0, 0x91, /* Sync Word Configuration [7:0] */ - CC1120_SYNC_CFG1, 0x08, /* Sync Word Detection Configuration */ + CC1120_SYNC_CFG1, /* Sync Word Detection Configuration */ + (CC1120_SYNC_CFG1_DEM_CFG_PQT_GATING_ENABLED << CC1120_SYNC_CFG1_DEM_CFG) | + (0x07 << CC1120_SYNC_CFG1_SYNC_THR), CC1120_SYNC_CFG0, (CC1120_SYNC_CFG0_SYNC_MODE_16_BITS << CC1120_SYNC_CFG0_SYNC_MODE) | (CC1120_SYNC_CFG0_SYNC_NUM_ERROR_2 << CC1120_SYNC_CFG0_SYNC_NUM_ERROR), @@ -34,12 +36,21 @@ CC1120_PREAMBLE_CFG1, /* Preamble Length Configuration */ (CC1120_PREAMBLE_CFG1_NUM_PREAMBLE_4_BYTES << CC1120_PREAMBLE_CFG1_NUM_PREAMBLE) | (CC1120_PREAMBLE_CFG1_PREAMBLE_WORD_AA << CC1120_PREAMBLE_CFG1_PREAMBLE_WORD), - CC1120_PREAMBLE_CFG0, 0x2a, /* */ + CC1120_PREAMBLE_CFG0, + (1 << CC1120_PREAMBLE_CFG0_PQT_EN) | + (0x6 << CC1120_PREAMBLE_CFG0_PQT), CC1120_FREQ_IF_CFG, 0x40, /* RX Mixer Frequency Configuration */ CC1120_IQIC, 0x46, /* Digital Image Channel Compensation Configuration */ CC1120_CHAN_BW, 0x02, /* Channel Filter Configuration */ - CC1120_MDMCFG1, 0x46, /* General Modem Parameter Configuration */ + CC1120_MDMCFG1, /* General Modem Parameter Configuration */ + (0 << CC1120_MDMCFG1_CARRIER_SENSE_GATE) | + (1 << CC1120_MDMCFG1_FIFO_EN) | + (0 << CC1120_MDMCFG1_MANCHESTER_EN) | + (0 << CC1120_MDMCFG1_INVERT_DATA_EN) | + (0 << CC1120_MDMCFG1_COLLISION_DETECT_EN) | + (CC1120_MDMCFG1_DVGA_GAIN_9 << CC1120_MDMCFG1_DVGA_GAIN) | + (0 << CC1120_MDMCFG1_SINGLE_ADC_EN), CC1120_MDMCFG0, 0x05, /* General Modem Parameter Configuration */ CC1120_AGC_REF, 0x20, /* AGC Reference Level Configuration */ @@ -49,7 +60,9 @@ CC1120_AGC_CFG2, 0x20, /* AGC Configuration */ CC1120_AGC_CFG1, 0xa9, /* AGC Configuration */ CC1120_AGC_CFG0, 0xcf, /* AGC Configuration */ - CC1120_FIFO_CFG, 0x00, /* FIFO Configuration */ + CC1120_FIFO_CFG, /* FIFO Configuration */ + (0 << CC1120_FIFO_CFG_CRC_AUTOFLUSH) | + (0x40 << CC1120_FIFO_CFG_FIFO_THR), CC1120_DEV_ADDR, 0x00, /* Device Address Configuration */ CC1120_SETTLING_CFG, /* Frequency Synthesizer Calibration and Settling Configuration */ (CC1120_SETTLING_CFG_FS_AUTOCAL_IDLE_TO_ON << CC1120_SETTLING_CFG_FS_AUTOCAL) | @@ -65,12 +78,12 @@ #if 0 CC1120_PKT_CFG2, 0x04, /* Packet Configuration, Reg 2 */ CC1120_PKT_CFG1, 0x45, /* Packet Configuration, Reg 1 */ -#endif CC1120_PKT_CFG0, 0x00, /* Packet Configuration, Reg 0 */ +#endif CC1120_RFEND_CFG1, 0x0f, /* RFEND Configuration, Reg 1 */ CC1120_RFEND_CFG0, 0x00, /* RFEND Configuration, Reg 0 */ // CC1120_PA_CFG2, 0x3f, /* Power Amplifier Configuration, Reg 2 */ - CC1120_PA_CFG2, 0x23, /* Power Amplifier Configuration, Reg 2 */ + CC1120_PA_CFG2, 0x04, /* Power Amplifier Configuration, Reg 2 */ CC1120_PA_CFG1, 0x56, /* Power Amplifier Configuration, Reg 1 */ CC1120_PA_CFG0, 0x7b, /* Power Amplifier Configuration, Reg 0 */ CC1120_PKT_LEN, 0xff, /* Packet Length Configuration */ @@ -80,7 +93,7 @@ CC1120_MARC_SPARE, 0x00, /* MARC Spare */ CC1120_ECG_CFG, 0x00, /* External Clock Frequency Configuration */ CC1120_SOFT_TX_DATA_CFG, 0x00, /* Soft TX Data Configuration */ - CC1120_EXT_CTRL, 0x01, /* External Control Configuration */ + CC1120_EXT_CTRL, 0x00, /* External Control Configuration */ CC1120_RCCAL_FINE, 0x00, /* RC Oscillator Calibration (fine) */ CC1120_RCCAL_COARSE, 0x00, /* RC Oscillator Calibration (coarse) */ CC1120_RCCAL_OFFSET, 0x00, /* RC Oscillator Calibration Clock Offset */ diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index bbd1b3b1..30cd9ea5 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -25,7 +25,7 @@ * STM32L definitions and code fragments for AltOS */ -#define AO_STACK_SIZE 1024 +#define AO_STACK_SIZE 512 #define AO_LED_TYPE uint16_t @@ -111,14 +111,22 @@ extern const uint16_t ao_serial_number; uint32_t *sp; \ asm("mov %0,sp" : "=&r" (sp) ); \ ao_cur_task->sp = (sp); \ - if ((uint8_t *) sp < ao_cur_task->stack) \ + if ((uint8_t *) sp < &ao_cur_task->stack[0]) \ ao_panic (AO_PANIC_STACK); \ } while (0) -#define ao_arch_isr_stack() /* nothing */ +#if 0 +#define ao_arch_isr_stack() do { \ + uint32_t *sp = (uint32_t *) 0x20004000; \ + asm("mov %0,sp" : "=&r" (sp) ); \ + } while (0) +#else +#define ao_arch_isr_stack() +#endif + #define ao_arch_cpu_idle() do { \ - asm("wfi"); \ + asm("wfi"); \ } while (0) #define ao_arch_restore_stack() do { \ @@ -173,6 +181,11 @@ extern const uint16_t ao_serial_number; #define AO_TIM91011_CLK (2 * AO_PCLK2) #endif +#define AO_STM_NVIC_HIGH_PRIORITY 4 +#define AO_STM_NVIC_CLOCK_PRIORITY 6 +#define AO_STM_NVIC_MED_PRIORITY 8 +#define AO_STM_NVIC_LOW_PRIORITY 10 + void ao_lcd_stm_init(void); void ao_lcd_font_init(void); @@ -215,7 +228,7 @@ ao_serial3_pollchar(void); void ao_serial3_set_speed(uint8_t speed); -extern uint32_t ao_radio_cal; +extern const uint32_t ao_radio_cal; void ao_adc_init(); diff --git a/src/stm/ao_exti.h b/src/stm/ao_exti.h index 87a072e7..b579ad9f 100644 --- a/src/stm/ao_exti.h +++ b/src/stm/ao_exti.h @@ -22,6 +22,9 @@ #define AO_EXTI_MODE_FALLING 2 #define AO_EXTI_MODE_PULL_UP 4 #define AO_EXTI_MODE_PULL_DOWN 8 +#define AO_EXTI_PRIORITY_LOW 16 +#define AO_EXTI_PRIORITY_MED 0 +#define AO_EXTI_PRIORITY_HIGH 32 void ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)()); diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c index 683a91b3..d54e6ee6 100644 --- a/src/stm/ao_exti_stm.c +++ b/src/stm/ao_exti_stm.c @@ -20,37 +20,50 @@ static void (*ao_exti_callback[16])(void); -static void -ao_exti_isr(void) { - uint32_t pending = stm_exti.pr; - uint8_t pin; +uint32_t ao_last_exti; + +static void ao_exti_one_isr(uint8_t pin) { + uint32_t pending = (ao_last_exti = stm_exti.pr) & (1 << pin); - /* Clear pending interrupts */ stm_exti.pr = pending; - for (pin = 0; pin < 16 && pending; pin++) { - uint32_t mask = (1 << pin); + if (pending && ao_exti_callback[pin]) + (*ao_exti_callback[pin])(); +} - if (pending & mask) { - pending &= ~mask; - if (ao_exti_callback[pin]) - (*ao_exti_callback[pin])(); - } +static void ao_exti_range_isr(uint8_t first, uint8_t last, uint16_t mask) { + uint16_t pending = (ao_last_exti = stm_exti.pr) & mask; + uint8_t pin; + static uint16_t last_mask; + static uint8_t last_pin; + + if (pending == last_mask) { + stm_exti.pr = last_mask; + (*ao_exti_callback[last_pin])(); + return; } + stm_exti.pr = pending; + for (pin = first; pin <= last; pin++) + if ((pending & ((uint32_t) 1 << pin)) && ao_exti_callback[pin]) { + last_mask = (1 << pin); + last_pin = pin; + (*ao_exti_callback[pin])(); + } } -void stm_exti0_isr(void) { ao_exti_isr(); } -void stm_exti1_isr(void) { ao_exti_isr(); } -void stm_exti2_isr(void) { ao_exti_isr(); } -void stm_exti3_isr(void) { ao_exti_isr(); } -void stm_exti4_isr(void) { ao_exti_isr(); } -void stm_exti9_5_isr(void) { ao_exti_isr(); } -void stm_exti15_10_isr(void) { ao_exti_isr(); } +void stm_exti0_isr(void) { ao_exti_one_isr(0); } +void stm_exti1_isr(void) { ao_exti_one_isr(1); } +void stm_exti2_isr(void) { ao_exti_one_isr(2); } +void stm_exti3_isr(void) { ao_exti_one_isr(3); } +void stm_exti4_isr(void) { ao_exti_one_isr(4); } +void stm_exti9_5_isr(void) { ao_exti_range_isr(5, 9, 0x3e0); } +void stm_exti15_10_isr(void) { ao_exti_range_isr(10, 15, 0xfc00); } void ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)(void)) { uint32_t mask = 1 << pin; uint32_t pupdr; uint8_t irq; + uint8_t prio; ao_exti_callback[pin] = callback; @@ -90,7 +103,15 @@ ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback irq = STM_ISR_EXTI9_5_POS; else irq = STM_ISR_EXTI15_10_POS; - stm_nvic_set_priority(irq, 10); + + /* Set priority */ + prio = AO_STM_NVIC_MED_PRIORITY; + if (mode & AO_EXTI_PRIORITY_LOW) + prio = AO_STM_NVIC_LOW_PRIORITY; + else if (mode & AO_EXTI_PRIORITY_HIGH) + prio = AO_STM_NVIC_HIGH_PRIORITY; + + stm_nvic_set_priority(irq, prio); stm_nvic_set_enable(irq); } @@ -116,10 +137,10 @@ ao_exti_disable(struct stm_gpio *gpio, uint8_t pin) { void ao_exti_init(void) { - stm_nvic_set_priority(STM_ISR_EXTI1_POS, 10); - stm_nvic_set_priority(STM_ISR_EXTI2_POS, 10); - stm_nvic_set_priority(STM_ISR_EXTI3_POS, 10); - stm_nvic_set_priority(STM_ISR_EXTI4_POS, 10); - stm_nvic_set_priority(STM_ISR_EXTI9_5_POS, 10); - stm_nvic_set_priority(STM_ISR_EXTI15_10_POS, 10); + stm_nvic_set_priority(STM_ISR_EXTI1_POS, AO_STM_NVIC_MED_PRIORITY); + stm_nvic_set_priority(STM_ISR_EXTI2_POS, AO_STM_NVIC_MED_PRIORITY); + stm_nvic_set_priority(STM_ISR_EXTI3_POS, AO_STM_NVIC_MED_PRIORITY); + stm_nvic_set_priority(STM_ISR_EXTI4_POS, AO_STM_NVIC_MED_PRIORITY); + stm_nvic_set_priority(STM_ISR_EXTI9_5_POS, AO_STM_NVIC_MED_PRIORITY); + stm_nvic_set_priority(STM_ISR_EXTI15_10_POS, AO_STM_NVIC_MED_PRIORITY); } diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index d3378648..26227086 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -23,7 +23,8 @@ struct ao_spi_stm_info { struct stm_spi *stm_spi; }; -uint8_t ao_spi_mutex[STM_NUM_SPI]; +uint8_t ao_spi_mutex[STM_NUM_SPI]; +uint16_t ao_spi_speed[STM_NUM_SPI]; static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = { { @@ -282,7 +283,7 @@ ao_spi_get(uint8_t spi_index) (1 << STM_SPI_CR1_SSI) | /* ... */ (0 << STM_SPI_CR1_LSBFIRST) | /* Big endian */ (1 << STM_SPI_CR1_SPE) | /* Enable SPI unit */ - (STM_SPI_CR1_BR_PCLK_16 << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ + (ao_spi_speed[spi_index] << STM_SPI_CR1_BR) | /* baud rate to pclk/4 */ (1 << STM_SPI_CR1_MSTR) | (0 << STM_SPI_CR1_CPOL) | /* Format 0 */ (0 << STM_SPI_CR1_CPHA)); @@ -310,6 +311,7 @@ ao_spi_channel_init(uint8_t spi_index) (0 << STM_SPI_CR2_SSOE) | (0 << STM_SPI_CR2_TXDMAEN) | (0 << STM_SPI_CR2_RXDMAEN)); + ao_spi_speed[spi_index] = AO_SPI_SPEED_FAST; } void diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 0c44f352..936dc881 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -87,7 +87,7 @@ void ao_timer_init(void) { stm_nvic_set_enable(STM_ISR_TIM6_POS); - stm_nvic_set_priority(STM_ISR_TIM6_POS, 1); + stm_nvic_set_priority(STM_ISR_TIM6_POS, AO_STM_NVIC_CLOCK_PRIORITY); /* Turn on timer 6 */ stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN); diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c index e8d3d8b1..8ce532c8 100644 --- a/src/test/ao_fec_test.c +++ b/src/test/ao_fec_test.c @@ -74,6 +74,12 @@ gaussian_random(double mean, double dev) #define DECODE_LEN(input_len) ((input_len) + AO_FEC_PREPARE_EXTRA) #define EXPAND_LEN(input_len) (ENCODE_LEN(input_len) * 8) +static uint8_t ao_bit(uint8_t b) { + if (b) + return 0x00; + return 0xff; +} + static int ao_expand(uint8_t *bits, int bits_len, uint8_t *bytes) { @@ -83,7 +89,7 @@ ao_expand(uint8_t *bits, int bits_len, uint8_t *bytes) for (i = 0; i < bits_len; i++) { b = bits[i]; for (bit = 7; bit >= 0; bit--) - *bytes++ = ((b >> bit) & 1) * 0xff; + *bytes++ = ao_bit ((b >> bit) & 1); } return bits_len * 8; @@ -127,7 +133,7 @@ ao_random_data(uint8_t *out, uint8_t out_len) static uint8_t real_packet[] = { - 0x00, 0x40, 0x38, 0xcd, 0x38, 0x3d, 0x34, 0xca, 0x31, 0xc3, 0xc1, 0xc6, 0x35, 0xcc, 0x3a, 0x3c, + 0x40, 0x38, 0xcd, 0x38, 0x3d, 0x34, 0xca, 0x31, 0xc3, 0xc1, 0xc6, 0x35, 0xcc, 0x3a, 0x3c, 0x3c, 0x3d, 0x3c, 0x37, 0xc5, 0xc1, 0xc0, 0xc1, 0xc1, 0xc3, 0xc0, 0xc1, 0xc6, 0x38, 0x3b, 0xc6, 0xc0, 0xc6, 0x32, 0xc9, 0xc9, 0x34, 0xcf, 0x35, 0xcf, 0x3a, 0x3b, 0xc6, 0xc7, 0x35, 0xcf, 0x36, 0xce, 0x37, 0xc8, 0xc8, 0x3a, 0x3c, 0xc9, 0xc8, 0x3a, 0x3c, 0xcc, 0x32, 0xcd, 0x32, 0xce, 0x32, @@ -258,22 +264,24 @@ static uint8_t real_packet[] = { }; -void +int ao_real_packet(void) { uint8_t decode[64]; uint8_t decode_len; - int off; + int ok = 0; - for (off = 0; off < sizeof (real_packet) - 576; off++) { - decode_len = ao_fec_decode(real_packet+off, 576, decode, 34, NULL); + decode_len = ao_fec_decode(real_packet, 576, decode, 34, NULL); - if (ao_fec_check_crc(decode, 32)) { - printf ("match at %d\n", off); + if (decode[32] == 0 && decode[33] == 0) { + printf ("match\n"); - ao_fec_dump_bytes(decode, decode_len, "Decode"); - } + ao_fec_dump_bytes(decode, decode_len, "Decode"); + ok = 1; + } else { + printf ("actual packet crc error\n"); } + return ok; } int @@ -299,9 +307,11 @@ main(int argc, char **argv) int errors = 0; int error; - ao_real_packet(); exit(0); + if (!ao_real_packet()) + errors++; + srandom(0); - for (trial = 0; trial < 10000; trial++) { + for (trial = 0; trial < 100000; trial++) { /* Compute some random data */ original_len = ao_random_data(original, sizeof(original)); @@ -313,7 +323,7 @@ main(int argc, char **argv) transmit_len = ao_expand(encode, encode_len, transmit); /* Add gaussian noise to the signal */ - receive_errors = ao_fuzz(transmit, transmit_len, receive, 0x30); + receive_errors = ao_fuzz(transmit, transmit_len, receive, 0x38); receive_len = transmit_len; /* Decode it */ @@ -327,7 +337,7 @@ main(int argc, char **argv) error++; } - if (!ao_fec_check_crc(decode, original_len)) { + if (decode[original_len] != 0 || decode[original_len+1] != 0) { printf ("crc mis-match\n"); error++; } @@ -343,6 +353,7 @@ main(int argc, char **argv) errors += error; } } + printf ("%d packets coded\n", trial); return errors; } -- cgit v1.2.3 From b5f5fd92109ac6f4909a81303d52bc9220cc2520 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:13:14 -0700 Subject: altos: custom hex printer for telemetry packets Using printf is way too slow with pdclib; just hand-write hex byte output. Signed-off-by: Keith Packard --- src/core/ao_monitor.c | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 4ca641b7..51d61425 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -103,6 +103,13 @@ ao_monitor_blink(void) #if HAS_MONITOR_PUT +static const char xdigit[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' +}; + +#define hex(c) do { putchar(xdigit[(c) >> 4]); putchar(xdigit[(c)&0xf]); } while (0) + void ao_monitor_put(void) { @@ -210,14 +217,27 @@ ao_monitor_put(void) break; #endif /* LEGACY_MONITOR */ default: - printf ("TELEM %02x", ao_monitoring + 2); +#if AO_PROFILE + { + extern uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick; + extern uint32_t ao_fec_decode_start, ao_fec_decode_end; + + printf ("between packet: %d\n", ao_rx_start_tick - ao_rx_last_done_tick); + printf ("receive start delay: %d\n", ao_rx_packet_tick - ao_rx_start_tick); + printf ("decode time: %d\n", ao_fec_decode_end - ao_fec_decode_start); + printf ("rx cleanup: %d\n", ao_rx_done_tick - ao_fec_decode_end); + } +#endif + printf("TELEM "); + hex((uint8_t) (ao_monitoring + 2)); sum = 0x5a; for (state = 0; state < ao_monitoring + 2; state++) { byte = recv_raw.packet[state]; sum += byte; - printf("%02x", byte); + hex(byte); } - printf("%02x\n", sum); + hex(sum); + putchar ('\n'); #if HAS_RSSI if (recv_raw.packet[ao_monitoring + 1] & PKT_APPEND_STATUS_1_CRC_OK) { rssi = ((int16_t) recv_raw.packet[ao_monitoring] >> 1) - 74; -- cgit v1.2.3 From c4036bf6e7997b618f89a05dd1214c16066ba2b2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:14:13 -0700 Subject: altos: Turn radio-related bits of ao_flight_mm.c Now that MM has full radio functionality, we can make it work right. Signed-off-by: Keith Packard --- src/core/ao_flight_mm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/core/ao_flight_mm.c b/src/core/ao_flight_mm.c index 28b9869f..a0affc48 100644 --- a/src/core/ao_flight_mm.c +++ b/src/core/ao_flight_mm.c @@ -87,7 +87,7 @@ ao_flight(void) * - pad mode if we're upright, * - idle mode otherwise */ -#if HAS_ACCEL && 0 +#if HAS_ACCEL if (ao_config.accel_plus_g == 0 || ao_config.accel_minus_g == 0 || ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || @@ -105,14 +105,14 @@ ao_flight(void) } else #endif if (!ao_flight_force_idle -#if HAS_ACCEL && 0 +#if HAS_ACCEL && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP #endif ) { /* Set pad mode - we can fly! */ ao_flight_state = ao_flight_pad; -#if HAS_USB && HAS_RADIO && 0 +#if HAS_USB && HAS_RADIO /* Disable the USB controller in flight mode * to save power */ -- cgit v1.2.3 From 1ae69a1c2ce7e45db9d9c175bc63867eff68ebe5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:15:54 -0700 Subject: altos: Make gcc happy with ao_telemetry_set_interval Using unsigned locals made GCC sad as it was compared with a signed value. Signed-off-by: Keith Packard --- src/core/ao_telemetry.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 9000a149..b3ce8ba9 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -333,7 +333,7 @@ ao_telemetry(void) void ao_telemetry_set_interval(uint16_t interval) { - uint8_t cur = 0; + int8_t cur = 0; ao_telemetry_interval = interval; #if AO_SEND_MEGA -- cgit v1.2.3 From 097b337eb9b7deff13d5dcdafddec9bec3868b93 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:17:00 -0700 Subject: altos: Abort radio receive when using flash memory on megametrum Radio receive camps on the SPI bus, making it impossible to access flash memory. Abort any pending receive operation when trying to get to the flash part. Yes, this is a total hack. Signed-off-by: Keith Packard --- src/drivers/ao_m25.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/drivers/ao_m25.c b/src/drivers/ao_m25.c index c807cd68..2983a405 100644 --- a/src/drivers/ao_m25.c +++ b/src/drivers/ao_m25.c @@ -99,7 +99,18 @@ static __xdata uint8_t ao_m25_mutex; static __xdata uint8_t ao_m25_instruction[4]; -#define M25_SELECT(cs) ao_spi_get_mask(AO_M25_SPI_CS_PORT,cs,AO_M25_SPI_BUS) +#if HAS_BOOT_RADIO +extern uint8_t ao_radio_in_recv; + +static void ao_boot_radio(void) { + if (ao_radio_in_recv) + ao_radio_recv_abort(); +} +#else +#define ao_boot_radio() +#endif + +#define M25_SELECT(cs) do { ao_boot_radio(); ao_spi_get_mask(AO_M25_SPI_CS_PORT,cs,AO_M25_SPI_BUS); } while (0) #define M25_DESELECT(cs) ao_spi_put_mask(AO_M25_SPI_CS_PORT,cs,AO_M25_SPI_BUS) #define M25_BLOCK_SHIFT 16 -- cgit v1.2.3 From fb2b83fcd28199d8c686e676d46d6ecfbf706f37 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:18:44 -0700 Subject: altos: Create a 32-bit 1MHz timer for use in profiling execution This provides a simple method for getting high-resolution timer data to use in performance tuning code. It's not used by default anywhere. Signed-off-by: Keith Packard --- src/stm/ao_profile.c | 112 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/stm/ao_profile.h | 34 ++++++++++++++++ src/stm/stm32l.h | 10 +++-- 3 files changed, 152 insertions(+), 4 deletions(-) create mode 100644 src/stm/ao_profile.c create mode 100644 src/stm/ao_profile.h (limited to 'src') diff --git a/src/stm/ao_profile.c b/src/stm/ao_profile.c new file mode 100644 index 00000000..149ca29f --- /dev/null +++ b/src/stm/ao_profile.c @@ -0,0 +1,112 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +static void ao_profile_test(void) +{ + uint8_t i; + uint32_t ticks[20]; + + for (i = 0; i < 20; i++) { + ticks[i] = ao_profile_tick(); + ao_delay(0); + } + for (i = 0; i < 19; i++) + printf ("%d\n", ticks[i+1] - ticks[i]); +} + +static const struct ao_cmds ao_profile_cmds[] = { + { ao_profile_test, "P\0Test profile counter" }, + { 0, NULL } +}; + +void ao_profile_init(void) +{ + /* Turn on timer 2 and 4 */ + stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM2EN) | + (1 << STM_RCC_APB1ENR_TIM4EN); + + /* disable timers */ + stm_tim4.cr1 = 0; + stm_tim2.cr1 = 0; + + /* tim4 is master */ + + + stm_tim4.cr2 = ((0 << STM_TIM234_CR2_TI1S) | + (STM_TIM234_CR2_MMS_UPDATE << STM_TIM234_CR2_MMS) | + (0 << STM_TIM234_CR2_CCDS)); + + stm_tim4.smcr = ((0 << STM_TIM234_SMCR_ETP) | + (0 << STM_TIM234_SMCR_ECE) | + (STM_TIM234_SMCR_ETPS_OFF << STM_TIM234_SMCR_ETPS) | + (STM_TIM234_SMCR_ETF_NONE << STM_TIM234_SMCR_ETF) | + (0 << STM_TIM234_SMCR_MSM) | + (STM_TIM234_SMCR_TS_ITR3 << STM_TIM234_SMCR_TS) | + (0 << STM_TIM234_SMCR_OCCS) | + (STM_TIM234_SMCR_SMS_DISABLE << STM_TIM234_SMCR_SMS)); + + stm_tim4.dier = 0; + stm_tim4.sr = 0; + + stm_tim4.psc = 31; + stm_tim4.cnt = 0; + stm_tim4.arr = 0xffff; + + /* tim2 is slaved to tim4 */ + + stm_tim2.cr2 = ((0 << STM_TIM234_CR2_TI1S) | + (STM_TIM234_CR2_MMS_ENABLE << STM_TIM234_CR2_MMS) | + (0 << STM_TIM234_CR2_CCDS)); + stm_tim2.smcr = ((0 << STM_TIM234_SMCR_ETP) | + (0 << STM_TIM234_SMCR_ECE) | + (STM_TIM234_SMCR_ETPS_OFF << STM_TIM234_SMCR_ETPS) | + (STM_TIM234_SMCR_ETF_NONE << STM_TIM234_SMCR_ETF) | + (0 << STM_TIM234_SMCR_MSM) | + (STM_TIM234_SMCR_TS_ITR3 << STM_TIM234_SMCR_TS) | + (0 << STM_TIM234_SMCR_OCCS) | + (STM_TIM234_SMCR_SMS_EXTERNAL_CLOCK << STM_TIM234_SMCR_SMS)); + stm_tim2.dier = 0; + stm_tim2.sr = 0; + stm_tim2.psc = 0; + stm_tim2.cnt = 0; + stm_tim2.arr = 0xffff; + + /* Start your timers */ + + stm_tim2.cr1 = ((STM_TIM234_CR1_CKD_1 << STM_TIM234_CR1_CKD) | + (0 << STM_TIM234_CR1_ARPE) | + (STM_TIM234_CR1_CMS_EDGE | STM_TIM234_CR1_CMS) | + (STM_TIM234_CR1_DIR_UP << STM_TIM234_CR1_DIR) | + (0 << STM_TIM234_CR1_OPM) | + (0 << STM_TIM234_CR1_URS) | + (0 << STM_TIM234_CR1_UDIS) | + (1 << STM_TIM234_CR1_CEN)); + + stm_tim4.cr1 = ((STM_TIM234_CR1_CKD_1 << STM_TIM234_CR1_CKD) | + (0 << STM_TIM234_CR1_ARPE) | + (STM_TIM234_CR1_CMS_EDGE | STM_TIM234_CR1_CMS) | + (STM_TIM234_CR1_DIR_UP << STM_TIM234_CR1_DIR) | + (0 << STM_TIM234_CR1_OPM) | + (1 << STM_TIM234_CR1_URS) | + (0 << STM_TIM234_CR1_UDIS) | + (1 << STM_TIM234_CR1_CEN)); + + ao_cmd_register(&ao_profile_cmds[0]); +} diff --git a/src/stm/ao_profile.h b/src/stm/ao_profile.h new file mode 100644 index 00000000..f7dd029d --- /dev/null +++ b/src/stm/ao_profile.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PROFILE_H_ +#define _AO_PROFILE_H_ + +void ao_profile_init(); + +static uint32_t inline ao_profile_tick(void) { + uint16_t hi, lo, second_hi; + + do { + hi = stm_tim2.cnt; + lo = stm_tim4.cnt; + second_hi = stm_tim2.cnt; + } while (hi != second_hi); + return ((uint32_t) hi << 16) | lo; +} + +#endif diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index cb66df6c..60f0b6d0 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -1331,6 +1331,8 @@ extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4; #define STM_TIM234_CR1_CMS_CENTER_3 3 #define STM_TIM234_CR1_CMS_MASK 3 #define STM_TIM234_CR1_DIR 4 +#define STM_TIM234_CR1_DIR_UP 0 +#define STM_TIM234_CR1_DIR_DOWN 1 #define STM_TIM234_CR1_OPM 3 #define STM_TIM234_CR1_URS 2 #define STM_TIM234_CR1_UDIS 1 @@ -1377,10 +1379,10 @@ extern struct stm_tim234 stm_tim2, stm_tim3, stm_tim4; #define STM_TIM234_SMCR_ETF_MASK 15 #define STM_TIM234_SMCR_MSM 7 #define STM_TIM234_SMCR_TS 4 -#define STM_TIM234_SMCR_TS_TR0 0 -#define STM_TIM234_SMCR_TS_TR1 1 -#define STM_TIM234_SMCR_TS_TR2 2 -#define STM_TIM234_SMCR_TS_TR3 3 +#define STM_TIM234_SMCR_TS_ITR0 0 +#define STM_TIM234_SMCR_TS_ITR1 1 +#define STM_TIM234_SMCR_TS_ITR2 2 +#define STM_TIM234_SMCR_TS_ITR3 3 #define STM_TIM234_SMCR_TS_TI1F_ED 4 #define STM_TIM234_SMCR_TS_TI1FP1 5 #define STM_TIM234_SMCR_TS_TI2FP2 6 -- cgit v1.2.3 From ebeac02a990da3fa6dd71487141d0bc6f78b42de Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:20:17 -0700 Subject: altos: Enable full flight computer functionality in MegaMetrum This turns on everything that currently works Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 8 +++++++- src/megametrum-v0.1/ao_megametrum.c | 40 +++++++++++++++++++++++++------------ 2 files changed, 34 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 22a58ff4..07a339b9 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -19,6 +19,7 @@ INC = \ ao_hmc5883.h \ ao_mpu6000.h \ ao_cc1120_CC1120.h \ + ao_profile.h \ ao_whiten.h \ stm32l.h @@ -43,6 +44,8 @@ ALTOS_SRC = \ ao_mutex.c \ ao_serial_stm.c \ ao_gps_skytraq.c \ + ao_gps_report_mega.c \ + ao_ignite.c \ ao_freq.c \ ao_dma_stm.c \ ao_spi_stm.c \ @@ -66,7 +69,10 @@ ALTOS_SRC = \ ao_sample_mm.c \ ao_kalman.c \ ao_flight_mm.c \ - ao_telemetry.c + ao_telemetry.c \ + ao_packet_slave.c \ + ao_packet.c \ + ao_companion.c PRODUCT=MegaMetrum-v0.1 diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index a2ac186b..ed35efa4 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -20,6 +20,9 @@ #include #include #include +#include +#include +#include int main(void) @@ -30,24 +33,35 @@ main(void) ao_led_init(LEDS_AVAILABLE); ao_led_on(AO_LED_GREEN); ao_timer_init(); - ao_cmd_init(); - ao_gps_init(); - ao_dma_init(); + + ao_i2c_init(); ao_spi_init(); - ao_ms5607_init(); - ao_beep_init(); - ao_adc_init(); - ao_storage_init(); - ao_usb_init(); + ao_dma_init(); ao_exti_init(); - ao_radio_init(); - ao_i2c_init(); + + ao_adc_init(); + ao_beep_init(); + ao_cmd_init(); + + ao_ms5607_init(); ao_hmc5883_init(); ao_mpu6000_init(); -// ao_flight_init(); -// ao_log_init(); -// ao_report_init(); + + ao_storage_init(); + + ao_flight_init(); + ao_log_init(); + ao_report_init(); + + ao_usb_init(); + ao_gps_init(); + ao_gps_report_mega_init(); ao_telemetry_init(); + ao_radio_init(); + ao_packet_slave_init(FALSE); + ao_igniter_init(); + ao_companion_init(); + ao_config_init(); ao_start_scheduler(); -- cgit v1.2.3 From 8efac8eb99a9aabb45d9fbf742e4be91e4b331a5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:21:04 -0700 Subject: altos: Add debugging code to check for stack overflow Stack overflow often happens from interrupt handlers sitting on top of a task stack. Check for this during ao_wakeup as that is often called during interrupt processing. Signed-off-by: Keith Packard --- src/core/ao_task.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_task.c b/src/core/ao_task.c index 910f1587..4011a36e 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" +#include #define AO_NO_TASK_INDEX 0xff @@ -28,6 +28,20 @@ __xdata struct ao_task *__data ao_cur_task; ao_arch_task_globals #endif +#define AO_CHECK_STACK 0 + +#if AO_CHECK_STACK +static uint8_t in_yield; + +static inline void ao_check_stack(void) { + uint8_t q; + if (!in_yield && ao_cur_task && &q < &ao_cur_task->stack[0]) + ao_panic(AO_PANIC_STACK); +} +#else +#define ao_check_stack() +#endif + void ao_add_task(__xdata struct ao_task * task, void (*start)(void), __code char *name) __reentrant { @@ -68,6 +82,9 @@ ao_yield(void) ao_arch_naked_define ao_arch_isr_stack(); +#if CHECK_STACK + in_yield = 1; +#endif /* Find a task to run. If there isn't any runnable task, * this loop will run forever, which is just fine */ @@ -97,6 +114,10 @@ ao_yield(void) ao_arch_naked_define } } } +#if CHECK_STACK + cli(); + in_yield = 0; +#endif ao_arch_restore_stack(); } @@ -117,6 +138,7 @@ ao_wakeup(__xdata void *wchan) { uint8_t i; + ao_check_stack(); for (i = 0; i < ao_num_tasks; i++) if (ao_tasks[i]->wchan == wchan) ao_tasks[i]->wchan = NULL; -- cgit v1.2.3 From 4847595e0383e5ff9c5a373f3c7f2af8c210c50a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 26 Jun 2012 23:25:00 -0700 Subject: altos: ao_ignite.c is no longer cc1111 specific Move it to core Signed-off-by: Keith Packard --- src/cc1111/ao_ignite.c | 193 --------------------------------------------- src/core/ao_ignite.c | 210 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 210 insertions(+), 193 deletions(-) delete mode 100644 src/cc1111/ao_ignite.c create mode 100644 src/core/ao_ignite.c (limited to 'src') diff --git a/src/cc1111/ao_ignite.c b/src/cc1111/ao_ignite.c deleted file mode 100644 index cf07dfe8..00000000 --- a/src/cc1111/ao_ignite.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright © 2009 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include - -__xdata struct ao_ignition ao_ignition[2]; - -void -ao_ignite(enum ao_igniter igniter) __critical -{ - ao_ignition[igniter].request = 1; - ao_wakeup(&ao_ignition); -} - -enum ao_igniter_status -ao_igniter_status(enum ao_igniter igniter) -{ - __xdata struct ao_data packet; - __pdata int16_t value; - __pdata uint8_t request, firing, fired; - - __critical { - ao_data_get(&packet); - request = ao_ignition[igniter].request; - fired = ao_ignition[igniter].fired; - firing = ao_ignition[igniter].firing; - } - if (firing || (request && !fired)) - return ao_igniter_active; - - value = (AO_IGNITER_CLOSED>>1); - switch (igniter) { - case ao_igniter_drogue: - value = packet.adc.sense_d; - break; - case ao_igniter_main: - value = packet.adc.sense_m; - break; - } - if (value < AO_IGNITER_OPEN) - return ao_igniter_open; - else if (value > AO_IGNITER_CLOSED) - return ao_igniter_ready; - else - return ao_igniter_unknown; -} - -void -ao_igniter_fire(enum ao_igniter igniter) __critical -{ - ao_mutex_get(&ao_radio_mutex); - ao_ignition[igniter].firing = 1; - switch(ao_config.ignite_mode) { - case AO_IGNITE_MODE_DUAL: - switch (igniter) { - case ao_igniter_drogue: - AO_IGNITER_DROGUE = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_DROGUE = 0; - break; - case ao_igniter_main: - AO_IGNITER_MAIN = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_MAIN = 0; - break; - } - break; - case AO_IGNITE_MODE_APOGEE: - switch (igniter) { - case ao_igniter_drogue: - AO_IGNITER_DROGUE = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_DROGUE = 0; - ao_delay(AO_IGNITER_CHARGE_TIME); - AO_IGNITER_MAIN = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_MAIN = 0; - break; - } - break; - case AO_IGNITE_MODE_MAIN: - switch (igniter) { - case ao_igniter_main: - AO_IGNITER_DROGUE = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_DROGUE = 0; - ao_delay(AO_IGNITER_CHARGE_TIME); - AO_IGNITER_MAIN = 1; - ao_delay(AO_IGNITER_FIRE_TIME); - AO_IGNITER_MAIN = 0; - break; - } - break; - } - ao_ignition[igniter].firing = 0; - ao_mutex_put(&ao_radio_mutex); -} - -void -ao_igniter(void) -{ - __xdata enum ao_ignter igniter; - - ao_config_get(); - for (;;) { - ao_sleep(&ao_ignition); - for (igniter = ao_igniter_drogue; igniter <= ao_igniter_main; igniter++) { - if (ao_ignition[igniter].request && !ao_ignition[igniter].fired) { - if (igniter == ao_igniter_drogue && ao_config.apogee_delay) - ao_delay(AO_SEC_TO_TICKS(ao_config.apogee_delay)); - - ao_igniter_fire(igniter); - ao_delay(AO_IGNITER_CHARGE_TIME); - ao_ignition[igniter].fired = 1; - } - } - } -} - -void -ao_ignite_manual(void) -{ - ao_cmd_white(); - if (!ao_match_word("DoIt")) - return; - ao_cmd_white(); - if (ao_cmd_lex_c == 'm') { - if(ao_match_word("main")) - ao_igniter_fire(ao_igniter_main); - } else { - if(ao_match_word("drogue")) - ao_igniter_fire(ao_igniter_drogue); - } -} - -static __code char * __code igniter_status_names[] = { - "unknown", "ready", "active", "open" -}; - -void -ao_ignite_print_status(enum ao_igniter igniter, __code char *name) __reentrant -{ - enum ao_igniter_status status = ao_igniter_status(igniter); - printf("Igniter: %6s Status: %s\n", - name, - igniter_status_names[status]); -} - -void -ao_ignite_test(void) -{ - ao_ignite_print_status(ao_igniter_drogue, "drogue"); - ao_ignite_print_status(ao_igniter_main, "main"); -} - -__code struct ao_cmds ao_ignite_cmds[] = { - { ao_ignite_manual, "i {main|drogue}\0Fire igniter. is doit with D&I" }, - { ao_ignite_test, "t\0Test igniter" }, - { 0, NULL }, -}; - -__xdata struct ao_task ao_igniter_task; - -void -ao_ignite_set_pins(void) -{ - AO_IGNITER_DROGUE = 0; - AO_IGNITER_MAIN = 0; - AO_IGNITER_DIR |= AO_IGNITER_DROGUE_BIT | AO_IGNITER_MAIN_BIT; -} - -void -ao_igniter_init(void) -{ - ao_ignite_set_pins(); - ao_cmd_register(&ao_ignite_cmds[0]); - ao_add_task(&ao_igniter_task, ao_igniter, "igniter"); -} diff --git a/src/core/ao_ignite.c b/src/core/ao_ignite.c new file mode 100644 index 00000000..561b5513 --- /dev/null +++ b/src/core/ao_ignite.c @@ -0,0 +1,210 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include + +__xdata struct ao_ignition ao_ignition[2]; + +void +ao_ignite(enum ao_igniter igniter) __critical +{ + ao_ignition[igniter].request = 1; + ao_wakeup(&ao_ignition); +} + +#ifndef AO_SENSE_DROGUE +#define AO_SENSE_DROGUE(p) ((p)->adc.sense_d) +#define AO_SENSE_MAIN(p) ((p)->adc.sense_m) +#endif + +enum ao_igniter_status +ao_igniter_status(enum ao_igniter igniter) +{ + __xdata struct ao_data packet; + __pdata int16_t value; + __pdata uint8_t request, firing, fired; + + __critical { + ao_data_get(&packet); + request = ao_ignition[igniter].request; + fired = ao_ignition[igniter].fired; + firing = ao_ignition[igniter].firing; + } + if (firing || (request && !fired)) + return ao_igniter_active; + + value = (AO_IGNITER_CLOSED>>1); + switch (igniter) { + case ao_igniter_drogue: + value = AO_SENSE_DROGUE(&packet); + break; + case ao_igniter_main: + value = AO_SENSE_MAIN(&packet); + break; + } + if (value < AO_IGNITER_OPEN) + return ao_igniter_open; + else if (value > AO_IGNITER_CLOSED) + return ao_igniter_ready; + else + return ao_igniter_unknown; +} + +#ifndef AO_IGNITER_SET_DROGUE +#define AO_IGNITER_SET_DROGUE(v) AO_IGNITER_DROGUE = (v) +#define AO_IGNITER_SET_MAIN(v) AO_IGNITER_MAIN = (v) +#endif + +#ifndef AO_IGNITER_FIRE_TIME +#define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) +#endif + +#ifndef AO_IGNITER_CHARGE_TIME +#define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) +#endif + +void +ao_igniter_fire(enum ao_igniter igniter) __critical +{ + ao_mutex_get(&ao_radio_mutex); + ao_ignition[igniter].firing = 1; + switch(ao_config.ignite_mode) { + case AO_IGNITE_MODE_DUAL: + switch (igniter) { + case ao_igniter_drogue: + AO_IGNITER_SET_DROGUE(1); + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_SET_DROGUE(0); + break; + case ao_igniter_main: + AO_IGNITER_SET_MAIN(1); + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_SET_MAIN(0); + break; + } + break; + case AO_IGNITE_MODE_APOGEE: + switch (igniter) { + case ao_igniter_drogue: + AO_IGNITER_SET_DROGUE(1); + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_SET_DROGUE(0); + ao_delay(AO_IGNITER_CHARGE_TIME); + AO_IGNITER_SET_MAIN(1); + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_SET_MAIN(0); + break; + } + break; + case AO_IGNITE_MODE_MAIN: + switch (igniter) { + case ao_igniter_main: + AO_IGNITER_SET_DROGUE(1); + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_SET_DROGUE(0); + ao_delay(AO_IGNITER_CHARGE_TIME); + AO_IGNITER_SET_MAIN(1); + ao_delay(AO_IGNITER_FIRE_TIME); + AO_IGNITER_SET_MAIN(0); + break; + } + break; + } + ao_ignition[igniter].firing = 0; + ao_mutex_put(&ao_radio_mutex); +} + +void +ao_igniter(void) +{ + __xdata enum ao_igniter igniter; + + ao_config_get(); + for (;;) { + ao_sleep(&ao_ignition); + for (igniter = ao_igniter_drogue; igniter <= ao_igniter_main; igniter++) { + if (ao_ignition[igniter].request && !ao_ignition[igniter].fired) { + if (igniter == ao_igniter_drogue && ao_config.apogee_delay) + ao_delay(AO_SEC_TO_TICKS(ao_config.apogee_delay)); + + ao_igniter_fire(igniter); + ao_delay(AO_IGNITER_CHARGE_TIME); + ao_ignition[igniter].fired = 1; + } + } + } +} + +void +ao_ignite_manual(void) +{ + ao_cmd_white(); + if (!ao_match_word("DoIt")) + return; + ao_cmd_white(); + if (ao_cmd_lex_c == 'm') { + if(ao_match_word("main")) + ao_igniter_fire(ao_igniter_main); + } else { + if(ao_match_word("drogue")) + ao_igniter_fire(ao_igniter_drogue); + } +} + +static __code char * __code igniter_status_names[] = { + "unknown", "ready", "active", "open" +}; + +void +ao_ignite_print_status(enum ao_igniter igniter, __code char *name) __reentrant +{ + enum ao_igniter_status status = ao_igniter_status(igniter); + printf("Igniter: %6s Status: %s\n", + name, + igniter_status_names[status]); +} + +void +ao_ignite_test(void) +{ + ao_ignite_print_status(ao_igniter_drogue, "drogue"); + ao_ignite_print_status(ao_igniter_main, "main"); +} + +__code struct ao_cmds ao_ignite_cmds[] = { + { ao_ignite_manual, "i {main|drogue}\0Fire igniter. is doit with D&I" }, + { ao_ignite_test, "t\0Test igniter" }, + { 0, NULL }, +}; + +__xdata struct ao_task ao_igniter_task; + +void +ao_ignite_set_pins(void) +{ + ao_enable_output(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, 0); + ao_enable_output(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, 0); +} + +void +ao_igniter_init(void) +{ + ao_ignite_set_pins(); + ao_cmd_register(&ao_ignite_cmds[0]); + ao_add_task(&ao_igniter_task, ao_igniter, "igniter"); +} -- cgit v1.2.3 From 0285696e5280fc64774b6c3a2fcdaa36bd36ae7c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 01:17:51 -0700 Subject: altos: mpu6000 requires a delay during start I have no idea why this is required, but the mpu6000 will not come up and run if this isn't present. Signed-off-by: Keith Packard --- src/stm/ao_i2c_stm.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index c205706d..12b9e8b4 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -136,6 +136,15 @@ ao_i2c_put(uint8_t index) ao_mutex_put(&ao_i2c_mutex[index]); } +static inline void +ao_i2c_delay(void) +{ + uint8_t i; + + for (i = 0; i < 10; i++) + ao_arch_nop(); +} + #define I2C_DEBUG 0 #if I2C_DEBUG #define DBG(x...) printf(x) @@ -194,6 +203,7 @@ ao_i2c_start(uint8_t index, uint16_t addr) out_cr2("start", stm_i2c, AO_STM_I2C_CR2); out_cr1("start", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START)); + ao_i2c_delay(); out_cr2("start", stm_i2c, AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN)); ao_alarm(1); @@ -429,4 +439,3 @@ ao_i2c_init(void) stm_nvic_set_priority(STM_ISR_I2C2_ER_POS, 3); #endif } - -- cgit v1.2.3 From 8fc643c9768f0db31a248331681af9490f5715af Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 01:19:05 -0700 Subject: altos: stm i2c debug code was calling flush() even when disabled The fancy stm i2c debugging code had calls to flush() that were invoked outside of the conditionals leading to all kinds of fun -- flush() may re-enable interrupts, yield or do all kinds of wacky stuff, none of which is appropriate from the middle of a device driver Signed-off-by: Keith Packard --- src/stm/ao_i2c_stm.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index 12b9e8b4..51631cb7 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -147,47 +147,47 @@ ao_i2c_delay(void) #define I2C_DEBUG 0 #if I2C_DEBUG -#define DBG(x...) printf(x) +#define DBG(x...) do { printf(x); flush(); } while (0) #else -#define DBG(x...) +#define DBG(x...) #endif static inline uint32_t in_sr1(char *where, struct stm_i2c *stm_i2c) { uint32_t sr1 = stm_i2c->sr1; - DBG("%s: sr1: %x\n", where, sr1); flush(); + DBG("%s: sr1: %x\n", where, sr1); return sr1; } static inline uint32_t in_sr2(char *where, struct stm_i2c *stm_i2c) { uint32_t sr2 = stm_i2c->sr2; - DBG("%s: sr2: %x\n", where, sr2); flush(); + DBG("%s: sr2: %x\n", where, sr2); return sr2; } static inline void out_cr1(char *where, struct stm_i2c *stm_i2c, uint32_t cr1) { - DBG("%s: cr1: %x\n", where, cr1); flush(); + DBG("%s: cr1: %x\n", where, cr1); stm_i2c->cr1 = cr1; } static inline uint32_t in_cr1(char *where, struct stm_i2c *stm_i2c) { uint32_t cr1 = stm_i2c->cr1; - DBG("%s: cr1: %x\n", where, cr1); flush(); + DBG("%s: cr1: %x\n", where, cr1); return cr1; } static inline void out_cr2(char *where, struct stm_i2c *stm_i2c, uint32_t cr2) { - DBG("%s: cr2: %x\n", where, cr2); flush(); + DBG("%s: cr2: %x\n", where, cr2); stm_i2c->cr2 = cr2; } static inline uint32_t in_dr(char *where, struct stm_i2c *stm_i2c) { uint32_t dr = stm_i2c->dr; - DBG("%s: dr: %x\n", where, dr); flush(); + DBG("%s: dr: %x\n", where, dr); return dr; } static inline void out_dr(char *where, struct stm_i2c *stm_i2c, uint32_t dr) { - DBG("%s: dr: %x\n", where, dr); flush(); + DBG("%s: dr: %x\n", where, dr); stm_i2c->dr = dr; } @@ -236,8 +236,6 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; uint8_t *b = block; uint32_t sr1; - int t; - uint8_t tx_dma_index = ao_i2c_stm_info[index].tx_dma_index; /* Clear any pending ADDR bit */ -- cgit v1.2.3 From a00aff5ee93ea9763b5c0466fcecc823cad135ef Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 01:20:43 -0700 Subject: altos: Don't try to grab radio while firing MM igniters If you're in idle mode, you stop forever as the packet mode receiver will own the radio mutex forever. Signed-off-by: Keith Packard --- src/core/ao_ignite.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/core/ao_ignite.c b/src/core/ao_ignite.c index 561b5513..d4aef153 100644 --- a/src/core/ao_ignite.c +++ b/src/core/ao_ignite.c @@ -81,7 +81,9 @@ ao_igniter_status(enum ao_igniter igniter) void ao_igniter_fire(enum ao_igniter igniter) __critical { +#ifndef MEGAMETRUM ao_mutex_get(&ao_radio_mutex); +#endif ao_ignition[igniter].firing = 1; switch(ao_config.ignite_mode) { case AO_IGNITE_MODE_DUAL: @@ -126,7 +128,9 @@ ao_igniter_fire(enum ao_igniter igniter) __critical break; } ao_ignition[igniter].firing = 0; +#ifndef MEGAMETRUM ao_mutex_put(&ao_radio_mutex); +#endif } void -- cgit v1.2.3 From b96eece8e42df0713fc92d47b6bb27604c0168a2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 01:22:00 -0700 Subject: altos: Clean up cc1120 driver a bit Make some variables static, remove stale debug code Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 501b9370..cc9ebd30 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -29,12 +29,6 @@ uint8_t ao_radio_in_recv; #define CC1120_DEBUG AO_FEC_DEBUG #define CC1120_TRACE 0 -#if CC1120_TRACE -#define fec_dump_bytes(b,l,n) ao_fec_dump_bytes(b,l,n) -#else -#define fec_dump_bytes(b,l,n) -#endif - const uint32_t ao_radio_cal = 0x6ca333; #define FOSC 32000000 @@ -582,12 +576,12 @@ ao_radio_send(const void *d, uint8_t size) #define AO_RADIO_MAX_RECV 90 -uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8]; -uint16_t rx_data_count; -uint16_t rx_data_consumed; -uint16_t rx_data_cur; -uint8_t rx_ignore; -uint8_t rx_waiting; +static uint8_t rx_data[(AO_RADIO_MAX_RECV + 4) * 2 * 8]; +static uint16_t rx_data_count; +static uint16_t rx_data_consumed; +static uint16_t rx_data_cur; +static uint8_t rx_ignore; +static uint8_t rx_waiting; #if AO_PROFILE static uint32_t rx_start_tick, rx_packet_tick, rx_done_tick, rx_last_done_tick; -- cgit v1.2.3 From 9695a217e13f9d194b6dc40e2696017e5f8e8176 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 01:22:32 -0700 Subject: altos: disable FEC debug on MM Seems to work; we'll leave the code around in case something bad happens later. Signed-off-by: Keith Packard --- src/megametrum-v0.1/ao_pins.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index f5bd3e0d..1d2051e1 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -271,7 +271,7 @@ struct ao_adc { * Radio (cc1120) */ -#define AO_FEC_DEBUG 1 +#define AO_FEC_DEBUG 0 #define AO_CC1120_SPI_CS_PORT (&stm_gpioc) #define AO_CC1120_SPI_CS_PIN 5 #define AO_CC1120_SPI_BUS STM_SPI_INDEX(2) -- cgit v1.2.3 From 1a1d4a557a30e2e743936b828b654187ec562ca8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 02:46:27 -0700 Subject: altos: Wait for i2c START condition before setting interrupt bits This seems better than the random loop that it replaces, but I still have no idea why this is required; it doesn't coorespond to the docs at all... Signed-off-by: Keith Packard --- src/stm/ao_i2c_stm.c | 128 ++++++++++++++++++--------------------------------- src/stm/stm32l.h | 2 +- 2 files changed, 45 insertions(+), 85 deletions(-) (limited to 'src') diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index 51631cb7..4d7d8d87 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -33,6 +33,22 @@ static uint8_t ao_i2c_state[STM_NUM_I2C]; static uint16_t ao_i2c_addr[STM_NUM_I2C]; uint8_t ao_i2c_mutex[STM_NUM_I2C]; +#if AO_PCLK1 == 2000000 +# define AO_STM_I2C_CR2_FREQ STM_I2C_CR2_FREQ_2_MHZ +#endif +#if AO_PCLK1 == 4000000 +# define AO_STM_I2C_CR2_FREQ STM_I2C_CR2_FREQ_4_MHZ +#endif +#if AO_PCLK1 == 8000000 +# define AO_STM_I2C_CR2_FREQ STM_I2C_CR2_FREQ_8_MHZ +#endif +#if AO_PCLK1 == 16000000 +# define AO_STM_I2C_CR2_FREQ STM_I2C_CR2_FREQ_16_MHZ +#endif +#if AO_PCLK1 == 32000000 +# define AO_STM_I2C_CR2_FREQ STM_I2C_CR2_FREQ_32_MHZ +#endif + #define AO_STM_I2C_CR1 ((0 << STM_I2C_CR1_SWRST) | \ (0 << STM_I2C_CR1_ALERT) | \ (0 << STM_I2C_CR1_PEC) | \ @@ -53,7 +69,7 @@ uint8_t ao_i2c_mutex[STM_NUM_I2C]; (0 << STM_I2C_CR2_ITBUFEN) | \ (0 << STM_I2C_CR2_ITEVTEN) | \ (0 << STM_I2C_CR2_ITERREN) | \ - (STM_I2C_CR2_FREQ_16_MHZ << STM_I2C_CR2_FREQ)) + (AO_STM_I2C_CR2_FREQ << STM_I2C_CR2_FREQ)) static const struct ao_i2c_stm_info ao_i2c_stm_info[STM_NUM_I2C] = { { @@ -136,61 +152,6 @@ ao_i2c_put(uint8_t index) ao_mutex_put(&ao_i2c_mutex[index]); } -static inline void -ao_i2c_delay(void) -{ - uint8_t i; - - for (i = 0; i < 10; i++) - ao_arch_nop(); -} - -#define I2C_DEBUG 0 -#if I2C_DEBUG -#define DBG(x...) do { printf(x); flush(); } while (0) -#else -#define DBG(x...) -#endif - -static inline uint32_t in_sr1(char *where, struct stm_i2c *stm_i2c) { - uint32_t sr1 = stm_i2c->sr1; - DBG("%s: sr1: %x\n", where, sr1); - return sr1; -} - -static inline uint32_t in_sr2(char *where, struct stm_i2c *stm_i2c) { - uint32_t sr2 = stm_i2c->sr2; - DBG("%s: sr2: %x\n", where, sr2); - return sr2; -} - -static inline void out_cr1(char *where, struct stm_i2c *stm_i2c, uint32_t cr1) { - DBG("%s: cr1: %x\n", where, cr1); - stm_i2c->cr1 = cr1; -} - -static inline uint32_t in_cr1(char *where, struct stm_i2c *stm_i2c) { - uint32_t cr1 = stm_i2c->cr1; - DBG("%s: cr1: %x\n", where, cr1); - return cr1; -} - -static inline void out_cr2(char *where, struct stm_i2c *stm_i2c, uint32_t cr2) { - DBG("%s: cr2: %x\n", where, cr2); - stm_i2c->cr2 = cr2; -} - -static inline uint32_t in_dr(char *where, struct stm_i2c *stm_i2c) { - uint32_t dr = stm_i2c->dr; - DBG("%s: dr: %x\n", where, dr); - return dr; -} - -static inline void out_dr(char *where, struct stm_i2c *stm_i2c, uint32_t dr) { - DBG("%s: dr: %x\n", where, dr); - stm_i2c->dr = dr; -} - uint8_t ao_i2c_start(uint8_t index, uint16_t addr) { @@ -200,13 +161,14 @@ ao_i2c_start(uint8_t index, uint16_t addr) ao_i2c_state[index] = I2C_IDLE; ao_i2c_addr[index] = addr; - out_cr2("start", stm_i2c, AO_STM_I2C_CR2); - out_cr1("start", stm_i2c, - AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START)); - ao_i2c_delay(); - out_cr2("start", stm_i2c, - AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN)); - ao_alarm(1); + stm_i2c->cr2 = AO_STM_I2C_CR2; + stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_START); + for (t = 0; t < I2C_TIMEOUT; t++) { + if (!(stm_i2c->cr1 & (1 << STM_I2C_CR1_START))) + break; + } + stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN); + ao_alarm(AO_MS_TO_TICKS(250)); cli(); while (ao_i2c_state[index] == I2C_IDLE) if (ao_sleep(&ao_i2c_state[index])) @@ -223,7 +185,7 @@ ao_i2c_wait_stop(uint8_t index) int t; for (t = 0; t < I2C_TIMEOUT; t++) { - if (!(in_cr1("wait stop", stm_i2c) & (1 << STM_I2C_CR1_STOP))) + if (!(stm_i2c->cr1 & (1 << STM_I2C_CR1_STOP))) break; ao_yield(); } @@ -239,8 +201,8 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) uint8_t tx_dma_index = ao_i2c_stm_info[index].tx_dma_index; /* Clear any pending ADDR bit */ - in_sr2("send clear addr", stm_i2c); - out_cr2("send", stm_i2c, AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_DMAEN)); + (void) stm_i2c->sr2; + stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_DMAEN); ao_dma_set_transfer(tx_dma_index, &stm_i2c->dr, block, @@ -262,15 +224,14 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) break; ao_clear_alarm(); ao_dma_done_transfer(tx_dma_index); - out_cr2("send enable isr", stm_i2c, - AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN)); - while ((in_sr1("send_btf", stm_i2c) & (1 << STM_I2C_SR1_BTF)) == 0) + stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN); + while ((stm_i2c->sr1 & (1 << STM_I2C_SR1_BTF)) == 0) if (ao_sleep(&ao_i2c_state[index])) break; - out_cr2("send disable isr", stm_i2c, AO_STM_I2C_CR2); + stm_i2c->cr2 = AO_STM_I2C_CR2; sei(); if (stop) { - out_cr1("stop", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); + stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP); ao_i2c_wait_stop(index); } return TRUE; @@ -307,19 +268,18 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) if (len == 1) { ao_i2c_recv_data[index] = block; ao_i2c_recv_len[index] = 1; - out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1); + stm_i2c->cr1 = AO_STM_I2C_CR1; /* Clear any pending ADDR bit */ - in_sr2("clear addr", stm_i2c); + stm_i2c->sr2; /* Enable interrupts to transfer the byte */ - out_cr2("setup recv 1", stm_i2c, - AO_STM_I2C_CR2 | - (1 << STM_I2C_CR2_ITEVTEN) | - (1 << STM_I2C_CR2_ITERREN) | - (1 << STM_I2C_CR2_ITBUFEN)); + stm_i2c->cr2 = (AO_STM_I2C_CR2 | + (1 << STM_I2C_CR2_ITEVTEN) | + (1 << STM_I2C_CR2_ITERREN) | + (1 << STM_I2C_CR2_ITBUFEN)); if (stop) - out_cr1("setup recv 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); + stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP); ao_alarm(1); cli(); @@ -343,11 +303,11 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) (0 << STM_DMA_CCR_PINC) | (0 << STM_DMA_CCR_CIRC) | (STM_DMA_CCR_DIR_PER_TO_MEM << STM_DMA_CCR_DIR)); - out_cr1("recv > 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK)); - out_cr2("recv > 1", stm_i2c, AO_STM_I2C_CR2 | - (1 << STM_I2C_CR2_DMAEN) | (1 << STM_I2C_CR2_LAST)); + stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_ACK); + stm_i2c->cr2 = AO_STM_I2C_CR2 | + (1 << STM_I2C_CR2_DMAEN) | (1 << STM_I2C_CR2_LAST); /* Clear any pending ADDR bit */ - in_sr2("clear addr", stm_i2c); + (void) stm_i2c->sr2; ao_dma_start(rx_dma_index); ao_alarm(len); @@ -359,7 +319,7 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) ao_clear_alarm(); ret = ao_dma_done[rx_dma_index]; ao_dma_done_transfer(rx_dma_index); - out_cr1("stop recv > 1", stm_i2c, AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP)); + stm_i2c->cr1 = AO_STM_I2C_CR1 | (1 << STM_I2C_CR1_STOP); } if (stop) ao_i2c_wait_stop(index); diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 60f0b6d0..ff8dddff 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -1255,7 +1255,7 @@ extern struct stm_i2c stm_i2c1, stm_i2c2; #define STM_I2C_CR2_FREQ_8_MHZ 8 #define STM_I2C_CR2_FREQ_16_MHZ 16 #define STM_I2C_CR2_FREQ_32_MHZ 32 -#define STM_I2C_CR2_FREQ_MASK 0x3f; +#define STM_I2C_CR2_FREQ_MASK 0x3f #define STM_I2C_SR1_SMBALERT 15 #define STM_I2C_SR1_TIMEOUT 14 -- cgit v1.2.3 From 08a4ed8fe794a2b2b52147bd5535fe0954822e95 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 14:34:53 -0700 Subject: altos: include targe SPI speed in get request STM needs it to be provided when enabling the SPI device, so just fix AVR and cc1111 to do the same. Signed-off-by: Keith Packard --- src/avr/ao_arch_funcs.h | 10 +++++----- src/cc1111/ao_arch_funcs.h | 19 +++++++++++++++---- src/drivers/ao_25lc1024.c | 2 +- src/drivers/ao_at45db161d.c | 2 +- src/drivers/ao_cc1120.c | 2 +- src/drivers/ao_companion.c | 18 +++++------------- src/drivers/ao_m25.c | 2 +- src/drivers/ao_ms5607.c | 2 +- src/stm-demo/ao_demo.c | 4 ++-- src/stm/ao_arch_funcs.h | 19 ++++++++----------- src/stm/ao_spi_stm.c | 6 ++---- 11 files changed, 42 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/avr/ao_arch_funcs.h b/src/avr/ao_arch_funcs.h index 1eeca6cc..e400c98b 100644 --- a/src/avr/ao_arch_funcs.h +++ b/src/avr/ao_arch_funcs.h @@ -21,7 +21,7 @@ extern __xdata uint8_t ao_spi_mutex; -#define ao_spi_get_mask(reg,mask,bus) do { \ +#define ao_spi_get_mask(reg,mask,bus,speed) do { \ ao_mutex_get(&ao_spi_mutex); \ (reg) &= ~(mask); \ } while (0) @@ -31,13 +31,13 @@ extern __xdata uint8_t ao_spi_mutex; ao_mutex_put(&ao_spi_mutex); \ } while (0) -#define ao_spi_get_bit(bit) do { \ +#define ao_spi_get_bit(reg,bit,pin,bus,speed) do { \ ao_mutex_get(&ao_spi_mutex); \ - (bit) = 0; \ + (pin) = 0; \ } while (0) -#define ao_spi_put_bit(bit) do { \ - (bit) = 1; \ +#define ao_spi_put_bit(reg,bit,pin,bus) do { \ + (pin) = 1; \ ao_mutex_put(&ao_spi_mutex); \ } while (0) diff --git a/src/cc1111/ao_arch_funcs.h b/src/cc1111/ao_arch_funcs.h index 728f1f76..0a322961 100644 --- a/src/cc1111/ao_arch_funcs.h +++ b/src/cc1111/ao_arch_funcs.h @@ -21,9 +21,18 @@ extern __xdata uint8_t ao_spi_mutex; -#define ao_spi_get_mask(reg,mask,bus) do { \ - ao_mutex_get(&ao_spi_mutex); \ - (reg) &= ~(mask); \ +#define AO_SPI_SPEED_FAST 17 +#define AO_SPI_SPEED_200kHz 13 + +#define ao_spi_set_speed(speed) (U0GCR = (UxGCR_CPOL_NEGATIVE | \ + UxGCR_CPHA_FIRST_EDGE | \ + UxGCR_ORDER_MSB | \ + ((speed) << UxGCR_BAUD_E_SHIFT))) + +#define ao_spi_get_mask(reg,mask,bus,speed) do { \ + ao_mutex_get(&ao_spi_mutex); \ + ao_spi_set_speed(speed); \ + (reg) &= ~(mask); \ } while (0) #define ao_spi_put_mask(reg,mask,bus) do { \ @@ -31,8 +40,10 @@ extern __xdata uint8_t ao_spi_mutex; ao_mutex_put(&ao_spi_mutex); \ } while (0) -#define ao_spi_get_bit(reg,bit,pin,bus) do { \ + +#define ao_spi_get_bit(reg,bit,pin,bus,speed) do { \ ao_mutex_get(&ao_spi_mutex); \ + ao_spi_set_speed(speed); \ pin = 0; \ } while (0) diff --git a/src/drivers/ao_25lc1024.c b/src/drivers/ao_25lc1024.c index b25d52c4..c5d811f7 100644 --- a/src/drivers/ao_25lc1024.c +++ b/src/drivers/ao_25lc1024.c @@ -50,7 +50,7 @@ static __xdata uint8_t ao_ee_mutex; _asm nop _endasm; \ } while(0) -#define ao_ee_cs_low() ao_spi_get_bit(EE_CS_PORT, EE_CS_PIN, EE_CS, AO_EE_SPI_BUS) +#define ao_ee_cs_low() ao_spi_get_bit(EE_CS_PORT, EE_CS_PIN, EE_CS, AO_EE_SPI_BUS, AO_SPI_SPEED_FAST) #define ao_ee_cs_high() ao_spi_put_bit(EE_CS_PORT, EE_CS_PIN, EE_CS, AO_EE_SPI_BUS) diff --git a/src/drivers/ao_at45db161d.c b/src/drivers/ao_at45db161d.c index 5eb25acf..e7e74153 100644 --- a/src/drivers/ao_at45db161d.c +++ b/src/drivers/ao_at45db161d.c @@ -43,7 +43,7 @@ __xdata uint8_t ao_flash_mutex; _asm nop _endasm; \ } while(0) -#define ao_flash_cs_low() ao_spi_get_bit(FLASH_CS_PORT, FLASH_CS_PIN, FLASH_CS, AO_FLASH_SPI_BUS) +#define ao_flash_cs_low() ao_spi_get_bit(FLASH_CS_PORT, FLASH_CS_PIN, FLASH_CS, AO_FLASH_SPI_BUS, AO_SPI_SPEED_FAST) #define ao_flash_cs_high() ao_spi_put_bit(FLASH_CS_PORT, FLASH_CS_PIN, FLASH_CS, AO_FLASH_SPI_BUS) diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index cc9ebd30..c974613e 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -33,7 +33,7 @@ const uint32_t ao_radio_cal = 0x6ca333; #define FOSC 32000000 -#define ao_radio_select() ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS) +#define ao_radio_select() ao_spi_get_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS,AO_SPI_SPEED_1MHz) #define ao_radio_deselect() ao_spi_put_mask(AO_CC1120_SPI_CS_PORT,(1 << AO_CC1120_SPI_CS_PIN),AO_CC1120_SPI_BUS) #define ao_radio_spi_send(d,l) ao_spi_send((d), (l), AO_CC1120_SPI_BUS) #define ao_radio_spi_send_fixed(d,l) ao_spi_send_fixed((d), (l), AO_CC1120_SPI_BUS) diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index a31cc2ea..85d68c44 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -18,28 +18,20 @@ #include #include -#ifndef ao_spi_slow -#define ao_spi_slow(bus) (U0GCR = (UxGCR_CPOL_NEGATIVE | \ - UxGCR_CPHA_FIRST_EDGE | \ - UxGCR_ORDER_MSB | \ - (13 << UxGCR_BAUD_E_SHIFT))) - -#define ao_spi_fast(bus) (U0GCR = (UxGCR_CPOL_NEGATIVE | \ - UxGCR_CPHA_FIRST_EDGE | \ - UxGCR_ORDER_MSB | \ - (17 << UxGCR_BAUD_E_SHIFT))) +#ifdef MEGAMETRUM +#define ao_spi_slow(b) +#define ao_spi_fast(b) #endif #define COMPANION_SELECT() do { \ ao_spi_get_bit(AO_COMPANION_CS_PORT, \ AO_COMPANION_CS_PIN, \ AO_COMPANION_CS, \ - AO_COMPANION_SPI_BUS); \ - ao_spi_slow(AO_COMPANION_SPI_BUS); \ + AO_COMPANION_SPI_BUS, \ + AO_SPI_SPEED_200kHz); \ } while (0) #define COMPANION_DESELECT() do { \ - ao_spi_fast(AO_COMPANION_SPI_BUS); \ ao_spi_put_bit(AO_COMPANION_CS_PORT, \ AO_COMPANION_CS_PIN, \ AO_COMPANION_CS, \ diff --git a/src/drivers/ao_m25.c b/src/drivers/ao_m25.c index 2983a405..9603c1de 100644 --- a/src/drivers/ao_m25.c +++ b/src/drivers/ao_m25.c @@ -110,7 +110,7 @@ static void ao_boot_radio(void) { #define ao_boot_radio() #endif -#define M25_SELECT(cs) do { ao_boot_radio(); ao_spi_get_mask(AO_M25_SPI_CS_PORT,cs,AO_M25_SPI_BUS); } while (0) +#define M25_SELECT(cs) do { ao_boot_radio(); ao_spi_get_mask(AO_M25_SPI_CS_PORT,cs,AO_M25_SPI_BUS, AO_SPI_SPEED_FAST); } while (0) #define M25_DESELECT(cs) ao_spi_put_mask(AO_M25_SPI_CS_PORT,cs,AO_M25_SPI_BUS) #define M25_BLOCK_SHIFT 16 diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index e08f4d40..e1d0507e 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -24,7 +24,7 @@ static uint8_t ms5607_configured; static void ao_ms5607_start(void) { - ao_spi_get(AO_MS5607_SPI_INDEX); + ao_spi_get(AO_MS5607_SPI_INDEX,AO_SPI_SPEED_FAST); stm_gpio_set(AO_MS5607_CS_GPIO, AO_MS5607_CS, 0); } diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 73ace558..9a581ff9 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -83,7 +83,7 @@ ao_spi_write(void) { int i; for (i = 0; i < 10; i++) { - ao_spi_get(0); + ao_spi_get(0, AO_SPI_SPEED_FAST); stm_gpio_set(&stm_gpioc, 12, 0); ao_spi_send(data, 4, 0); stm_gpio_set(&stm_gpioc, 12, 1); @@ -100,7 +100,7 @@ ao_spi_read(void) { int i; for (i = 0; i < 10; i++) { - ao_spi_get(0); + ao_spi_get(0, AO_SPI_SPEED_FAST); stm_gpio_set(&stm_gpioc, 12, 0); ao_spi_recv(data, 4, 0); stm_gpio_set(&stm_gpioc, 12, 1); diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 62b10063..7820bf79 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -22,8 +22,12 @@ */ extern uint8_t ao_spi_mutex[STM_NUM_SPI]; +#define AO_SPI_SPEED_FAST STM_SPI_CR1_BR_PCLK_4 +#define AO_SPI_SPEED_1MHz STM_SPI_CR1_BR_PCLK_16 +#define AO_SPI_SPEED_200kHz STM_SPI_CR1_BR_PCLK_256 + void -ao_spi_get(uint8_t spi_index); +ao_spi_get(uint8_t spi_index, uint32_t speed); void ao_spi_put(uint8_t spi_index); @@ -40,20 +44,13 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index); void ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index); -#define AO_SPI_SPEED_FAST STM_SPI_CR1_BR_PCLK_16 -#define AO_SPI_SPEED_200kHz STM_SPI_CR1_BR_PCLK_256 - extern uint16_t ao_spi_speed[STM_NUM_SPI]; -#define ao_spi_slow(bus) (ao_spi_speed[bus] = AO_SPI_SPEED_200kHz) - -#define ao_spi_fast(bus) (ao_spi_speed[bus] = AO_SPI_SPEED_FAST) - void ao_spi_init(void); -#define ao_spi_get_mask(reg,mask,bus) do { \ - ao_spi_get(bus); \ +#define ao_spi_get_mask(reg,mask,bus, speed) do { \ + ao_spi_get(bus, speed); \ (reg)->bsrr = ((uint32_t) mask) << 16; \ } while (0) @@ -62,7 +59,7 @@ ao_spi_init(void); ao_spi_put(bus); \ } while (0) -#define ao_spi_get_bit(reg,bit,pin,bus) ao_spi_get_mask(reg,(1< Date: Wed, 27 Jun 2012 14:35:56 -0700 Subject: altos: reorder stm USB state stores to avoid races Must set ao_usb_in_pending before telling USB about new data or an interrupt could arrive at the wrong time to clear it. Same for ao_usb_in_flushed. Without these changes, I've seen the USB bus lock up on occasion, waiting for an IN packet to consume data, but with no IN data pending in the hardware. Signed-off-by: Keith Packard --- src/stm/ao_usb_stm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/stm/ao_usb_stm.c b/src/stm/ao_usb_stm.c index c093f526..4f37a7d9 100644 --- a/src/stm/ao_usb_stm.c +++ b/src/stm/ao_usb_stm.c @@ -792,10 +792,10 @@ static void ao_usb_in_send(void) { debug ("send %d\n", ao_usb_tx_count); + ao_usb_in_pending = 1; ao_usb_write(ao_usb_tx_buffer, ao_usb_in_tx_buffer, 0, ao_usb_tx_count); ao_usb_bdt[AO_USB_IN_EPR].single.count_tx = ao_usb_tx_count; ao_usb_set_stat_tx(AO_USB_IN_EPR, STM_USB_EPR_STAT_TX_VALID); - ao_usb_in_pending = 1; ao_usb_tx_count = 0; } @@ -848,12 +848,12 @@ ao_usb_putchar(char c) __critical __reentrant ao_usb_in_wait(); + ao_usb_in_flushed = 0; ao_usb_tx_buffer[ao_usb_tx_count++] = (uint8_t) c; /* Send the packet when full */ if (ao_usb_tx_count == AO_USB_IN_SIZE) ao_usb_in_send(); - ao_usb_in_flushed = 0; } static void -- cgit v1.2.3 From b0b7f5da2d29716959c6793d744e47a3d435c247 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 14:38:35 -0700 Subject: altos: get MPU6000 I2C link working reliably This slows the i2c bus to 100kHz (yuck), sets the rise time to spec (it was way off) and adds more delays during bus setup. I've run this for hours now without trouble. Will try to adjust things back to fast mode and see if I can make that work as 100kHz isn't fast enough to reliably get data at 100 samples/sec. Signed-off-by: Keith Packard --- src/stm/ao_i2c_stm.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index 4d7d8d87..c4a6c5a3 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -167,9 +167,10 @@ ao_i2c_start(uint8_t index, uint16_t addr) if (!(stm_i2c->cr1 & (1 << STM_I2C_CR1_START))) break; } - stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN); ao_alarm(AO_MS_TO_TICKS(250)); cli(); + stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_ITEVTEN) | (1 << STM_I2C_CR2_ITERREN); + ao_i2c_ev_isr(index); while (ao_i2c_state[index] == I2C_IDLE) if (ao_sleep(&ao_i2c_state[index])) break; @@ -192,6 +193,19 @@ ao_i2c_wait_stop(uint8_t index) ao_i2c_state[index] = I2C_IDLE; } +static void +ao_i2c_wait_addr(uint8_t index) +{ + struct stm_i2c *stm_i2c = ao_i2c_stm_info[index].stm_i2c; + int t; + + for (t = 0; t < I2C_TIMEOUT; t++) + if (!(stm_i2c->sr1 & (1 << STM_I2C_SR1_ADDR))) + break; + if (t) + printf ("wait_addr %d\n", t); +} + uint8_t ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) { @@ -199,9 +213,11 @@ ao_i2c_send(void *block, uint16_t len, uint8_t index, uint8_t stop) uint8_t *b = block; uint32_t sr1; uint8_t tx_dma_index = ao_i2c_stm_info[index].tx_dma_index; + int t; /* Clear any pending ADDR bit */ (void) stm_i2c->sr2; + ao_i2c_wait_addr(index); stm_i2c->cr2 = AO_STM_I2C_CR2 | (1 << STM_I2C_CR2_DMAEN); ao_dma_set_transfer(tx_dma_index, &stm_i2c->dr, @@ -272,6 +288,7 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) /* Clear any pending ADDR bit */ stm_i2c->sr2; + ao_i2c_wait_addr(index); /* Enable interrupts to transfer the byte */ stm_i2c->cr2 = (AO_STM_I2C_CR2 | @@ -308,6 +325,7 @@ ao_i2c_recv(void *block, uint16_t len, uint8_t index, uint8_t stop) (1 << STM_I2C_CR2_DMAEN) | (1 << STM_I2C_CR2_LAST); /* Clear any pending ADDR bit */ (void) stm_i2c->sr2; + ao_i2c_wait_addr(index); ao_dma_start(rx_dma_index); ao_alarm(len); @@ -346,10 +364,11 @@ ao_i2c_channel_init(uint8_t index) stm_i2c->sr1 = 0; stm_i2c->sr2 = 0; - stm_i2c->ccr = ((1 << STM_I2C_CCR_FS) | + stm_i2c->ccr = ((0 << STM_I2C_CCR_FS) | (0 << STM_I2C_CCR_DUTY) | - (20 << STM_I2C_CCR_CCR)); - + (80 << STM_I2C_CCR_CCR)); + + stm_i2c->trise = 17; stm_i2c->cr1 = AO_STM_I2C_CR1; } -- cgit v1.2.3 From 84f9a525c64491afa9b7a565e3c10a4cee106e14 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 17:17:44 -0700 Subject: altos: Clean up radio CRC handling Make the FEC code just set the CRC_OK bit like the cc1111 radio does; eliminates a bunch of weird conventions across the FEC API. Signed-off-by: Keith Packard --- src/core/ao.h | 7 +++++++ src/core/ao_fec.h | 2 ++ src/core/ao_fec_rx.c | 26 +++++++++++++++----------- src/drivers/ao_cc1120.c | 7 +------ src/drivers/ao_packet.c | 4 +--- src/test/ao_fec_test.c | 21 ++++++++++----------- 6 files changed, 36 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 62eb488e..861a0fd4 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -511,6 +511,13 @@ extern __xdata uint8_t ao_radio_dma_done; extern __xdata uint8_t ao_radio_done; extern __xdata uint8_t ao_radio_mutex; +#ifdef PKT_APPEND_STATUS_1_CRC_OK +#define AO_RADIO_STATUS_CRC_OK PKT_APPEND_STATUS_1_CRC_OK +#else +#include +#define AO_RADIO_STATUS_CRC_OK AO_FEC_DECODE_CRC_OK +#endif + void ao_radio_general_isr(void) ao_arch_interrupt(16); diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index f1192b62..771732bd 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -70,6 +70,8 @@ ao_fec_encode(const uint8_t *in, uint8_t len, uint8_t *out); #define AO_FEC_DECODE_BLOCK (32) /* callback must return multiples of this many bits */ +#define AO_FEC_DECODE_CRC_OK 0x80 /* stored in out[out_len-1] */ + uint8_t ao_fec_decode(const uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()); diff --git a/src/core/ao_fec_rx.c b/src/core/ao_fec_rx.c index 0d400bb0..d4c98475 100644 --- a/src/core/ao_fec_rx.c +++ b/src/core/ao_fec_rx.c @@ -211,6 +211,7 @@ ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, ui int8_t dist = b - (o + 8); /* distance to last ready-for-writing bit */ uint32_t min_cost; /* lowest cost */ uint8_t min_state; /* lowest cost state */ + uint8_t byte; /* Find the best fit at the current point * of the decode. @@ -238,24 +239,27 @@ ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, ui printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x whiten %0x\n", i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff, *whiten); #endif - if (out_len) { - uint8_t byte = (bits[p][min_state] >> dist) ^ *whiten++; + byte = (bits[p][min_state] >> dist) ^ *whiten++; + *out++ = byte; + if (out_len > 2) + crc = ao_fec_crc_byte(byte, crc); - if (out_len > 2) { - crc = ao_fec_crc_byte(byte, crc); - *out++ = byte; - } else { - *out++ = byte ^ (crc >> 8); - crc <<= 8; - } - --out_len; + if (!--out_len) { + if ((out[-2] == (uint8_t) (crc >> 8)) && + out[-1] == (uint8_t) crc) + out[-1] = AO_FEC_DECODE_CRC_OK; + else + out[-1] = 0; + out[-2] = 0; + goto done; } o += 8; } } +done: #if AO_PROFILE ao_fec_decode_start = start_tick; ao_fec_decode_end = ao_profile_tick(); #endif - return len/16; + return 1; } diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index c974613e..30663042 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -690,12 +690,7 @@ ao_radio_recv(__xdata void *d, uint8_t size) ao_radio_put(); - /* Construct final packet */ - - if (ret && ((uint8_t *) d)[size] == 0 && ((uint8_t *)d)[size+1] == 0) - ((uint8_t *) d)[size + 1] = 0x80; - else - ((uint8_t *) d)[size + 1] = 0x00; + /* Store the received RSSI value; the crc-OK byte is already done */ ((uint8_t *) d)[size] = (uint8_t) rssi; diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c index 19fe0558..28a0c415 100644 --- a/src/drivers/ao_packet.c +++ b/src/drivers/ao_packet.c @@ -65,10 +65,8 @@ ao_packet_recv(void) /* Check to see if we got a valid packet */ if (!dma_done) return 0; -#ifdef PKT_APPEND_STATUS_1_CRC_OK - if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) + if (!(ao_rx_packet.status & AO_RADIO_STATUS_CRC_OK)) return 0; -#endif /* Accept packets with matching call signs, or any packet if * our callsign hasn't been configured diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c index 8ce532c8..671fcafc 100644 --- a/src/test/ao_fec_test.c +++ b/src/test/ao_fec_test.c @@ -268,18 +268,17 @@ int ao_real_packet(void) { uint8_t decode[64]; - uint8_t decode_len; - int ok = 0; + int ok; - decode_len = ao_fec_decode(real_packet, 576, decode, 34, NULL); + ok = ao_fec_decode(real_packet, 576, decode, 34, NULL); - if (decode[32] == 0 && decode[33] == 0) { + if (ok && decode[33] == AO_FEC_DECODE_CRC_OK) { printf ("match\n"); - ao_fec_dump_bytes(decode, decode_len, "Decode"); - ok = 1; + ao_fec_dump_bytes(decode, 34, "Decode"); } else { printf ("actual packet crc error\n"); + ok = 0; } return ok; } @@ -302,7 +301,7 @@ main(int argc, char **argv) int receive_len, receive_errors; uint8_t decode[DECODE_LEN(sizeof(original))]; - int decode_len; + int decode_ok; int errors = 0; int error; @@ -327,17 +326,17 @@ main(int argc, char **argv) receive_len = transmit_len; /* Decode it */ - decode_len = ao_fec_decode(receive, receive_len, decode, original_len + 2, NULL); + decode_ok = ao_fec_decode(receive, receive_len, decode, original_len + 2, NULL); /* Check to see if we received the right data */ error = 0; - if (decode_len < original_len + 2) { - printf ("len mis-match\n"); + if (!decode_ok) { + printf ("decode failed\n"); error++; } - if (decode[original_len] != 0 || decode[original_len+1] != 0) { + if (decode[original_len +1] != AO_FEC_DECODE_CRC_OK) { printf ("crc mis-match\n"); error++; } -- cgit v1.2.3 From 4f258fe565dc3e58b83761bfa1a2276946012163 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 17:18:57 -0700 Subject: altos: Clean up STM I2C clock computations Fix both clock time and rise time. Signed-off-by: Keith Packard --- src/stm/ao_i2c_stm.c | 63 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 50 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/stm/ao_i2c_stm.c b/src/stm/ao_i2c_stm.c index c4a6c5a3..b6dd7056 100644 --- a/src/stm/ao_i2c_stm.c +++ b/src/stm/ao_i2c_stm.c @@ -23,6 +23,8 @@ struct ao_i2c_stm_info { struct stm_i2c *stm_i2c; }; +#define I2C_FAST 1 + #define I2C_TIMEOUT 100 #define I2C_IDLE 0 @@ -33,6 +35,33 @@ static uint8_t ao_i2c_state[STM_NUM_I2C]; static uint16_t ao_i2c_addr[STM_NUM_I2C]; uint8_t ao_i2c_mutex[STM_NUM_I2C]; +# define I2C_HIGH_SLOW 5000 /* ns, 100kHz clock */ +#ifdef MEGAMETRUM +# define I2C_HIGH_FAST 2000 /* ns, 167kHz clock */ +#else +# define I2C_HIGH_FAST 1000 /* ns, 333kHz clock */ +#endif + +# define I2C_RISE_SLOW 500 /* ns */ +# define I2C_RISE_FAST 100 /* ns */ + +/* Clock period in ns */ +#define CYCLES(period) (((period) * (AO_PCLK1 / 1000)) / 1000000) + +#define max(a,b) ((a) > (b) ? (a) : (b)) +#define I2C_CCR_HIGH_SLOW max(4,CYCLES(I2C_HIGH_SLOW)) +#define I2C_CCR_HIGH_FAST max(4,CYCLES(I2C_HIGH_FAST)) +#define I2C_TRISE_SLOW (CYCLES(I2C_RISE_SLOW) + 1) +#define I2C_TRISE_FAST (CYCLES(I2C_RISE_FAST) + 1) + +#if I2C_FAST +#define I2C_TRISE I2C_TRISE_FAST +#define I2C_CCR_HIGH I2C_CCR_HIGH_FAST +#else +#define I2C_TRISE I2C_TRISE_SLOW +#define I2C_CCR_HIGH I2C_CCR_HIGH_SLOW +#endif + #if AO_PCLK1 == 2000000 # define AO_STM_I2C_CR2_FREQ STM_I2C_CR2_FREQ_2_MHZ #endif @@ -364,15 +393,23 @@ ao_i2c_channel_init(uint8_t index) stm_i2c->sr1 = 0; stm_i2c->sr2 = 0; - stm_i2c->ccr = ((0 << STM_I2C_CCR_FS) | + stm_i2c->ccr = ((I2C_FAST << STM_I2C_CCR_FS) | (0 << STM_I2C_CCR_DUTY) | - (80 << STM_I2C_CCR_CCR)); + (I2C_CCR_HIGH << STM_I2C_CCR_CCR)); - stm_i2c->trise = 17; + stm_i2c->trise = I2C_TRISE; stm_i2c->cr1 = AO_STM_I2C_CR1; } +static inline void +i2c_pin_set(struct stm_gpio *gpio, int pin) +{ + stm_afr_set(gpio, pin, STM_AFR_AF4); + stm_ospeedr_set(gpio, pin, STM_OSPEEDR_400kHz); + stm_pupdr_set(gpio, pin, STM_PUPDR_PULL_UP); +} + void ao_i2c_init(void) { @@ -380,12 +417,12 @@ ao_i2c_init(void) stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); #if HAS_I2C_1 # if I2C_1_PB6_PB7 - stm_afr_set(&stm_gpiob, 6, STM_AFR_AF4); - stm_afr_set(&stm_gpiob, 7, STM_AFR_AF4); + i2c_pin_set(&stm_gpiob, 6); + i2c_pin_set(&stm_gpiob, 7); # else # if I2C_1_PB8_PB9 - stm_afr_set(&stm_gpiob, 8, STM_AFR_AF4); - stm_afr_set(&stm_gpiob, 9, STM_AFR_AF4); + i2c_pin_set(&stm_gpiob, 8); + i2c_pin_set(&stm_gpiob, 9); # else # error "No I2C_1 port configuration specified" # endif @@ -395,15 +432,15 @@ ao_i2c_init(void) ao_i2c_channel_init(0); stm_nvic_set_enable(STM_ISR_I2C1_EV_POS); - stm_nvic_set_priority(STM_ISR_I2C1_EV_POS, 3); + stm_nvic_set_priority(STM_ISR_I2C1_EV_POS, AO_STM_NVIC_MED_PRIORITY); stm_nvic_set_enable(STM_ISR_I2C1_ER_POS); - stm_nvic_set_priority(STM_ISR_I2C1_ER_POS, 3); + stm_nvic_set_priority(STM_ISR_I2C1_ER_POS, AO_STM_NVIC_MED_PRIORITY); #endif #if HAS_I2C_2 # if I2C_2_PB10_PB11 - stm_afr_set(&stm_gpiob, 10, STM_AFR_AF4); - stm_afr_set(&stm_gpiob, 11, STM_AFR_AF4); + i2c_pin_set(&stm_gpiob, 10); + i2c_pin_set(&stm_gpiob, 11); # else # error "No I2C_2 port configuration specified" # endif @@ -411,8 +448,8 @@ ao_i2c_init(void) ao_i2c_channel_init(1); stm_nvic_set_enable(STM_ISR_I2C2_EV_POS); - stm_nvic_set_priority(STM_ISR_I2C2_EV_POS, 3); + stm_nvic_set_priority(STM_ISR_I2C2_EV_POS, AO_STM_NVIC_MED_PRIORITY); stm_nvic_set_enable(STM_ISR_I2C2_ER_POS); - stm_nvic_set_priority(STM_ISR_I2C2_ER_POS, 3); + stm_nvic_set_priority(STM_ISR_I2C2_ER_POS, AO_STM_NVIC_MED_PRIORITY); #endif } -- cgit v1.2.3 From 407cefae9cb95c5910b3bd79851776c48729e06b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 19:45:22 -0700 Subject: altos: Unroll viterbi state loop for >30% performance boost 9.3ms vs 14.7ms, a clear win. Signed-off-by: Keith Packard --- src/core/ao_fec_rx.c | 56 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/core/ao_fec_rx.c b/src/core/ao_fec_rx.c index d4c98475..c1a3918b 100644 --- a/src/core/ao_fec_rx.c +++ b/src/core/ao_fec_rx.c @@ -161,31 +161,43 @@ ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, ui cost[n][state] = 0x7fffffff; /* Compute path costs and accumulate output bit path - * for each state and encoded bit value + * for each state and encoded bit value. Unrolling + * this loop is worth about > 30% performance boost. + * Decoding 76-byte remote access packets is reduced + * from 14.700ms to 9.3ms */ - for (state = 0; state < NUM_STATE; state++) { - uint32_t bitcost = ((uint32_t) (s0 ^ ao_fec_decode_table[(state<<1)]) + - (uint32_t) (s1 ^ ao_fec_decode_table[(state<<1)+1])); - { - uint32_t cost0 = cost[p][state] + bitcost; - uint8_t state0 = ao_next_state(state, 0); - - if (cost0 < cost[n][state0]) { - cost[n][state0] = cost0; - bits[n][state0] = (bits[p][state] << 1) | (state & 1); - } - } - { - uint32_t cost1 = cost[p][state] + 510 - bitcost; - uint8_t state1 = ao_next_state(state, 1); - - if (cost1 < cost[n][state1]) { - cost[n][state1] = cost1; - bits[n][state1] = (bits[p][state] << 1) | (state & 1); - } - } +#define DO_STATE(state) { \ + uint32_t bitcost = ((uint32_t) (s0 ^ ao_fec_decode_table[(state<<1)]) + \ + (uint32_t) (s1 ^ ao_fec_decode_table[(state<<1)+1])); \ + { \ + uint32_t cost0 = cost[p][state] + bitcost; \ + uint8_t state0 = ao_next_state(state, 0); \ + \ + if (cost0 < cost[n][state0]) { \ + cost[n][state0] = cost0; \ + bits[n][state0] = (bits[p][state] << 1) | (state & 1); \ + } \ + } \ + { \ + uint32_t cost1 = cost[p][state] + 510 - bitcost; \ + uint8_t state1 = ao_next_state(state, 1); \ + \ + if (cost1 < cost[n][state1]) { \ + cost[n][state1] = cost1; \ + bits[n][state1] = (bits[p][state] << 1) | (state & 1); \ + } \ + } \ } + DO_STATE(0); + DO_STATE(1); + DO_STATE(2); + DO_STATE(3); + DO_STATE(4); + DO_STATE(5); + DO_STATE(6); + DO_STATE(7); + #if 0 printf ("bit %3d symbol %2x %2x:", i/2, s0, s1); for (state = 0; state < NUM_STATE; state++) { -- cgit v1.2.3 From bd21c050fd8b96b33ab6859c942bf55cf2b91868 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 19:47:52 -0700 Subject: altos: Make profiling Viterbi decoder more useful This blocks starting the decoder until all of the data have arrived so that the time spent in the decoder is easily computed. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 8 +++++++- src/drivers/ao_packet.c | 12 ++++++++++++ src/megametrum-v0.1/Makefile | 7 +++---- src/megametrum-v0.1/ao_megametrum.c | 3 +++ 4 files changed, 25 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 30663042..1d28148b 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -605,8 +605,10 @@ ao_radio_rx_isr(void) rx_data[rx_data_cur++] = d; if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) { #if AO_PROFILE - if (rx_data_consumed == 0) + if (!rx_packet_tick) rx_packet_tick = ao_profile_tick(); + if (rx_data_cur < rx_data_count) + return; #endif rx_waiting = 0; ao_wakeup(&ao_radio_wake); @@ -630,6 +632,9 @@ ao_radio_rx_wait(void) if (ao_radio_abort) return 0; rx_data_consumed += AO_FEC_DECODE_BLOCK; +#if AO_PROFILE + return rx_data_cur - rx_data_consumed; +#endif return AO_FEC_DECODE_BLOCK; } @@ -649,6 +654,7 @@ ao_radio_recv(__xdata void *d, uint8_t size) } #if AO_PROFILE rx_start_tick = ao_profile_tick(); + rx_packet_tick = 0; #endif len = size + 2; /* CRC bytes */ len += 1 + ~(len & 1); /* 1 or two pad bytes */ diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c index 28a0c415..e020c003 100644 --- a/src/drivers/ao_packet.c +++ b/src/drivers/ao_packet.c @@ -61,6 +61,18 @@ ao_packet_recv(void) #ifdef AO_LED_GREEN ao_led_off(AO_LED_GREEN); #endif +#if AO_PROFILE + { + extern uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick; + extern uint32_t ao_fec_decode_start, ao_fec_decode_end; + + printf ("between packet: %d\n", ao_rx_start_tick - ao_rx_last_done_tick); + printf ("receive start delay: %d\n", ao_rx_packet_tick - ao_rx_start_tick); + printf ("decode time: %d\n", ao_fec_decode_end - ao_fec_decode_start); + printf ("rx cleanup: %d\n\n", ao_rx_done_tick - ao_fec_decode_end); + flush(); + } +#endif /* Check to see if we got a valid packet */ if (!dma_done) diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 07a339b9..06b5e2ae 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -27,8 +27,7 @@ INC = \ # Common AltOS sources # -# ao_packet.c \ -# ao_packet_slave.c \ +#PROFILE=ao_profile.c ALTOS_SRC = \ ao_interrupt.c \ @@ -72,8 +71,8 @@ ALTOS_SRC = \ ao_telemetry.c \ ao_packet_slave.c \ ao_packet.c \ - ao_companion.c - + ao_companion.c \ + $(PROFILE) PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index ed35efa4..749f251d 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -63,6 +63,9 @@ main(void) ao_companion_init(); ao_config_init(); +#if AO_PROFILE + ao_profile_init(); +#endif ao_start_scheduler(); return 0; -- cgit v1.2.3 From dd623b21cb904238c6d903b6936ff2f8ebf6f339 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 23:03:33 -0700 Subject: altos: Allow megametrum to be built without using the mag sensor I'm having trouble getting it working reliably, so we'll like disable it for now. This patch makes that possible. Signed-off-by: Keith Packard --- src/core/ao_log_mega.c | 8 +++++++- src/core/ao_telemetry.c | 4 ++++ src/megametrum-v0.1/ao_megametrum.c | 6 ++++++ 3 files changed, 17 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_log_mega.c b/src/core/ao_log_mega.c index e7c2b0d9..ac1590db 100644 --- a/src/core/ao_log_mega.c +++ b/src/core/ao_log_mega.c @@ -112,18 +112,24 @@ ao_log(void) log.tick = ao_data_ring[ao_log_data_pos].tick; if ((int16_t) (log.tick - next_sensor) >= 0) { log.type = AO_LOG_SENSOR; +#if HAS_MS5607 log.u.sensor.pres = ao_data_ring[ao_log_data_pos].ms5607_raw.pres; log.u.sensor.temp = ao_data_ring[ao_log_data_pos].ms5607_raw.temp; +#endif +#if HAS_MPU6000 log.u.sensor.accel_x = ao_data_ring[ao_log_data_pos].mpu6000.accel_x; log.u.sensor.accel_y = ao_data_ring[ao_log_data_pos].mpu6000.accel_y; log.u.sensor.accel_z = ao_data_ring[ao_log_data_pos].mpu6000.accel_z; log.u.sensor.gyro_x = ao_data_ring[ao_log_data_pos].mpu6000.gyro_x; log.u.sensor.gyro_y = ao_data_ring[ao_log_data_pos].mpu6000.gyro_y; log.u.sensor.gyro_z = ao_data_ring[ao_log_data_pos].mpu6000.gyro_z; +#endif +#if HAS_HMC5883 log.u.sensor.mag_x = ao_data_ring[ao_log_data_pos].hmc5883.x; log.u.sensor.mag_y = ao_data_ring[ao_log_data_pos].hmc5883.y; log.u.sensor.mag_z = ao_data_ring[ao_log_data_pos].hmc5883.z; - log.u.sensor.accel = ao_data_ring[ao_log_data_pos].adc.accel; +#endif + log.u.sensor.accel = ao_data_accel(&ao_data_ring[ao_log_data_pos]); ao_log_mega(&log); if (ao_log_state <= ao_flight_coast) next_sensor = log.tick + AO_SENSOR_INTERVAL_ASCENT; diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index b3ce8ba9..3c747520 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -104,6 +104,7 @@ ao_send_mega_sensor(void) telemetry.mega_sensor.pres = ao_data_pres(packet); telemetry.mega_sensor.temp = ao_data_temp(packet); +#if HAS_MPU6000 telemetry.mega_sensor.accel_x = packet->mpu6000.accel_x; telemetry.mega_sensor.accel_y = packet->mpu6000.accel_y; telemetry.mega_sensor.accel_z = packet->mpu6000.accel_z; @@ -111,10 +112,13 @@ ao_send_mega_sensor(void) telemetry.mega_sensor.gyro_x = packet->mpu6000.gyro_x; telemetry.mega_sensor.gyro_y = packet->mpu6000.gyro_y; telemetry.mega_sensor.gyro_z = packet->mpu6000.gyro_z; +#endif +#if HAS_HMC5883 telemetry.mega_sensor.mag_x = packet->hmc5883.x; telemetry.mega_sensor.mag_y = packet->hmc5883.y; telemetry.mega_sensor.mag_z = packet->hmc5883.z; +#endif ao_radio_send(&telemetry, sizeof (telemetry)); } diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 749f251d..a6d93733 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -43,9 +43,15 @@ main(void) ao_beep_init(); ao_cmd_init(); +#if HAS_MS5607 ao_ms5607_init(); +#endif +#if HAS_HMC5883 ao_hmc5883_init(); +#endif +#if HAS_MPU6000 ao_mpu6000_init(); +#endif ao_storage_init(); -- cgit v1.2.3 From f9f65211c378849270a6138fda05ed2a166f7d82 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 23:04:25 -0700 Subject: altos: Disable mag sensor for megametrum It doesn't work unless USB is connected or occasionally while the debug port is enabled. It's mystic. Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 3 ++- src/megametrum-v0.1/ao_pins.h | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 06b5e2ae..e789a0e8 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -29,6 +29,8 @@ INC = \ #PROFILE=ao_profile.c +# ao_hmc5883.c + ALTOS_SRC = \ ao_interrupt.c \ ao_product.c \ @@ -60,7 +62,6 @@ ALTOS_SRC = \ ao_exti_stm.c \ ao_report.c \ ao_i2c_stm.c \ - ao_hmc5883.c \ ao_mpu6000.c \ ao_convert_pa.c \ ao_log.c \ diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 1d2051e1..dc3761ba 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -286,7 +286,7 @@ struct ao_adc { * Mag sensor (hmc5883) */ -#define HAS_HMC5883 1 +#define HAS_HMC5883 0 #define AO_HMC5883_INT_PORT (&stm_gpioc) #define AO_HMC5883_INT_PIN 12 #define AO_HMC5883_I2C_INDEX STM_I2C_INDEX(1) -- cgit v1.2.3 From aab7b31b71aa7c87c5a5003084e4b7773c30835f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 23:05:36 -0700 Subject: altos: panic if MPU6000 self test fails Don't try to fly if the board isn't working right. Signed-off-by: Keith Packard --- src/drivers/ao_mpu6000.c | 53 +++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index 065ed221..a1c32d4d 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -102,16 +102,12 @@ ao_mpu6000_accel_check(int16_t normal, int16_t test, char *which) int16_t diff = test - normal; if (diff < MPU6000_ST_ACCEL(16) / 2) { - printf ("%s accel self test value too small (normal %d, test %d)\n", - which, normal, test); - return FALSE; + return 1; } if (diff > MPU6000_ST_ACCEL(16) * 2) { - printf ("%s accel self test value too large (normal %d, test %d)\n", - which, normal, test); - return FALSE; + return 1; } - return TRUE; + return 0; } static uint8_t @@ -122,23 +118,19 @@ ao_mpu6000_gyro_check(int16_t normal, int16_t test, char *which) if (diff < 0) diff = -diff; if (diff < MPU6000_ST_GYRO(2000) / 2) { - printf ("%s gyro self test value too small (normal %d, test %d)\n", - which, normal, test); - return FALSE; + return 1; } if (diff > MPU6000_ST_GYRO(2000) * 2) { - printf ("%s gyro self test value too large (normal %d, test %d)\n", - which, normal, test); - return FALSE; + return 1; } - return TRUE; + return 0; } static void ao_mpu6000_setup(void) { struct ao_mpu6000_sample normal_mode, test_mode; - int t; + int errors =0; if (ao_mpu6000_configured) return; @@ -224,13 +216,16 @@ ao_mpu6000_setup(void) ao_delay(AO_MS_TO_TICKS(10)); ao_mpu6000_sample(&normal_mode); - ao_mpu6000_accel_check(normal_mode.accel_x, test_mode.accel_x, "x"); - ao_mpu6000_accel_check(normal_mode.accel_y, test_mode.accel_y, "y"); - ao_mpu6000_accel_check(normal_mode.accel_z, test_mode.accel_z, "z"); + errors += ao_mpu6000_accel_check(normal_mode.accel_x, test_mode.accel_x, "x"); + errors += ao_mpu6000_accel_check(normal_mode.accel_y, test_mode.accel_y, "y"); + errors += ao_mpu6000_accel_check(normal_mode.accel_z, test_mode.accel_z, "z"); - ao_mpu6000_gyro_check(normal_mode.gyro_x, test_mode.gyro_x, "x"); - ao_mpu6000_gyro_check(normal_mode.gyro_y, test_mode.gyro_y, "y"); - ao_mpu6000_gyro_check(normal_mode.gyro_z, test_mode.gyro_z, "z"); + errors += ao_mpu6000_gyro_check(normal_mode.gyro_x, test_mode.gyro_x, "x"); + errors += ao_mpu6000_gyro_check(normal_mode.gyro_y, test_mode.gyro_y, "y"); + errors += ao_mpu6000_gyro_check(normal_mode.gyro_z, test_mode.gyro_z, "z"); + + if (errors) + ao_panic(AO_PANIC_SELF_TEST); /* Filter to about 100Hz, which also sets the gyro rate to 1000Hz */ ao_mpu6000_reg_write(MPU6000_CONFIG, @@ -271,14 +266,16 @@ ao_mpu6000_show(void) { struct ao_mpu6000_sample sample; - sample = ao_mpu6000_current; + ao_arch_critical( + sample = ao_mpu6000_current; + ); printf ("Accel: %7d %7d %7d Gyro: %7d %7d %7d\n", - ao_mpu6000_accel(sample.accel_x), - ao_mpu6000_accel(sample.accel_y), - ao_mpu6000_accel(sample.accel_z), - ao_mpu6000_gyro(sample.gyro_x), - ao_mpu6000_gyro(sample.gyro_y), - ao_mpu6000_gyro(sample.gyro_z)); + sample.accel_x, + sample.accel_y, + sample.accel_z, + sample.gyro_x, + sample.gyro_y, + sample.gyro_z); } static const struct ao_cmds ao_mpu6000_cmds[] = { -- cgit v1.2.3 From 79dbe1a5e46d7f0b8929400897631ab969cd2bc0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 23:09:16 -0700 Subject: altos: Increase default STM stack to 648 bytes 512 seems cozy given the printf implementation we're using and the extensive interrupts. Signed-off-by: Keith Packard --- src/stm/ao_arch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 30cd9ea5..baae1902 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -25,7 +25,7 @@ * STM32L definitions and code fragments for AltOS */ -#define AO_STACK_SIZE 512 +#define AO_STACK_SIZE 700 #define AO_LED_TYPE uint16_t -- cgit v1.2.3 From 572e1664938c7ce6c308b36779f6a412959e03f1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 23:11:27 -0700 Subject: altos: Track missed HMC5883 interrupts When it fails to signal conversion complete to the CPU, keep track of that and report it with the rest of the current data. Signed-off-by: Keith Packard --- src/drivers/ao_hmc5883.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c index 64663ea6..dbeb66b8 100644 --- a/src/drivers/ao_hmc5883.c +++ b/src/drivers/ao_hmc5883.c @@ -63,6 +63,8 @@ ao_hmc5883_isr(void) ao_wakeup(&ao_hmc5883_done); } +static uint32_t ao_hmc5883_missed_irq; + void ao_hmc5883_sample(struct ao_hmc5883_sample *sample) { @@ -74,10 +76,13 @@ ao_hmc5883_sample(struct ao_hmc5883_sample *sample) ao_exti_enable(AO_HMC5883_INT_PORT, AO_HMC5883_INT_PIN); ao_hmc5883_reg_write(HMC5883_MODE, HMC5883_MODE_SINGLE); + ao_alarm(AO_MS_TO_TICKS(10)); cli(); while (!ao_hmc5883_done) - ao_sleep(&ao_hmc5883_done); + if (ao_sleep(&ao_hmc5883_done)) + ++ao_hmc5883_missed_irq; sei(); + ao_clear_alarm(); ao_hmc5883_read(HMC5883_X_MSB, (uint8_t *) sample, sizeof (struct ao_hmc5883_sample)); #if __BYTE_ORDER == __LITTLE_ENDIAN @@ -144,7 +149,8 @@ ao_hmc5883_show(void) struct ao_hmc5883_sample sample; sample = ao_hmc5883_current; - printf ("X: %d Y: %d Z: %d\n", sample.x, sample.y, sample.z); + printf ("X: %d Y: %d Z: %d missed irq: %lu\n", + sample.x, sample.y, sample.z, ao_hmc5883_missed_irq); } static const struct ao_cmds ao_hmc5883_cmds[] = { -- cgit v1.2.3 From ca1bc20735a170a77066f5f37e0ad728899a3989 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Jun 2012 16:05:56 -0700 Subject: altos: Disable MS5607 interrupt in the handler Avoids having the interrupt re-raised multiple times until the reading task finally wakes up. Signed-off-by: Keith Packard --- src/drivers/ao_ms5607.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index e1d0507e..17fe853b 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -118,6 +118,7 @@ static uint8_t ao_ms5607_done; static void ao_ms5607_isr(void) { + ao_exti_disable(AO_MS5607_MISO_GPIO, AO_MS5607_MISO); ao_ms5607_done = 1; ao_wakeup(&ao_ms5607_done); } @@ -137,7 +138,6 @@ ao_ms5607_get_sample(uint8_t cmd) { while (!ao_ms5607_done) ao_sleep(&ao_ms5607_done); sei(); - ao_exti_disable(AO_MS5607_MISO_GPIO, AO_MS5607_MISO); ao_ms5607_stop(); ao_ms5607_start(); -- cgit v1.2.3 From edbc5d27c8c2936b59ff5289276d9198b501ebc8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Jun 2012 17:43:36 -0700 Subject: altos: Declare cc1111 accel_ref as unsigned so the math works If accel_ref is signed, then the careful shifting and dividing dance necessary to correct for changes in the relationship between the 5V and 3.3V supplies always generates zero. Signed-off-by: Keith Packard --- src/cc1111/ao_arch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index cece09eb..8d9e4952 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -206,7 +206,7 @@ struct ao_adc { int16_t sense_d; /* drogue continuity sense */ int16_t sense_m; /* main continuity sense */ #if HAS_ACCEL_REF - int16_t accel_ref; /* acceleration reference */ + uint16_t accel_ref; /* acceleration reference */ #endif }; -- cgit v1.2.3 From f0ec8416f2e308e40e1b9f34a7c2549989fee5fb Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sat, 30 Jun 2012 13:00:33 -0600 Subject: conditionalize build of ARM binaries on presence of arm-none-eabi-gcc in PATH --- src/Makefile | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 3fca2ab2..1b0dabe4 100644 --- a/src/Makefile +++ b/src/Makefile @@ -15,8 +15,6 @@ vpath matrix.5c kalman include Version SUBDIRS=\ - megametrum-v0.1 \ - stm-bringup stm-demo \ telemetrum-v1.2 telemetrum-v1.1 telemetrum-v1.0 \ teledongle-v0.2 teledongle-v0.1 \ telemini-v1.0 telenano-v0.1 \ @@ -26,6 +24,10 @@ SUBDIRS=\ tidongle test telescience-v0.1 telepyro-v0.1 \ teleterra-v0.2 teleshield-v0.1 +ifneq ($(shell which arm-none-eabi-gcc),) + SUBDIRS += megametrum-v0.1 stm-bringup stm-demo +endif + all: all-local all-recursive RECURSIVE_TARGETS = all-recursive clean-recursive install-recursive -- cgit v1.2.3 From 50b343d389039eae082e82b8ac0b76ae3e2b3ad4 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Sun, 1 Jul 2012 23:24:20 -0600 Subject: extend cross-compiler availability logic to all target CPUs, not just ARM --- src/Makefile | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 1b0dabe4..491618f6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,7 +1,6 @@ # # AltOS build # -# vpath make-altitude util vpath make-altitude-pa util @@ -14,15 +13,20 @@ vpath matrix.5c kalman include Version -SUBDIRS=\ +ifneq ($(shell which sdcc),) + SUBDIRS+=\ telemetrum-v1.2 telemetrum-v1.1 telemetrum-v1.0 \ teledongle-v0.2 teledongle-v0.1 \ telemini-v1.0 telenano-v0.1 \ telebt-v0.0 telebt-v0.1 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ - telelaunch-v0.1 \ - tidongle test telescience-v0.1 telepyro-v0.1 \ + telelaunch-v0.1 tidongle test \ teleterra-v0.2 teleshield-v0.1 +endif + +ifneq ($(shell which avr-gcc),) + SUBDIRS += telescience-v0.1 telepyro-v0.1 +endif ifneq ($(shell which arm-none-eabi-gcc),) SUBDIRS += megametrum-v0.1 stm-bringup stm-demo -- cgit v1.2.3 From 933fc7e4c2f617e49e1cfdf45b83695290b51456 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Jul 2012 23:44:10 -0700 Subject: altos: Do not block igniters on the radio mutex. Blocking igniters on the radio mutex fails when doing igniter testing over the RF link; the packet receiver task will never release the mutex and the CPU at the same time, causing the system to lock up. Signed-off-by: Keith Packard --- src/core/ao_ignite.c | 6 ------ src/telemetrum-v1.1/.sdcdbrc | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) (limited to 'src') diff --git a/src/core/ao_ignite.c b/src/core/ao_ignite.c index d4aef153..e82de355 100644 --- a/src/core/ao_ignite.c +++ b/src/core/ao_ignite.c @@ -81,9 +81,6 @@ ao_igniter_status(enum ao_igniter igniter) void ao_igniter_fire(enum ao_igniter igniter) __critical { -#ifndef MEGAMETRUM - ao_mutex_get(&ao_radio_mutex); -#endif ao_ignition[igniter].firing = 1; switch(ao_config.ignite_mode) { case AO_IGNITE_MODE_DUAL: @@ -128,9 +125,6 @@ ao_igniter_fire(enum ao_igniter igniter) __critical break; } ao_ignition[igniter].firing = 0; -#ifndef MEGAMETRUM - ao_mutex_put(&ao_radio_mutex); -#endif } void diff --git a/src/telemetrum-v1.1/.sdcdbrc b/src/telemetrum-v1.1/.sdcdbrc index 710b4a2f..fbe9a599 100644 --- a/src/telemetrum-v1.1/.sdcdbrc +++ b/src/telemetrum-v1.1/.sdcdbrc @@ -1 +1 @@ ---directory=.. +--directory=../cc1111:../product:../core:../drivers:. -- cgit v1.2.3 From e8ab00cc45e48230e3b2018ce959114d3fedd228 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Jul 2012 20:59:35 -0700 Subject: altos: Viterbi performance improvments. Down to 5.7ms for command decode Stealing more of Phil's good ideas, decoding a command mode packet has been reduced from 9ms to 5.7ms. Lots more comments to help future-me figure out how this code works. Signed-off-by: Keith Packard --- src/core/ao_fec_rx.c | 105 +++++++++++++++++++++++++++++++++++---------------- 1 file changed, 73 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/core/ao_fec_rx.c b/src/core/ao_fec_rx.c index c1a3918b..64426d72 100644 --- a/src/core/ao_fec_rx.c +++ b/src/core/ao_fec_rx.c @@ -62,7 +62,9 @@ static inline uint16_t ao_interleave_index(uint16_t i) { } #define NUM_STATE 8 -#define NUM_HIST 8 +#define NUM_HIST 24 + +typedef uint32_t bits_t; #define V_0 0xff #define V_1 0x00 @@ -97,7 +99,7 @@ uint8_t ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()) { static uint32_t cost[2][NUM_STATE]; /* path cost */ - static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */ + static bits_t bits[2][NUM_STATE]; /* save bits to quickly output them */ uint16_t i; /* input byte index */ uint16_t b; /* encoded symbol index (bytes/2) */ @@ -154,54 +156,93 @@ ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, ui avail -= 2; - /* Reset next costs to 'impossibly high' values so that - * the first path through this state is cheaper than this - */ - for (state = 0; state < NUM_STATE; state++) - cost[n][state] = 0x7fffffff; - /* Compute path costs and accumulate output bit path * for each state and encoded bit value. Unrolling * this loop is worth about > 30% performance boost. * Decoding 76-byte remote access packets is reduced - * from 14.700ms to 9.3ms + * from 14.700ms to 9.3ms. Redoing the loop to + * directly compare the two pasts for each future state + * reduces this down to 5.7ms + */ + + /* Ok, of course this is tricky, it's optimized. + * + * First, it's important to realize that we have 8 + * states representing the combinations of the three + * most recent bits from the encoder. Flipping any + * of these three bits flips both output bits. + * + * 'state<<1' represents the target state for a new + * bit value of 0. '(state<<1)+1' represents the + * target state for a new bit value of 1. + * + * 'state' is the previous state with an oldest bit + * value of 0. 'state + 4' is the previous state with + * an oldest bit value of 1. These two states will + * either lead to 'state<<1' or '(state<<1)+1', depending + * on whether the next encoded bit was a zero or a one. + * + * m0 and m1 are the cost of coming to 'state<<1' from + * one of the two possible previous states 'state' and + * 'state + 4'. + * + * Because we know the expected values of each + * received bit are flipped between these two previous + * states: + * + * bitcost(state+4) = 510 - bitcost(state) + * + * With those two total costs in hand, we then pick + * the lower as the cost of the 'state<<1', and compute + * the path of bits leading to that state. + * + * Then, do the same for '(state<<1) + 1'. This time, + * instead of computing the m0 and m1 values from + * scratch, because the only difference is that we're + * expecting a one bit instead of a zero bit, we just + * flip the bitcost values around to match the + * expected transmitted bits with some tricky + * arithmetic which is equivalent to: + * + * m0 = cost[p][state] + (510 - bitcost); + * m1 = cost[p][state+4] + bitcost + * + * Then, the lowest cost and bit trace of the new state + * is saved. */ + #define DO_STATE(state) { \ - uint32_t bitcost = ((uint32_t) (s0 ^ ao_fec_decode_table[(state<<1)]) + \ - (uint32_t) (s1 ^ ao_fec_decode_table[(state<<1)+1])); \ - { \ - uint32_t cost0 = cost[p][state] + bitcost; \ - uint8_t state0 = ao_next_state(state, 0); \ + uint32_t bitcost; \ + \ + uint32_t m0; \ + uint32_t m1; \ + uint32_t bit; \ + \ + bitcost = ((uint32_t) (s0 ^ ao_fec_decode_table[(state<<1)]) + \ + (uint32_t) (s1 ^ ao_fec_decode_table[(state<<1)|1])); \ \ - if (cost0 < cost[n][state0]) { \ - cost[n][state0] = cost0; \ - bits[n][state0] = (bits[p][state] << 1) | (state & 1); \ - } \ - } \ - { \ - uint32_t cost1 = cost[p][state] + 510 - bitcost; \ - uint8_t state1 = ao_next_state(state, 1); \ + m0 = cost[p][state] + bitcost; \ + m1 = cost[p][state+4] + (510 - bitcost); \ + bit = m0 > m1; \ + cost[n][state<<1] = bit ? m1 : m0; \ + bits[n][state<<1] = (bits[p][state + (bit<<2)] << 1) | (state&1); \ \ - if (cost1 < cost[n][state1]) { \ - cost[n][state1] = cost1; \ - bits[n][state1] = (bits[p][state] << 1) | (state & 1); \ - } \ - } \ + m0 -= (bitcost+bitcost-510); \ + m1 += (bitcost+bitcost-510); \ + bit = m0 > m1; \ + cost[n][(state<<1)+1] = bit ? m1 : m0; \ + bits[n][(state<<1)+1] = (bits[p][state + (bit<<2)] << 1) | (state&1); \ } DO_STATE(0); DO_STATE(1); DO_STATE(2); DO_STATE(3); - DO_STATE(4); - DO_STATE(5); - DO_STATE(6); - DO_STATE(7); #if 0 printf ("bit %3d symbol %2x %2x:", i/2, s0, s1); for (state = 0; state < NUM_STATE; state++) { - printf (" %5d(%04x)", cost[n][state], bits[n][state]); + printf (" %8u(%08x)", cost[n][state], bits[n][state]); } printf ("\n"); #endif -- cgit v1.2.3 From 939ad8bfd640ed55116703a58f87af06e75ef87e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Jul 2012 21:01:01 -0700 Subject: altos: Crank up the gaussian noise in the FEC test This lets us check to make sure our receive performance isn't degrading at all, instead of just making sure we can receive perfect packets well. Signed-off-by: Keith Packard --- src/test/ao_fec_test.c | 54 +++++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c index 671fcafc..b94b16dc 100644 --- a/src/test/ao_fec_test.c +++ b/src/test/ao_fec_test.c @@ -283,6 +283,11 @@ ao_real_packet(void) return ok; } +#define EXPECT_DECODE_FAIL 0 +#define EXPECT_CRC_MISMATCH 6386 +#define EXPECT_DATA_MISMATCH 0 +#define NOISE_AMOUNT 0x50 + int main(int argc, char **argv) { @@ -298,13 +303,15 @@ main(int argc, char **argv) int transmit_len; uint8_t receive[EXPAND_LEN(sizeof(original))]; - int receive_len, receive_errors; + int receive_len; uint8_t decode[DECODE_LEN(sizeof(original))]; int decode_ok; int errors = 0; - int error; + int decode_fail = 0; + int crc_mismatch = 0; + int data_mismatch = 0; if (!ao_real_packet()) errors++; @@ -322,37 +329,38 @@ main(int argc, char **argv) transmit_len = ao_expand(encode, encode_len, transmit); /* Add gaussian noise to the signal */ - receive_errors = ao_fuzz(transmit, transmit_len, receive, 0x38); + (void) ao_fuzz(transmit, transmit_len, receive, NOISE_AMOUNT); receive_len = transmit_len; /* Decode it */ decode_ok = ao_fec_decode(receive, receive_len, decode, original_len + 2, NULL); /* Check to see if we received the right data */ - error = 0; - if (!decode_ok) { - printf ("decode failed\n"); - error++; - } + if (!decode_ok) + decode_fail++; + else if (decode[original_len +1] != AO_FEC_DECODE_CRC_OK) + crc_mismatch++; + else if (memcmp(original, decode, original_len) != 0) + data_mismatch++; + } - if (decode[original_len +1] != AO_FEC_DECODE_CRC_OK) { - printf ("crc mis-match\n"); - error++; - } - if (memcmp(original, decode, original_len) != 0) { - printf ("data mis-match\n"); - error++; - } - if (error) { - printf ("Errors: %d\n", receive_errors); - ao_fec_dump_bytes(original, original_len, "Input"); - ao_fec_dump_bytes(decode, original_len, "Decode"); - errors += error; - } - } printf ("%d packets coded\n", trial); + printf ("decode_fail %d crc_mismatch %d data_mismatch %d\n", + decode_fail, crc_mismatch, data_mismatch); + if (decode_fail != EXPECT_DECODE_FAIL) { + printf ("expected %d decode failures\n", EXPECT_DECODE_FAIL); + errors++; + } + if (crc_mismatch != EXPECT_CRC_MISMATCH) { + printf ("expected %d crc mismatch\n", EXPECT_CRC_MISMATCH); + errors++; + } + if (data_mismatch != EXPECT_DATA_MISMATCH) { + printf ("expected %d data mismatch\n", EXPECT_DATA_MISMATCH); + errors++; + } return errors; } -- cgit v1.2.3 From 31b05454ec8d90b89fa3039563ff0e86ae80b2a0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 3 Jul 2012 21:02:20 -0700 Subject: altos: Move profiling settings to Makefile Instead of splitting the changes across Makefile and ao_pins.h, put them both in Makefile to simplify enabling profiling. Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 3 ++- src/megametrum-v0.1/ao_pins.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index e789a0e8..6fc9324e 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -28,6 +28,7 @@ INC = \ # #PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 # ao_hmc5883.c @@ -79,7 +80,7 @@ PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM IDPRODUCT=0x0023 -CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) -Os -g +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g PROG=megametrum-v0.1-$(VERSION).elf diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index dc3761ba..34b75255 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -326,6 +326,8 @@ struct ao_adc { * Profiling Viterbi decoding */ +#ifndef AO_PROFILE #define AO_PROFILE 0 +#endif #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 702ca87983594880d7926d2317d63802af82746e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 15:07:34 -0700 Subject: altos: remove stale ao_flight.c and ao_sample.c The mega-metrum versions are now the official versions Signed-off-by: Keith Packard --- src/core/ao_flight.c | 350 --------------------------------------------------- src/core/ao_sample.c | 214 ------------------------------- 2 files changed, 564 deletions(-) delete mode 100644 src/core/ao_flight.c delete mode 100644 src/core/ao_sample.c (limited to 'src') diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c deleted file mode 100644 index 494e656d..00000000 --- a/src/core/ao_flight.c +++ /dev/null @@ -1,350 +0,0 @@ -/* - * 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. - */ - -#ifndef AO_FLIGHT_TEST -#include "ao.h" -#endif - -#ifndef HAS_ACCEL -#error Please define HAS_ACCEL -#endif - -#ifndef HAS_GPS -#error Please define HAS_GPS -#endif - -#ifndef HAS_USB -#error Please define HAS_USB -#endif - -/* Main flight thread. */ - -__pdata enum ao_flight_state ao_flight_state; /* current flight state */ -__pdata uint16_t ao_boost_tick; /* time of launch detect */ - -/* - * track min/max data over a long interval to detect - * resting - */ -static __data uint16_t ao_interval_end; -static __data int16_t ao_interval_min_height; -static __data int16_t ao_interval_max_height; -static __data int16_t ao_coast_avg_accel; - -__pdata uint8_t ao_flight_force_idle; - -/* We also have a clock, which can be used to sanity check things in - * case of other failures - */ - -#define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) - -/* Landing is detected by getting constant readings from both pressure and accelerometer - * for a fairly long time (AO_INTERVAL_TICKS) - */ -#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(10) - -#define abs(a) ((a) < 0 ? -(a) : (a)) - -void -ao_flight(void) -{ - ao_sample_init(); - ao_flight_state = ao_flight_startup; - for (;;) { - - /* - * Process ADC samples, just looping - * until the sensors are calibrated. - */ - if (!ao_sample()) - continue; - - switch (ao_flight_state) { - case ao_flight_startup: - - /* Check to see what mode we should go to. - * - Invalid mode if accel cal appears to be out - * - pad mode if we're upright, - * - idle mode otherwise - */ -#if HAS_ACCEL - if (ao_config.accel_plus_g == 0 || - ao_config.accel_minus_g == 0 || - ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || - ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) - { - /* Detected an accel value outside -1.5g to 1.5g - * (or uncalibrated values), so we go into invalid mode - */ - ao_flight_state = ao_flight_invalid; - - /* Turn on packet system in invalid mode on TeleMetrum */ - ao_packet_slave_start(); - } else -#endif - if (!ao_flight_force_idle -#if HAS_ACCEL - && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP -#endif - ) - { - /* Set pad mode - we can fly! */ - ao_flight_state = ao_flight_pad; -#if HAS_USB - /* Disable the USB controller in flight mode - * to save power - */ - ao_usb_disable(); -#endif - -#if !HAS_ACCEL - /* Disable packet mode in pad state on TeleMini */ - ao_packet_slave_stop(); -#endif - - /* Turn on telemetry system */ - ao_rdf_set(1); - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); - - /* signal successful initialization by turning off the LED */ - ao_led_off(AO_LED_RED); - } else { - /* Set idle mode */ - ao_flight_state = ao_flight_idle; - -#if HAS_ACCEL - /* Turn on packet system in idle mode on TeleMetrum */ - ao_packet_slave_start(); -#endif - - /* signal successful initialization by turning off the LED */ - ao_led_off(AO_LED_RED); - } - /* wakeup threads due to state change */ - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - - break; - case ao_flight_pad: - - /* pad to boost: - * - * barometer: > 20m vertical motion - * OR - * accelerometer: > 2g AND velocity > 5m/s - * - * The accelerometer should always detect motion before - * the barometer, but we use both to make sure this - * transition is detected. If the device - * doesn't have an accelerometer, then ignore the - * speed and acceleration as they are quite noisy - * on the pad. - */ - if (ao_height > AO_M_TO_HEIGHT(20) -#if HAS_ACCEL - || (ao_accel > AO_MSS_TO_ACCEL(20) && - ao_speed > AO_MS_TO_SPEED(5)) -#endif - ) - { - ao_flight_state = ao_flight_boost; - ao_boost_tick = ao_sample_tick; - - /* start logging data */ - ao_log_start(); - - /* Increase telemetry rate */ - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); - - /* disable RDF beacon */ - ao_rdf_set(0); - -#if HAS_GPS - /* Record current GPS position by waking up GPS log tasks */ - ao_wakeup(&ao_gps_data); - ao_wakeup(&ao_gps_tracking_data); -#endif - - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; - case ao_flight_boost: - - /* boost to fast: - * - * accelerometer: start to fall at > 1/4 G - * OR - * time: boost for more than 15 seconds - * - * Detects motor burn out by the switch from acceleration to - * deceleration, or by waiting until the maximum burn duration - * (15 seconds) has past. - */ - if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || - (int16_t) (ao_sample_tick - ao_boost_tick) > BOOST_TICKS_MAX) - { -#if HAS_ACCEL - ao_flight_state = ao_flight_fast; - ao_coast_avg_accel = ao_accel; -#else - ao_flight_state = ao_flight_coast; -#endif - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; -#if HAS_ACCEL - case ao_flight_fast: - /* - * This is essentially the same as coast, - * but the barometer is being ignored as - * it may be unreliable. - */ - if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) - { - ao_flight_state = ao_flight_coast; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } else - goto check_re_boost; - break; -#endif - case ao_flight_coast: - - /* - * By customer request - allow the user - * to lock out apogee detection for a specified - * number of seconds. - */ - if (ao_config.apogee_lockout) { - if ((ao_sample_tick - ao_boost_tick) < - AO_SEC_TO_TICKS(ao_config.apogee_lockout)) - break; - } - - /* apogee detect: coast to drogue deploy: - * - * speed: < 0 - * - * Also make sure the model altitude is tracking - * the measured altitude reasonably closely; otherwise - * we're probably transsonic. - */ - if (ao_speed < 0 -#if !HAS_ACCEL - && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) -#endif - ) - { - /* ignite the drogue charge */ - ao_ignite(ao_igniter_drogue); - - /* slow down the telemetry system */ - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); - - /* Turn the RDF beacon back on */ - ao_rdf_set(1); - - /* and enter drogue state */ - ao_flight_state = ao_flight_drogue; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } -#if HAS_ACCEL - else { - check_re_boost: - ao_coast_avg_accel = ao_coast_avg_accel - (ao_coast_avg_accel >> 6) + (ao_accel >> 6); - if (ao_coast_avg_accel > AO_MSS_TO_ACCEL(20)) { - ao_boost_tick = ao_sample_tick; - ao_flight_state = ao_flight_boost; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - } -#endif - - break; - case ao_flight_drogue: - - /* drogue to main deploy: - * - * barometer: reach main deploy altitude - * - * Would like to use the accelerometer for this test, but - * the orientation of the flight computer is unknown after - * drogue deploy, so we ignore it. Could also detect - * high descent rate using the pressure sensor to - * recognize drogue deploy failure and eject the main - * at that point. Perhaps also use the drogue sense lines - * to notice continutity? - */ - if (ao_height <= ao_config.main_deploy) - { - ao_ignite(ao_igniter_main); - - /* - * Start recording min/max height - * to figure out when the rocket has landed - */ - - /* initialize interval values */ - ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; - - ao_interval_min_height = ao_interval_max_height = ao_avg_height; - - ao_flight_state = ao_flight_main; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; - - /* fall through... */ - case ao_flight_main: - - /* main to land: - * - * barometer: altitude stable - */ - - if (ao_avg_height < ao_interval_min_height) - ao_interval_min_height = ao_avg_height; - if (ao_avg_height > ao_interval_max_height) - ao_interval_max_height = ao_avg_height; - - if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { - if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4)) - { - ao_flight_state = ao_flight_landed; - - /* turn off the ADC capture */ - ao_timer_set_adc_interval(0); - - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - ao_interval_min_height = ao_interval_max_height = ao_avg_height; - ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; - } - break; - case ao_flight_landed: - break; - } - } -} - -static __xdata struct ao_task flight_task; - -void -ao_flight_init(void) -{ - ao_flight_state = ao_flight_startup; - ao_add_task(&flight_task, ao_flight, "flight"); -} diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c deleted file mode 100644 index 2bf9632f..00000000 --- a/src/core/ao_sample.c +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef AO_FLIGHT_TEST -#include "ao.h" -#endif - -/* - * Current sensor values - */ - -__pdata uint16_t ao_sample_tick; /* time of last data */ -__pdata int16_t ao_sample_pres; -__pdata int16_t ao_sample_alt; -__pdata int16_t ao_sample_height; -#if HAS_ACCEL -__pdata int16_t ao_sample_accel; -#endif - -__data uint8_t ao_sample_adc; - -/* - * Sensor calibration values - */ - -__pdata int16_t ao_ground_pres; /* startup pressure */ -__pdata int16_t ao_ground_height; /* MSL of ao_ground_pres */ - -#if HAS_ACCEL -__pdata int16_t ao_ground_accel; /* startup acceleration */ -__pdata int16_t ao_accel_2g; /* factory accel calibration */ -__pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ -#endif - -static __pdata uint8_t ao_preflight; /* in preflight mode */ - -static __pdata uint16_t nsamples; -__pdata int32_t ao_sample_pres_sum; -#if HAS_ACCEL -__pdata int32_t ao_sample_accel_sum; -#endif - -static void -ao_sample_preflight(void) -{ - /* startup state: - * - * Collect 512 samples of acceleration and pressure - * data and average them to find the resting values - */ - if (nsamples < 512) { -#if HAS_ACCEL - ao_sample_accel_sum += ao_sample_accel; -#endif - ao_sample_pres_sum += ao_sample_pres; - ++nsamples; - } else { - ao_config_get(); -#if HAS_ACCEL - ao_ground_accel = ao_sample_accel_sum >> 9; - ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; - ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; -#endif - ao_ground_pres = ao_sample_pres_sum >> 9; - ao_ground_height = ao_pres_to_altitude(ao_ground_pres); - ao_preflight = FALSE; - } -} - -uint8_t -ao_sample(void) -{ - ao_wakeup(DATA_TO_XDATA(&ao_sample_adc)); - ao_sleep(DATA_TO_XDATA(&ao_adc_head)); - while (ao_sample_adc != ao_adc_head) { - __xdata struct ao_adc *ao_adc; - - /* Capture a sample */ - ao_adc = &ao_adc_ring[ao_sample_adc]; - ao_sample_tick = ao_adc->tick; - ao_sample_pres = ao_adc->pres; - ao_sample_alt = ao_pres_to_altitude(ao_sample_pres); - ao_sample_height = ao_sample_alt - ao_ground_height; -#if HAS_ACCEL - ao_sample_accel = ao_adc->accel; -#if HAS_ACCEL_REF - /* - * Ok, the math here is a bit tricky. - * - * ao_sample_accel: ADC output for acceleration - * ao_accel_ref: ADC output for the 5V reference. - * ao_cook_accel: Corrected acceleration value - * Vcc: 3.3V supply to the CC1111 - * Vac: 5V supply to the accelerometer - * accel: input voltage to accelerometer ADC pin - * ref: input voltage to 5V reference ADC pin - * - * - * Measured acceleration is ratiometric to Vcc: - * - * ao_sample_accel accel - * ------------ = ----- - * 32767 Vcc - * - * Measured 5v reference is also ratiometric to Vcc: - * - * ao_accel_ref ref - * ------------ = ----- - * 32767 Vcc - * - * - * ao_accel_ref = 32767 * (ref / Vcc) - * - * Acceleration is measured ratiometric to the 5V supply, - * so what we want is: - * - * ao_cook_accel accel - * ------------- = ----- - * 32767 ref - * - * - * accel Vcc - * = ----- * --- - * Vcc ref - * - * ao_sample_accel 32767 - * = ------------ * ------------ - * 32767 ao_accel_ref - * - * Multiply through by 32767: - * - * ao_sample_accel * 32767 - * ao_cook_accel = -------------------- - * ao_accel_ref - * - * Now, the tricky part. Getting this to compile efficiently - * and keeping all of the values in-range. - * - * First off, we need to use a shift of 16 instead of * 32767 as SDCC - * does the obvious optimizations for byte-granularity shifts: - * - * ao_cook_accel = (ao_sample_accel << 16) / ao_accel_ref - * - * Next, lets check our input ranges: - * - * 0 <= ao_sample_accel <= 0x7fff (singled ended ADC conversion) - * 0x7000 <= ao_accel_ref <= 0x7fff (the 5V ref value is close to 0x7fff) - * - * Plugging in our input ranges, we get an output range of 0 - 0x12490, - * which is 17 bits. That won't work. If we take the accel ref and shift - * by a bit, we'll change its range: - * - * 0xe000 <= ao_accel_ref<<1 <= 0xfffe - * - * ao_cook_accel = (ao_sample_accel << 16) / (ao_accel_ref << 1) - * - * Now the output range is 0 - 0x9248, which nicely fits in 16 bits. It - * is, however, one bit too large for our signed computations. So, we - * take the result and shift that by a bit: - * - * ao_cook_accel = ((ao_sample_accel << 16) / (ao_accel_ref << 1)) >> 1 - * - * This finally creates an output range of 0 - 0x4924. As the ADC only - * provides 11 bits of data, we haven't actually lost any precision, - * just dropped a bit of noise off the low end. - */ - ao_sample_accel = (uint16_t) ((((uint32_t) ao_sample_accel << 16) / (ao_accel_ref[ao_sample_adc] << 1))) >> 1; - if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) - ao_sample_accel = 0x7fff - ao_sample_accel; - ao_adc->accel = ao_sample_accel; -#else - if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) { - ao_sample_accel = 0x7fff - ao_sample_accel; - ao_adc->accel = ao_sample_accel; - } -#endif -#endif - - if (ao_preflight) - ao_sample_preflight(); - else - ao_kalman(); - ao_sample_adc = ao_adc_ring_next(ao_sample_adc); - } - return !ao_preflight; -} - -void -ao_sample_init(void) -{ - nsamples = 0; - ao_sample_pres_sum = 0; - ao_sample_pres = 0; -#if HAS_ACCEL - ao_sample_accel_sum = 0; - ao_sample_accel = 0; -#endif - ao_sample_adc = ao_adc_head; - ao_preflight = TRUE; -} -- cgit v1.2.3 From 1ae3f467a1d7be2fc3b1a45ba12568a3a25a0099 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 15:11:36 -0700 Subject: altos: Rename *_mm.c back to *.c Was just a temporary hack to keep cc1111 products building during MM development. Signed-off-by: Keith Packard --- src/core/ao_flight.c | 418 ++++++++++++++++++++++++++++++++++++++++ src/core/ao_flight_mm.c | 418 ---------------------------------------- src/core/ao_sample.c | 138 +++++++++++++ src/core/ao_sample_mm.c | 138 ------------- src/megametrum-v0.1/Makefile | 4 +- src/product/Makefile.telemetrum | 4 +- src/product/Makefile.telemini | 4 +- src/product/Makefile.telenano | 2 +- src/test/Makefile | 9 +- src/test/ao_flight_test.c | 35 ++-- 10 files changed, 591 insertions(+), 579 deletions(-) create mode 100644 src/core/ao_flight.c delete mode 100644 src/core/ao_flight_mm.c create mode 100644 src/core/ao_sample.c delete mode 100644 src/core/ao_sample_mm.c (limited to 'src') diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c new file mode 100644 index 00000000..a0affc48 --- /dev/null +++ b/src/core/ao_flight.c @@ -0,0 +1,418 @@ +/* + * 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. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#include +#endif + +#ifndef HAS_ACCEL +#error Please define HAS_ACCEL +#endif + +#ifndef HAS_GPS +#error Please define HAS_GPS +#endif + +#ifndef HAS_USB +#error Please define HAS_USB +#endif + +#ifndef HAS_TELEMETRY +#define HAS_TELEMETRY HAS_RADIO +#endif + +/* Main flight thread. */ + +__pdata enum ao_flight_state ao_flight_state; /* current flight state */ +__pdata uint16_t ao_boost_tick; /* time of launch detect */ + +/* + * track min/max data over a long interval to detect + * resting + */ +static __data uint16_t ao_interval_end; +static __data int16_t ao_interval_min_height; +static __data int16_t ao_interval_max_height; +static __data int16_t ao_coast_avg_accel; + +__pdata uint8_t ao_flight_force_idle; + +/* We also have a clock, which can be used to sanity check things in + * case of other failures + */ + +#define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) + +/* Landing is detected by getting constant readings from both pressure and accelerometer + * for a fairly long time (AO_INTERVAL_TICKS) + */ +#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(10) + +#define abs(a) ((a) < 0 ? -(a) : (a)) + +void +ao_flight(void) +{ + ao_sample_init(); + ao_flight_state = ao_flight_startup; + for (;;) { + + /* + * Process ADC samples, just looping + * until the sensors are calibrated. + */ + if (!ao_sample()) + continue; + + switch (ao_flight_state) { + case ao_flight_startup: + + /* Check to see what mode we should go to. + * - Invalid mode if accel cal appears to be out + * - pad mode if we're upright, + * - idle mode otherwise + */ +#if HAS_ACCEL + if (ao_config.accel_plus_g == 0 || + ao_config.accel_minus_g == 0 || + ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || + ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) + { + /* Detected an accel value outside -1.5g to 1.5g + * (or uncalibrated values), so we go into invalid mode + */ + ao_flight_state = ao_flight_invalid; + +#if HAS_RADIO && PACKET_HAS_SLAVE + /* Turn on packet system in invalid mode on TeleMetrum */ + ao_packet_slave_start(); +#endif + } else +#endif + if (!ao_flight_force_idle +#if HAS_ACCEL + && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP +#endif + ) + { + /* Set pad mode - we can fly! */ + ao_flight_state = ao_flight_pad; +#if HAS_USB && HAS_RADIO + /* Disable the USB controller in flight mode + * to save power + */ + ao_usb_disable(); +#endif + +#if !HAS_ACCEL + /* Disable packet mode in pad state on TeleMini */ + ao_packet_slave_stop(); +#endif + +#if HAS_TELEMETRY + /* Turn on telemetry system */ + ao_rdf_set(1); + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); +#endif + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } else { + /* Set idle mode */ + ao_flight_state = ao_flight_idle; + +#if HAS_ACCEL && HAS_RADIO && PACKET_HAS_SLAVE + /* Turn on packet system in idle mode on TeleMetrum */ + ao_packet_slave_start(); +#endif + + /* signal successful initialization by turning off the LED */ + ao_led_off(AO_LED_RED); + } + /* wakeup threads due to state change */ + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + + break; + case ao_flight_pad: + + /* pad to boost: + * + * barometer: > 20m vertical motion + * OR + * accelerometer: > 2g AND velocity > 5m/s + * + * The accelerometer should always detect motion before + * the barometer, but we use both to make sure this + * transition is detected. If the device + * doesn't have an accelerometer, then ignore the + * speed and acceleration as they are quite noisy + * on the pad. + */ + if (ao_height > AO_M_TO_HEIGHT(20) +#if HAS_ACCEL + || (ao_accel > AO_MSS_TO_ACCEL(20) && + ao_speed > AO_MS_TO_SPEED(5)) +#endif + ) + { + ao_flight_state = ao_flight_boost; + ao_boost_tick = ao_sample_tick; + + /* start logging data */ + ao_log_start(); + +#if HAS_TELEMETRY + /* Increase telemetry rate */ + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); + + /* disable RDF beacon */ + ao_rdf_set(0); +#endif + +#if HAS_GPS + /* Record current GPS position by waking up GPS log tasks */ + ao_wakeup(&ao_gps_data); + ao_wakeup(&ao_gps_tracking_data); +#endif + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + case ao_flight_boost: + + /* boost to fast: + * + * accelerometer: start to fall at > 1/4 G + * OR + * time: boost for more than 15 seconds + * + * Detects motor burn out by the switch from acceleration to + * deceleration, or by waiting until the maximum burn duration + * (15 seconds) has past. + */ + if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || + (int16_t) (ao_sample_tick - ao_boost_tick) > BOOST_TICKS_MAX) + { +#if HAS_ACCEL + ao_flight_state = ao_flight_fast; + ao_coast_avg_accel = ao_accel; +#else + ao_flight_state = ao_flight_coast; +#endif + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; +#if HAS_ACCEL + case ao_flight_fast: + /* + * This is essentially the same as coast, + * but the barometer is being ignored as + * it may be unreliable. + */ + if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) + { + ao_flight_state = ao_flight_coast; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } else + goto check_re_boost; + break; +#endif + case ao_flight_coast: + + /* + * By customer request - allow the user + * to lock out apogee detection for a specified + * number of seconds. + */ + if (ao_config.apogee_lockout) { + if ((ao_sample_tick - ao_boost_tick) < + AO_SEC_TO_TICKS(ao_config.apogee_lockout)) + break; + } + + /* apogee detect: coast to drogue deploy: + * + * speed: < 0 + * + * Also make sure the model altitude is tracking + * the measured altitude reasonably closely; otherwise + * we're probably transsonic. + */ + if (ao_speed < 0 +#if !HAS_ACCEL + && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) +#endif + ) + { +#if HAS_IGNITE + /* ignite the drogue charge */ + ao_ignite(ao_igniter_drogue); +#endif + +#if HAS_TELEMETRY + /* slow down the telemetry system */ + ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); + + /* Turn the RDF beacon back on */ + ao_rdf_set(1); +#endif + + /* and enter drogue state */ + ao_flight_state = ao_flight_drogue; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } +#if HAS_ACCEL + else { + check_re_boost: + ao_coast_avg_accel = ao_coast_avg_accel - (ao_coast_avg_accel >> 6) + (ao_accel >> 6); + if (ao_coast_avg_accel > AO_MSS_TO_ACCEL(20)) { + ao_boost_tick = ao_sample_tick; + ao_flight_state = ao_flight_boost; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + } +#endif + + break; + case ao_flight_drogue: + + /* drogue to main deploy: + * + * barometer: reach main deploy altitude + * + * Would like to use the accelerometer for this test, but + * the orientation of the flight computer is unknown after + * drogue deploy, so we ignore it. Could also detect + * high descent rate using the pressure sensor to + * recognize drogue deploy failure and eject the main + * at that point. Perhaps also use the drogue sense lines + * to notice continutity? + */ + if (ao_height <= ao_config.main_deploy) + { +#if HAS_IGNITE + ao_ignite(ao_igniter_main); +#endif + + /* + * Start recording min/max height + * to figure out when the rocket has landed + */ + + /* initialize interval values */ + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + + ao_interval_min_height = ao_interval_max_height = ao_avg_height; + + ao_flight_state = ao_flight_main; + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + break; + + /* fall through... */ + case ao_flight_main: + + /* main to land: + * + * barometer: altitude stable + */ + + if (ao_avg_height < ao_interval_min_height) + ao_interval_min_height = ao_avg_height; + if (ao_avg_height > ao_interval_max_height) + ao_interval_max_height = ao_avg_height; + + if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { + if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4)) + { + ao_flight_state = ao_flight_landed; + + /* turn off the ADC capture */ + ao_timer_set_adc_interval(0); + + ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); + } + ao_interval_min_height = ao_interval_max_height = ao_avg_height; + ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; + } + break; + case ao_flight_landed: + break; + } + } +} + +#if !HAS_RADIO +static inline int int_part(int16_t i) { return i >> 4; } +static inline int frac_part(int16_t i) { return ((i & 0xf) * 100 + 8) / 16; } + +static void +ao_flight_dump(void) +{ +#if HAS_ACCEL + int16_t accel; + + accel = ((ao_ground_accel - ao_sample_accel) * ao_accel_scale) >> 16; +#endif + + printf ("sample:\n"); + printf (" tick %d\n", ao_sample_tick); + printf (" raw pres %d\n", ao_sample_pres); +#if HAS_ACCEL + printf (" raw accel %d\n", ao_sample_accel); +#endif + printf (" ground pres %d\n", ao_ground_pres); +#if HAS_ACCEL + printf (" raw accel %d\n", ao_sample_accel); + printf (" groundaccel %d\n", ao_ground_accel); + printf (" accel_2g %d\n", ao_accel_2g); +#endif + + printf (" alt %d\n", ao_sample_alt); + printf (" height %d\n", ao_sample_height); +#if HAS_ACCEL + printf (" accel %d.%02d\n", int_part(accel), frac_part(accel)); +#endif + + + printf ("kalman:\n"); + printf (" height %d\n", ao_height); + printf (" speed %d.%02d\n", int_part(ao_speed), frac_part(ao_speed)); + printf (" accel %d.%02d\n", int_part(ao_accel), frac_part(ao_accel)); + printf (" max_height %d\n", ao_max_height); + printf (" avg_height %d\n", ao_avg_height); + printf (" error_h %d\n", ao_error_h); + printf (" error_avg %d\n", ao_error_h_sq_avg); +} + +__code struct ao_cmds ao_flight_cmds[] = { + { ao_flight_dump, "F\0Dump flight status" }, + { 0, NULL }, +}; +#endif + +static __xdata struct ao_task flight_task; + +void +ao_flight_init(void) +{ + ao_flight_state = ao_flight_startup; +#if !HAS_RADIO + ao_cmd_register(&ao_flight_cmds[0]); +#endif + ao_add_task(&flight_task, ao_flight, "flight"); +} diff --git a/src/core/ao_flight_mm.c b/src/core/ao_flight_mm.c deleted file mode 100644 index a0affc48..00000000 --- a/src/core/ao_flight_mm.c +++ /dev/null @@ -1,418 +0,0 @@ -/* - * 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. - */ - -#ifndef AO_FLIGHT_TEST -#include "ao.h" -#include -#endif - -#ifndef HAS_ACCEL -#error Please define HAS_ACCEL -#endif - -#ifndef HAS_GPS -#error Please define HAS_GPS -#endif - -#ifndef HAS_USB -#error Please define HAS_USB -#endif - -#ifndef HAS_TELEMETRY -#define HAS_TELEMETRY HAS_RADIO -#endif - -/* Main flight thread. */ - -__pdata enum ao_flight_state ao_flight_state; /* current flight state */ -__pdata uint16_t ao_boost_tick; /* time of launch detect */ - -/* - * track min/max data over a long interval to detect - * resting - */ -static __data uint16_t ao_interval_end; -static __data int16_t ao_interval_min_height; -static __data int16_t ao_interval_max_height; -static __data int16_t ao_coast_avg_accel; - -__pdata uint8_t ao_flight_force_idle; - -/* We also have a clock, which can be used to sanity check things in - * case of other failures - */ - -#define BOOST_TICKS_MAX AO_SEC_TO_TICKS(15) - -/* Landing is detected by getting constant readings from both pressure and accelerometer - * for a fairly long time (AO_INTERVAL_TICKS) - */ -#define AO_INTERVAL_TICKS AO_SEC_TO_TICKS(10) - -#define abs(a) ((a) < 0 ? -(a) : (a)) - -void -ao_flight(void) -{ - ao_sample_init(); - ao_flight_state = ao_flight_startup; - for (;;) { - - /* - * Process ADC samples, just looping - * until the sensors are calibrated. - */ - if (!ao_sample()) - continue; - - switch (ao_flight_state) { - case ao_flight_startup: - - /* Check to see what mode we should go to. - * - Invalid mode if accel cal appears to be out - * - pad mode if we're upright, - * - idle mode otherwise - */ -#if HAS_ACCEL - if (ao_config.accel_plus_g == 0 || - ao_config.accel_minus_g == 0 || - ao_ground_accel < ao_config.accel_plus_g - ACCEL_NOSE_UP || - ao_ground_accel > ao_config.accel_minus_g + ACCEL_NOSE_UP) - { - /* Detected an accel value outside -1.5g to 1.5g - * (or uncalibrated values), so we go into invalid mode - */ - ao_flight_state = ao_flight_invalid; - -#if HAS_RADIO && PACKET_HAS_SLAVE - /* Turn on packet system in invalid mode on TeleMetrum */ - ao_packet_slave_start(); -#endif - } else -#endif - if (!ao_flight_force_idle -#if HAS_ACCEL - && ao_ground_accel < ao_config.accel_plus_g + ACCEL_NOSE_UP -#endif - ) - { - /* Set pad mode - we can fly! */ - ao_flight_state = ao_flight_pad; -#if HAS_USB && HAS_RADIO - /* Disable the USB controller in flight mode - * to save power - */ - ao_usb_disable(); -#endif - -#if !HAS_ACCEL - /* Disable packet mode in pad state on TeleMini */ - ao_packet_slave_stop(); -#endif - -#if HAS_TELEMETRY - /* Turn on telemetry system */ - ao_rdf_set(1); - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_PAD); -#endif - /* signal successful initialization by turning off the LED */ - ao_led_off(AO_LED_RED); - } else { - /* Set idle mode */ - ao_flight_state = ao_flight_idle; - -#if HAS_ACCEL && HAS_RADIO && PACKET_HAS_SLAVE - /* Turn on packet system in idle mode on TeleMetrum */ - ao_packet_slave_start(); -#endif - - /* signal successful initialization by turning off the LED */ - ao_led_off(AO_LED_RED); - } - /* wakeup threads due to state change */ - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - - break; - case ao_flight_pad: - - /* pad to boost: - * - * barometer: > 20m vertical motion - * OR - * accelerometer: > 2g AND velocity > 5m/s - * - * The accelerometer should always detect motion before - * the barometer, but we use both to make sure this - * transition is detected. If the device - * doesn't have an accelerometer, then ignore the - * speed and acceleration as they are quite noisy - * on the pad. - */ - if (ao_height > AO_M_TO_HEIGHT(20) -#if HAS_ACCEL - || (ao_accel > AO_MSS_TO_ACCEL(20) && - ao_speed > AO_MS_TO_SPEED(5)) -#endif - ) - { - ao_flight_state = ao_flight_boost; - ao_boost_tick = ao_sample_tick; - - /* start logging data */ - ao_log_start(); - -#if HAS_TELEMETRY - /* Increase telemetry rate */ - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_FLIGHT); - - /* disable RDF beacon */ - ao_rdf_set(0); -#endif - -#if HAS_GPS - /* Record current GPS position by waking up GPS log tasks */ - ao_wakeup(&ao_gps_data); - ao_wakeup(&ao_gps_tracking_data); -#endif - - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; - case ao_flight_boost: - - /* boost to fast: - * - * accelerometer: start to fall at > 1/4 G - * OR - * time: boost for more than 15 seconds - * - * Detects motor burn out by the switch from acceleration to - * deceleration, or by waiting until the maximum burn duration - * (15 seconds) has past. - */ - if ((ao_accel < AO_MSS_TO_ACCEL(-2.5) && ao_height > AO_M_TO_HEIGHT(100)) || - (int16_t) (ao_sample_tick - ao_boost_tick) > BOOST_TICKS_MAX) - { -#if HAS_ACCEL - ao_flight_state = ao_flight_fast; - ao_coast_avg_accel = ao_accel; -#else - ao_flight_state = ao_flight_coast; -#endif - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; -#if HAS_ACCEL - case ao_flight_fast: - /* - * This is essentially the same as coast, - * but the barometer is being ignored as - * it may be unreliable. - */ - if (ao_speed < AO_MS_TO_SPEED(AO_MAX_BARO_SPEED)) - { - ao_flight_state = ao_flight_coast; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } else - goto check_re_boost; - break; -#endif - case ao_flight_coast: - - /* - * By customer request - allow the user - * to lock out apogee detection for a specified - * number of seconds. - */ - if (ao_config.apogee_lockout) { - if ((ao_sample_tick - ao_boost_tick) < - AO_SEC_TO_TICKS(ao_config.apogee_lockout)) - break; - } - - /* apogee detect: coast to drogue deploy: - * - * speed: < 0 - * - * Also make sure the model altitude is tracking - * the measured altitude reasonably closely; otherwise - * we're probably transsonic. - */ - if (ao_speed < 0 -#if !HAS_ACCEL - && (ao_sample_alt >= AO_MAX_BARO_HEIGHT || ao_error_h_sq_avg < 100) -#endif - ) - { -#if HAS_IGNITE - /* ignite the drogue charge */ - ao_ignite(ao_igniter_drogue); -#endif - -#if HAS_TELEMETRY - /* slow down the telemetry system */ - ao_telemetry_set_interval(AO_TELEMETRY_INTERVAL_RECOVER); - - /* Turn the RDF beacon back on */ - ao_rdf_set(1); -#endif - - /* and enter drogue state */ - ao_flight_state = ao_flight_drogue; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } -#if HAS_ACCEL - else { - check_re_boost: - ao_coast_avg_accel = ao_coast_avg_accel - (ao_coast_avg_accel >> 6) + (ao_accel >> 6); - if (ao_coast_avg_accel > AO_MSS_TO_ACCEL(20)) { - ao_boost_tick = ao_sample_tick; - ao_flight_state = ao_flight_boost; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - } -#endif - - break; - case ao_flight_drogue: - - /* drogue to main deploy: - * - * barometer: reach main deploy altitude - * - * Would like to use the accelerometer for this test, but - * the orientation of the flight computer is unknown after - * drogue deploy, so we ignore it. Could also detect - * high descent rate using the pressure sensor to - * recognize drogue deploy failure and eject the main - * at that point. Perhaps also use the drogue sense lines - * to notice continutity? - */ - if (ao_height <= ao_config.main_deploy) - { -#if HAS_IGNITE - ao_ignite(ao_igniter_main); -#endif - - /* - * Start recording min/max height - * to figure out when the rocket has landed - */ - - /* initialize interval values */ - ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; - - ao_interval_min_height = ao_interval_max_height = ao_avg_height; - - ao_flight_state = ao_flight_main; - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - break; - - /* fall through... */ - case ao_flight_main: - - /* main to land: - * - * barometer: altitude stable - */ - - if (ao_avg_height < ao_interval_min_height) - ao_interval_min_height = ao_avg_height; - if (ao_avg_height > ao_interval_max_height) - ao_interval_max_height = ao_avg_height; - - if ((int16_t) (ao_sample_tick - ao_interval_end) >= 0) { - if (ao_interval_max_height - ao_interval_min_height <= AO_M_TO_HEIGHT(4)) - { - ao_flight_state = ao_flight_landed; - - /* turn off the ADC capture */ - ao_timer_set_adc_interval(0); - - ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); - } - ao_interval_min_height = ao_interval_max_height = ao_avg_height; - ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; - } - break; - case ao_flight_landed: - break; - } - } -} - -#if !HAS_RADIO -static inline int int_part(int16_t i) { return i >> 4; } -static inline int frac_part(int16_t i) { return ((i & 0xf) * 100 + 8) / 16; } - -static void -ao_flight_dump(void) -{ -#if HAS_ACCEL - int16_t accel; - - accel = ((ao_ground_accel - ao_sample_accel) * ao_accel_scale) >> 16; -#endif - - printf ("sample:\n"); - printf (" tick %d\n", ao_sample_tick); - printf (" raw pres %d\n", ao_sample_pres); -#if HAS_ACCEL - printf (" raw accel %d\n", ao_sample_accel); -#endif - printf (" ground pres %d\n", ao_ground_pres); -#if HAS_ACCEL - printf (" raw accel %d\n", ao_sample_accel); - printf (" groundaccel %d\n", ao_ground_accel); - printf (" accel_2g %d\n", ao_accel_2g); -#endif - - printf (" alt %d\n", ao_sample_alt); - printf (" height %d\n", ao_sample_height); -#if HAS_ACCEL - printf (" accel %d.%02d\n", int_part(accel), frac_part(accel)); -#endif - - - printf ("kalman:\n"); - printf (" height %d\n", ao_height); - printf (" speed %d.%02d\n", int_part(ao_speed), frac_part(ao_speed)); - printf (" accel %d.%02d\n", int_part(ao_accel), frac_part(ao_accel)); - printf (" max_height %d\n", ao_max_height); - printf (" avg_height %d\n", ao_avg_height); - printf (" error_h %d\n", ao_error_h); - printf (" error_avg %d\n", ao_error_h_sq_avg); -} - -__code struct ao_cmds ao_flight_cmds[] = { - { ao_flight_dump, "F\0Dump flight status" }, - { 0, NULL }, -}; -#endif - -static __xdata struct ao_task flight_task; - -void -ao_flight_init(void) -{ - ao_flight_state = ao_flight_startup; -#if !HAS_RADIO - ao_cmd_register(&ao_flight_cmds[0]); -#endif - ao_add_task(&flight_task, ao_flight, "flight"); -} diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c new file mode 100644 index 00000000..ac11eef0 --- /dev/null +++ b/src/core/ao_sample.c @@ -0,0 +1,138 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef AO_FLIGHT_TEST +#include "ao.h" +#include +#endif + +/* + * Current sensor values + */ + +#ifndef PRES_TYPE +#define PRES_TYPE int32_t +#define ALT_TYPE int32_t +#define ACCEL_TYPE int16_t +#endif + +__pdata uint16_t ao_sample_tick; /* time of last data */ +__pdata pres_t ao_sample_pres; +__pdata alt_t ao_sample_alt; +__pdata alt_t ao_sample_height; +#if HAS_ACCEL +__pdata accel_t ao_sample_accel; +#endif + +__data uint8_t ao_sample_data; + +/* + * Sensor calibration values + */ + +__pdata pres_t ao_ground_pres; /* startup pressure */ +__pdata alt_t ao_ground_height; /* MSL of ao_ground_pres */ + +#if HAS_ACCEL +__pdata accel_t ao_ground_accel; /* startup acceleration */ +__pdata accel_t ao_accel_2g; /* factory accel calibration */ +__pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ +#endif + +static __pdata uint8_t ao_preflight; /* in preflight mode */ + +static __pdata uint16_t nsamples; +__pdata int32_t ao_sample_pres_sum; +#if HAS_ACCEL +__pdata int32_t ao_sample_accel_sum; +#endif + +static void +ao_sample_preflight(void) +{ + /* startup state: + * + * Collect 512 samples of acceleration and pressure + * data and average them to find the resting values + */ + if (nsamples < 512) { +#if HAS_ACCEL + ao_sample_accel_sum += ao_sample_accel; +#endif + ao_sample_pres_sum += ao_sample_pres; + ++nsamples; + } else { + ao_config_get(); +#if HAS_ACCEL + ao_ground_accel = ao_sample_accel_sum >> 9; + ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; + ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; +#endif + ao_ground_pres = ao_sample_pres_sum >> 9; + ao_ground_height = pres_to_altitude(ao_ground_pres); + ao_preflight = FALSE; + } +} + + +uint8_t +ao_sample(void) +{ + ao_config_get(); + ao_wakeup(DATA_TO_XDATA(&ao_sample_data)); + ao_sleep((void *) DATA_TO_XDATA(&ao_data_head)); + while (ao_sample_data != ao_data_head) { + __xdata struct ao_data *ao_data; + + /* Capture a sample */ + ao_data = (struct ao_data *) &ao_data_ring[ao_sample_data]; + ao_sample_tick = ao_data->tick; + + ao_data_pres_cook(ao_data); + ao_sample_pres = ao_data_pres(ao_data); + ao_sample_alt = pres_to_altitude(ao_sample_pres); + ao_sample_height = ao_sample_alt - ao_ground_height; + +#if HAS_ACCEL + ao_sample_accel = ao_data_accel_cook(ao_data); + if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) + ao_sample_accel = ao_data_accel_invert(ao_sample_accel); + ao_data_set_accel(ao_data, ao_sample_accel); +#endif + + if (ao_preflight) + ao_sample_preflight(); + else + ao_kalman(); + ao_sample_data = ao_data_ring_next(ao_sample_data); + } + return !ao_preflight; +} + +void +ao_sample_init(void) +{ + nsamples = 0; + ao_sample_pres_sum = 0; + ao_sample_pres = 0; +#if HAS_ACCEL + ao_sample_accel_sum = 0; + ao_sample_accel = 0; +#endif + ao_sample_data = ao_data_head; + ao_preflight = TRUE; +} diff --git a/src/core/ao_sample_mm.c b/src/core/ao_sample_mm.c deleted file mode 100644 index ac11eef0..00000000 --- a/src/core/ao_sample_mm.c +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef AO_FLIGHT_TEST -#include "ao.h" -#include -#endif - -/* - * Current sensor values - */ - -#ifndef PRES_TYPE -#define PRES_TYPE int32_t -#define ALT_TYPE int32_t -#define ACCEL_TYPE int16_t -#endif - -__pdata uint16_t ao_sample_tick; /* time of last data */ -__pdata pres_t ao_sample_pres; -__pdata alt_t ao_sample_alt; -__pdata alt_t ao_sample_height; -#if HAS_ACCEL -__pdata accel_t ao_sample_accel; -#endif - -__data uint8_t ao_sample_data; - -/* - * Sensor calibration values - */ - -__pdata pres_t ao_ground_pres; /* startup pressure */ -__pdata alt_t ao_ground_height; /* MSL of ao_ground_pres */ - -#if HAS_ACCEL -__pdata accel_t ao_ground_accel; /* startup acceleration */ -__pdata accel_t ao_accel_2g; /* factory accel calibration */ -__pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ -#endif - -static __pdata uint8_t ao_preflight; /* in preflight mode */ - -static __pdata uint16_t nsamples; -__pdata int32_t ao_sample_pres_sum; -#if HAS_ACCEL -__pdata int32_t ao_sample_accel_sum; -#endif - -static void -ao_sample_preflight(void) -{ - /* startup state: - * - * Collect 512 samples of acceleration and pressure - * data and average them to find the resting values - */ - if (nsamples < 512) { -#if HAS_ACCEL - ao_sample_accel_sum += ao_sample_accel; -#endif - ao_sample_pres_sum += ao_sample_pres; - ++nsamples; - } else { - ao_config_get(); -#if HAS_ACCEL - ao_ground_accel = ao_sample_accel_sum >> 9; - ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; - ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; -#endif - ao_ground_pres = ao_sample_pres_sum >> 9; - ao_ground_height = pres_to_altitude(ao_ground_pres); - ao_preflight = FALSE; - } -} - - -uint8_t -ao_sample(void) -{ - ao_config_get(); - ao_wakeup(DATA_TO_XDATA(&ao_sample_data)); - ao_sleep((void *) DATA_TO_XDATA(&ao_data_head)); - while (ao_sample_data != ao_data_head) { - __xdata struct ao_data *ao_data; - - /* Capture a sample */ - ao_data = (struct ao_data *) &ao_data_ring[ao_sample_data]; - ao_sample_tick = ao_data->tick; - - ao_data_pres_cook(ao_data); - ao_sample_pres = ao_data_pres(ao_data); - ao_sample_alt = pres_to_altitude(ao_sample_pres); - ao_sample_height = ao_sample_alt - ao_ground_height; - -#if HAS_ACCEL - ao_sample_accel = ao_data_accel_cook(ao_data); - if (ao_config.pad_orientation != AO_PAD_ORIENTATION_ANTENNA_UP) - ao_sample_accel = ao_data_accel_invert(ao_sample_accel); - ao_data_set_accel(ao_data, ao_sample_accel); -#endif - - if (ao_preflight) - ao_sample_preflight(); - else - ao_kalman(); - ao_sample_data = ao_data_ring_next(ao_sample_data); - } - return !ao_preflight; -} - -void -ao_sample_init(void) -{ - nsamples = 0; - ao_sample_pres_sum = 0; - ao_sample_pres = 0; -#if HAS_ACCEL - ao_sample_accel_sum = 0; - ao_sample_accel = 0; -#endif - ao_sample_data = ao_data_head; - ao_preflight = TRUE; -} diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 6fc9324e..13e46c97 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -67,9 +67,9 @@ ALTOS_SRC = \ ao_convert_pa.c \ ao_log.c \ ao_log_mega.c \ - ao_sample_mm.c \ + ao_sample.c \ ao_kalman.c \ - ao_flight_mm.c \ + ao_flight.c \ ao_telemetry.c \ ao_packet_slave.c \ ao_packet.c \ diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index fba2c19a..57586c95 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -36,8 +36,8 @@ CORE_SRC = \ ao_stdio.c \ ao_storage.c \ ao_task.c \ - ao_flight_mm.c \ - ao_sample_mm.c \ + ao_flight.c \ + ao_sample.c \ ao_kalman.c \ ao_log.c \ ao_log_big.c \ diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini index f0ab2b14..23aed1c7 100644 --- a/src/product/Makefile.telemini +++ b/src/product/Makefile.telemini @@ -24,14 +24,14 @@ CORE_SRC = \ ao_cmd.c \ ao_config.c \ ao_convert.c \ - ao_flight_mm.c \ + ao_flight.c \ ao_kalman.c \ ao_log.c \ ao_log_tiny.c \ ao_mutex.c \ ao_panic.c \ ao_report.c \ - ao_sample_mm.c \ + ao_sample.c \ ao_stdio.c \ ao_storage.c \ ao_task.c \ diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index a55bcf95..ca719bbf 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -31,7 +31,7 @@ CORE_SRC = \ ao_mutex.c \ ao_panic.c \ ao_report.c \ - ao_sample_mm.c \ + ao_sample.c \ ao_stdio.c \ ao_storage.c \ ao_task.c \ diff --git a/src/test/Makefile b/src/test/Makefile index 4631fb78..963f4131 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -4,7 +4,7 @@ PROGS=ao_flight_test ao_flight_test_baro ao_flight_test_accel ao_flight_test_noi KALMAN=make-kalman -CFLAGS=-I.. -I. -I../core -I../drivers -O0 -g -Wall +CFLAGS=-I.. -I. -I../core -I../drivers -O3 -g -Wall all: $(PROGS) @@ -13,10 +13,10 @@ clean: install: -ao_flight_test: ao_flight_test.c ao_host.h ao_flight_mm.c ao_sample_mm.c ao_kalman.c altitude.h ao_kalman.h +ao_flight_test: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h cc $(CFLAGS) -o $@ $< -ao_flight_test_noisy_accel: ao_flight_test.c ao_host.h ao_flight_mm.c ao_sample_mm.c ao_kalman.c altitude.h ao_kalman.h +ao_flight_test_noisy_accel: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h cc -DNOISY_ACCEL=1 $(CFLAGS) -o $@ $< ao_flight_test_baro: ao_flight_test.c ao_host.h ao_flight.c ao_sample.c ao_kalman.c altitude.h ao_kalman.h @@ -42,3 +42,6 @@ ao_kalman.h: $(KALMAN) ao_fec_test: ao_fec_test.c ao_fec_tx.c ao_fec_rx.c cc $(CFLAGS) -DAO_FEC_DEBUG=1 -o $@ ao_fec_test.c ../core/ao_fec_tx.c ../core/ao_fec_rx.c -lm + +check: ao_fec_test ao_flight_test ao_flight_test_baro run-tests + ./ao_fec_test && ./run-tests \ No newline at end of file diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index baf2ad1d..9bb03d68 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -141,7 +141,7 @@ struct ao_task { int dummy; }; -#define ao_add_task(t,f,n) +#define ao_add_task(t,f,n) ((void) (t)) #define ao_log_start() #define ao_log_stop() @@ -156,6 +156,7 @@ int ao_flight_debug; FILE *emulator_in; char *emulator_app; char *emulator_name; +char *emulator_info; double emulator_error_max = 4; double emulator_height_error_max = 20; /* noise in the baro sensor */ @@ -199,6 +200,7 @@ struct ao_config ao_config; #define DATA_TO_XDATA(x) (x) #define HAS_FLIGHT 1 +#define HAS_IGNITE 1 #define HAS_ADC 1 #define HAS_USB 1 #define HAS_GPS 1 @@ -223,8 +225,8 @@ int ao_sample_prev_tick; uint16_t prev_tick; #include "ao_kalman.c" -#include "ao_sample_mm.c" -#include "ao_flight_mm.c" +#include "ao_sample.c" +#include "ao_flight.c" #define to_double(f) ((f) / 65536.0) @@ -259,10 +261,11 @@ ao_test_exit(void) main_error = fabs(ao_test_main_height_time - main_time); landed_error = fabs(ao_test_landed_height - landed_height); landed_time_error = ao_test_landed_time - landed_time; - if (drogue_error > emulator_error_max || main_error > emulator_error_max || - landed_time_error > emulator_error_max || landed_error > emulator_height_error_max) { + if (drogue_error > emulator_error_max || main_error > emulator_error_max) { printf ("%s %s\n", emulator_app, emulator_name); + if (emulator_info) + printf ("\t%s\n", emulator_info); printf ("\tApogee error %g\n", drogue_error); printf ("\tMain error %g\n", main_error); printf ("\tLanded height error %g\n", landed_error); @@ -477,10 +480,9 @@ void ao_sleep(void *wchan) { if (wchan == &ao_data_head) { - char type; - uint16_t tick; - uint16_t a, b; - int ret; + char type = 0; + uint16_t tick = 0; + uint16_t a = 0, b = 0; uint8_t bytes[1024]; union ao_telemetry_all telem; char line[1024]; @@ -676,13 +678,15 @@ ao_dump_state(void) static const struct option options[] = { { .name = "summary", .has_arg = 0, .val = 's' }, { .name = "debug", .has_arg = 0, .val = 'd' }, + { .name = "info", .has_arg = 1, .val = 'i' }, { 0, 0, 0, 0}, }; -void run_flight_fixed(char *name, FILE *f, int summary) +void run_flight_fixed(char *name, FILE *f, int summary, char *info) { emulator_name = name; emulator_in = f; + emulator_info = info; ao_summary = summary; ao_flight_init(); ao_flight(); @@ -694,13 +698,14 @@ main (int argc, char **argv) int summary = 0; int c; int i; + char *info = NULL; #if HAS_ACCEL emulator_app="full"; #else emulator_app="baro"; #endif - while ((c = getopt_long(argc, argv, "sd", options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "sdi:", options, NULL)) != -1) { switch (c) { case 's': summary = 1; @@ -708,11 +713,14 @@ main (int argc, char **argv) case 'd': ao_flight_debug = 1; break; + case 'i': + info = optarg; + break; } } if (optind == argc) - run_flight_fixed("", stdin, summary); + run_flight_fixed("", stdin, summary, info); else for (i = optind; i < argc; i++) { FILE *f = fopen(argv[i], "r"); @@ -720,7 +728,8 @@ main (int argc, char **argv) perror(argv[i]); continue; } - run_flight_fixed(argv[i], f, summary); + run_flight_fixed(argv[i], f, summary, info); fclose(f); } + exit(0); } -- cgit v1.2.3 From 6694cedd560a7ea9520ef11472c2770b489187c0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 15:13:18 -0700 Subject: altos: Eliminate compiler warnings when building ao_flight_test We turn on a pile of warnings for that. Signed-off-by: Keith Packard --- src/core/ao_flight.c | 4 +++- src/core/ao_kalman.c | 7 +++++-- 2 files changed, 8 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index a0affc48..39084fd0 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -48,7 +48,9 @@ __pdata uint16_t ao_boost_tick; /* time of launch detect */ static __data uint16_t ao_interval_end; static __data int16_t ao_interval_min_height; static __data int16_t ao_interval_max_height; +#if HAS_ACCEL static __data int16_t ao_coast_avg_accel; +#endif __pdata uint8_t ao_flight_force_idle; @@ -350,7 +352,7 @@ ao_flight(void) ao_interval_end = ao_sample_tick + AO_INTERVAL_TICKS; } break; - case ao_flight_landed: + default: break; } } diff --git a/src/core/ao_kalman.c b/src/core/ao_kalman.c index 68725f69..59ffd8b2 100644 --- a/src/core/ao_kalman.c +++ b/src/core/ao_kalman.c @@ -172,6 +172,7 @@ ao_kalman_err_accel(void) ao_error_a = (accel - ao_k_accel) >> 16; } +#ifndef FORCE_ACCEL static void ao_kalman_correct_both(void) { @@ -242,7 +243,8 @@ ao_kalman_correct_both(void) (int32_t) AO_BOTH_K21_100 * ao_error_a; } -#ifdef FORCE_ACCEL +#else + static void ao_kalman_correct_accel(void) { @@ -258,7 +260,8 @@ ao_kalman_correct_accel(void) ao_k_speed += (int32_t) AO_ACCEL_K1_100 * ao_error_a; ao_k_accel += (int32_t) AO_ACCEL_K2_100 * ao_error_a; } -#endif + +#endif /* else FORCE_ACCEL */ #endif /* HAS_ACCEL */ void -- cgit v1.2.3 From b89d37d357273b97050c00d7fe12022e32799fa8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 15:13:55 -0700 Subject: altos: add some (unused) test code for different soft-decision sizes This lets us experiment with hard-decision and other possible soft_decision bit depths. Signed-off-by: Keith Packard --- src/test/ao_fec_test.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'src') diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c index b94b16dc..216a4b79 100644 --- a/src/test/ao_fec_test.c +++ b/src/test/ao_fec_test.c @@ -100,6 +100,7 @@ ao_fuzz (uint8_t *in, int in_len, uint8_t *out, double dev) { int i; int errors = 0; + int s; for (i = 0; i < in_len; i++) { double error = gaussian_random(0, dev); @@ -115,6 +116,24 @@ ao_fuzz (uint8_t *in, int in_len, uint8_t *out, double dev) else byte -= error; } + + /* abcd efgh 8 + * abcd efga 7 + * abcd efab 6 + * abcd eabc 5 + * abcd abcd 4 + * abca bcab 3 + * abab abab 2 + * aaaa aaaa 1 + */ + +#define SAVE 8 +#define SAVE_MASK (((1 << SAVE) - 1) << (8 - SAVE)) + + byte &= SAVE_MASK; + for (s = SAVE; s < 8; s += SAVE) + byte |= byte >> s; + out[i] = byte; } return errors; -- cgit v1.2.3 From a60c5a728530e4659a6750d8d5b87000735d4531 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 15:15:00 -0700 Subject: altos: Improve ao_flight_test a bit Add -i flag to include flight description Have run-tests know how many failures to expect Add run_baro to plot a single flight using the baro-only mode Signed-off-by: Keith Packard --- src/test/run-baro | 31 +++++++++++++++++++++++++++++++ src/test/run-tests | 17 +++++++++++------ src/test/test-flights | 14 +++++++------- 3 files changed, 49 insertions(+), 13 deletions(-) create mode 100755 src/test/run-baro (limited to 'src') diff --git a/src/test/run-baro b/src/test/run-baro new file mode 100755 index 00000000..21bab9fb --- /dev/null +++ b/src/test/run-baro @@ -0,0 +1,31 @@ +#!/bin/sh + +for i in "$@"; do +./ao_flight_test_baro "$i" > run-out.baro + +#./ao_flight_test_accel "$i" > run-out.accel +#"run-out.accel" using 1:9 with lines lt 4 axes x1y1 title "accel height",\ +#"run-out.accel" using 1:11 with lines lt 4 axes x1y2 title "accel speed",\ +#"run-out.accel" using 1:13 with lines lt 4 axes x1y2 title "accel accel",\ +#"run-out.accel" using 1:15 with lines lt 4 axes x1y1 title "accel drogue",\ +#"run-out.accel" using 1:17 with lines lt 4 axes x1y1 title "accel main",\ +# + +gnuplot << EOF +set ylabel "altitude (m)" +set y2label "velocity (m/s), acceleration(m/s²)" +set xlabel "time (s)" +set xtics border out nomirror +set ytics border out nomirror +set y2tics border out nomirror +set title "$i" +plot "run-out.baro" using 1:3 with lines lw 2 lt 1 axes x1y1 title "raw height",\ +"run-out.baro" using 1:5 with lines lw 2 lt 2 axes x1y2 title "raw accel",\ +"run-out.baro" using 1:9 with lines lt 3 axes x1y1 title "baro height",\ +"run-out.baro" using 1:11 with lines lt 4 axes x1y2 title "baro speed",\ +"run-out.baro" using 1:13 with lines lt 5 axes x1y2 title "baro accel",\ +"run-out.baro" using 1:17 with lines lt 6 axes x1y1 title "baro drogue",\ +"run-out.baro" using 1:19 with lines lt 7 axes x1y1 title "baro main" +pause mouse close +EOF +done \ No newline at end of file diff --git a/src/test/run-tests b/src/test/run-tests index a8a8dc3f..4edecf1a 100755 --- a/src/test/run-tests +++ b/src/test/run-tests @@ -2,21 +2,26 @@ DIR=~/misc/rockets/flights +expect_baro=2 +expect_full=5 + bad_baro=0 bad_full=0 while read flight description; do - if ./ao_flight_test_baro -s $DIR/$flight; then + if ./ao_flight_test_baro -s -i "$description" $DIR/$flight; then : else : $((bad_baro++)) fi - if ./ao_flight_test -s $DIR/$flight; then + if ./ao_flight_test -s -i "$description" $DIR/$flight; then : else : $((bad_full++)) fi done < test-flights -echo baro errors $bad_baro -echo full errors $bad_full -: $((bad = bad_baro + bad_full)) -exit $bad \ No newline at end of file +echo baro errors $bad_baro expected $expect_baro +echo full errors $bad_full expected $expect_full +: $((miss_baro = bad_baro > expect_baro ? bad_baro - expect_baro : expect_baro - bad_baro)) +: $((miss_full = bad_full > expect_full ? bad_full - expect_full : expect_full - bad_full)) +: $((miss = miss_baro + miss_full)) +exit $miss \ No newline at end of file diff --git a/src/test/test-flights b/src/test/test-flights index f6b3b992..12f62ea9 100644 --- a/src/test/test-flights +++ b/src/test/test-flights @@ -29,7 +29,7 @@ 2010-02-28-serial-052-flight-004.eeprom LDDD Tillamook airport, 2010-02-28, I161 2010-03-06-serial-010-flight-004.eeprom Robert's Lil Nuke at Hudson Ranch on a CTI 108G57CL Pro29 2010-03-06-serial-013-flight-003.eeprom Trick-O-Treat at Hudson Ranch on a J595BS -2010-03-06-serial-051-flight-003.eeprom G-Spot at Hudson Ranch on an H180W +2010-03-06-serial-051-flight-003.eeprom G-Spot at Hudson Ranch on an H180W (apogee early, fools ao_flight_test_baro) 2010-03-06-serial-053-flight-004.eeprom Horizon Rebuilt at Hudson Ranch on a J530IM with MAWD as backup 2010-05-08-serial-229-flight-002.eeprom First customer flight on a sparky. 2010-05-28-serial-215-flight-002.eeprom Mike's L1 cert flight. Congrats! @@ -38,28 +38,28 @@ 2010-05-30-serial-010-flight-005.eeprom Robert's Lil Nuke on a 84G88 Smoky Sam at Mile High Mayhem 2010 Version 0.1 TeleMetrum with 5010 GPS board. 2010-05-30-serial-051-flight-004.eeprom Bdale's G-Spot on a CTI 298H159 Green3 at Mile High Mayhem 2010 2010-05-30-serial-224-flight-003.eeprom Bill Mott's L3 cert flight -2010-05-30-serial-226-flight-001.eeprom Robert's RG-2 on a 159G54RL at Mile High Mayhem. Very noise accel data, early apogee +2010-05-30-serial-226-flight-001.eeprom Robert's RG-2 on a 159G54RL at Mile High Mayhem. Very noise accel data, early apogee (fools full) 2010-05-31-serial-010-flight-006.eeprom Robert's Lil Nuke with a v0.1 TeleMetrum and 5010 GPS board flying on a 159G118 Blue Streak on the last day of Mile High Mayhem 2010 2010-05-31-serial-216-flight-001.eeprom Sharp Stick in the Sky on an "I something" EX motor from James Russell -2010-05-31-serial-219-flight-001.eeprom Candy Cane on CTI K300 at MHM. +2010-05-31-serial-219-flight-001.eeprom Candy Cane on CTI K300 at MHM. (accel noise fools full) 2010-05-31-serial-227-flight-003.eeprom Mike's Rocket on J285 for successful L2 cert at MHM 2010-06-05-serial-220-flight-001.eeprom Mini-mmuchness on 159G54RL, Sunday at MHM 2010 2010-06-26-serial-209-flight-003.eeprom Tripoli Colorado Spring Fling with COSROCS at the Buffalo Ranch -2010-06-26-serial-215-flight-004.eeprom Tripoli Colorado Spring Fling with COSROCS at the Buffalo Ranch +2010-06-26-serial-215-flight-004.eeprom Tripoli Colorado Spring Fling with COSROCS at the Buffalo Ranch (accel noise fools full) 2010-06-26-serial-220-flight-002.eeprom Mini Mmuchness on CTI H120CL to 1975m, OROC June 2010 2010-06-26-serial-226-flight-002.eeprom Tripoli Colorado Spring Fling with COSROCS at the Buffalo Ranch 2010-06-27-serial-221-flight-002.eeprom PSAS LV2c on N2000 at OROC june launch 2010-07-17-serial-230-flight-001.eeprom Mike Ward's Level 1 cert flight on H225 2010-07-18-serial-219-flight-002.eeprom MMuchness on M1230 for successful L3 cert flight 2010-08-07-serial-216-flight-003.eeprom Sharp stick on I300T at Metra's august launch. Main out at apogee. -2010-08-07-serial-220-flight-003.eeprom Mini-mmuchness flight at Metra after debconf. Unstable on G80. ABNORMAL FLIGHT. -2010-08-12-serial-236-flight-001.eeprom Edgar's L1 flight, Madcow Momba on Aerotech H128 +2010-08-07-serial-220-flight-003.eeprom Mini-mmuchness flight at Metra after debconf. Unstable on G80. ABNORMAL FLIGHT. (fools full) +2010-08-12-serial-236-flight-001.eeprom Edgar's L1 flight, Madcow Momba on Aerotech H128 (early apogee charge fools baro) 2010-08-21-serial-010-flight-007.eeprom Robert's Lil Nuke, flying on a CTI Pro29 2-grain 110G250 Vmax. Just awesome! PFND. 2010-08-21-serial-224-flight-004.eeprom Anthony Towns' LDDD clone, successful L1 cert on a CTI Pro38 2-grain 266H125 classic. Airframe was set up for apogee-only with motor based ejection. The BP charge was larger than necessary, caused nose cone to snap back against aft airframe. Minor damage to leading edge of aft airframe, big chunk of the nose cone skin cracked away. Same problem Bdale saw on Sharp Stick's nosecone, also from Performance Rocketry, where there was apparently an air bubble below the gel coat. Determination was that damage was cosmetic and would not affect cert... confirmed by successful L2 later in the day! 2010-08-21-serial-224-flight-005.eeprom Anthony Towns' LDDD clone, successful L2 cert on a CTI Pro38 5-grain 58J357 blue streak. Perfect drogueless dual deploy! 0.8-0.9 grams aft charge and about 1.0 grams forward. Flew without ground testing charges due to time pressure before waiver closed for the day. About as close to the waiver as you'd ever want to be on a cert flight, again demonstrating that OpenRocket under-estimates apogee ... approximately 6800 ft predicted... 2010-08-21-serial-233-flight-002.eeprom Tim van Milligan's 5.5" L2 airframe, flying on a CTI Pro38 6-grain 774J410 red, TM indicated a problem with the apogee igniter continuity, noticed during countdown, turned out to be a loose wire! Perfect dual deploy flight once that was fixed. 2010-09-03-serial-051-flight-005.eeprom G-spot on an old Aerotech H125-20W single use 29mm motor. It appears the ejection at apogee actually happened much later, perhaps as much as 10 seconds late! -2010-09-03-serial-215-flight-005.eeprom Horizon Rebuild on a K490 Green3 reload. PFND. About 1.4 grams each end. +2010-09-03-serial-215-flight-005.eeprom Horizon Rebuild on a K490 Green3 reload. PFND. About 1.4 grams each end. (accel noise fools full) 2010-09-24-serial-236-flight-006.eeprom LDDD on I236 in Sheridan on 2010-09-24 to 1216m 2010-09-25-serial-223-flight-001.eeprom Bdale's 10" Goblin, flying on a CTI Pro75 M1300 Imax dual thrust during Chili Blaster 2 at Hudson Ranch. First flight after rebuild to do dual deploy from one bay with ARRD and 15' surplus "+ sign" parachute. 2010-10-17-serial-215-flight-006.eeprom Horizon Rebuild on CTI J595BS at Tripoli Colorado launch site near Hartsel, CO -- cgit v1.2.3 From aafa8859ecb27383f697b98f6991643b44f4721a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 20:32:31 -0700 Subject: altos: Save some memory. A few minor space savings in ao_cmd.c and ao_config.c. Don't build unused conversion functions ao_altitude_to_pres and ao_temp_to_dC Signed-off-by: Keith Packard --- src/core/ao_cmd.c | 24 +++++++++++++----------- src/core/ao_config.c | 26 ++++++++++++++------------ src/core/ao_convert.c | 4 ++++ src/core/ao_convert_test.c | 5 +++-- src/test/ao_flight_test.c | 1 + 5 files changed, 35 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index fbf0c347..05dbfb51 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -36,10 +36,16 @@ put_string(__code char *s) putchar(c); } +static void +backspace(void) +{ + put_string ("\010 \010"); +} + static void readline(void) { - __pdata char c; + char c; if (ao_echo()) put_string("> "); cmd_len = 0; @@ -50,7 +56,7 @@ readline(void) if (c == '\010' || c == '\177') { if (cmd_len != 0) { if (ao_echo()) - put_string("\010 \010"); + backspace(); --cmd_len; } continue; @@ -60,7 +66,7 @@ readline(void) if (c == '\025') { while (cmd_len != 0) { if (ao_echo()) - put_string("\010 \010"); + backspace(); --cmd_len; } continue; @@ -76,11 +82,8 @@ readline(void) break; } - if (cmd_len >= CMD_LEN - 2) { - if (ao_echo()) - putchar('\007'); + if (cmd_len >= CMD_LEN - 2) continue; - } cmd_line[cmd_len++] = c; if (ao_echo()) putchar(c); @@ -271,13 +274,12 @@ help(void) __pdata uint8_t cmds; __pdata uint8_t cmd; __code struct ao_cmds * __pdata cs; + const char *h; for (cmds = 0; cmds < ao_ncmds; cmds++) { cs = ao_cmds[cmds]; - for (cmd = 0; cs[cmd].func; cmd++) - printf("%-45s %s\n", - cs[cmd].help, - cs[cmd].help+1+strlen(cs[cmd].help)); + for (cmd = 0; (h = cs[cmd].help); cmd++) + printf("%-45s %s\n", h, h + 1 + strlen(h)); } } diff --git a/src/core/ao_config.c b/src/core/ao_config.c index cc580d66..e0dabcd9 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -78,6 +78,8 @@ ao_config_set_radio(void) static void _ao_config_get(void) { + uint8_t minor; + if (ao_config_loaded) return; #if HAS_EEPROM @@ -97,37 +99,37 @@ _ao_config_get(void) ao_xmemset(&ao_config.callsign, '\0', sizeof (ao_config.callsign)); ao_xmemcpy(&ao_config.callsign, CODE_TO_XDATA(AO_CONFIG_DEFAULT_CALLSIGN), sizeof(AO_CONFIG_DEFAULT_CALLSIGN) - 1); - ao_config_dirty = 1; } - if (ao_config.minor != AO_CONFIG_MINOR) { + minor = ao_config.minor; + if (minor != AO_CONFIG_MINOR) { /* Fixups for minor version 1 */ - if (ao_config.minor < 1) + if (minor < 1) ao_config.apogee_delay = AO_CONFIG_DEFAULT_APOGEE_DELAY; /* Fixups for minor version 2 */ - if (ao_config.minor < 2) { + if (minor < 2) { ao_config.accel_plus_g = 0; ao_config.accel_minus_g = 0; } /* Fixups for minor version 3 */ #if HAS_RADIO - if (ao_config.minor < 3) + if (minor < 3) ao_config.radio_cal = ao_radio_cal; #endif /* Fixups for minor version 4 */ - if (ao_config.minor < 4) + if (minor < 4) ao_config.flight_log_max = AO_CONFIG_DEFAULT_FLIGHT_LOG_MAX; /* Fixupes for minor version 5 */ - if (ao_config.minor < 5) + if (minor < 5) ao_config.ignite_mode = AO_CONFIG_DEFAULT_IGNITE_MODE; - if (ao_config.minor < 6) + if (minor < 6) ao_config.pad_orientation = AO_CONFIG_DEFAULT_PAD_ORIENTATION; - if (ao_config.minor < 8) + if (minor < 8) ao_config.radio_enable = TRUE; - if (ao_config.minor < 9) + if (minor < 9) ao_xmemset(&ao_config.aes_key, '\0', AO_AES_LEN); - if (ao_config.minor < 10) + if (minor < 10) ao_config.frequency = 434550; - if (ao_config.minor < 11) + if (minor < 11) ao_config.apogee_lockout = 0; ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; diff --git a/src/core/ao_convert.c b/src/core/ao_convert.c index 0969f107..aa9b5f48 100644 --- a/src/core/ao_convert.c +++ b/src/core/ao_convert.c @@ -41,6 +41,7 @@ ao_pres_to_altitude(int16_t pres) __reentrant (int32_t) altitude_table[o+1] * part + (ALT_FRAC_SCALE >> 1)) >> ALT_FRAC_BITS; } +#if AO_NEED_ALTITUDE_TO_PRES int16_t ao_altitude_to_pres(int16_t alt) __reentrant { @@ -66,7 +67,9 @@ ao_altitude_to_pres(int16_t alt) __reentrant pres = 0; return (int16_t) pres; } +#endif +#if 0 int16_t ao_temp_to_dC(int16_t temp) __reentrant { @@ -83,3 +86,4 @@ ao_temp_to_dC(int16_t temp) __reentrant ret = ((temp - 19791) * 1012L) >> 16; return ret; } +#endif diff --git a/src/core/ao_convert_test.c b/src/core/ao_convert_test.c index e2c28b73..87e76841 100644 --- a/src/core/ao_convert_test.c +++ b/src/core/ao_convert_test.c @@ -17,14 +17,15 @@ #include #define AO_CONVERT_TEST +#define AO_NEED_ALTITUDE_TO_PRES 1 #include "ao_host.h" #include "ao_convert.c" #define STEP 1 -static inline i_abs(int i) { return i < 0 ? -i : i; } +static inline int i_abs(int i) { return i < 0 ? -i : i; } -main () +int main (int argc, char **argv) { int i; int16_t p_to_a, p_to_a_to_p; diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index 9bb03d68..a4ef8dc0 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -180,6 +180,7 @@ struct ao_cmds { #define ao_xmemset(d,v,c) memset(d,v,c) #define ao_xmemcmp(d,s,c) memcmp(d,s,c) +#define AO_NEED_ALTITUDE_TO_PRES 1 #include "ao_convert.c" struct ao_config { -- cgit v1.2.3 From bca72b782a2909ecedef15ad589292647221ca56 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 20:34:02 -0700 Subject: altos: Add 'void' parameter to ao_fec_decode callback parameter This keeps the compiler from whinging about the lack of a prototype. Signed-off-by: Keith Packard --- src/core/ao_fec.h | 2 +- src/core/ao_fec_rx.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index 771732bd..eedea8f4 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -73,7 +73,7 @@ ao_fec_encode(const uint8_t *in, uint8_t len, uint8_t *out); #define AO_FEC_DECODE_CRC_OK 0x80 /* stored in out[out_len-1] */ uint8_t -ao_fec_decode(const uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()); +ao_fec_decode(const uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len, uint16_t (*callback)(void)); /* * Interleave data packed in bytes. 'out' must be 'len' bytes long. diff --git a/src/core/ao_fec_rx.c b/src/core/ao_fec_rx.c index 64426d72..072a9e90 100644 --- a/src/core/ao_fec_rx.c +++ b/src/core/ao_fec_rx.c @@ -96,7 +96,7 @@ ao_next_state(uint8_t state, uint8_t bit) */ uint8_t -ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()) +ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)(void)) { static uint32_t cost[2][NUM_STATE]; /* path cost */ static bits_t bits[2][NUM_STATE]; /* save bits to quickly output them */ -- cgit v1.2.3 From fb60d87b02c0fc83a0b4268212f0b6b740c984e3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 20:35:19 -0700 Subject: altos: Signal continuity over radio in pad mode (trac #40) This is especially useful for telemini which has no beeper, allowing you to hear the continuity signal while at the pad over the air. Signed-off-by: Keith Packard --- src/cc1111/ao_radio.c | 89 ++++++++++++++++++++++++++++++++++++++++--------- src/core/ao.h | 25 ++++++++++++-- src/core/ao_report.c | 10 ++++-- src/core/ao_telemetry.c | 14 +++++--- src/drivers/ao_cc1120.c | 69 +++++++++++++++++++++++++++++--------- 5 files changed, 167 insertions(+), 40 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index 2c4a661e..2071c47a 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -200,7 +200,7 @@ static __code uint8_t rdf_setup[] = { RF_MDMCFG3_OFF, (RDF_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_MDMCFG2_SYNC_MODE_NONE), RF_MDMCFG1_OFF, (RF_MDMCFG1_FEC_DIS | RF_MDMCFG1_NUM_PREAMBLE_2 | (2 << RF_MDMCFG1_CHANSPC_E_SHIFT)), @@ -366,29 +366,22 @@ ao_radio_recv_abort(void) ao_wakeup(&ao_radio_dma_done); } -__xdata ao_radio_rdf_value = 0x55; +__code ao_radio_rdf_value = 0x55; -void -ao_radio_rdf(uint8_t pkt_len) +static void +ao_radio_rdf_start(void) { uint8_t i; - ao_radio_abort = 0; - ao_radio_get(pkt_len); + ao_radio_get(AO_RADIO_RDF_LEN); ao_radio_done = 0; for (i = 0; i < sizeof (rdf_setup); i += 2) RF[rdf_setup[i]] = rdf_setup[i+1]; +} - ao_dma_set_transfer(ao_radio_dma, - &ao_radio_rdf_value, - &RFDXADDR, - pkt_len, - DMA_CFG0_WORDSIZE_8 | - DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_RADIO, - DMA_CFG1_SRCINC_0 | - DMA_CFG1_DESTINC_0 | - DMA_CFG1_PRIORITY_HIGH); +static void +ao_radio_rdf_run(void) +{ ao_dma_start(ao_radio_dma); RFST = RFST_STX; __critical while (!ao_radio_done && !ao_radio_abort) @@ -401,6 +394,70 @@ ao_radio_rdf(uint8_t pkt_len) ao_radio_put(); } +void +ao_radio_rdf(void) +{ + ao_radio_rdf_start(); + + ao_dma_set_transfer(ao_radio_dma, + CODE_TO_XDATA(&ao_radio_rdf_value), + &RFDXADDR, + AO_RADIO_RDF_LEN, + DMA_CFG0_WORDSIZE_8 | + DMA_CFG0_TMODE_SINGLE | + DMA_CFG0_TRIGGER_RADIO, + DMA_CFG1_SRCINC_0 | + DMA_CFG1_DESTINC_0 | + DMA_CFG1_PRIORITY_HIGH); + ao_radio_rdf_run(); +} + +#define PA 0x00 +#define BE 0x55 + +#define CONT_PAUSE_8 PA, PA, PA, PA, PA, PA, PA, PA +#define CONT_PAUSE_16 CONT_PAUSE_8, CONT_PAUSE_8 +#define CONT_PAUSE_24 CONT_PAUSE_16, CONT_PAUSE_8 + +#define CONT_BEEP_8 BE, BE, BE, BE, BE, BE, BE, BE + +#if AO_RADIO_CONT_PAUSE_LEN == 24 +#define CONT_PAUSE CONT_PAUSE_24 +#endif + +#if AO_RADIO_CONT_TONE_LEN == 8 +#define CONT_BEEP CONT_BEEP_8 +#define CONT_PAUSE_SHORT CONT_PAUSE_8 +#endif + +#define CONT_ADDR(c) CODE_TO_XDATA(&ao_radio_cont[(3-(c)) * (AO_RADIO_CONT_PAUSE_LEN + AO_RADIO_CONT_TONE_LEN)]) + +__code uint8_t ao_radio_cont[] = { + CONT_PAUSE, CONT_BEEP, + CONT_PAUSE, CONT_BEEP, + CONT_PAUSE, CONT_BEEP, + CONT_PAUSE, CONT_PAUSE_SHORT, + CONT_PAUSE, CONT_PAUSE_SHORT, + CONT_PAUSE, +}; + +void +ao_radio_continuity(uint8_t c) +{ + ao_radio_rdf_start(); + ao_dma_set_transfer(ao_radio_dma, + CONT_ADDR(c), + &RFDXADDR, + AO_RADIO_CONT_TOTAL_LEN, + 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_radio_rdf_run(); +} + void ao_radio_rdf_abort(void) { diff --git a/src/core/ao.h b/src/core/ao.h index 861a0fd4..2e012f08 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -264,6 +264,26 @@ ao_cmd_filter(void); * ao_report.c */ +#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) +#define AO_RDF_LENGTH_MS 500 +#define AO_RDF_CONTINUITY_MS 32 +#define AO_RDF_CONTINUITY_PAUSE 96 +#define AO_RDF_CONTINUITY_TOTAL ((AO_RDF_CONTINUITY_PAUSE + AO_RDF_CONTINUITY_MS) * 3 + AO_RDF_CONTINUITY_PAUSE) + +/* This assumes that we're generating a 1kHz tone, which + * modulates the carrier at 2kbps, or 250kBps + */ +#define AO_MS_TO_RDF_LEN(ms) ((ms) / 4) + +#define AO_RADIO_RDF_LEN AO_MS_TO_RDF_LEN(AO_RDF_LENGTH_MS) +#define AO_RADIO_CONT_TONE_LEN AO_MS_TO_RDF_LEN(AO_RDF_CONTINUITY_MS) +#define AO_RADIO_CONT_PAUSE_LEN AO_MS_TO_RDF_LEN(AO_RDF_CONTINUITY_PAUSE) +#define AO_RADIO_CONT_TOTAL_LEN AO_MS_TO_RDF_LEN(AO_RDF_CONTINUITY_TOTAL) + +/* returns a value 0-3 to indicate igniter continuity */ +uint8_t +ao_report_igniter(void); + void ao_report_init(void); @@ -538,10 +558,11 @@ ao_radio_recv_abort(void); * 2 * ms bits, or ms / 4 bytes */ -#define AO_MS_TO_RDF_LEN(ms) ((ms) > 255 * 4 ? 255 : ((ms) >> 2)) +void +ao_radio_rdf(void); void -ao_radio_rdf(uint8_t pkt_len); +ao_radio_continuity(uint8_t c); void ao_radio_rdf_abort(void); diff --git a/src/core/ao_report.c b/src/core/ao_report.c index eb90a4f8..1104cd82 100644 --- a/src/core/ao_report.c +++ b/src/core/ao_report.c @@ -114,6 +114,13 @@ ao_report_igniter_ready(enum ao_igniter igniter) return ao_igniter_status(igniter) == ao_igniter_ready ? 1 : 0; } +uint8_t +ao_report_igniter(void) +{ + return (ao_report_igniter_ready(ao_igniter_drogue) | + (ao_report_igniter_ready(ao_igniter_main) << 1)); +} + static void ao_report_continuity(void) __reentrant { @@ -123,8 +130,7 @@ ao_report_continuity(void) __reentrant if (!ao_igniter_present) return; #endif - c = (ao_report_igniter_ready(ao_igniter_drogue) | - (ao_report_igniter_ready(ao_igniter_main) << 1)); + c = ao_report_igniter(); if (c) { while (c--) { high(AO_MS_TO_TICKS(25)); diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 3c747520..583a6636 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -22,9 +22,6 @@ static __pdata uint16_t ao_telemetry_interval; static __pdata uint8_t ao_rdf = 0; static __pdata uint16_t ao_rdf_time; -#define AO_RDF_INTERVAL_TICKS AO_SEC_TO_TICKS(5) -#define AO_RDF_LENGTH_MS 500 - #if defined(MEGAMETRUM) #define AO_SEND_MEGA 1 #endif @@ -317,8 +314,16 @@ ao_telemetry(void) if (ao_rdf && (int16_t) (ao_time() - ao_rdf_time) >= 0) { +#if HAS_IGNITE_REPORT + uint8_t c; +#endif ao_rdf_time = ao_time() + AO_RDF_INTERVAL_TICKS; - ao_radio_rdf(AO_MS_TO_RDF_LEN(AO_RDF_LENGTH_MS)); +#if HAS_IGNITE_REPORT + if (ao_flight_state == ao_flight_pad && (c = ao_report_igniter())) + ao_radio_continuity(c); + else +#endif + ao_radio_rdf(); } #endif time += ao_telemetry_interval; @@ -330,6 +335,7 @@ ao_telemetry(void) } else time = ao_time(); + bottom: ; } } } diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 1d28148b..a36d922c 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -160,7 +160,7 @@ ao_radio_fifo_read(uint8_t *data, uint8_t len) } static uint8_t -ao_radio_fifo_write(uint8_t *data, uint8_t len) +ao_radio_fifo_write_start(void) { uint8_t addr = ((0 << CC1120_READ) | (1 << CC1120_BURST) | @@ -169,24 +169,28 @@ ao_radio_fifo_write(uint8_t *data, uint8_t len) ao_radio_select(); ao_radio_duplex(&addr, &status, 1); - ao_radio_spi_send(data, len); + return status; +} + +static inline uint8_t ao_radio_fifo_write_stop(uint8_t status) { ao_radio_deselect(); return status; } static uint8_t -ao_radio_fifo_write_fixed(uint8_t data, uint8_t len) +ao_radio_fifo_write(uint8_t *data, uint8_t len) { - uint8_t addr = ((0 << CC1120_READ) | - (1 << CC1120_BURST) | - CC1120_FIFO); - uint8_t status; + uint8_t status = ao_radio_fifo_write_start(); + ao_radio_spi_send(data, len); + return ao_radio_fifo_write_stop(status); +} - ao_radio_select(); - ao_radio_duplex(&addr, &status, 1); +static uint8_t +ao_radio_fifo_write_fixed(uint8_t data, uint8_t len) +{ + uint8_t status = ao_radio_fifo_write_start(); ao_radio_spi_send_fixed(data, len); - ao_radio_deselect(); - return status; + return ao_radio_fifo_write_stop(status); } static uint8_t @@ -446,19 +450,20 @@ ao_radio_get(uint8_t len) #define ao_radio_put() ao_mutex_put(&ao_radio_mutex) -void -ao_radio_rdf(uint8_t len) +static void +ao_rdf_start(uint8_t len) { - int i; - ao_radio_abort = 0; ao_radio_get(len); ao_radio_set_mode(AO_RADIO_MODE_RDF); ao_radio_wake = 0; - ao_radio_fifo_write_fixed(ao_radio_rdf_value, len); +} +static void +ao_rdf_run(void) +{ ao_radio_start_tx(); cli(); @@ -470,6 +475,38 @@ ao_radio_rdf(uint8_t len) ao_radio_put(); } +void +ao_radio_rdf(void) +{ + ao_rdf_start(AO_RADIO_RDF_LEN); + + ao_radio_fifo_write_fixed(ao_radio_rdf_value, AO_RADIO_RDF_LEN); + + ao_rdf_run(); +} + +void +ao_radio_continuity(uint8_t c) +{ + uint8_t i; + uint8_t status; + + ao_rdf_start(AO_RADIO_CONT_TOTAL_LEN); + + status = ao_radio_fifo_write_start(); + for (i = 0; i < 3; i++) { + ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN); + if (i < c) + ao_radio_spi_send_fixed(ao_radio_rdf_value, AO_RADIO_CONT_TONE_LEN); + else + ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_TONE_LEN); + } + ao_radio_spi_send_fixed(0x00, AO_RADIO_CONT_PAUSE_LEN); + status = ao_radio_fifo_write_stop(status); + (void) status; + ao_rdf_run(); +} + void ao_radio_rdf_abort(void) { -- cgit v1.2.3 From 0b92164143aaf0d2aa3d5d742484391c16545289 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 22:08:28 -0700 Subject: altos: Set HAS_FLIGHT_DEBUG=1 to include the flight debugging commands This leaves USB enabled, and adds the 'F' command to dump internal flight state. Signed-off-by: Keith Packard --- src/core/ao_flight.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index 39084fd0..c6786455 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -114,7 +114,7 @@ ao_flight(void) { /* Set pad mode - we can fly! */ ao_flight_state = ao_flight_pad; -#if HAS_USB && HAS_RADIO +#if HAS_USB && HAS_RADIO && !HAS_FLIGHT_DEBUG /* Disable the USB controller in flight mode * to save power */ @@ -358,7 +358,7 @@ ao_flight(void) } } -#if !HAS_RADIO +#if HAS_FLIGHT_DEBUG static inline int int_part(int16_t i) { return i >> 4; } static inline int frac_part(int16_t i) { return ((i & 0xf) * 100 + 8) / 16; } @@ -378,6 +378,7 @@ ao_flight_dump(void) printf (" raw accel %d\n", ao_sample_accel); #endif printf (" ground pres %d\n", ao_ground_pres); + printf (" ground alt %d\n", ao_ground_height); #if HAS_ACCEL printf (" raw accel %d\n", ao_sample_accel); printf (" groundaccel %d\n", ao_ground_accel); @@ -413,7 +414,7 @@ void ao_flight_init(void) { ao_flight_state = ao_flight_startup; -#if !HAS_RADIO +#if HAS_FLIGHT_DEBUG ao_cmd_register(&ao_flight_cmds[0]); #endif ao_add_task(&flight_task, ao_flight, "flight"); -- cgit v1.2.3 From aa305da7e5dc182c99c09e422c053d85ed48d5d5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 22:09:44 -0700 Subject: altos: Continuously update ground state while on pad (trac #42) Average data for 5 seconds, wait 5 seconds and if still in pad mode, replace the existing data with the new data. This should avoid averaging in boost data while still keeping things reasonably current. Signed-off-by: Keith Packard --- src/core/ao_sample.c | 58 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c index ac11eef0..6461def0 100644 --- a/src/core/ao_sample.c +++ b/src/core/ao_sample.c @@ -61,6 +61,29 @@ __pdata int32_t ao_sample_pres_sum; __pdata int32_t ao_sample_accel_sum; #endif +static void +ao_sample_preflight_add(void) +{ +#if HAS_ACCEL + ao_sample_accel_sum += ao_sample_accel; +#endif + ao_sample_pres_sum += ao_sample_pres; + ++nsamples; +} + +static void +ao_sample_preflight_set(void) +{ +#if HAS_ACCEL + ao_ground_accel = ao_sample_accel_sum >> 9; + ao_sample_accel_sum = 0; +#endif + ao_ground_pres = ao_sample_pres_sum >> 9; + ao_ground_height = pres_to_altitude(ao_ground_pres); + nsamples = 0; + ao_sample_pres_sum = 0; +} + static void ao_sample_preflight(void) { @@ -70,29 +93,38 @@ ao_sample_preflight(void) * data and average them to find the resting values */ if (nsamples < 512) { -#if HAS_ACCEL - ao_sample_accel_sum += ao_sample_accel; -#endif - ao_sample_pres_sum += ao_sample_pres; - ++nsamples; + ao_sample_preflight_add(); } else { - ao_config_get(); #if HAS_ACCEL - ao_ground_accel = ao_sample_accel_sum >> 9; ao_accel_2g = ao_config.accel_minus_g - ao_config.accel_plus_g; ao_accel_scale = to_fix32(GRAVITY * 2 * 16) / ao_accel_2g; #endif - ao_ground_pres = ao_sample_pres_sum >> 9; - ao_ground_height = pres_to_altitude(ao_ground_pres); + ao_sample_preflight_set(); ao_preflight = FALSE; } } +/* + * While in pad mode, constantly update the ground state by + * re-averaging the data. This tracks changes in orientation, which + * might be caused by adjustments to the rocket on the pad and + * pressure, which might be caused by changes in the weather. + */ + +static void +ao_sample_preflight_update(void) +{ + if (nsamples < 512) + ao_sample_preflight_add(); + else if (nsamples < 1024) + ++nsamples; + else + ao_sample_preflight_set(); +} uint8_t ao_sample(void) { - ao_config_get(); ao_wakeup(DATA_TO_XDATA(&ao_sample_data)); ao_sleep((void *) DATA_TO_XDATA(&ao_data_head)); while (ao_sample_data != ao_data_head) { @@ -116,8 +148,11 @@ ao_sample(void) if (ao_preflight) ao_sample_preflight(); - else + else { + if (ao_flight_state < ao_flight_boost) + ao_sample_preflight_update(); ao_kalman(); + } ao_sample_data = ao_data_ring_next(ao_sample_data); } return !ao_preflight; @@ -126,6 +161,7 @@ ao_sample(void) void ao_sample_init(void) { + ao_config_get(); nsamples = 0; ao_sample_pres_sum = 0; ao_sample_pres = 0; -- cgit v1.2.3 From 46407f7f3e4d2b6e74b3a2e90b38736a792cfc54 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Jul 2012 22:41:59 -0700 Subject: altos: Force 434.550Mhz by connecting debug gnd and clk (trac #41) Check for pin P2_2 low at startup and set the frequency to 434.550MHz. This value won't get written to flash, so rebooting again will restore the configured frequency. Signed-off-by: Keith Packard --- src/cc1111/ao_pins.h | 1 + src/core/ao.h | 7 +++++++ src/core/ao_config.c | 4 ++++ src/product/ao_telemini.c | 13 +++++++++++++ 4 files changed, 25 insertions(+) (limited to 'src') diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index e28a7b65..fc6ed3ec 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -163,6 +163,7 @@ #define HAS_ADC 1 #define HAS_EEPROM 1 #define HAS_LOG 1 + #define HAS_FORCE_FREQ 1 #define USE_INTERNAL_FLASH 1 #define HAS_DBG 0 #define IGNITE_ON_P2 0 diff --git a/src/core/ao.h b/src/core/ao.h index 2e012f08..06daf48f 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -682,6 +682,13 @@ ao_igniter_init(void); * ao_config.c */ +#if HAS_FORCE_FREQ +/* + * Set this to force the frequency to 434.550MHz + */ +extern __xdata uint8_t ao_force_freq; +#endif + #define AO_CONFIG_MAJOR 1 #define AO_CONFIG_MINOR 11 diff --git a/src/core/ao_config.c b/src/core/ao_config.c index e0dabcd9..ced8b1f2 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -135,6 +135,10 @@ _ao_config_get(void) ao_config_dirty = 1; } #if HAS_RADIO +#if HAS_FORCE_FREQ + if (ao_force_freq) + ao_config.frequency = 434550; +#endif ao_config_set_radio(); #endif ao_config_loaded = 1; diff --git a/src/product/ao_telemini.c b/src/product/ao_telemini.c index fa23de01..21551ee9 100644 --- a/src/product/ao_telemini.c +++ b/src/product/ao_telemini.c @@ -18,6 +18,8 @@ #include "ao.h" #include "ao_pins.h" +__xdata uint8_t ao_force_freq; + void main(void) { @@ -33,6 +35,17 @@ main(void) ao_led_init(LEDS_AVAILABLE); ao_led_on(AO_LED_RED); + /* A hack -- look at the debug clock pin, if it's sitting at + * ground, then we force the computer to idle mode instead of + * flight mode + */ + if (P2_2 == 0) { + ao_flight_force_idle = 1; + ao_force_freq = 1; + while (P2_2 == 0) + ; + } + ao_timer_init(); ao_adc_init(); ao_cmd_init(); -- cgit v1.2.3 From cc5d106f014f714a9a2d5f595a2de0da8f7da80a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jul 2012 13:40:07 -0700 Subject: altos: Ignore megametrum built files Signed-off-by: Keith Packard --- src/megametrum-v0.1/.gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/megametrum-v0.1/.gitignore (limited to 'src') diff --git a/src/megametrum-v0.1/.gitignore b/src/megametrum-v0.1/.gitignore new file mode 100644 index 00000000..b04d3950 --- /dev/null +++ b/src/megametrum-v0.1/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +megametrum-*.elf -- cgit v1.2.3 From 726f47c8a07f060aed930e1d102a1e8b5a5c7aed Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jul 2012 13:47:25 -0700 Subject: altos: remove optimization for 'help' that confuses cc1111 compiler The cc1111 compiler gets this very wrong and prints piles of garbage Signed-off-by: Keith Packard --- src/core/ao_cmd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_cmd.c b/src/core/ao_cmd.c index 05dbfb51..1814cecf 100644 --- a/src/core/ao_cmd.c +++ b/src/core/ao_cmd.c @@ -278,8 +278,10 @@ help(void) for (cmds = 0; cmds < ao_ncmds; cmds++) { cs = ao_cmds[cmds]; - for (cmd = 0; (h = cs[cmd].help); cmd++) + for (cmd = 0; cs[cmd].func; cmd++) { + h = cs[cmd].help; printf("%-45s %s\n", h, h + 1 + strlen(h)); + } } } -- cgit v1.2.3 From 18431c88c8a6cb267922b97192e8b7ddb88d0e7e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jul 2012 13:49:26 -0700 Subject: altos: Have 'make clean' remove all programs, even old ones This makes sure that changing version numbers doesn't leave old compiled output lying around. Signed-off-by: Keith Packard --- src/cc1111/Makefile.cc1111 | 8 ++++++++ src/megametrum-v0.1/Makefile | 5 +++-- src/product/Makefile.telebt | 13 +++++-------- src/product/Makefile.teledongle | 9 +++------ src/product/Makefile.telelaunch | 9 +++------ src/product/Makefile.telemetrum | 9 +++------ src/product/Makefile.telemini | 9 +++------ src/product/Makefile.telenano | 9 +++------ src/stm-demo/Makefile | 2 +- src/teleballoon-v1.1/Makefile | 13 +++++-------- src/telescience-v0.1/Makefile | 2 +- src/teleshield-v0.1/Makefile | 9 +++------ src/teleterra-v0.2/Makefile | 9 +++------ src/test/Makefile | 2 +- src/tidongle/Makefile | 9 +++------ 15 files changed, 48 insertions(+), 69 deletions(-) (limited to 'src') diff --git a/src/cc1111/Makefile.cc1111 b/src/cc1111/Makefile.cc1111 index 8de4a9b2..f7ecce33 100644 --- a/src/cc1111/Makefile.cc1111 +++ b/src/cc1111/Makefile.cc1111 @@ -25,3 +25,11 @@ PAOM=$(PROG:.ihx=) %.rel : %.c $(INC) $(call quiet,CC,$(PRODUCT_DEF)) $(CFLAGS) -c -o$@ $< + +all: + +clean-cc1111: + rm -f *.adb *.asm *.lnk *.lst *.rel *.rst *.sym + rm -f $(PROGNAME)-* + rm -f ao_product.h + rm -f ../$(PROGNAME)-* diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 13e46c97..59cfb64d 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -82,7 +82,8 @@ IDPRODUCT=0x0023 CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g -PROG=megametrum-v0.1-$(VERSION).elf +PROGNAME=megametrum-v0.1 +PROG=$(PROGNAME)-$(VERSION).elf SRC=$(ALTOS_SRC) ao_megametrum.c OBJ=$(SRC:.c=.o) @@ -103,7 +104,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean clean: - rm -f $(OBJ) + rm -f *.o $(PROGNAME)-*.elf rm -f ao_product.h install: diff --git a/src/product/Makefile.telebt b/src/product/Makefile.telebt index 90525d63..fd52cec4 100644 --- a/src/product/Makefile.telebt +++ b/src/product/Makefile.telebt @@ -60,7 +60,8 @@ SRC = \ $(PRODUCT_SRC) \ $(TELEBT_SRC) -PROG = telebt-v$(TELEBT_VER)-$(VERSION).ihx +PROGNAME = telebt-v$(TELEBT_VER) +PROG = $(PROGNAME)-$(VERSION).ihx PRODUCT=TeleBT-v$(TELEBT_VER) PRODUCT_DEF=-DTELEBT_V_$(TELEBT_DEF) IDPRODUCT=0x000e @@ -78,9 +79,9 @@ endif # Otherwise, print the full command line. quiet ?= $($1) -all: ../$(PROG) +all: $(PROG) -../$(PROG): $(REL) Makefile +$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ @@ -89,11 +90,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f ao_product.h - rm -f ../$(PROG) ../$(PMAP) +clean: clean-cc1111 install: diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle index fbf14a04..5105b567 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -60,7 +60,8 @@ SRC = \ $(DRIVER_SRC) \ $(PRODUCT_SRC) -PROG = teledongle-v$(TD_VER)-$(VERSION).ihx +PROGNAME = teledongle-v$(TD_VER) +PROG = $(PROGNAME)-$(VERSION).ihx PRODUCT=TeleDongle-v$(TD_VER) PRODUCT_DEF=-DTELEDONGLE_V_$(TD_DEF) IDPRODUCT=0x000c @@ -89,11 +90,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f ao_product.h - rm -f ../$(PROG) ../$(PMAP) +clean: clean-cc1111 install: diff --git a/src/product/Makefile.telelaunch b/src/product/Makefile.telelaunch index 3753f3c9..1e55989c 100644 --- a/src/product/Makefile.telelaunch +++ b/src/product/Makefile.telelaunch @@ -62,7 +62,8 @@ SRC = \ $(DRIVER_SRC) \ $(PRODUCT_SRC) -PROG = telelaunch-v$(TELELAUNCH_VER)-$(VERSION).ihx +PROGNAME = telelaunch-v$(TELELAUNCH_VER) +PROG = $(PROGNAME)-$(VERSION).ihx PRODUCT=TeleLaunch-v$(TELELAUNCH_VER) PRODUCT_DEF=-DTELELAUNCH_V_$(TELELAUNCH_DEF) IDPRODUCT=0x000f @@ -92,11 +93,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f ao_product.h - rm -f ../$(PROG) ../$(PMAP) +clean: clean-cc1111 install: diff --git a/src/product/Makefile.telemetrum b/src/product/Makefile.telemetrum index 57586c95..5e3eed7f 100644 --- a/src/product/Makefile.telemetrum +++ b/src/product/Makefile.telemetrum @@ -75,7 +75,8 @@ SRC = \ $(DRIVER_SRC) \ $(PRODUCT_SRC) -PROG = telemetrum-v$(TM_VER)-$(VERSION)$(TM_EXTRA).ihx +PROGNAME = telemetrum-v$(TM_VER)$(TM_EXTRA) +PROG = $(PROGNAME)-$(VERSION).ihx PRODUCT=TeleMetrum-v$(TM_VER) PRODUCT_DEF=-DTELEMETRUM_V_$(TM_DEF) IDPRODUCT=0x000b @@ -104,11 +105,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f ao_product.h - rm -f ../$(PROG) ../$(PMAP) +clean: clean-cc1111 install: diff --git a/src/product/Makefile.telemini b/src/product/Makefile.telemini index 23aed1c7..ef8906ba 100644 --- a/src/product/Makefile.telemini +++ b/src/product/Makefile.telemini @@ -63,7 +63,8 @@ SRC = \ $(DRIVER_SRC) \ $(PRODUCT_SRC) -PROG = telemini-v$(TELEMINI_VER)-$(VERSION).ihx +PROGNAME = telemini-v$(TELEMINI_VER) +PROG = $(PROGNAME)-$(VERSION).ihx PRODUCT=TeleMini-v$(TELEMINI_VER) PRODUCT_DEF=-DTELEMINI_V_$(TELEMINI_DEF) IDPRODUCT=0x000a @@ -93,11 +94,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f ao_product.h - rm -f ../$(PROG) ../$(PMAP) +clean: clean-cc1111 install: diff --git a/src/product/Makefile.telenano b/src/product/Makefile.telenano index ca719bbf..67410ae0 100644 --- a/src/product/Makefile.telenano +++ b/src/product/Makefile.telenano @@ -62,7 +62,8 @@ SRC = \ $(DRIVER_SRC) \ $(PRODUCT_SRC) -PROG = telenano-v$(TELENANO_VER)-$(VERSION).ihx +PROGNAME = telenano-v$(TELENANO_VER) +PROG = $(PROGNAME)-$(VERSION).ihx PRODUCT=TeleNano-v$(TELENANO_VER) PRODUCT_DEF=-DTELENANO_V_$(TELENANO_DEF) IDPRODUCT=0x000a @@ -92,11 +93,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f ao_product.h - rm -f ../$(PROG) ../$(PMAP) +clean: clean-cc1111 install: diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index dd7e6e02..055a73af 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -61,7 +61,7 @@ $(OBJ): $(INC) distclean: clean clean: - rm -f $(OBJ) + rm -f *.o $(PROG) rm -f ao_product.h install: diff --git a/src/teleballoon-v1.1/Makefile b/src/teleballoon-v1.1/Makefile index fb88787b..2eea996e 100644 --- a/src/teleballoon-v1.1/Makefile +++ b/src/teleballoon-v1.1/Makefile @@ -81,7 +81,8 @@ SRC = \ $(DRIVER_SRC) \ $(PRODUCT_SRC) -PROG = teleballoon-v$(TELEBALLOON_VER)-$(VERSION).ihx +PROGNAME = teleballoon-v$(TELEBALLOON_VER) +PROG = $(PROGNAME)-$(VERSION).ihx PRODUCT=TeleBalloon-v$(TELEBALLOON_VER) PRODUCT_DEF=-DTELEBALLOON_V_$(TELEBALLOON_DEF) IDPRODUCT=0x000b @@ -99,9 +100,9 @@ endif # Otherwise, print the full command line. quiet ?= $($1) -all: ../$(PROG) +all: $(PROG) -../$(PROG): $(REL) Makefile +$(PROG): $(REL) Makefile $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ @@ -110,11 +111,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f ao_product.h - rm -f ../$(PROG) ../$(PMAP) +clean: clean-cc1111 install: diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index 10e4a2a3..d24128ef 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -105,7 +105,7 @@ ao_product.o: ao_product.c ao_product.h distclean: clean clean: - rm -f $(OBJ) + rm -f *.o $(PROG) $(PROG).hex rm -f ao_product.h install: diff --git a/src/teleshield-v0.1/Makefile b/src/teleshield-v0.1/Makefile index c1f45f37..ab2a025f 100644 --- a/src/teleshield-v0.1/Makefile +++ b/src/teleshield-v0.1/Makefile @@ -72,7 +72,8 @@ SRC = \ $(DRIVER_SRC) \ $(PRODUCT_SRC) -PROG = teleshield-v$(TELESHIELD_VER)-$(VERSION).ihx +PROGNAME = teleshield-v$(TELESHIELD_VER) +PROG = $(PROGNAME)-$(VERSION).ihx PRODUCT=TeleShield-v$(TELESHIELD_VER) PRODUCT_DEF=-DTELESHIELD_V_$(TELESHIELD_DEF) IDPRODUCT=0x0013 @@ -102,11 +103,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f ao_product.h - rm -f ../$(PROG) ../$(PMAP) +clean: clean-cc1111 install: diff --git a/src/teleterra-v0.2/Makefile b/src/teleterra-v0.2/Makefile index 4967d187..65db57ce 100644 --- a/src/teleterra-v0.2/Makefile +++ b/src/teleterra-v0.2/Makefile @@ -66,7 +66,8 @@ SRC = \ TELETERRA_VER=0.2 TELETERRA_DEF=0_2 -PROG = teleterra-v$(TELETERRA_VER)-$(VERSION).ihx +PROGNAME = teleterra-v$(TELETERRA_VER) +PROG = $(PROGNAME)-$(VERSION).ihx PRODUCT=TeleTerra-v$(TELETERRA_VER) PRODUCT_DEF=-DTELETERRA_V_$(TELETERRA_DEF) IDPRODUCT=0x000d @@ -95,11 +96,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f ao_product.h - rm -f ../$(PROG) ../$(PMAP) +clean: clean-cc1111 install: diff --git a/src/test/Makefile b/src/test/Makefile index 963f4131..db3cc04b 100644 --- a/src/test/Makefile +++ b/src/test/Makefile @@ -9,7 +9,7 @@ CFLAGS=-I.. -I. -I../core -I../drivers -O3 -g -Wall all: $(PROGS) clean: - rm -f $(PROGS) + rm -f $(PROGS) run-out.baro run-out.full install: diff --git a/src/tidongle/Makefile b/src/tidongle/Makefile index 0bb2ce32..1514c4df 100644 --- a/src/tidongle/Makefile +++ b/src/tidongle/Makefile @@ -53,7 +53,8 @@ SRC = \ $(DRIVER_SRC) \ $(PRODUCT_SRC) -PROG = tidongle-$(VERSION).ihx +PROGNAME = tidongle +PROG = $(PROGNAME)-$(VERSION).ihx PRODUCT=TIDongle PRODUCT_DEF=-DTIDONGLE IDPRODUCT=0x000a @@ -82,11 +83,7 @@ ao_product.h: ao-make-product.5c ../Version distclean: clean -clean: - rm -f $(ADB) $(ASM) $(LNK) $(LST) $(REL) $(RST) $(SYM) - rm -f $(PROG) $(PCDB) $(PLNK) $(PMAP) $(PMEM) $(PAOM) - rm -f ao_product.h - rm -f ../$(PROG) ../$(PMAP) +clean: clean-cc1111 install: -- cgit v1.2.3 From fe70611c3c7d4b8cce3b5292f0ec549f3191bf86 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jul 2012 13:50:56 -0700 Subject: altos: Create macros to convert from/to radio RSSI representation AO_RSSI_FROM_RADIO and AO_RADIO_FROM_RSSI. Removes a bunch of open-coded versions of the same function. Signed-off-by: Keith Packard --- src/core/ao.h | 6 ++++++ src/core/ao_monitor.c | 5 ++--- src/drivers/ao_cc1120.c | 4 ++-- src/product/ao_terraui.c | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 06daf48f..eb2d47cf 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -487,6 +487,12 @@ struct ao_telemetry_tiny_recv { uint8_t status; }; +/* Unfortunately, we've exposed the CC1111 rssi units as the 'usual' method + * for reporting RSSI. So, now we use these values everywhere + */ +#define AO_RSSI_FROM_RADIO(radio) ((int16_t) ((int8_t) (radio) >> 1) - 74) +#define AO_RADIO_FROM_RSSI(rssi) (((int8_t) (rssi) + 74) << 1) + /* * ao_radio_recv tacks on rssi and status bytes */ diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index 51d61425..d492e32a 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -141,8 +141,7 @@ ao_monitor_put(void) case AO_MONITORING_ORIG: state = recv_orig.telemetry_orig.flight_state; - /* Typical RSSI offset for 38.4kBaud at 433 MHz is 74 */ - rssi = (int16_t) (recv_orig.rssi >> 1) - 74; + rssi = (int16_t) AO_RSSI_FROM_RADIO(recv_orig.rssi); ao_xmemcpy(callsign, recv_orig.telemetry_orig.callsign, AO_MAX_CALLSIGN); if (state > ao_flight_invalid) state = ao_flight_invalid; @@ -240,7 +239,7 @@ ao_monitor_put(void) putchar ('\n'); #if HAS_RSSI if (recv_raw.packet[ao_monitoring + 1] & PKT_APPEND_STATUS_1_CRC_OK) { - rssi = ((int16_t) recv_raw.packet[ao_monitoring] >> 1) - 74; + rssi = AO_RSSI_FROM_RADIO(recv_raw.packet[ao_monitoring]); ao_rssi_set(rssi); } #endif diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index a36d922c..569df3b7 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -729,7 +729,7 @@ ao_radio_recv(__xdata void *d, uint8_t size) /* Convert from 'real' rssi to cc1111-style values */ - rssi = (((int8_t) ao_radio_reg_read(CC1120_RSSI1)) + 74) * 2; + rssi = AO_RADIO_FROM_RSSI(ao_radio_reg_read(CC1120_RSSI1)); ao_radio_put(); @@ -998,7 +998,7 @@ ao_radio_test_recv() printf ("CRC OK"); else printf ("CRC BAD"); - printf (" RSSI %d", (int16_t) ((int8_t) bytes[32] >> 1) - 74); + printf (" RSSI %d", AO_RSSI_FROM_RADIO(bytes[32])); for (b = 0; b < 32; b++) printf (" %02x", bytes[b]); printf ("\n"); diff --git a/src/product/ao_terraui.c b/src/product/ao_terraui.c index 963c7be4..1866eb0c 100644 --- a/src/product/ao_terraui.c +++ b/src/product/ao_terraui.c @@ -594,7 +594,7 @@ ao_terramonitor(void) continue; if (!(ao_monitor_ring[monitor].all.status & PKT_APPEND_STATUS_1_CRC_OK)) continue; - ao_tel_rssi = (ao_monitor_ring[monitor].all.rssi >> 1) - 74; + ao_tel_rssi = AO_RSSI_FROM_RADIO(ao_monitor_ring[monitor].all.rssi); switch (ao_monitor_ring[monitor].all.telemetry.generic.type) { case AO_TELEMETRY_SENSOR_TELEMETRUM: case AO_TELEMETRY_SENSOR_TELEMINI: -- cgit v1.2.3 From cf44ea354c2d1780cee343132c6058e11e9eefa3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jul 2012 13:52:32 -0700 Subject: altos: Fix gcc compiler warnings in GPS code unused variables and mis-matches in printf format codes. Signed-off-by: Keith Packard --- src/core/ao_gps_print.c | 4 ++-- src/drivers/ao_gps_skytraq.c | 2 +- src/test/ao_gps_test.c | 7 ++++++- src/test/ao_gps_test_skytraq.c | 12 +++++++++--- 4 files changed, 18 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/core/ao_gps_print.c b/src/core/ao_gps_print.c index fcdedd30..47c945d7 100644 --- a/src/core/ao_gps_print.c +++ b/src/core/ao_gps_print.c @@ -40,8 +40,8 @@ ao_gps_print(__xdata struct ao_gps_orig *gps_data) __reentrant printf(AO_TELEM_GPS_LATITUDE " %ld " AO_TELEM_GPS_LONGITUDE " %ld " AO_TELEM_GPS_ALTITUDE " %d ", - gps_data->latitude, - gps_data->longitude, + (long) gps_data->latitude, + (long) gps_data->longitude, gps_data->altitude); if (gps_data->flags & AO_GPS_DATE_VALID) diff --git a/src/drivers/ao_gps_skytraq.c b/src/drivers/ao_gps_skytraq.c index 84616a05..d80da97c 100644 --- a/src/drivers/ao_gps_skytraq.c +++ b/src/drivers/ao_gps_skytraq.c @@ -480,7 +480,7 @@ gps_dump(void) __reentrant ao_mutex_get(&ao_gps_mutex); printf ("Date: %02d/%02d/%02d\n", ao_gps_data.year, ao_gps_data.month, ao_gps_data.day); printf ("Time: %02d:%02d:%02d\n", ao_gps_data.hour, ao_gps_data.minute, ao_gps_data.second); - printf ("Lat/Lon: %ld %ld\n", ao_gps_data.latitude, ao_gps_data.longitude); + printf ("Lat/Lon: %ld %ld\n", (long) ao_gps_data.latitude, (long) ao_gps_data.longitude); printf ("Alt: %d\n", ao_gps_data.altitude); printf ("Flags: 0x%x\n", ao_gps_data.flags); printf ("Sats: %d", ao_gps_tracking_data.channels); diff --git a/src/test/ao_gps_test.c b/src/test/ao_gps_test.c index 4d4012df..d75a12ec 100644 --- a/src/test/ao_gps_test.c +++ b/src/test/ao_gps_test.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #define AO_GPS_NUM_SAT_MASK (0xf << 0) #define AO_GPS_NUM_SAT_SHIFT (0) @@ -220,6 +221,8 @@ check_sirf_message(char *from, uint8_t *msg, int len) get_u16(h_v_error); + (void) mag_var; + (void) id; printf ("Geodetic Navigation Data (41):\n"); printf ("\tNav valid %04x\n", nav_valid); printf ("\tNav type %04x\n", nav_type); @@ -257,6 +260,7 @@ check_sirf_message(char *from, uint8_t *msg, int len) get_u32(gps_tow); get_u8(channels); + (void) id; printf ("Measured Tracker Data (4):\n"); printf ("GPS week: %d\n", gps_week); printf ("GPS time of week: %d\n", gps_tow); @@ -368,10 +372,11 @@ ao_serial1_putchar(char c) i = write(ao_gps_fd, &c, 1); if (i == 1) { if ((uint8_t) c == 0xb3 || c == '\r') { - static const struct timespec delay = { +/* static const struct timespec delay = { .tv_sec = 0, .tv_nsec = 100 * 1000 * 1000 }; +*/ tcdrain(ao_gps_fd); // nanosleep(&delay, NULL); } diff --git a/src/test/ao_gps_test_skytraq.c b/src/test/ao_gps_test_skytraq.c index 88bed305..846daa94 100644 --- a/src/test/ao_gps_test_skytraq.c +++ b/src/test/ao_gps_test_skytraq.c @@ -22,6 +22,7 @@ #include #include #include +#include #define AO_GPS_NUM_SAT_MASK (0xf << 0) #define AO_GPS_NUM_SAT_SHIFT (0) @@ -87,6 +88,7 @@ ao_mutex_put(uint8_t *mutex) static int ao_gps_fd; +#if 0 static void ao_dbg_char(char c) { @@ -102,6 +104,7 @@ ao_dbg_char(char c) } write(1, line, strlen(line)); } +#endif #define QUEUE_LEN 4096 @@ -222,6 +225,8 @@ check_skytraq_message(char *from, uint8_t *msg, int len) get_u16(h_v_error); + (void) mag_var; + (void) id; printf ("Geodetic Navigation Data (41):\n"); printf ("\tNav valid %04x\n", nav_valid); printf ("\tNav type %04x\n", nav_type); @@ -259,6 +264,7 @@ check_skytraq_message(char *from, uint8_t *msg, int len) get_u32(gps_tow); get_u8(channels); + (void) id; printf ("Measured Tracker Data (4):\n"); printf ("GPS week: %d\n", gps_week); printf ("GPS time of week: %d\n", gps_tow); @@ -371,10 +377,11 @@ ao_serial1_putchar(char c) i = write(ao_gps_fd, &c, 1); if (i == 1) { if ((uint8_t) c == 0xb3 || c == '\r') { - static const struct timespec delay = { +/* static const struct timespec delay = { .tv_sec = 0, .tv_nsec = 100 * 1000 * 1000 }; +*/ tcdrain(ao_gps_fd); // nanosleep(&delay, NULL); } @@ -422,8 +429,6 @@ ao_serial1_set_speed(uint8_t speed) void ao_dump_state(void *wchan) { - double lat, lon; - int i; if (wchan == &ao_gps_data) ao_gps_print(&ao_gps_data); else @@ -487,4 +492,5 @@ main (int argc, char **argv) exit (1); } ao_gps(); + return 0; } -- cgit v1.2.3 From 846a6298e4a8bfbe87bb24d7b0802c0bf6f233be Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jul 2012 13:53:30 -0700 Subject: Report RSSI values in monitor idle UI (trac #44) This adds a new 's' command to TeleDongle to report RSSI value from last received packet, and then has AltosUI request that value when closing the remote link. Signed-off-by: Keith Packard --- altosui/AltosIdleMonitorUI.java | 46 ++++++++++++++++++++++++++++------------- src/core/ao_packet.h | 2 ++ src/drivers/ao_packet.c | 11 ++++++---- src/drivers/ao_packet_master.c | 7 ++++++- 4 files changed, 47 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index 949e3926..eb6ec5e7 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -178,8 +178,23 @@ class AltosIdleMonitor extends Thread { AltosADC adc; AltosGPS gps; + int AltosRSSI() throws TimeoutException, InterruptedException { + serial.printf("s\n"); + String line = serial.get_reply_no_dialog(5000); + if (line == null) + throw new TimeoutException(); + String[] items = line.split("\\s+"); + if (items.length < 2) + return 0; + if (!items[0].equals("RSSI:")) + return 0; + int rssi = Integer.parseInt(items[1]); + return rssi; + } + void update_state() throws InterruptedException, TimeoutException { - AltosRecord record = new AltosRecord(); + AltosRecordTM record = new AltosRecordTM(); + int rssi; try { if (remote) { @@ -191,31 +206,34 @@ class AltosIdleMonitor extends Thread { adc = new AltosADC(serial); gps = new AltosGPSQuery(serial, config_data); } finally { - if (remote) + if (remote) { serial.stop_remote(); + rssi = AltosRSSI(); + } else + rssi = 0; } record.version = 0; record.callsign = config_data.callsign; record.serial = config_data.serial; record.flight = config_data.log_available() > 0 ? 255 : 0; - record.rssi = 0; + record.rssi = rssi; record.status = 0; record.state = Altos.ao_flight_idle; record.tick = adc.tick; -// record.accel = adc.accel; -// record.pres = adc.pres; -// record.batt = adc.batt; -// record.temp = adc.temp; -// record.drogue = adc.drogue; -// record.main = adc.main; - -// record.ground_accel = record.accel; -// record.ground_pres = record.pres; -// record.accel_plus_g = config_data.accel_cal_plus; -// record.accel_minus_g = config_data.accel_cal_minus; + record.accel = adc.accel; + record.pres = adc.pres; + record.batt = adc.batt; + record.temp = adc.temp; + record.drogue = adc.drogue; + record.main = adc.main; + + record.ground_accel = record.accel; + record.ground_pres = record.pres; + record.accel_plus_g = config_data.accel_cal_plus; + record.accel_minus_g = config_data.accel_cal_minus; record.acceleration = 0; record.speed = 0; record.height = 0; diff --git a/src/core/ao_packet.h b/src/core/ao_packet.h index 618ccda4..f232a878 100644 --- a/src/core/ao_packet.h +++ b/src/core/ao_packet.h @@ -67,6 +67,8 @@ ao_packet_pollchar(void) __critical; #if PACKET_HAS_MASTER /* ao_packet_master.c */ +extern __xdata uint8_t ao_packet_last_rssi; + void ao_packet_master_init(void); #endif diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c index e020c003..d813b25f 100644 --- a/src/drivers/ao_packet.c +++ b/src/drivers/ao_packet.c @@ -27,7 +27,11 @@ static __pdata uint8_t rx_seq; __xdata struct ao_task ao_packet_task; __xdata uint8_t ao_packet_enable; + +#if PACKET_HAS_MASTER __xdata uint8_t ao_packet_master_sleeping; +__xdata uint8_t ao_packet_last_rssi; +#endif void ao_packet_send(void) @@ -80,6 +84,9 @@ ao_packet_recv(void) if (!(ao_rx_packet.status & AO_RADIO_STATUS_CRC_OK)) return 0; +#if PACKET_HAS_MASTER + ao_packet_last_rssi = ao_rx_packet.rssi; +#endif /* Accept packets with matching call signs, or any packet if * our callsign hasn't been configured */ @@ -130,10 +137,6 @@ ao_packet_recv(void) return 1; } -#ifndef PACKET_HAS_MASTER -#define PACKET_HAS_MASTER 1 -#endif - #if PACKET_HAS_MASTER void ao_packet_flush(void) diff --git a/src/drivers/ao_packet_master.c b/src/drivers/ao_packet_master.c index 66f94288..e97a6648 100644 --- a/src/drivers/ao_packet_master.c +++ b/src/drivers/ao_packet_master.c @@ -137,10 +137,15 @@ ao_packet_forward(void) __reentrant #endif } - +static void +ao_packet_signal(void) +{ + printf ("RSSI: %d\n", AO_RSSI_FROM_RADIO(ao_packet_last_rssi)); +} __code struct ao_cmds ao_packet_master_cmds[] = { { ao_packet_forward, "p\0Remote packet link." }, + { ao_packet_signal, "s\0Report signal strength." }, { 0, NULL }, }; -- cgit v1.2.3 From 09633cac697e37d770b2b666ab20cab30628484f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jul 2012 01:24:14 -0700 Subject: altos/stm: Force STM stack to start at the top of RAM Using a fixed size means crashing if there's not enough space for that, or wasting memory if there's too much. Signed-off-by: Keith Packard --- src/stm/altos-ram.ld | 4 +--- src/stm/altos.ld | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/stm/altos-ram.ld b/src/stm/altos-ram.ld index b8fffedc..1143a08b 100644 --- a/src/stm/altos-ram.ld +++ b/src/stm/altos-ram.ld @@ -19,8 +19,6 @@ MEMORY { ram (rwx) : ORIGIN = 0x20000000, LENGTH = 16K } -C_STACK_SIZE = 512; - INCLUDE registers.ld SECTIONS { @@ -59,7 +57,7 @@ SECTIONS { __bss_end__ = .; } >ram - PROVIDE(__stack__ = . + C_STACK_SIZE); + PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram)); PROVIDE(end = .); } diff --git a/src/stm/altos.ld b/src/stm/altos.ld index 7fede558..f5a84f4c 100644 --- a/src/stm/altos.ld +++ b/src/stm/altos.ld @@ -23,7 +23,6 @@ MEMORY { INCLUDE registers.ld EXTERN (stm_interrupt_vector) -C_STACK_SIZE = 512; SECTIONS { . = ORIGIN(rom); @@ -62,7 +61,7 @@ SECTIONS { __bss_end__ = .; } >ram - PROVIDE(__stack__ = . + C_STACK_SIZE); + PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram)); PROVIDE(end = .); } -- cgit v1.2.3 From d90587535676f9492f0fde6b974353158104ef88 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jul 2012 01:26:38 -0700 Subject: altos: Add arbitrary pyro channel support Programmed by specifying a conjunction of flight conditions that trigger the igniter to fire. Signed-off-by: Keith Packard --- src/core/ao.h | 15 +- src/core/ao_config.c | 12 +- src/core/ao_flight.c | 6 + src/core/ao_flight.h | 4 + src/core/ao_pyro.c | 378 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/core/ao_pyro.h | 69 ++++++++++ 6 files changed, 481 insertions(+), 3 deletions(-) create mode 100644 src/core/ao_pyro.c create mode 100644 src/core/ao_pyro.h (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index eb2d47cf..d4be3be4 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -688,6 +688,10 @@ ao_igniter_init(void); * ao_config.c */ +#if AO_PYRO_NUM +#include +#endif + #if HAS_FORCE_FREQ /* * Set this to force the frequency to 434.550MHz @@ -696,7 +700,7 @@ extern __xdata uint8_t ao_force_freq; #endif #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 11 +#define AO_CONFIG_MINOR 12 #define AO_AES_LEN 16 @@ -718,6 +722,9 @@ struct ao_config { uint8_t aes_key[AO_AES_LEN]; /* minor version 9 */ uint32_t frequency; /* minor version 10 */ uint16_t apogee_lockout; /* minor version 11 */ +#if AO_PYRO_NUM + struct ao_pyro pyro[AO_PYRO_NUM]; /* minor version 12 */ +#endif }; #define AO_IGNITE_MODE_DUAL 0 @@ -731,6 +738,12 @@ extern __xdata struct ao_config ao_config; #define AO_CONFIG_MAX_SIZE 128 +void +_ao_config_edit_start(void); + +void +_ao_config_edit_finish(void); + void ao_config_get(void); diff --git a/src/core/ao_config.c b/src/core/ao_config.c index ced8b1f2..88fcc12d 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -131,6 +131,10 @@ _ao_config_get(void) ao_config.frequency = 434550; if (minor < 11) ao_config.apogee_lockout = 0; +#if AO_PYRO_NUM + if (minor < 12) + memset(&ao_config.pyro, '\0', sizeof (ao_config.pyro)); +#endif ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; } @@ -144,14 +148,14 @@ _ao_config_get(void) ao_config_loaded = 1; } -static void +void _ao_config_edit_start(void) { ao_mutex_get(&ao_config_mutex); _ao_config_get(); } -static void +void _ao_config_edit_finish(void) { ao_config_dirty = 1; @@ -537,6 +541,10 @@ __code struct ao_config_var ao_config_vars[] = { #if HAS_AES { "k <32 hex digits>\0Set AES encryption key", ao_config_key_set, ao_config_key_show }, +#endif +#if AO_PYRO_NUM + { "P \0Configure pyro channels", + ao_pyro_set, ao_pyro_show }, #endif { "s\0Show", ao_config_show, 0 }, diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index c6786455..fc018f00 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -40,6 +40,9 @@ __pdata enum ao_flight_state ao_flight_state; /* current flight state */ __pdata uint16_t ao_boost_tick; /* time of launch detect */ +#if AO_PYRO_NUM +__pdata uint16_t ao_motor_number; /* number of motors burned so far */ +#endif /* * track min/max data over a long interval to detect @@ -214,6 +217,9 @@ ao_flight(void) ao_coast_avg_accel = ao_accel; #else ao_flight_state = ao_flight_coast; +#endif +#if AO_PYRO_NUM + ++ao_motor_number; #endif ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } diff --git a/src/core/ao_flight.h b/src/core/ao_flight.h index aa5ab60d..c5c8af46 100644 --- a/src/core/ao_flight.h +++ b/src/core/ao_flight.h @@ -37,6 +37,10 @@ enum ao_flight_state { }; extern __pdata enum ao_flight_state ao_flight_state; +extern __pdata uint16_t ao_boost_tick; +#if AO_PYRO_NUM +extern __pdata uint16_t ao_motor_number; +#endif extern __pdata uint16_t ao_launch_time; extern __pdata uint8_t ao_flight_force_idle; diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c new file mode 100644 index 00000000..c060a866 --- /dev/null +++ b/src/core/ao_pyro.c @@ -0,0 +1,378 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include + +#define ao_lowbit(x) ((x) & (-x)) + +/* + * Given a pyro structure, figure out + * if the current flight state satisfies all + * of the requirements + */ +static uint8_t +ao_pyro_ready(struct ao_pyro *pyro) +{ + enum ao_pyro_flag flag, flags; + + flags = pyro->flags; + while (flags != ao_pyro_none) { + flag = ao_lowbit(flags); + flags &= ~flag; + switch (flag) { + + case ao_pyro_accel_less: + if (ao_accel <= pyro->accel_less) + continue; + break; + case ao_pyro_accel_greater: + if (ao_accel >= pyro->accel_greater) + continue; + break; + + + case ao_pyro_speed_less: + if (ao_speed <= pyro->speed_less) + continue; + break; + case ao_pyro_speed_greater: + if (ao_speed >= pyro->speed_greater) + continue; + break; + + case ao_pyro_height_less: + if (ao_height <= pyro->height_less) + continue; + break; + case ao_pyro_height_greater: + if (ao_height >= pyro->height_greater) + continue; + break; + + case ao_pyro_orient_less: +// if (ao_orient <= pyro->orient_less) + continue; + break; + case ao_pyro_orient_greater: +// if (ao_orient >= pyro->orient_greater) + continue; + break; + + case ao_pyro_time_less: + if ((int16_t) (ao_time() - ao_boost_tick) <= pyro->time_less) + continue; + break; + case ao_pyro_time_greater: + if ((int16_t) (ao_time() - ao_boost_tick) >= pyro->time_greater) + continue; + break; + + case ao_pyro_ascending: + if (ao_speed > 0) + continue; + break; + case ao_pyro_descending: + if (ao_speed < 0) + continue; + break; + + case ao_pyro_after_motor: + if (ao_motor_number == pyro->motor) + continue; + break; + + case ao_pyro_delay: + /* handled separately */ + continue; + + } + return FALSE; + } + return TRUE; +} + +#define ao_pyro_fire_port(port, pin) do { \ + ao_gpio_set(port, pin, 1); \ + ao_delay(AO_MS_TO_TICKS(50)); \ + ao_gpio_set(port, pin, 0); \ + } while (0) + + +static void +ao_pyro_fire(uint8_t p) +{ + switch (p) { +#if AO_PYRO_NUM > 0 + case 0: ao_pyro_fire_port(AO_PYRO_PORT_0, AO_PYRO_PIN_0); break; +#endif +#if AO_PYRO_NUM > 1 + case 1: ao_pyro_fire_port(AO_PYRO_PORT_1, AO_PYRO_PIN_1); break; +#endif +#if AO_PYRO_NUM > 2 + case 2: ao_pyro_fire_port(AO_PYRO_PORT_2, AO_PYRO_PIN_2); break; +#endif +#if AO_PYRO_NUM > 3 + case 3: ao_pyro_fire_port(AO_PYRO_PORT_3, AO_PYRO_PIN_3); break; +#endif +#if AO_PYRO_NUM > 4 + case 4: ao_pyro_fire_port(AO_PYRO_PORT_4, AO_PYRO_PIN_4); break; +#endif +#if AO_PYRO_NUM > 5 + case 5: ao_pyro_fire_port(AO_PYRO_PORT_5, AO_PYRO_PIN_5); break; +#endif +#if AO_PYRO_NUM > 6 + case 6: ao_pyro_fire_port(AO_PYRO_PORT_6, AO_PYRO_PIN_6); break; +#endif +#if AO_PYRO_NUM > 7 + case 7: ao_pyro_fire_port(AO_PYRO_PORT_7, AO_PYRO_PIN_7); break; +#endif + default: break; + } + ao_delay(AO_MS_TO_TICKS(50)); +} + +static void +ao_pyro(void) +{ + uint8_t p; + struct ao_pyro *pyro; + + ao_config_get(); + while (ao_flight_state < ao_flight_boost) + ao_sleep(&ao_flight_state); + + for (;;) { + ao_delay(AO_MS_TO_TICKS(100)); + for (p = 0; p < AO_PYRO_NUM; p++) { + pyro = &ao_config.pyro[p]; + + /* Ignore igniters which have already fired + */ + if (pyro->fired) + continue; + + /* Ignore disabled igniters + */ + if (!pyro->flags) + continue; + + /* Check pyro state to see if it shoule fire + */ + if (!pyro->delay_done) { + if (!ao_pyro_ready(pyro)) + continue; + + /* If there's a delay set, then remember when + * it expires + */ + if (pyro->flags & ao_pyro_delay) + pyro->delay_done = ao_time() + pyro->delay; + } + + /* Check to see if we're just waiting for + * the delay to expire + */ + if (pyro->delay_done) { + if ((int16_t) (ao_time() - pyro->delay_done) < 0) + continue; + } + + ao_pyro_fire(p); + } + } +} + +__xdata struct ao_task ao_pyro_task; + +#define NO_VALUE 0xff + +#define AO_PYRO_NAME_LEN 3 + +const struct { + char name[AO_PYRO_NAME_LEN]; + enum ao_pyro_flag flag; + uint8_t offset; + char *help; +} ao_pyro_values[] = { + { "a<", ao_pyro_accel_less, offsetof(struct ao_pyro, accel_less), "accel less (m/ss * 16)" }, + { "a>", ao_pyro_accel_greater, offsetof(struct ao_pyro, accel_greater), "accel greater (m/ss * 16)" }, + + { "s<", ao_pyro_speed_less, offsetof(struct ao_pyro, speed_less), "speed less (m/s * 16)" }, + { "s>", ao_pyro_speed_greater, offsetof(struct ao_pyro, speed_greater), "speed greater (m/s * 16)" }, + + { "h<", ao_pyro_height_less, offsetof(struct ao_pyro, height_less), "height less (m)" }, + { "h>", ao_pyro_height_greater, offsetof(struct ao_pyro, height_greater), "height greater (m)" }, + + { "o<", ao_pyro_orient_less, offsetof(struct ao_pyro, orient_less), "orient less (deg)" }, + { "o>", ao_pyro_orient_greater, offsetof(struct ao_pyro, orient_greater), "orient greater (deg)" }, + + { "t<", ao_pyro_time_less, offsetof(struct ao_pyro, time_less), "time less (s * 100)" }, + { "t>", ao_pyro_time_greater, offsetof(struct ao_pyro, time_greater), "time greater (s * 100)" }, + + { "A", ao_pyro_ascending, NO_VALUE, "ascending" }, + { "D", ao_pyro_descending, NO_VALUE, "descending" }, + + { "m", ao_pyro_after_motor, offsetof(struct ao_pyro, motor), "after motor" }, + + { "d", ao_pyro_delay, offsetof(struct ao_pyro, delay), "delay before firing (s * 100)" }, + { "", ao_pyro_none, NO_VALUE, NULL }, +}; + +static void +ao_pyro_print_name(uint8_t v) +{ + const char *s = ao_pyro_values[v].name; + printf ("%s%s", s, " " + strlen(s)); +} + +static void +ao_pyro_help(void) +{ + uint8_t v; + for (v = 0; ao_pyro_values[v].flag != ao_pyro_none; v++) { + ao_pyro_print_name(v); + if (ao_pyro_values[v].offset != NO_VALUE) + printf (" "); + else + printf (" "); + printf ("%s\n", ao_pyro_values[v].help); + } +} + +void +ao_pyro_show(void) +{ + uint8_t p; + uint8_t v; + struct ao_pyro *pyro; + + for (p = 0; p < AO_PYRO_NUM; p++) { + printf ("Pyro %2d: ", p); + pyro = &ao_config.pyro[p]; + if (!pyro->flags) { + printf ("\n"); + continue; + } + for (v = 0; ao_pyro_values[v].flag != ao_pyro_none; v++) { + if (!(pyro->flags & ao_pyro_values[v].flag)) + continue; + ao_pyro_print_name(v); + if (ao_pyro_values[v].offset != NO_VALUE) { + int16_t value; + + value = *((int16_t *) ((char *) pyro + ao_pyro_values[v].offset)); + printf ("%6d ", value); + } else { + printf (" "); + } + } + printf ("\n"); + } +} + +void +ao_pyro_set(void) +{ + uint8_t p; + struct ao_pyro *pyro; + struct ao_pyro pyro_tmp; + char name[AO_PYRO_NAME_LEN]; + uint8_t c; + uint8_t v; + + ao_cmd_white(); + switch (ao_cmd_lex_c) { + case '?': + ao_pyro_help(); + return; + } + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + p = ao_cmd_lex_i; + if (p < 0 || AO_PYRO_NUM <= p) { + printf ("invalid pyro channel %d\n", p); + return; + } + pyro_tmp.flags = 0; + for (;;) { + ao_cmd_white(); + if (ao_cmd_lex_c == '\n') + break; + + for (c = 0; c < AO_PYRO_NAME_LEN - 1; c++) { + if (ao_cmd_is_white()) + break; + name[c] = ao_cmd_lex_c; + ao_cmd_lex(); + } + name[c] = '\0'; + for (v = 0; ao_pyro_values[v].flag != ao_pyro_none; v++) { + if (!strcmp (ao_pyro_values[v].name, name)) + break; + } + if (ao_pyro_values[v].flag == ao_pyro_none) { + printf ("invalid pyro field %s\n", name); + ao_cmd_status = ao_cmd_syntax_error; + return; + } + pyro_tmp.flags |= ao_pyro_values[v].flag; + if (ao_pyro_values[v].offset != NO_VALUE) { + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + *((int16_t *) ((char *) &pyro_tmp + ao_pyro_values[v].offset)) = ao_cmd_lex_i; + } + } + _ao_config_edit_start(); + ao_config.pyro[p] = pyro_tmp; + _ao_config_edit_finish(); +} + +void +ao_pyro_init(void) +{ +#if AO_PYRO_NUM > 0 + ao_enable_output(AO_PYRO_PORT_0, AO_PYRO_PIN_0, 0); +#endif +#if AO_PYRO_NUM > 1 + ao_enable_output(AO_PYRO_PORT_1, AO_PYRO_PIN_1, 0); +#endif +#if AO_PYRO_NUM > 2 + ao_enable_output(AO_PYRO_PORT_2, AO_PYRO_PIN_2, 0); +#endif +#if AO_PYRO_NUM > 3 + ao_enable_output(AO_PYRO_PORT_3, AO_PYRO_PIN_3, 0); +#endif +#if AO_PYRO_NUM > 4 + ao_enable_output(AO_PYRO_PORT_4, AO_PYRO_PIN_4, 0); +#endif +#if AO_PYRO_NUM > 5 + ao_enable_output(AO_PYRO_PORT_5, AO_PYRO_PIN_5, 0); +#endif +#if AO_PYRO_NUM > 6 + ao_enable_output(AO_PYRO_PORT_6, AO_PYRO_PIN_6, 0); +#endif +#if AO_PYRO_NUM > 7 + ao_enable_output(AO_PYRO_PORT_7, AO_PYRO_PIN_7, 0); +#endif + ao_add_task(&ao_pyro_task, ao_pyro, "pyro"); +} diff --git a/src/core/ao_pyro.h b/src/core/ao_pyro.h new file mode 100644 index 00000000..1989a9e5 --- /dev/null +++ b/src/core/ao_pyro.h @@ -0,0 +1,69 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PYRO_H_ +#define _AO_PYRO_H_ + +enum ao_pyro_flag { + ao_pyro_none = 0x00000000, + + ao_pyro_accel_less = 0x00000001, + ao_pyro_accel_greater = 0x00000002, + + ao_pyro_speed_less = 0x00000004, + ao_pyro_speed_greater = 0x00000008, + + ao_pyro_height_less = 0x00000010, + ao_pyro_height_greater = 0x00000020, + + ao_pyro_orient_less = 0x00000040, + ao_pyro_orient_greater = 0x00000080, + + ao_pyro_time_less = 0x00000100, + ao_pyro_time_greater = 0x00000200, + + ao_pyro_ascending = 0x00000400, + ao_pyro_descending = 0x00000800, + + ao_pyro_after_motor = 0x00001000, + + ao_pyro_delay = 0x00002000, +}; + +struct ao_pyro { + enum ao_pyro_flag flags; + int16_t accel_less, accel_greater; + int16_t speed_less, speed_greater; + int16_t height_less, height_greater; + int16_t orient_less, orient_greater; + int16_t time_less, time_greater; + int16_t delay; + int16_t motor; + uint16_t delay_done; + uint8_t fired; +}; + +void +ao_pyro_set(void); + +void +ao_pyro_show(void); + +void +ao_pyro_init(void); + +#endif -- cgit v1.2.3 From 726e0f2c547b6bae1f1e640e2c1155c0b9631a9b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jul 2012 01:28:31 -0700 Subject: stm: running out of memory in MM -- reduce stack to 668 bytes Signed-off-by: Keith Packard --- src/stm/ao_arch.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index baae1902..d8fa3e89 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -25,7 +25,7 @@ * STM32L definitions and code fragments for AltOS */ -#define AO_STACK_SIZE 700 +#define AO_STACK_SIZE 668 #define AO_LED_TYPE uint16_t -- cgit v1.2.3 From 82b50fc1b7f2c6af7264fbad2c35508abc15e81e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jul 2012 01:28:55 -0700 Subject: altos/stm: Expose ao_gpio_set which sets a specific GPIO pin Will need versions for other architectures Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 7820bf79..4416bbab 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -76,9 +76,11 @@ ao_spi_init(void); } while (0) +#define ao_gpio_set(port, pin, v) stm_gpio_set(port, pin, v) + #define ao_enable_output(port,pin,v) do { \ ao_enable_port(port); \ - stm_gpio_set(port, pin, v); \ + ao_gpio_set(port, pin, v); \ stm_moder_set(port, pin, STM_MODER_OUTPUT); \ } while (0) -- cgit v1.2.3 From 37032e4b0cbac4c823e3dd18e60ad8900e9ceff1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jul 2012 01:29:50 -0700 Subject: altos/megametrum: Support the four additional pyro channels These use the new pyro code to allow for some flexibility in programming. Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 1 + src/megametrum-v0.1/ao_megametrum.c | 2 ++ src/megametrum-v0.1/ao_pins.h | 31 ++++++++++++++----------------- 3 files changed, 17 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 59cfb64d..d415b59b 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -74,6 +74,7 @@ ALTOS_SRC = \ ao_packet_slave.c \ ao_packet.c \ ao_companion.c \ + ao_pyro.c \ $(PROFILE) PRODUCT=MegaMetrum-v0.1 diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index a6d93733..55324514 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -23,6 +23,7 @@ #include #include #include +#include int main(void) @@ -67,6 +68,7 @@ main(void) ao_packet_slave_init(FALSE); ao_igniter_init(); ao_companion_init(); + ao_pyro_init(); ao_config_init(); #if AO_PROFILE diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 34b75255..2c438f6c 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -120,29 +120,26 @@ #define AO_IGNITER_CLOSED 400 #define AO_IGNITER_OPEN 60 -#define AO_IGNITER_PORT_A (&stm_gpiod) -#define AO_IGNITER_PIN_A 6 +#define AO_IGNITER_DROGUE_PORT (&stm_gpiod) +#define AO_IGNITER_DROGUE_PIN 6 -#define AO_IGNITER_PORT_B (&stm_gpiod) -#define AO_IGNITER_PIN_B 7 +#define AO_IGNITER_MAIN_PORT (&stm_gpiod) +#define AO_IGNITER_MAIN_PIN 7 -#define AO_IGNITER_PORT_C (&stm_gpiob) -#define AO_IGNITER_PIN_C 5 +#define AO_PYRO_PORT_0 (&stm_gpiob) +#define AO_PYRO_PIN_0 5 -#define AO_IGNITER_PORT_D (&stm_gpioe) -#define AO_IGNITER_PIN_D 4 +#define AO_PYRO_PORT_1 (&stm_gpioe) +#define AO_PYRO_PIN_1 4 -#define AO_IGNITER_PORT_E (&stm_gpioe) -#define AO_IGNITER_PIN_E 6 +#define AO_PYRO_PORT_2 (&stm_gpioe) +#define AO_PYRO_PIN_2 6 -#define AO_IGNITER_PORT_F (&stm_gpioe) -#define AO_IGNITER_PIN_F 5 +#define AO_PYRO_PORT_3 (&stm_gpioe) +#define AO_PYRO_PIN_3 5 -#define AO_IGNITER_DROGUE_PORT AO_IGNITER_PORT_A -#define AO_IGNITER_DROGUE_PIN AO_IGNITER_PIN_A - -#define AO_IGNITER_MAIN_PORT AO_IGNITER_PORT_B -#define AO_IGNITER_MAIN_PIN AO_IGNITER_PIN_B +/* Number of general purpose pyro channels available */ +#define AO_PYRO_NUM 4 #define AO_IGNITER_SET_DROGUE(v) stm_gpio_set(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, v) #define AO_IGNITER_SET_MAIN(v) stm_gpio_set(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, v) -- cgit v1.2.3 From 0cfd22baa6af44e053428c30c1a95cf5551b68af Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Jul 2012 02:44:17 -0700 Subject: src: Add explicit 'pin' argument to ao_enable_output This lets the cc1111 use the atomic bit operation instead of a mask, which is immune to interrupt issues as well as being a shorter code sequence. Signed-off-by: Keith Packard --- src/avr/ao_arch_funcs.h | 17 +++++++++++++++++ src/cc1111/ao_arch_funcs.h | 12 ++++++------ src/core/ao_ignite.c | 4 ++-- src/core/ao_pyro.c | 41 +++++++++++++++++++++-------------------- src/drivers/ao_25lc1024.c | 2 +- src/drivers/ao_companion.c | 2 +- src/stm/ao_arch_funcs.h | 8 ++++---- 7 files changed, 52 insertions(+), 34 deletions(-) (limited to 'src') diff --git a/src/avr/ao_arch_funcs.h b/src/avr/ao_arch_funcs.h index e400c98b..792ff744 100644 --- a/src/avr/ao_arch_funcs.h +++ b/src/avr/ao_arch_funcs.h @@ -41,12 +41,29 @@ extern __xdata uint8_t ao_spi_mutex; ao_mutex_put(&ao_spi_mutex); \ } while (0) + +#define ao_gpio_token_paster(x,y) x ## y +#define ao_gpio_token_evaluator(x,y) ao_gpio_token_paster(x,y) + +#define ao_gpio_set(port, bit, pin, v) do { \ + if (v) \ + (ao_gpio_token_evaluator(PORT,port)) |= (1 << bit); \ + else \ + (ao_gpio_token_evaluator(PORT,port)) &= ~(1 << bit); \ + } while (0) + /* * The SPI mutex must be held to call either of these * functions -- this mutex covers the entire SPI operation, * from chip select low to chip select high */ +#define ao_enable_output(port, bit, pin, v) do { \ + ao_gpio_set(port, bit, pin, v); \ + ao_gpio_token_evaluator(DDR,port) |= (1 << bit); \ + } while (0) + + void ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant; diff --git a/src/cc1111/ao_arch_funcs.h b/src/cc1111/ao_arch_funcs.h index 0a322961..0737e7ab 100644 --- a/src/cc1111/ao_arch_funcs.h +++ b/src/cc1111/ao_arch_funcs.h @@ -77,14 +77,14 @@ ao_spi_init(void); SPI_CS_SEL &= ~mask; \ } while (0) -#define cc1111_enable_output(port,dir,sel,mask,v) do { \ - port = port & ~(mask) | v; \ - dir |= mask; \ - sel &= ~mask; \ -} while (0) +#define cc1111_enable_output(port,dir,sel,pin,bit,v) do { \ + pin = v; \ + dir |= (1 << bit); \ + sel &= ~(1 << bit); \ + } while (0) #define disable_unreachable _Pragma("disable_warning 126") #define token_paster(x,y) x ## y #define token_evaluator(x,y) token_paster(x,y) -#define ao_enable_output(port,pin,v) cc1111_enable_output(port,token_evaluator(port,DIR), token_evaluator(port,SEL), 1 << pin, 1 << v) +#define ao_enable_output(port,bit,pin,v) cc1111_enable_output(port,token_evaluator(port,DIR), token_evaluator(port,SEL), pin, bit, v) diff --git a/src/core/ao_ignite.c b/src/core/ao_ignite.c index e82de355..c7829fc3 100644 --- a/src/core/ao_ignite.c +++ b/src/core/ao_ignite.c @@ -195,8 +195,8 @@ __xdata struct ao_task ao_igniter_task; void ao_ignite_set_pins(void) { - ao_enable_output(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, 0); - ao_enable_output(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, 0); + ao_enable_output(AO_IGNITER_DROGUE_PORT, AO_IGNITER_DROGUE_PIN, AO_IGNITER_DROGUE, 0); + ao_enable_output(AO_IGNITER_MAIN_PORT, AO_IGNITER_MAIN_PIN, AO_IGNITER_MAIN, 0); } void diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index c060a866..943413e6 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -102,16 +102,18 @@ ao_pyro_ready(struct ao_pyro *pyro) /* handled separately */ continue; + case ao_pyro_none: + break; } return FALSE; } return TRUE; } -#define ao_pyro_fire_port(port, pin) do { \ - ao_gpio_set(port, pin, 1); \ +#define ao_pyro_fire_port(port, bit, pin) do { \ + ao_gpio_set(port, bit, pin, 1); \ ao_delay(AO_MS_TO_TICKS(50)); \ - ao_gpio_set(port, pin, 0); \ + ao_gpio_set(port, bit, pin, 0); \ } while (0) @@ -120,28 +122,28 @@ ao_pyro_fire(uint8_t p) { switch (p) { #if AO_PYRO_NUM > 0 - case 0: ao_pyro_fire_port(AO_PYRO_PORT_0, AO_PYRO_PIN_0); break; + case 0: ao_pyro_fire_port(AO_PYRO_PORT_0, AO_PYRO_PIN_0, AO_PYRO_0); break; #endif #if AO_PYRO_NUM > 1 - case 1: ao_pyro_fire_port(AO_PYRO_PORT_1, AO_PYRO_PIN_1); break; + case 1: ao_pyro_fire_port(AO_PYRO_PORT_1, AO_PYRO_PIN_1, AO_PYRO_1); break; #endif #if AO_PYRO_NUM > 2 - case 2: ao_pyro_fire_port(AO_PYRO_PORT_2, AO_PYRO_PIN_2); break; + case 2: ao_pyro_fire_port(AO_PYRO_PORT_2, AO_PYRO_PIN_2, AO_PYRO_2); break; #endif #if AO_PYRO_NUM > 3 - case 3: ao_pyro_fire_port(AO_PYRO_PORT_3, AO_PYRO_PIN_3); break; + case 3: ao_pyro_fire_port(AO_PYRO_PORT_3, AO_PYRO_PIN_3, AO_PYRO_3); break; #endif #if AO_PYRO_NUM > 4 - case 4: ao_pyro_fire_port(AO_PYRO_PORT_4, AO_PYRO_PIN_4); break; + case 4: ao_pyro_fire_port(AO_PYRO_PORT_4, AO_PYRO_PIN_4, AO_PYRO_4); break; #endif #if AO_PYRO_NUM > 5 - case 5: ao_pyro_fire_port(AO_PYRO_PORT_5, AO_PYRO_PIN_5); break; + case 5: ao_pyro_fire_port(AO_PYRO_PORT_5, AO_PYRO_PIN_5, AO_PYRO_5); break; #endif #if AO_PYRO_NUM > 6 - case 6: ao_pyro_fire_port(AO_PYRO_PORT_6, AO_PYRO_PIN_6); break; + case 6: ao_pyro_fire_port(AO_PYRO_PORT_6, AO_PYRO_PIN_6, AO_PYRO_6); break; #endif #if AO_PYRO_NUM > 7 - case 7: ao_pyro_fire_port(AO_PYRO_PORT_7, AO_PYRO_PIN_7); break; + case 7: ao_pyro_fire_port(AO_PYRO_PORT_7, AO_PYRO_PIN_7, AO_PYRO_7); break; #endif default: break; } @@ -291,7 +293,6 @@ void ao_pyro_set(void) { uint8_t p; - struct ao_pyro *pyro; struct ao_pyro pyro_tmp; char name[AO_PYRO_NAME_LEN]; uint8_t c; @@ -351,28 +352,28 @@ void ao_pyro_init(void) { #if AO_PYRO_NUM > 0 - ao_enable_output(AO_PYRO_PORT_0, AO_PYRO_PIN_0, 0); + ao_enable_output(AO_PYRO_PORT_0, AO_PYRO_PIN_0, AO_PYRO_0, 0); #endif #if AO_PYRO_NUM > 1 - ao_enable_output(AO_PYRO_PORT_1, AO_PYRO_PIN_1, 0); + ao_enable_output(AO_PYRO_PORT_1, AO_PYRO_PIN_1, AO_PYRO_1, 0); #endif #if AO_PYRO_NUM > 2 - ao_enable_output(AO_PYRO_PORT_2, AO_PYRO_PIN_2, 0); + ao_enable_output(AO_PYRO_PORT_2, AO_PYRO_PIN_2, AO_PYRO_2, 0); #endif #if AO_PYRO_NUM > 3 - ao_enable_output(AO_PYRO_PORT_3, AO_PYRO_PIN_3, 0); + ao_enable_output(AO_PYRO_PORT_3, AO_PYRO_PIN_3, AO_PYRO_3, 0); #endif #if AO_PYRO_NUM > 4 - ao_enable_output(AO_PYRO_PORT_4, AO_PYRO_PIN_4, 0); + ao_enable_output(AO_PYRO_PORT_4, AO_PYRO_PIN_4, AO_PYRO_4, 0); #endif #if AO_PYRO_NUM > 5 - ao_enable_output(AO_PYRO_PORT_5, AO_PYRO_PIN_5, 0); + ao_enable_output(AO_PYRO_PORT_5, AO_PYRO_PIN_5, AO_PYRO_5, 0); #endif #if AO_PYRO_NUM > 6 - ao_enable_output(AO_PYRO_PORT_6, AO_PYRO_PIN_6, 0); + ao_enable_output(AO_PYRO_PORT_6, AO_PYRO_PIN_6, AO_PYRO_6, 0); #endif #if AO_PYRO_NUM > 7 - ao_enable_output(AO_PYRO_PORT_7, AO_PYRO_PIN_7, 0); + ao_enable_output(AO_PYRO_PORT_7, AO_PYRO_PIN_7, AO_PYRO_7, 0); #endif ao_add_task(&ao_pyro_task, ao_pyro, "pyro"); } diff --git a/src/drivers/ao_25lc1024.c b/src/drivers/ao_25lc1024.c index c5d811f7..fac0a430 100644 --- a/src/drivers/ao_25lc1024.c +++ b/src/drivers/ao_25lc1024.c @@ -236,5 +236,5 @@ void ao_storage_device_init(void) { /* set up CS */ - ao_enable_output(EE_CS_PORT, EE_CS_PIN,1); + ao_enable_output(EE_CS_PORT, EE_CS_PIN, EE_CS, 1); } diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index 85d68c44..a3167956 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -131,7 +131,7 @@ static __xdata struct ao_task ao_companion_task; void ao_companion_init(void) { - ao_enable_output(AO_COMPANION_CS_PORT, AO_COMPANION_CS_PIN, 1); + ao_enable_output(AO_COMPANION_CS_PORT, AO_COMPANION_CS_PIN, AO_COMPANION_CS, 1); ao_cmd_register(&ao_companion_cmds[0]); ao_add_task(&ao_companion_task, ao_companion, "companion"); } diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 4416bbab..d2c973f5 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -76,12 +76,12 @@ ao_spi_init(void); } while (0) -#define ao_gpio_set(port, pin, v) stm_gpio_set(port, pin, v) +#define ao_gpio_set(port, bit, pin, v) stm_gpio_set(port, bit, v) -#define ao_enable_output(port,pin,v) do { \ +#define ao_enable_output(port,bit,pin,v) do { \ ao_enable_port(port); \ - ao_gpio_set(port, pin, v); \ - stm_moder_set(port, pin, STM_MODER_OUTPUT); \ + ao_gpio_set(port, bit, pin, v); \ + stm_moder_set(port, bit, STM_MODER_OUTPUT);\ } while (0) #define ao_enable_cs(port,bit) do { \ -- cgit v1.2.3 From 42a51becf4b76f23dbd4f5f80f8879ce696aa543 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 14:36:51 -0700 Subject: altos/avr: Remove debugging printf in avr stdio startup Signed-off-by: Keith Packard --- src/avr/ao_avr_stdio.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/avr/ao_avr_stdio.c b/src/avr/ao_avr_stdio.c index ba562dbf..2765853a 100644 --- a/src/avr/ao_avr_stdio.c +++ b/src/avr/ao_avr_stdio.c @@ -48,5 +48,4 @@ ao_avr_stdio_init(void) { stdout = &mystdout; stdin = &mystdin; - printf("%d stdios registered\n", ao_num_stdios); } -- cgit v1.2.3 From 81b7b58c9df01847fa47747deeff8c3c91304ad1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 14:37:58 -0700 Subject: altos/avr: Remove debugging command from USB driver Signed-off-by: Keith Packard --- src/avr/ao_usb_avr.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'src') diff --git a/src/avr/ao_usb_avr.c b/src/avr/ao_usb_avr.c index 23a27c73..9ba407af 100644 --- a/src/avr/ao_usb_avr.c +++ b/src/avr/ao_usb_avr.c @@ -658,18 +658,6 @@ ao_usb_echo(void) } #endif -static void -ao_usb_irq(void) -{ - printf ("control: %d out: %d in: %d\n", - control_count, out_count, in_count); -} - -__code struct ao_cmds ao_usb_cmds[] = { - { ao_usb_irq, "i\0Show USB interrupt counts" }, - { 0, NULL } -}; - void ao_usb_init(void) { @@ -680,6 +668,5 @@ ao_usb_init(void) #if USB_DEBUG ao_add_task(&ao_usb_echo_task, ao_usb_echo, "usb echo"); #endif - ao_cmd_register(&ao_usb_cmds[0]); ao_add_stdio(ao_usb_pollchar, ao_usb_putchar, ao_usb_flush); } -- cgit v1.2.3 From 366217e86a4c353012b5102322ee6927f7b27a21 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 14:39:05 -0700 Subject: altos: Remove unused 'func' from ao_config_set Signed-off-by: Keith Packard --- src/core/ao_config.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src') diff --git a/src/core/ao_config.c b/src/core/ao_config.c index 88fcc12d..e2095e65 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -562,12 +562,10 @@ ao_config_set(void) { char c; uint8_t cmd; - void (*__xdata func)(void) __reentrant; ao_cmd_white(); c = ao_cmd_lex_c; ao_cmd_lex(); - func = 0; for (cmd = 0; ao_config_vars[cmd].str != NULL; cmd++) if (ao_config_vars[cmd].str[0] == c) { (*ao_config_vars[cmd].set)(); -- cgit v1.2.3 From 2a23030031c31267fc4f14accd9220f285c03b61 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 14:40:49 -0700 Subject: altos: No space for pyro help on TP v0.1 AVR doesn't have enough ram to hold the help messages, and we can't use them in flash. Signed-off-by: Keith Packard --- src/core/ao_pyro.c | 49 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 34 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index 943413e6..b0d45162 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -207,34 +207,48 @@ __xdata struct ao_task ao_pyro_task; #define AO_PYRO_NAME_LEN 3 +#if !DISABLE_HELP +#define ENABLE_HELP 1 +#endif + +#if ENABLE_HELP +#define HELP(s) (s) +#else +#define HELP(s) +#endif + const struct { char name[AO_PYRO_NAME_LEN]; enum ao_pyro_flag flag; uint8_t offset; +#if ENABLE_HELP char *help; +#endif } ao_pyro_values[] = { - { "a<", ao_pyro_accel_less, offsetof(struct ao_pyro, accel_less), "accel less (m/ss * 16)" }, - { "a>", ao_pyro_accel_greater, offsetof(struct ao_pyro, accel_greater), "accel greater (m/ss * 16)" }, + { "a<", ao_pyro_accel_less, offsetof(struct ao_pyro, accel_less), HELP("accel less (m/ss * 16)") }, + { "a>", ao_pyro_accel_greater, offsetof(struct ao_pyro, accel_greater), HELP("accel greater (m/ss * 16)") }, - { "s<", ao_pyro_speed_less, offsetof(struct ao_pyro, speed_less), "speed less (m/s * 16)" }, - { "s>", ao_pyro_speed_greater, offsetof(struct ao_pyro, speed_greater), "speed greater (m/s * 16)" }, + { "s<", ao_pyro_speed_less, offsetof(struct ao_pyro, speed_less), HELP("speed less (m/s * 16)") }, + { "s>", ao_pyro_speed_greater, offsetof(struct ao_pyro, speed_greater), HELP("speed greater (m/s * 16)") }, - { "h<", ao_pyro_height_less, offsetof(struct ao_pyro, height_less), "height less (m)" }, - { "h>", ao_pyro_height_greater, offsetof(struct ao_pyro, height_greater), "height greater (m)" }, + { "h<", ao_pyro_height_less, offsetof(struct ao_pyro, height_less), HELP("height less (m)") }, + { "h>", ao_pyro_height_greater, offsetof(struct ao_pyro, height_greater), HELP("height greater (m)") }, - { "o<", ao_pyro_orient_less, offsetof(struct ao_pyro, orient_less), "orient less (deg)" }, - { "o>", ao_pyro_orient_greater, offsetof(struct ao_pyro, orient_greater), "orient greater (deg)" }, +#if 0 + { "o<", ao_pyro_orient_less, offsetof(struct ao_pyro, orient_less), HELP("orient less (deg)") }, + { "o>", ao_pyro_orient_greater, offsetof(struct ao_pyro, orient_greater), HELP("orient greater (deg)") }, +#endif - { "t<", ao_pyro_time_less, offsetof(struct ao_pyro, time_less), "time less (s * 100)" }, - { "t>", ao_pyro_time_greater, offsetof(struct ao_pyro, time_greater), "time greater (s * 100)" }, + { "t<", ao_pyro_time_less, offsetof(struct ao_pyro, time_less), HELP("time less (s * 100)") }, + { "t>", ao_pyro_time_greater, offsetof(struct ao_pyro, time_greater), HELP("time greater (s * 100)") }, - { "A", ao_pyro_ascending, NO_VALUE, "ascending" }, - { "D", ao_pyro_descending, NO_VALUE, "descending" }, + { "A", ao_pyro_ascending, NO_VALUE, HELP("ascending") }, + { "D", ao_pyro_descending, NO_VALUE, HELP("descending") }, - { "m", ao_pyro_after_motor, offsetof(struct ao_pyro, motor), "after motor" }, + { "m", ao_pyro_after_motor, offsetof(struct ao_pyro, motor), HELP("after motor") }, - { "d", ao_pyro_delay, offsetof(struct ao_pyro, delay), "delay before firing (s * 100)" }, - { "", ao_pyro_none, NO_VALUE, NULL }, + { "d", ao_pyro_delay, offsetof(struct ao_pyro, delay), HELP("delay before firing (s * 100)") }, + { "", ao_pyro_none, NO_VALUE, HELP(NULL) }, }; static void @@ -244,6 +258,7 @@ ao_pyro_print_name(uint8_t v) printf ("%s%s", s, " " + strlen(s)); } +#if ENABLE_HELP static void ao_pyro_help(void) { @@ -257,6 +272,7 @@ ao_pyro_help(void) printf ("%s\n", ao_pyro_values[v].help); } } +#endif void ao_pyro_show(void) @@ -299,11 +315,14 @@ ao_pyro_set(void) uint8_t v; ao_cmd_white(); + +#if ENABLE_HELP switch (ao_cmd_lex_c) { case '?': ao_pyro_help(); return; } +#endif ao_cmd_decimal(); if (ao_cmd_status != ao_cmd_success) -- cgit v1.2.3 From 84d5e00d417af4924594908d19346bb965089cdd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 14:44:40 -0700 Subject: src: Add driver for AVR internal eeprom. Use for telepyro config. Signed-off-by: Keith Packard --- src/avr/ao_eeprom_avr.c | 133 +++++++++++++++++++++++++++++++++++++++++++++ src/avr/ao_pins.h | 6 ++ src/telepyro-v0.1/Makefile | 16 +++--- 3 files changed, 148 insertions(+), 7 deletions(-) create mode 100644 src/avr/ao_eeprom_avr.c (limited to 'src') diff --git a/src/avr/ao_eeprom_avr.c b/src/avr/ao_eeprom_avr.c new file mode 100644 index 00000000..2451fa8a --- /dev/null +++ b/src/avr/ao_eeprom_avr.c @@ -0,0 +1,133 @@ +/* + * Copyright © 2012 Keith Packard + * Copyright © 2011 Anthony Towns + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +/* Total bytes of available storage */ +__pdata ao_pos_t ao_storage_total = 1024; + +/* Block size - device is erased in these units. */ +__pdata ao_pos_t ao_storage_block = 1024; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +__pdata ao_pos_t ao_storage_config = 0; + +/* Storage unit size - device reads and writes must be within blocks of this size. */ +__pdata uint16_t ao_storage_unit = 1024; + +/* + * The internal flash chip is arranged in 8 byte sectors; the + * chip cannot erase in units smaller than that. + * + * Writing happens in units of 2 bytes and + * can only change bits from 1 to 0. So, you can rewrite + * the same contents, or append to an existing page easily enough + */ + +/* + * Erase the specified sector + */ +uint8_t +ao_storage_erase(ao_pos_t pos) __reentrant +{ + /* Not necessary */ + return 1; +} + +#define ao_intflash_wait_idle() do { \ + /* Wait for any outstanding writes to complete */ \ + while (EECR & (1 << EEPE)) \ + ; \ + } while (0) \ + +static void +ao_intflash_write(uint16_t pos, uint8_t d) +{ + ao_intflash_wait_idle(); + EEAR = pos; + EEDR = d; + ao_arch_critical( + EECR |= (1 << EEMPE); + EECR |= (1 << EEPE); + ); +} + +static uint8_t +ao_intflash_read(uint16_t pos) +{ + ao_intflash_wait_idle(); + EEAR = pos; + + EECR |= (1 << EERE); + return EEDR; +} +/* + * Write to flash + */ + +uint8_t +ao_storage_device_write(ao_pos_t pos32, __xdata void *v, uint16_t len) __reentrant +{ + uint16_t pos = pos32; + __xdata uint8_t *d = v; + + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + + while (len--) + ao_intflash_write(pos++, *d++); + + return 1; +} + +/* + * Read from flash + */ +uint8_t +ao_storage_device_read(ao_pos_t pos, __xdata void *v, uint16_t len) __reentrant +{ + uint8_t *d = v; + + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + while (len--) + *d++ = ao_intflash_read(pos++); + return 1; +} + +void +ao_storage_flush(void) __reentrant +{ +} + +void +ao_storage_setup(void) +{ +} + +void +ao_storage_device_info(void) __reentrant +{ + printf ("Using internal flash\n"); +} + +void +ao_storage_device_init(void) +{ +} diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index 850a08ec..3c9010a8 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -72,6 +72,12 @@ #define HAS_ADC 1 #define PACKET_HAS_SLAVE 0 #define HAS_BEEP 0 + #define HAS_EEPROM 1 + #define USE_INTERNAL_FLASH 1 + #define DISABLE_HELP 1 + #define HAS_STORAGE_DEBUG 0 + #define IS_COMPANION 1 + #define ao_storage_pos_t uint16_t #define AVR_VCC_5V 0 #define AVR_VCC_3V3 1 diff --git a/src/telepyro-v0.1/Makefile b/src/telepyro-v0.1/Makefile index 2ac7e747..bc57b9d7 100644 --- a/src/telepyro-v0.1/Makefile +++ b/src/telepyro-v0.1/Makefile @@ -22,7 +22,8 @@ INC = \ ao.h \ ao_usb.h \ ao_pins.h \ - altitude.h + ao_arch.h \ + ao_arch_funcs.h ALTOS_SRC = \ ao_clock.c \ @@ -39,14 +40,18 @@ ALTOS_SRC = \ ao_usb_avr.c \ ao_adc_avr.c \ ao_pyro_slave.c \ - ao_spi_slave.c + ao_spi_slave.c \ + ao_eeprom_avr.c \ + ao_storage.c \ + ao_config.c \ + ao_pyro.c PRODUCT=TelePyro-v0.1 MCU=atmega32u4 PRODUCT_DEF=-DTELEPYRO IDPRODUCT=0x0011 CFLAGS = $(PRODUCT_DEF) -I. -I../avr -I../core -I.. -CFLAGS += -g -mmcu=$(MCU) -Wall -Wstrict-prototypes -O3 -mcall-prologues -DAVR +CFLAGS += -mmcu=$(MCU) -Wall -Wstrict-prototypes -O3 -mcall-prologues -DAVR NICKLE=nickle @@ -79,9 +84,6 @@ $(PROG).hex: $(PROG) load: $(PROG).hex $(LOADCMD) $(LOADARG)$(PROG).hex -../altitude.h: make-altitude - nickle $< > $@ - ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ @@ -100,4 +102,4 @@ install: uninstall: -$(OBJ): ao.h ao_product.h ao_usb.h +$(OBJ): $(INC) -- cgit v1.2.3 From 4de789331098abc24abcb9390a35aef889a41784 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 14:47:53 -0700 Subject: altos: Make storage addresses datatype configurable No sense using 32 bits for tiny hardware Signed-off-by: Keith Packard --- src/core/ao_storage.c | 8 ++++---- src/core/ao_storage.h | 22 ++++++++++++++-------- 2 files changed, 18 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/core/ao_storage.c b/src/core/ao_storage.c index 66394e01..b2dd435b 100644 --- a/src/core/ao_storage.c +++ b/src/core/ao_storage.c @@ -18,7 +18,7 @@ #include uint8_t -ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +ao_storage_read(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant { uint16_t this_len; uint16_t this_off; @@ -48,7 +48,7 @@ ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant } uint8_t -ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant +ao_storage_write(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant { uint16_t this_len; uint16_t this_off; @@ -161,8 +161,8 @@ void ao_storage_info(void) __reentrant { ao_storage_setup(); - printf("Storage size: %ld\n", ao_storage_total); - printf("Storage erase unit: %ld\n", ao_storage_block); + printf("Storage size: %ld\n", (long) ao_storage_total); + printf("Storage erase unit: %ld\n", (long) ao_storage_block); ao_storage_device_info(); } diff --git a/src/core/ao_storage.h b/src/core/ao_storage.h index 873fe097..ea946399 100644 --- a/src/core/ao_storage.h +++ b/src/core/ao_storage.h @@ -23,14 +23,20 @@ * drivers */ +#ifndef ao_storage_pos_t +#define ao_storage_pos_t uint32_t +#endif + +typedef ao_storage_pos_t ao_pos_t; + /* Total bytes of available storage */ -extern __pdata uint32_t ao_storage_total; +extern __pdata ao_pos_t ao_storage_total; /* Block size - device is erased in these units. At least 256 bytes */ -extern __pdata uint32_t ao_storage_block; +extern __pdata ao_pos_t ao_storage_block; /* Byte offset of config block. Will be ao_storage_block bytes long */ -extern __pdata uint32_t ao_storage_config; +extern __pdata ao_pos_t ao_storage_config; /* Storage unit size - device reads and writes must be within blocks of this size. Usually 256 bytes. */ extern __pdata uint16_t ao_storage_unit; @@ -43,15 +49,15 @@ ao_storage_setup(void) __reentrant; /* Write data. Returns 0 on failure, 1 on success */ uint8_t -ao_storage_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; +ao_storage_write(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant; /* Read data. Returns 0 on failure, 1 on success */ uint8_t -ao_storage_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; +ao_storage_read(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant; /* Erase a block of storage. This always clears ao_storage_block bytes */ uint8_t -ao_storage_erase(uint32_t pos) __reentrant; +ao_storage_erase(ao_pos_t pos) __reentrant; /* Flush any pending writes to stable storage */ void @@ -67,11 +73,11 @@ ao_storage_init(void); /* Read data within a storage unit */ uint8_t -ao_storage_device_read(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; +ao_storage_device_read(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant; /* Write data within a storage unit */ uint8_t -ao_storage_device_write(uint32_t pos, __xdata void *buf, uint16_t len) __reentrant; +ao_storage_device_write(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant; /* Initialize low-level device bits */ void -- cgit v1.2.3 From e7ca3a7849b3cbbb38143d35fe86972290bd4e61 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:18:12 -0700 Subject: altos: Make sure telepyro ao_product.h is built before .o files Signed-off-by: Keith Packard --- src/telepyro-v0.1/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/telepyro-v0.1/Makefile b/src/telepyro-v0.1/Makefile index bc57b9d7..2ccd565f 100644 --- a/src/telepyro-v0.1/Makefile +++ b/src/telepyro-v0.1/Makefile @@ -2,7 +2,7 @@ # AltOS build # # -vpath % ..:../core:../product:../drivers:../avr +vpath % .:..:../core:../product:../drivers:../avr vpath ao-make-product.5c ../util MCU=atmega32u4 @@ -23,7 +23,8 @@ INC = \ ao_usb.h \ ao_pins.h \ ao_arch.h \ - ao_arch_funcs.h + ao_arch_funcs.h \ + ao_product.h ALTOS_SRC = \ ao_clock.c \ -- cgit v1.2.3 From 184e2ff4790974733df57facdeeb96bfe692ab54 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:21:21 -0700 Subject: altos: Remove some debug code from avr ADC driver Signed-off-by: Keith Packard --- src/avr/ao_adc_avr.c | 25 ++----------------------- 1 file changed, 2 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/avr/ao_adc_avr.c b/src/avr/ao_adc_avr.c index 928cd3e1..3a262977 100644 --- a/src/avr/ao_adc_avr.c +++ b/src/avr/ao_adc_avr.c @@ -125,42 +125,21 @@ ao_adc_dump(void) __reentrant static __xdata struct ao_data packet; uint8_t i; ao_data_get(&packet); -#ifdef TELEPYRO - printf("ADMUX: %02x\n", ADMUX); - printf("ADCSRA: %02x\n", ADCSRA); - printf("ADCSRB: %02x\n", ADCSRB); - printf("DIDR0: %02x\n", DIDR0); - printf("DIDR2: %02x\n", DIDR2); - printf("PORTF: %02x\n", PORTF); - printf("DDRF: %02x\n", DDRF); - printf("PINF: %02x\n", PINF); -#endif printf("tick: %5u", packet.tick); for (i = 0; i < NUM_ADC; i++) printf (" %2d: %5u", i, packet.adc.adc[i]); printf("\n"); - - -#ifdef TELEPYRO - ADMUX = 0x60; - ADCSRB = 0x00; - ADCSRA = 0xc6; - while (ADCSRA & 0x40) - ; - printf ("ADCL: %02x\n", ADCL); - printf ("ADCH: %02x\n", ADCH); - printf ("\n"); -#endif } __code struct ao_cmds ao_adc_cmds[] = { - { ao_adc_dump, "a\0Display current ADC values" }, + { ao_adc_dump, "a\0ADC" }, { 0, NULL }, }; void ao_adc_init(void) { + PRR0 &= ~(1 << PRADC); DIDR0 = 0xf3; DIDR2 = 0x3f; ADCSRB = ADCSRB_INIT; -- cgit v1.2.3 From 90507d4f7ef77b0870a032b1d9809898c2924721 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:24:21 -0700 Subject: altos: Make ao_tick_count visible Necessary to fetch it when interrupts are already disabled as we can't call ao_time then. Signed-off-by: Keith Packard --- src/avr/ao_timer.c | 2 +- src/cc1111/ao_timer.c | 2 +- src/core/ao.h | 2 ++ src/stm/ao_timer.c | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/avr/ao_timer.c b/src/avr/ao_timer.c index eef14345..cd81b163 100644 --- a/src/avr/ao_timer.c +++ b/src/avr/ao_timer.c @@ -17,7 +17,7 @@ #include "ao.h" -static volatile __data uint16_t ao_tick_count; +volatile __data uint16_t ao_tick_count; uint16_t ao_time(void) { diff --git a/src/cc1111/ao_timer.c b/src/cc1111/ao_timer.c index aadee71e..602f98c8 100644 --- a/src/cc1111/ao_timer.c +++ b/src/cc1111/ao_timer.c @@ -17,7 +17,7 @@ #include "ao.h" -static volatile __data uint16_t ao_tick_count; +volatile __data uint16_t ao_tick_count; uint16_t ao_time(void) __critical { diff --git a/src/core/ao.h b/src/core/ao.h index d4be3be4..65b9eb18 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -125,6 +125,8 @@ ao_panic(uint8_t reason); * ao_timer.c */ +extern volatile __data uint16_t ao_tick_count; + /* Our timer runs at 100Hz */ #define AO_HERTZ 100 #define AO_MS_TO_TICKS(ms) ((ms) / (1000 / AO_HERTZ)) diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 936dc881..ebe75366 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -17,7 +17,7 @@ #include "ao.h" -static volatile __data uint16_t ao_tick_count; +volatile __data uint16_t ao_tick_count; uint16_t ao_time(void) { -- cgit v1.2.3 From 1887ca3d7d4a0259686f8c1e68d1e47c47b4ab84 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:25:47 -0700 Subject: altos: Pass flight dynamics to companion boards Necessary for TelePyro Signed-off-by: Keith Packard --- src/core/ao_companion.h | 4 ++++ src/core/ao_flight.c | 4 ---- src/core/ao_flight.h | 2 -- src/drivers/ao_companion.c | 4 ++++ 4 files changed, 8 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/core/ao_companion.h b/src/core/ao_companion.h index 47e0acf5..035325a3 100644 --- a/src/core/ao_companion.h +++ b/src/core/ao_companion.h @@ -30,6 +30,10 @@ struct ao_companion_command { uint16_t tick; uint16_t serial; uint16_t flight; + int16_t accel; + int16_t speed; + int16_t height; + int16_t motor_number; }; struct ao_companion_setup { diff --git a/src/core/ao_flight.c b/src/core/ao_flight.c index fc018f00..aa4f6961 100644 --- a/src/core/ao_flight.c +++ b/src/core/ao_flight.c @@ -40,9 +40,7 @@ __pdata enum ao_flight_state ao_flight_state; /* current flight state */ __pdata uint16_t ao_boost_tick; /* time of launch detect */ -#if AO_PYRO_NUM __pdata uint16_t ao_motor_number; /* number of motors burned so far */ -#endif /* * track min/max data over a long interval to detect @@ -218,9 +216,7 @@ ao_flight(void) #else ao_flight_state = ao_flight_coast; #endif -#if AO_PYRO_NUM ++ao_motor_number; -#endif ao_wakeup(DATA_TO_XDATA(&ao_flight_state)); } break; diff --git a/src/core/ao_flight.h b/src/core/ao_flight.h index c5c8af46..b80202f0 100644 --- a/src/core/ao_flight.h +++ b/src/core/ao_flight.h @@ -38,9 +38,7 @@ enum ao_flight_state { extern __pdata enum ao_flight_state ao_flight_state; extern __pdata uint16_t ao_boost_tick; -#if AO_PYRO_NUM extern __pdata uint16_t ao_motor_number; -#endif extern __pdata uint16_t ao_launch_time; extern __pdata uint8_t ao_flight_force_idle; diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index a3167956..6e0bd2ec 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -53,6 +53,10 @@ ao_companion_send_command(uint8_t command) ao_companion_command.tick = ao_time(); ao_companion_command.serial = ao_serial_number; ao_companion_command.flight = ao_flight_number; + ao_companion_command.accel = ao_accel; + ao_companion_command.speed = ao_speed; + ao_companion_command.height = ao_height; + ao_companion_command.motor_number = ao_motor_number; ao_spi_send(&ao_companion_command, sizeof (ao_companion_command), AO_COMPANION_SPI_BUS); } -- cgit v1.2.3 From 6581eefbdbd8d3e94f615bdf11652a000d131c8e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:27:58 -0700 Subject: altos: Use 'HAS_ORIENT' to enable orientation selection in pyro code Don't expose orientation options when no orientation data is available Signed-off-by: Keith Packard --- src/core/ao_pyro.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index b0d45162..162f5e1e 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -66,14 +66,16 @@ ao_pyro_ready(struct ao_pyro *pyro) continue; break; +#if HAS_ORIENT case ao_pyro_orient_less: -// if (ao_orient <= pyro->orient_less) + if (ao_orient <= pyro->orient_less) continue; break; case ao_pyro_orient_greater: -// if (ao_orient >= pyro->orient_greater) + if (ao_orient >= pyro->orient_greater) continue; break; +#endif case ao_pyro_time_less: if ((int16_t) (ao_time() - ao_boost_tick) <= pyro->time_less) @@ -102,8 +104,8 @@ ao_pyro_ready(struct ao_pyro *pyro) /* handled separately */ continue; - case ao_pyro_none: - break; + default: + continue; } return FALSE; } @@ -234,7 +236,7 @@ const struct { { "h<", ao_pyro_height_less, offsetof(struct ao_pyro, height_less), HELP("height less (m)") }, { "h>", ao_pyro_height_greater, offsetof(struct ao_pyro, height_greater), HELP("height greater (m)") }, -#if 0 +#if HAS_ORIENT { "o<", ao_pyro_orient_less, offsetof(struct ao_pyro, orient_less), HELP("orient less (deg)") }, { "o>", ao_pyro_orient_greater, offsetof(struct ao_pyro, orient_greater), HELP("orient greater (deg)") }, #endif @@ -281,6 +283,7 @@ ao_pyro_show(void) uint8_t v; struct ao_pyro *pyro; + printf ("Pyro-count: %d\n", AO_PYRO_NUM); for (p = 0; p < AO_PYRO_NUM; p++) { printf ("Pyro %2d: ", p); pyro = &ao_config.pyro[p]; -- cgit v1.2.3 From 3ce645a79b54e22d7835c6e390a22a5ad501a339 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:30:29 -0700 Subject: altos: Add manual firing command for extra pyro channels In parallel with the existing igniter commands, this tests the programmable pyro channels Signed-off-by: Keith Packard --- src/core/ao_pyro.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index 162f5e1e..a1377d21 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -103,7 +103,7 @@ ao_pyro_ready(struct ao_pyro *pyro) case ao_pyro_delay: /* handled separately */ continue; - + default: continue; } @@ -117,7 +117,7 @@ ao_pyro_ready(struct ao_pyro *pyro) ao_delay(AO_MS_TO_TICKS(50)); \ ao_gpio_set(port, bit, pin, 0); \ } while (0) - + static void ao_pyro_fire(uint8_t p) @@ -246,7 +246,7 @@ const struct { { "A", ao_pyro_ascending, NO_VALUE, HELP("ascending") }, { "D", ao_pyro_descending, NO_VALUE, HELP("descending") }, - + { "m", ao_pyro_after_motor, offsetof(struct ao_pyro, motor), HELP("after motor") }, { "d", ao_pyro_delay, offsetof(struct ao_pyro, delay), HELP("delay before firing (s * 100)") }, @@ -275,7 +275,7 @@ ao_pyro_help(void) } } #endif - + void ao_pyro_show(void) { @@ -340,7 +340,7 @@ ao_pyro_set(void) ao_cmd_white(); if (ao_cmd_lex_c == '\n') break; - + for (c = 0; c < AO_PYRO_NAME_LEN - 1; c++) { if (ao_cmd_is_white()) break; @@ -370,6 +370,25 @@ ao_pyro_set(void) _ao_config_edit_finish(); } +static void +ao_pyro_manual(void) +{ + ao_cmd_white(); + if (!ao_match_word("DoIt")) + return; + ao_cmd_white(); + ao_cmd_decimal(); + if (ao_cmd_lex_i < 0 || AO_PYRO_NUM <= ao_cmd_lex_i) + return; + ao_pyro_fire(ao_cmd_lex_i); + +} + +const struct ao_cmds ao_pyro_cmds[] = { + { ao_pyro_manual, "P DoIt \0Fire igniter" }, + { 0, NULL } +}; + void ao_pyro_init(void) { @@ -397,5 +416,6 @@ ao_pyro_init(void) #if AO_PYRO_NUM > 7 ao_enable_output(AO_PYRO_PORT_7, AO_PYRO_PIN_7, AO_PYRO_7, 0); #endif + ao_cmd_register(&ao_pyro_cmds[0]); ao_add_task(&ao_pyro_task, ao_pyro, "pyro"); } -- cgit v1.2.3 From 5860f75677ee20fcf35ab89a6b62f3e14a1c32f5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:32:26 -0700 Subject: altos: Enable pyro channel control in telepyro This should make the board actually work now. Signed-off-by: Keith Packard --- src/avr/ao_pins.h | 30 ++++++++++++++++++++++++++++++ src/core/ao_pyro.c | 15 ++++++++++++++- src/core/ao_pyro.h | 2 ++ src/drivers/ao_pyro_slave.c | 11 +++++++++++ src/product/ao_telepyro.c | 3 +++ 5 files changed, 60 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/avr/ao_pins.h b/src/avr/ao_pins.h index 3c9010a8..bc423ff7 100644 --- a/src/avr/ao_pins.h +++ b/src/avr/ao_pins.h @@ -59,6 +59,8 @@ #define SPI_SLAVE_PIN_0_3 1 #define SPI_SLAVE_PIN_2_5 0 + + #define IS_COMPANION 1 #endif #ifdef TELEPYRO @@ -77,6 +79,7 @@ #define DISABLE_HELP 1 #define HAS_STORAGE_DEBUG 0 #define IS_COMPANION 1 + #define HAS_ORIENT 0 #define ao_storage_pos_t uint16_t #define AVR_VCC_5V 0 @@ -89,6 +92,33 @@ #define SPI_SLAVE_PIN_0_3 1 #define SPI_SLAVE_PIN_2_5 0 + + #define AO_PYRO_NUM 8 + + #define AO_PYRO_PORT_0 B + #define AO_PYRO_PIN_0 5 + + #define AO_PYRO_PORT_1 B + #define AO_PYRO_PIN_1 6 + + #define AO_PYRO_PORT_2 B + #define AO_PYRO_PIN_2 7 + + #define AO_PYRO_PORT_3 C + #define AO_PYRO_PIN_3 6 + + #define AO_PYRO_PORT_4 C + #define AO_PYRO_PIN_4 7 + + #define AO_PYRO_PORT_5 D + #define AO_PYRO_PIN_5 5 + + #define AO_PYRO_PORT_6 D + #define AO_PYRO_PIN_6 3 + + #define AO_PYRO_PORT_7 D + #define AO_PYRO_PIN_7 2 + #endif #define AO_M25_SPI_CS_PORT SPI_CS_PORT diff --git a/src/core/ao_pyro.c b/src/core/ao_pyro.c index a1377d21..4f37e979 100644 --- a/src/core/ao_pyro.c +++ b/src/core/ao_pyro.c @@ -20,6 +20,15 @@ #include #include +#if IS_COMPANION +#include +#define ao_accel ao_companion_command.accel +#define ao_speed ao_companion_command.speed +#define ao_height ao_companion_command.height +#define ao_flight_state ao_companion_command.flight_state +#define ao_motor_number ao_companion_command.motor_number +#endif + #define ao_lowbit(x) ((x) & (-x)) /* @@ -152,6 +161,8 @@ ao_pyro_fire(uint8_t p) ao_delay(AO_MS_TO_TICKS(50)); } +uint8_t ao_pyro_wakeup; + static void ao_pyro(void) { @@ -163,7 +174,9 @@ ao_pyro(void) ao_sleep(&ao_flight_state); for (;;) { - ao_delay(AO_MS_TO_TICKS(100)); + ao_alarm(AO_MS_TO_TICKS(100)); + ao_sleep(&ao_pyro_wakeup); + ao_clear_alarm(); for (p = 0; p < AO_PYRO_NUM; p++) { pyro = &ao_config.pyro[p]; diff --git a/src/core/ao_pyro.h b/src/core/ao_pyro.h index 1989a9e5..5deb69d0 100644 --- a/src/core/ao_pyro.h +++ b/src/core/ao_pyro.h @@ -57,6 +57,8 @@ struct ao_pyro { uint8_t fired; }; +extern uint8_t ao_pyro_wakeup; + void ao_pyro_set(void); diff --git a/src/drivers/ao_pyro_slave.c b/src/drivers/ao_pyro_slave.c index 70206a00..f07c2cba 100644 --- a/src/drivers/ao_pyro_slave.c +++ b/src/drivers/ao_pyro_slave.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include struct ao_companion_command ao_companion_command; @@ -28,6 +30,11 @@ static const struct ao_companion_setup ao_telepyro_setup = { .channels = AO_TELEPYRO_NUM_ADC, }; +struct ao_config ao_config; + +extern volatile __data uint16_t ao_tick_count; +uint16_t ao_boost_tick; + void ao_spi_slave(void) { if (!ao_spi_slave_recv((uint8_t *) &ao_companion_command, @@ -45,6 +52,10 @@ void ao_spi_slave(void) AO_TELEPYRO_NUM_ADC * sizeof (uint16_t)); break; case AO_COMPANION_NOTIFY: + /* Can't use ao_time because we have interrupts suspended */ + if (ao_companion_command.flight_state < ao_flight_boost && ao_companion_command.flight_state >= ao_flight_boost) + ao_boost_tick = ao_tick_count; + ao_wakeup(&ao_pyro_wakeup); break; default: return; diff --git a/src/product/ao_telepyro.c b/src/product/ao_telepyro.c index a2b8f83c..79454fb7 100644 --- a/src/product/ao_telepyro.c +++ b/src/product/ao_telepyro.c @@ -31,6 +31,9 @@ main(void) ao_spi_slave_init(); ao_usb_init(); ao_adc_init(); + ao_storage_init(); + ao_config_init(); + ao_pyro_init(); ao_start_scheduler(); return 0; } -- cgit v1.2.3 From 0edb5616a70fd480317acc99ec3c28c662aa8556 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 16 Jul 2012 15:34:01 -0700 Subject: altos: megametrum depends on ao_companion.h Signed-off-by: Keith Packard --- src/megametrum-v0.1/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index d415b59b..a519609e 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -9,6 +9,7 @@ INC = \ ao.h \ ao_arch.h \ ao_arch_funcs.h \ + ao_companion.h \ ao_data.h \ ao_sample.h \ ao_pins.h \ -- cgit v1.2.3 From a5d873d47b3b16ca32559b4de668bf07b25eddb0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Jul 2012 01:24:52 -0700 Subject: altos: Place STM config values at fixed addresses for re-use Just like cc1111, stick the serial number and radio calibration values at known fixed addresses so that when re-flashing the board, we can go find the existing values. Signed-off-by: Keith Packard --- ao-tools/ao-load/ao-load.c | 2 +- src/avr/ao_arch.h | 6 +++++- src/avr/ao_romconfig.c | 2 +- src/cc1111/ao_arch.h | 10 ++++++---- src/core/ao_product.c | 2 +- src/drivers/ao_cc1120.c | 2 +- src/drivers/ao_companion.c | 4 +++- src/megametrum-v0.1/Makefile | 2 +- src/megametrum-v0.1/ao_pins.h | 4 ++++ src/stm-bringup/Makefile | 4 ++-- src/stm/altos.ld | 21 +++++++++++---------- src/stm/ao_arch.h | 12 ++++++++++++ src/stm/ao_romconfig.c | 7 ++++++- 13 files changed, 54 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/ao-tools/ao-load/ao-load.c b/ao-tools/ao-load/ao-load.c index 1b729d39..e3cef4a5 100644 --- a/ao-tools/ao-load/ao-load.c +++ b/ao-tools/ao-load/ao-load.c @@ -197,7 +197,7 @@ main (int argc, char **argv) serial = strtoul(serial_string, NULL, 0); if (!serial) -(argv[0]); + usage(argv[0]); serial_int[0] = serial & 0xff; serial_int[1] = (serial >> 8) & 0xff; diff --git a/src/avr/ao_arch.h b/src/avr/ao_arch.h index c775dab6..a14d0ade 100644 --- a/src/avr/ao_arch.h +++ b/src/avr/ao_arch.h @@ -67,7 +67,11 @@ extern void putchar(char c); extern char getchar(void); extern void ao_avr_stdio_init(void); -extern const uint16_t ao_serial_number; +#define AO_ROMCONFIG_VERSION 2 + +#define AO_ROMCONFIG_SYMBOL(a) const + +extern AO_ROMCONFIG_SYMBOL(0) uint16_t ao_serial_number; #define AVR_PUSH8(stack, val) (*((stack)--) = (val)) diff --git a/src/avr/ao_romconfig.c b/src/avr/ao_romconfig.c index bbb677e2..ecc19c76 100644 --- a/src/avr/ao_romconfig.c +++ b/src/avr/ao_romconfig.c @@ -17,4 +17,4 @@ #include "ao.h" -const uint16_t ao_serial_number = 0; +AO_ROMCONFIG_SYMBOL (0) uint16_t ao_serial_number = 0; diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 8d9e4952..06b04b93 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -59,10 +59,12 @@ #define AO_ROMCONFIG_VERSION 2 -extern __code __at (0x00a0) uint16_t ao_romconfig_version; -extern __code __at (0x00a2) uint16_t ao_romconfig_check; -extern __code __at (0x00a4) uint16_t ao_serial_number; -extern __code __at (0x00a6) uint32_t ao_radio_cal; +#define AO_ROMCONFIG_SYMBOL(a) __code __at(a) + +extern AO_ROMCONFIG_SYMBOL(0x00a0) uint16_t ao_romconfig_version; +extern AO_ROMCONFIG_SYMBOL(0x00a2) uint16_t ao_romconfig_check; +extern AO_ROMCONFIG_SYMBOL(0x00a4) uint16_t ao_serial_number; +extern AO_ROMCONFIG_SYMBOL(0x00a6) uint32_t ao_radio_cal; #ifndef HAS_USB #error Please define HAS_USB diff --git a/src/core/ao_product.c b/src/core/ao_product.c index 67ec6793..ec91b978 100644 --- a/src/core/ao_product.c +++ b/src/core/ao_product.c @@ -29,7 +29,7 @@ const char ao_product[] = AO_iProduct_STRING; #if HAS_USB #include "ao_usb.h" /* USB descriptors in one giant block of bytes */ -__code __at(0x00aa) uint8_t ao_usb_descriptors [] = +AO_ROMCONFIG_SYMBOL(0x00aa) uint8_t ao_usb_descriptors [] = { /* Device descriptor */ 0x12, diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 569df3b7..97a434d8 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -29,7 +29,7 @@ uint8_t ao_radio_in_recv; #define CC1120_DEBUG AO_FEC_DEBUG #define CC1120_TRACE 0 -const uint32_t ao_radio_cal = 0x6ca333; +extern const uint32_t ao_radio_cal; #define FOSC 32000000 diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index 6e0bd2ec..c749adea 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -68,7 +68,7 @@ ao_companion_get_setup(void) ao_spi_recv(&ao_companion_setup, sizeof (ao_companion_setup), AO_COMPANION_SPI_BUS); COMPANION_DESELECT(); return (ao_companion_setup.board_id == - ~ao_companion_setup.board_id_inverse); + (uint16_t) ~ao_companion_setup.board_id_inverse); } static void @@ -116,6 +116,8 @@ ao_companion_status(void) __reentrant { uint8_t i; printf("Companion running: %d\n", ao_companion_running); + if (!ao_companion_running) + return; printf("device: %d\n", ao_companion_setup.board_id); printf("update period: %d\n", ao_companion_setup.update_period); printf("channels: %d\n", ao_companion_setup.channels); diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index a519609e..4a4c983a 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -92,7 +92,7 @@ OBJ=$(SRC:.c=.o) all: $(PROG) -$(PROG): Makefile $(OBJ) +$(PROG): Makefile $(OBJ) altos.ld $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc ../altitude.h: make-altitude diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 2c438f6c..6b0f9832 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -268,6 +268,10 @@ struct ao_adc { * Radio (cc1120) */ +/* gets pretty close to 434.550 */ + +#define AO_RADIO_CAL_DEFAULT 0x6ca333 + #define AO_FEC_DEBUG 0 #define AO_CC1120_SPI_CS_PORT (&stm_gpioc) #define AO_CC1120_SPI_CS_PIN 5 diff --git a/src/stm-bringup/Makefile b/src/stm-bringup/Makefile index 01c80614..d45e836d 100644 --- a/src/stm-bringup/Makefile +++ b/src/stm-bringup/Makefile @@ -16,7 +16,7 @@ DEF_CFLAGS=-g -std=gnu99 -Os -mlittle-endian -mthumb -ffreestanding -nostdlib -I # to run from SRAM LD_FLAGS_RAM=-L../stm -Wl,-Taltos-ram.ld -LD_FLAGS=-L../stm -Wl,-Taltos.ld +LD_FLAGS=-L../stm -Wl,-Tbringup.ld CFLAGS=$(DEF_CFLAGS) -mcpu=cortex-m3 -DCONFIG_STM32L_DISCOVERY @@ -28,7 +28,7 @@ all: bringup-ram.elf bringup.elf %.bin: %.elf $(OBJCOPY) -O binary $^ $@ -bringup.elf: $(OBJ) $(C_LIB) altos.ld +bringup.elf: $(OBJ) $(C_LIB) bringup.ld $(CC) $(CFLAGS) $(LD_FLAGS) -o $@ $(OBJ) $(C_LIB) -lgcc bringup-ram.elf: $(OBJ) $(C_LIB) altos-ram.ld diff --git a/src/stm/altos.ld b/src/stm/altos.ld index f5a84f4c..f78a45d6 100644 --- a/src/stm/altos.ld +++ b/src/stm/altos.ld @@ -25,18 +25,22 @@ INCLUDE registers.ld EXTERN (stm_interrupt_vector) SECTIONS { - . = ORIGIN(rom); - /* * Rom contents */ - __text_start__ = .; - - .text : { + .text ORIGIN(rom) : { + __text_start__ = .; *(.interrupt) /* Interrupt vectors */ + + . = ORIGIN(rom) + 0x100; + + ao_romconfig.o(.romconfig*) + ao_product.o(.romconfig*) + *(.text*) /* Executable code */ *(.rodata*) /* Constants */ + } > rom .ARM.exidx : { @@ -44,12 +48,10 @@ SECTIONS { __text_end__ = .; } > rom - . = ORIGIN(ram); - __data_start__ = .; - /* Data -- relocated to RAM, but written to ROM */ - .data : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + .data ORIGIN(ram) : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + __data_start__ = .; *(.data) /* initialized data */ __data_end__ = .; __bss_start__ = .; @@ -63,7 +65,6 @@ SECTIONS { PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram)); PROVIDE(end = .); - } ENTRY(start); diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index d8fa3e89..484ce89e 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -59,7 +59,19 @@ extern void putchar(char c); extern char getchar(void); extern void ao_avr_stdio_init(void); + +/* + * ao_romconfig.c + */ + +#define AO_ROMCONFIG_VERSION 2 + +#define AO_ROMCONFIG_SYMBOL(a) __attribute__((section(".romconfig"))) const + +extern const uint16_t ao_romconfig_version; +extern const uint16_t ao_romconfig_check; extern const uint16_t ao_serial_number; +extern const uint32_t ao_radio_cal; #define ARM_PUSH32(stack, val) (*(--(stack)) = (val)) diff --git a/src/stm/ao_romconfig.c b/src/stm/ao_romconfig.c index 84317458..cbb922ec 100644 --- a/src/stm/ao_romconfig.c +++ b/src/stm/ao_romconfig.c @@ -17,4 +17,9 @@ #include "ao.h" -const uint16_t ao_serial_number = 58; +AO_ROMCONFIG_SYMBOL (0) uint16_t ao_romconfig_version = AO_ROMCONFIG_VERSION; +AO_ROMCONFIG_SYMBOL (0) uint16_t ao_romconfig_check = ~AO_ROMCONFIG_VERSION; +AO_ROMCONFIG_SYMBOL (0) uint16_t ao_serial_number = 0; +#ifdef AO_RADIO_CAL_DEFAULT +AO_ROMCONFIG_SYMBOL (0) uint32_t ao_radio_cal = AO_RADIO_CAL_DEFAULT; +#endif -- cgit v1.2.3 From e93c6bcc799d76d4ff425815e2601a25e6796229 Mon Sep 17 00:00:00 2001 From: Robert Garbee Date: Tue, 17 Jul 2012 13:23:48 -0600 Subject: first work on PWM input to TeleScience, 'p' command displays timer 1 --- src/avr/ao_pwmin.c | 54 +++++++++++++++++++++++++++++++++++++++++++ src/avr/ao_pwmin.h | 18 +++++++++++++++ src/product/ao_telescience.c | 2 ++ src/telescience-v0.1/Makefile | 1 + 4 files changed, 75 insertions(+) create mode 100644 src/avr/ao_pwmin.c create mode 100644 src/avr/ao_pwmin.h (limited to 'src') diff --git a/src/avr/ao_pwmin.c b/src/avr/ao_pwmin.c new file mode 100644 index 00000000..4d96404d --- /dev/null +++ b/src/avr/ao_pwmin.c @@ -0,0 +1,54 @@ +/* + * Copyright © 2012 Robert D. Garbee + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pwmin.h" + +/* + * This code implements a PWM input using ICP3. + * + * The initial use is to measure wind speed in the ULA/Ball summer intern + * project payload developed at Challenger Middle School. + */ + +static void +ao_pwmin_display(void) __reentrant +{ + uint8_t lo = TCNT1L; + uint8_t hi = TCNT1H; + uint16_t value = (hi <<8) | lo; + + /* now display the value we read */ + printf("timer 1: %5u", value); + +} + +__code struct ao_cmds ao_pwmin_cmds[] = { + { ao_pwmin_display, "p\0PWM input" }, + { 0, NULL }, +}; + +void +ao_pwmin_init(void) +{ + /* do hardware setup here */ + /* set the spike filter bit in the TCCR3B register */ + + ao_cmd_register(&ao_pwmin_cmds[0]); +} + + diff --git a/src/avr/ao_pwmin.h b/src/avr/ao_pwmin.h new file mode 100644 index 00000000..bbab4ddc --- /dev/null +++ b/src/avr/ao_pwmin.h @@ -0,0 +1,18 @@ +/* + * Copyright © 2012 Robert D. Garbee + * + * 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. + */ + +void ao_pwmin_init(void); diff --git a/src/product/ao_telescience.c b/src/product/ao_telescience.c index 45b6d40e..2d594d7f 100644 --- a/src/product/ao_telescience.c +++ b/src/product/ao_telescience.c @@ -16,6 +16,7 @@ */ #include "ao.h" +#include "ao_pwmin.h" int main(void) @@ -34,6 +35,7 @@ main(void) ao_usb_init(); ao_adc_init(); ao_log_single_init(); + ao_pwmin_init(); ao_start_scheduler(); return 0; } diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index d24128ef..5542913d 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -53,6 +53,7 @@ ALTOS_SRC = \ ao_adc_avr.c \ ao_science_slave.c \ ao_spi_slave.c \ + ao_pwmin.c \ $(TELESCIENCE_STORAGE)\ $(TELESCIENCE_LOG) -- cgit v1.2.3 From b4be63627e146c7c868b5b3468d34880a561cfba Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Jul 2012 20:44:55 -0700 Subject: altos: Megametrum ADC values are 12 bits, discard low 4 for telemetry We've only got space for 8 bits for the ADC values for pyro channels, discard the low 4 bits instead of the low 8 bits. Signed-off-by: Keith Packard --- src/core/ao_telemetry.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/ao_telemetry.c b/src/core/ao_telemetry.c index 583a6636..52ac9489 100644 --- a/src/core/ao_telemetry.c +++ b/src/core/ao_telemetry.c @@ -138,9 +138,9 @@ ao_send_mega_data(void) telemetry.mega_data.v_batt = packet->adc.v_batt; telemetry.mega_data.v_pyro = packet->adc.v_pbatt; - /* XXX figure out right shift value; 4 might suffice */ + /* ADC range is 0-4095, so shift by four to save the high 8 bits */ for (i = 0; i < AO_ADC_NUM_SENSE; i++) - telemetry.mega_data.sense[i] = packet->adc.sense[i] >> 8; + telemetry.mega_data.sense[i] = packet->adc.sense[i] >> 4; telemetry.mega_data.ground_pres = ao_ground_pres; telemetry.mega_data.ground_accel = ao_ground_accel; -- cgit v1.2.3 From 9fd5e3c28fb0fd6da8641e7dd18b9912866d1b75 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Jul 2012 21:06:07 -0700 Subject: altos: With debug cables disconnected, CC1120 seems happy at +16dBm Let's see how it goes... Signed-off-by: Keith Packard --- src/drivers/ao_cc1120_CC1120.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/drivers/ao_cc1120_CC1120.h b/src/drivers/ao_cc1120_CC1120.h index 5376afd5..44cca938 100644 --- a/src/drivers/ao_cc1120_CC1120.h +++ b/src/drivers/ao_cc1120_CC1120.h @@ -83,7 +83,7 @@ CC1120_RFEND_CFG1, 0x0f, /* RFEND Configuration, Reg 1 */ CC1120_RFEND_CFG0, 0x00, /* RFEND Configuration, Reg 0 */ // CC1120_PA_CFG2, 0x3f, /* Power Amplifier Configuration, Reg 2 */ - CC1120_PA_CFG2, 0x04, /* Power Amplifier Configuration, Reg 2 */ + CC1120_PA_CFG2, 0x3f, /* Power Amplifier Configuration, Reg 2 */ CC1120_PA_CFG1, 0x56, /* Power Amplifier Configuration, Reg 1 */ CC1120_PA_CFG0, 0x7b, /* Power Amplifier Configuration, Reg 0 */ CC1120_PKT_LEN, 0xff, /* Packet Length Configuration */ -- cgit v1.2.3 From a698cd68968fc0be5f96b1729cdea2f65d2ccbf6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Jul 2012 23:59:13 -0700 Subject: altos: Toggling telemetry monitoring would replay the telem queue Using the 'm' command to turn telem off and back on would end up going around the whole telemetry queue replaying everything there as the wait loop would exit when disabling monitoring even if the ring was empty. Signed-off-by: Keith Packard --- src/core/ao_monitor.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/core/ao_monitor.c b/src/core/ao_monitor.c index d492e32a..5876bef7 100644 --- a/src/core/ao_monitor.c +++ b/src/core/ao_monitor.c @@ -132,6 +132,8 @@ ao_monitor_put(void) ao_sleep(DATA_TO_XDATA(&ao_external_monitoring)); while (ao_monitor_tail == ao_monitor_head && ao_external_monitoring) ao_sleep(DATA_TO_XDATA(&ao_monitor_head)); + if (!ao_external_monitoring) + continue; m = &ao_monitor_ring[ao_monitor_tail]; ao_monitor_tail = ao_monitor_ring_next(ao_monitor_tail); switch (ao_monitoring) { -- cgit v1.2.3 From 49b1ff4c614d24977b33cd17b583acc87acff476 Mon Sep 17 00:00:00 2001 From: Robert Garbee Date: Wed, 18 Jul 2012 13:41:27 -0600 Subject: Timer 3 working with slower clock and all 16 bits. --- src/avr/ao_pwmin.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/avr/ao_pwmin.c b/src/avr/ao_pwmin.c index 4d96404d..edcb1636 100644 --- a/src/avr/ao_pwmin.c +++ b/src/avr/ao_pwmin.c @@ -25,6 +25,8 @@ * project payload developed at Challenger Middle School. */ +volatile __data uint16_t ao_tick3_count; + static void ao_pwmin_display(void) __reentrant { @@ -32,10 +34,19 @@ ao_pwmin_display(void) __reentrant uint8_t hi = TCNT1H; uint16_t value = (hi <<8) | lo; + uint8_t lo3 = TCNT3L; + uint8_t hi3 = TCNT3H; + uint16_t value3 = (hi3 <<8) | lo3; + /* now display the value we read */ - printf("timer 1: %5u", value); + printf("timer 1: %5u %2x %2x\n", value, hi, lo); + printf("timer 3: %5u %2x %2x\n", value3, hi3, lo3); } +ISR(TIMER3_COMPA_vect) +{ + ++ao_tick3_count; +} __code struct ao_cmds ao_pwmin_cmds[] = { { ao_pwmin_display, "p\0PWM input" }, @@ -46,6 +57,18 @@ void ao_pwmin_init(void) { /* do hardware setup here */ + TCCR3A = ((0 << WGM31) | /* normal mode, OCR3A */ + (0 << WGM30)); /* normal mode, OCR3A */ + TCCR3B = ((0 << ICNC3) | /* no input capture noise canceler */ + (0 << ICES3) | /* input capture on falling edge (don't care) */ + (0 << WGM33) | /* normal mode, OCR3A */ + (0 << WGM32) | /* normal mode, OCR3A */ + (4 << CS30)); /* clk/256 from prescaler */ + + OCR3A = 1250; /* 8MHz clock */ + + TIMSK3 = (1 << OCIE3A); /* Interrupt on compare match */ + /* set the spike filter bit in the TCCR3B register */ ao_cmd_register(&ao_pwmin_cmds[0]); -- cgit v1.2.3 From 75d6aa6f798606f1a6c5a46542065dda81e63b2a Mon Sep 17 00:00:00 2001 From: Robert Garbee Date: Wed, 18 Jul 2012 14:24:05 -0600 Subject: ICP3 working --- src/avr/ao_pwmin.c | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/avr/ao_pwmin.c b/src/avr/ao_pwmin.c index edcb1636..73a153b2 100644 --- a/src/avr/ao_pwmin.c +++ b/src/avr/ao_pwmin.c @@ -25,27 +25,20 @@ * project payload developed at Challenger Middle School. */ -volatile __data uint16_t ao_tick3_count; +volatile __data uint16_t ao_icp3_count; static void ao_pwmin_display(void) __reentrant { - uint8_t lo = TCNT1L; - uint8_t hi = TCNT1H; - uint16_t value = (hi <<8) | lo; - - uint8_t lo3 = TCNT3L; - uint8_t hi3 = TCNT3H; - uint16_t value3 = (hi3 <<8) | lo3; - - /* now display the value we read */ - printf("timer 1: %5u %2x %2x\n", value, hi, lo); - printf("timer 3: %5u %2x %2x\n", value3, hi3, lo3); + /* display the most recent value */ + printf("icp 3: %5u\n", ao_icp3_count); } -ISR(TIMER3_COMPA_vect) +ISR(TIMER3_CAPT_vect) { - ++ao_tick3_count; + uint8_t lo = ICR3L; + uint8_t hi = ICR3H; + ao_icp3_count = (hi <<8) | lo; } __code struct ao_cmds ao_pwmin_cmds[] = { @@ -59,15 +52,15 @@ ao_pwmin_init(void) /* do hardware setup here */ TCCR3A = ((0 << WGM31) | /* normal mode, OCR3A */ (0 << WGM30)); /* normal mode, OCR3A */ - TCCR3B = ((0 << ICNC3) | /* no input capture noise canceler */ + TCCR3B = ((1 << ICNC3) | /* input capture noise canceler on */ (0 << ICES3) | /* input capture on falling edge (don't care) */ (0 << WGM33) | /* normal mode, OCR3A */ (0 << WGM32) | /* normal mode, OCR3A */ (4 << CS30)); /* clk/256 from prescaler */ - OCR3A = 1250; /* 8MHz clock */ + - TIMSK3 = (1 << OCIE3A); /* Interrupt on compare match */ + TIMSK3 = (1 << ICIE3); /* Interrupt on input compare */ /* set the spike filter bit in the TCCR3B register */ -- cgit v1.2.3 From ada6f2dfc045e77cb9499f20cdec1b4a54ef0db1 Mon Sep 17 00:00:00 2001 From: Robert Garbee Date: Wed, 18 Jul 2012 18:41:00 -0600 Subject: telescience: correctly calculating rate values with higher resolution --- src/avr/ao_pwmin.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/avr/ao_pwmin.c b/src/avr/ao_pwmin.c index 73a153b2..84397357 100644 --- a/src/avr/ao_pwmin.c +++ b/src/avr/ao_pwmin.c @@ -25,20 +25,40 @@ * project payload developed at Challenger Middle School. */ -volatile __data uint16_t ao_icp3_count; +volatile __data uint16_t ao_icp3_count = 0; +volatile __data uint16_t ao_icp3_last = 0; + +uint16_t ao_icp3(void) +{ + uint16_t v; + ao_arch_critical( + v = ao_icp3_count; + ); + return v; +} static void ao_pwmin_display(void) __reentrant { /* display the most recent value */ - printf("icp 3: %5u\n", ao_icp3_count); + printf("icp 3: %5u\n", ao_icp3()); } + + ISR(TIMER3_CAPT_vect) { + uint8_t lo = ICR3L; uint8_t hi = ICR3H; - ao_icp3_count = (hi <<8) | lo; + uint16_t ao_icp3_this = (hi <<8) | lo; + + /* handling counter rollovers */ + if (ao_icp3_this >= ao_icp3_last) + ao_icp3_count = ao_icp3_this - ao_icp3_last; + else + ao_icp3_count = ao_icp3_this + (65536 - ao_icp3_last); + ao_icp3_last = ao_icp3_this; } __code struct ao_cmds ao_pwmin_cmds[] = { @@ -56,7 +76,7 @@ ao_pwmin_init(void) (0 << ICES3) | /* input capture on falling edge (don't care) */ (0 << WGM33) | /* normal mode, OCR3A */ (0 << WGM32) | /* normal mode, OCR3A */ - (4 << CS30)); /* clk/256 from prescaler */ + (3 << CS30)); /* clk/64 from prescaler */ -- cgit v1.2.3 From e033a72d3f420e18ed24354c7dfc7e1317a03fb6 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 20 Jul 2012 11:08:22 -0700 Subject: Add stlink pinout Signed-off-by: Keith Packard --- src/megametrum-v0.1/stlink-pins | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/megametrum-v0.1/stlink-pins (limited to 'src') diff --git a/src/megametrum-v0.1/stlink-pins b/src/megametrum-v0.1/stlink-pins new file mode 100644 index 00000000..71042acc --- /dev/null +++ b/src/megametrum-v0.1/stlink-pins @@ -0,0 +1,41 @@ + ST discovery card pins + +1 AIN-1 +2 JTCK +3 GND +4 JTMS +5 NRST +6 SWO + +MM misc connector + +1 GND +2 reset_n +3 boot0 +4 tx1 +5 rx1 +6 +3.3V +7 GND +8 jtms +9 jtck +10 jtdi +11 jtdo +12 jntrst +13 sda2 +14 scl2 +15 pe1 +16 pe0 + +For debugging: + + ST MM +JTCK 2 9 +GND 3 7 +JTMS 4 8 +NRST 5 2 + +MegaAccel: + +Jumpers +PC0 (pin15) (blue) PE0 (pin97) accel_ref (debug 16) +PC1 (pin16) (green) PE1 (pin98) accel (debug 15) -- cgit v1.2.3 From 52e920bc7a98edf5c6f2ad0bd59d581011dcd5c9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 22 Jul 2012 15:18:27 -0700 Subject: altos: Move ao_radio_cmac.c to core (it doesn't depend on hardware) Signed-off-by: Keith Packard --- src/ao_radio_cmac.c | 406 ----------------------------------------------- src/core/ao_radio_cmac.c | 406 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 406 insertions(+), 406 deletions(-) delete mode 100644 src/ao_radio_cmac.c create mode 100644 src/core/ao_radio_cmac.c (limited to 'src') diff --git a/src/ao_radio_cmac.c b/src/ao_radio_cmac.c deleted file mode 100644 index e263f0db..00000000 --- a/src/ao_radio_cmac.c +++ /dev/null @@ -1,406 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" - -#define AO_CMAC_KEY_LEN AO_AES_LEN -#define AO_CMAC_MAX_LEN (128 - AO_CMAC_KEY_LEN) - -static __xdata uint8_t ao_radio_cmac_mutex; -__pdata int16_t ao_radio_cmac_rssi; -static __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN]; -static __pdata uint8_t ao_radio_cmac_len; - -static uint8_t -getnibble(void) -{ - int8_t b; - - b = ao_cmd_hexchar(getchar()); - if (b < 0) { - ao_cmd_status = ao_cmd_lex_error; - return 0; - } - return (uint8_t) b; -} - -static uint8_t -getbyte(void) -{ - uint8_t b; - b = getnibble() << 4; - b |= getnibble(); - return b; -} - -static uint8_t -round_len(uint8_t len) -{ - uint8_t rem; - - /* Make sure we transfer at least one packet, and - * then make sure every packet is full. Note that - * there is no length encoded, and that the receiver - * must deal with any extra bytes in the packet - */ - if (len < AO_CMAC_KEY_LEN) - len = AO_CMAC_KEY_LEN; - rem = len % AO_CMAC_KEY_LEN; - if (rem != 0) - len += (AO_CMAC_KEY_LEN - rem); - return len; -} - -/* - * Sign and deliver the data sitting in the cmac buffer - */ -static void -radio_cmac_send(uint8_t len) __reentrant -{ - uint8_t i; - - len = round_len(len); - /* Make sure the AES key is loaded */ - ao_config_get(); - -#if HAS_MONITOR - ao_monitor_set(0); -#endif - - ao_mutex_get(&ao_aes_mutex); - ao_aes_set_mode(ao_aes_mode_cbc_mac); - ao_aes_set_key(ao_config.aes_key); - ao_aes_zero_iv(); - for (i = 0; i < len; i += AO_CMAC_KEY_LEN) { - if (i + AO_CMAC_KEY_LEN < len) - ao_aes_run(&cmac_data[i], NULL); - else - ao_aes_run(&cmac_data[i], &cmac_data[len]); - } - ao_mutex_put(&ao_aes_mutex); - - ao_radio_send(cmac_data, len + AO_CMAC_KEY_LEN); -} - -/* - * Receive and validate an incoming packet - */ - -static int8_t -radio_cmac_recv(uint8_t len, uint16_t timeout) __reentrant -{ - uint8_t i; - - len = round_len(len); -#if HAS_MONITOR - ao_monitor_set(0); -#endif - if (timeout) - ao_alarm(timeout); - - i = ao_radio_recv(cmac_data, len + AO_CMAC_KEY_LEN + 2); - ao_clear_alarm(); - - if (!i) { - ao_radio_cmac_rssi = 0; - return AO_RADIO_CMAC_TIMEOUT; - } - - ao_radio_cmac_rssi = (int16_t) (((int8_t) cmac_data[len + AO_CMAC_KEY_LEN]) >> 1) - 74; - if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & PKT_APPEND_STATUS_1_CRC_OK)) - return AO_RADIO_CMAC_CRC_ERROR; - - ao_config_get(); - - /* Compute the packet signature - */ - ao_mutex_get(&ao_aes_mutex); - ao_aes_set_mode(ao_aes_mode_cbc_mac); - ao_aes_set_key(ao_config.aes_key); - ao_aes_zero_iv(); - for (i = 0; i < len; i += AO_CMAC_KEY_LEN) { - if (i + AO_CMAC_KEY_LEN < len) - ao_aes_run(&cmac_data[i], NULL); - else - ao_aes_run(&cmac_data[i], &cmac_data[len + AO_CMAC_KEY_LEN + 2]); - } - ao_mutex_put(&ao_aes_mutex); - - /* Check the packet signature against the signature provided - * over the link - */ - - if (memcmp(&cmac_data[len], - &cmac_data[len + AO_CMAC_KEY_LEN + 2], - AO_CMAC_KEY_LEN) != 0) { - return AO_RADIO_CMAC_MAC_ERROR; - } - - return AO_RADIO_CMAC_OK; -} - -int8_t -ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant -{ - if (len > AO_CMAC_MAX_LEN) - return AO_RADIO_CMAC_LEN_ERROR; - ao_mutex_get(&ao_radio_cmac_mutex); - memcpy(cmac_data, packet, len); - radio_cmac_send(len); - ao_mutex_put(&ao_radio_cmac_mutex); - return AO_RADIO_CMAC_OK; -} - -int8_t -ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant -{ - uint8_t i; - if (len > AO_CMAC_MAX_LEN) - return AO_RADIO_CMAC_LEN_ERROR; - ao_mutex_get(&ao_radio_cmac_mutex); - i = radio_cmac_recv(len, timeout); - if (i == AO_RADIO_CMAC_OK) - memcpy(packet, cmac_data, len); - ao_mutex_put(&ao_radio_cmac_mutex); - return i; -} - -static void -radio_cmac_send_cmd(void) __reentrant -{ - uint8_t i; - uint8_t len; - - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - len = ao_cmd_lex_i; - if (len > AO_CMAC_MAX_LEN) { - ao_cmd_status = ao_cmd_syntax_error; - return; - } - flush(); - ao_mutex_get(&ao_radio_cmac_mutex); - len = ao_cmd_lex_i; - for (i = 0; i < len; i++) { - cmac_data[i] = getbyte(); - if (ao_cmd_status != ao_cmd_success) - return; - } - radio_cmac_send(len); - ao_mutex_put(&ao_radio_cmac_mutex); -} - -static void -radio_cmac_recv_cmd(void) __reentrant -{ - uint8_t len, i; - uint16_t timeout; - - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - len = ao_cmd_lex_i; - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - timeout = AO_MS_TO_TICKS(ao_cmd_lex_i); - ao_mutex_get(&ao_radio_cmac_mutex); - i = radio_cmac_recv(len, timeout); - if (i == AO_RADIO_CMAC_OK) { - printf ("PACKET "); - for (i = 0; i < len; i++) - printf("%02x", cmac_data[i]); - printf (" %d\n", ao_radio_cmac_rssi); - } else - printf ("ERROR %d %d\n", i, ao_radio_cmac_rssi); - ao_mutex_put(&ao_radio_cmac_mutex); -} - -static __xdata struct ao_launch_command command; -static __xdata struct ao_launch_query query; -static pdata uint16_t launch_serial; -static pdata uint8_t launch_channel; -static pdata uint16_t tick_offset; - -static void -launch_args(void) __reentrant -{ - ao_cmd_decimal(); - launch_serial = ao_cmd_lex_i; - ao_cmd_decimal(); - launch_channel = ao_cmd_lex_i; -} - -static int8_t -launch_query(void) -{ - uint8_t i; - int8_t r = AO_RADIO_CMAC_OK; - - tick_offset = ao_time(); - for (i = 0; i < 10; i++) { - printf ("."); flush(); - command.tick = ao_time(); - command.serial = launch_serial; - command.cmd = AO_LAUNCH_QUERY; - command.channel = launch_channel; - ao_radio_cmac_send(&command, sizeof (command)); - r = ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500)); - if (r == AO_RADIO_CMAC_OK) - break; - } - tick_offset -= query.tick; - printf("\n"); flush(); - return r; -} - -static void -launch_report_cmd(void) __reentrant -{ - int8_t r; - - launch_args(); - if (ao_cmd_status != ao_cmd_success) - return; - r = launch_query(); - switch (r) { - case AO_RADIO_CMAC_OK: - if (query.valid) { - switch (query.arm_status) { - case ao_igniter_ready: - case ao_igniter_active: - printf ("Armed: "); - break; - default: - printf("Disarmed: "); - } - switch (query.igniter_status) { - default: - printf("unknown\n"); - break; - case ao_igniter_ready: - printf("igniter good\n"); - break; - case ao_igniter_open: - printf("igniter bad\n"); - break; - } - } else { - printf("Invalid channel %d\n", launch_channel); - } - printf("Rssi: %d\n", ao_radio_cmac_rssi); - break; - default: - printf("Error %d\n", r); - break; - } -} - -static void -launch_arm(void) __reentrant -{ - command.tick = ao_time() - tick_offset; - command.serial = launch_serial; - command.cmd = AO_LAUNCH_ARM; - command.channel = launch_channel; - ao_radio_cmac_send(&command, sizeof (command)); -} - -static void -launch_ignite(void) __reentrant -{ - command.tick = ao_time() - tick_offset; - command.serial = launch_serial; - command.cmd = AO_LAUNCH_FIRE; - command.channel = 0; - ao_radio_cmac_send(&command, sizeof (command)); -} - -static void -launch_fire_cmd(void) __reentrant -{ - static __xdata struct ao_launch_command command; - uint8_t secs; - uint8_t i; - int8_t r; - - launch_args(); - ao_cmd_decimal(); - secs = ao_cmd_lex_i; - if (ao_cmd_status != ao_cmd_success) - return; - r = launch_query(); - if (r != AO_RADIO_CMAC_OK) { - printf("query failed %d\n", r); - return; - } - - for (i = 0; i < 4; i++) { - printf("arm %d\n", i); flush(); - launch_arm(); - } - - secs = secs * 10 - 5; - if (secs > 100) - secs = 100; - for (i = 0; i < secs; i++) { - printf("fire %d\n", i); flush(); - launch_ignite(); - ao_delay(AO_MS_TO_TICKS(100)); - } -} - -static void -launch_arm_cmd(void) __reentrant -{ - uint8_t i; - int8_t r; - launch_args(); - r = launch_query(); - if (r != AO_RADIO_CMAC_OK) { - printf("query failed %d\n", r); - return; - } - for (i = 0; i < 4; i++) - launch_arm(); -} - -static void -launch_ignite_cmd(void) __reentrant -{ - uint8_t i; - launch_args(); - for (i = 0; i < 4; i++) - launch_ignite(); -} - -static __code struct ao_cmds ao_radio_cmac_cmds[] = { - { radio_cmac_send_cmd, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, - { radio_cmac_recv_cmd, "S \0Receive AES-CMAC packet. Timeout in ms" }, - { launch_report_cmd, "l \0Get remote launch status" }, - { launch_fire_cmd, "f \0Fire remote igniter" }, - { launch_arm_cmd, "a \0Arm remote igniter" }, - { launch_ignite_cmd, "i \0Pulse remote igniter" }, - { 0, NULL }, -}; - -void -ao_radio_cmac_init(void) -{ - ao_cmd_register(&ao_radio_cmac_cmds[0]); -} diff --git a/src/core/ao_radio_cmac.c b/src/core/ao_radio_cmac.c new file mode 100644 index 00000000..e263f0db --- /dev/null +++ b/src/core/ao_radio_cmac.c @@ -0,0 +1,406 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +#define AO_CMAC_KEY_LEN AO_AES_LEN +#define AO_CMAC_MAX_LEN (128 - AO_CMAC_KEY_LEN) + +static __xdata uint8_t ao_radio_cmac_mutex; +__pdata int16_t ao_radio_cmac_rssi; +static __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN]; +static __pdata uint8_t ao_radio_cmac_len; + +static uint8_t +getnibble(void) +{ + int8_t b; + + b = ao_cmd_hexchar(getchar()); + if (b < 0) { + ao_cmd_status = ao_cmd_lex_error; + return 0; + } + return (uint8_t) b; +} + +static uint8_t +getbyte(void) +{ + uint8_t b; + b = getnibble() << 4; + b |= getnibble(); + return b; +} + +static uint8_t +round_len(uint8_t len) +{ + uint8_t rem; + + /* Make sure we transfer at least one packet, and + * then make sure every packet is full. Note that + * there is no length encoded, and that the receiver + * must deal with any extra bytes in the packet + */ + if (len < AO_CMAC_KEY_LEN) + len = AO_CMAC_KEY_LEN; + rem = len % AO_CMAC_KEY_LEN; + if (rem != 0) + len += (AO_CMAC_KEY_LEN - rem); + return len; +} + +/* + * Sign and deliver the data sitting in the cmac buffer + */ +static void +radio_cmac_send(uint8_t len) __reentrant +{ + uint8_t i; + + len = round_len(len); + /* Make sure the AES key is loaded */ + ao_config_get(); + +#if HAS_MONITOR + ao_monitor_set(0); +#endif + + ao_mutex_get(&ao_aes_mutex); + ao_aes_set_mode(ao_aes_mode_cbc_mac); + ao_aes_set_key(ao_config.aes_key); + ao_aes_zero_iv(); + for (i = 0; i < len; i += AO_CMAC_KEY_LEN) { + if (i + AO_CMAC_KEY_LEN < len) + ao_aes_run(&cmac_data[i], NULL); + else + ao_aes_run(&cmac_data[i], &cmac_data[len]); + } + ao_mutex_put(&ao_aes_mutex); + + ao_radio_send(cmac_data, len + AO_CMAC_KEY_LEN); +} + +/* + * Receive and validate an incoming packet + */ + +static int8_t +radio_cmac_recv(uint8_t len, uint16_t timeout) __reentrant +{ + uint8_t i; + + len = round_len(len); +#if HAS_MONITOR + ao_monitor_set(0); +#endif + if (timeout) + ao_alarm(timeout); + + i = ao_radio_recv(cmac_data, len + AO_CMAC_KEY_LEN + 2); + ao_clear_alarm(); + + if (!i) { + ao_radio_cmac_rssi = 0; + return AO_RADIO_CMAC_TIMEOUT; + } + + ao_radio_cmac_rssi = (int16_t) (((int8_t) cmac_data[len + AO_CMAC_KEY_LEN]) >> 1) - 74; + if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & PKT_APPEND_STATUS_1_CRC_OK)) + return AO_RADIO_CMAC_CRC_ERROR; + + ao_config_get(); + + /* Compute the packet signature + */ + ao_mutex_get(&ao_aes_mutex); + ao_aes_set_mode(ao_aes_mode_cbc_mac); + ao_aes_set_key(ao_config.aes_key); + ao_aes_zero_iv(); + for (i = 0; i < len; i += AO_CMAC_KEY_LEN) { + if (i + AO_CMAC_KEY_LEN < len) + ao_aes_run(&cmac_data[i], NULL); + else + ao_aes_run(&cmac_data[i], &cmac_data[len + AO_CMAC_KEY_LEN + 2]); + } + ao_mutex_put(&ao_aes_mutex); + + /* Check the packet signature against the signature provided + * over the link + */ + + if (memcmp(&cmac_data[len], + &cmac_data[len + AO_CMAC_KEY_LEN + 2], + AO_CMAC_KEY_LEN) != 0) { + return AO_RADIO_CMAC_MAC_ERROR; + } + + return AO_RADIO_CMAC_OK; +} + +int8_t +ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant +{ + if (len > AO_CMAC_MAX_LEN) + return AO_RADIO_CMAC_LEN_ERROR; + ao_mutex_get(&ao_radio_cmac_mutex); + memcpy(cmac_data, packet, len); + radio_cmac_send(len); + ao_mutex_put(&ao_radio_cmac_mutex); + return AO_RADIO_CMAC_OK; +} + +int8_t +ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant +{ + uint8_t i; + if (len > AO_CMAC_MAX_LEN) + return AO_RADIO_CMAC_LEN_ERROR; + ao_mutex_get(&ao_radio_cmac_mutex); + i = radio_cmac_recv(len, timeout); + if (i == AO_RADIO_CMAC_OK) + memcpy(packet, cmac_data, len); + ao_mutex_put(&ao_radio_cmac_mutex); + return i; +} + +static void +radio_cmac_send_cmd(void) __reentrant +{ + uint8_t i; + uint8_t len; + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + len = ao_cmd_lex_i; + if (len > AO_CMAC_MAX_LEN) { + ao_cmd_status = ao_cmd_syntax_error; + return; + } + flush(); + ao_mutex_get(&ao_radio_cmac_mutex); + len = ao_cmd_lex_i; + for (i = 0; i < len; i++) { + cmac_data[i] = getbyte(); + if (ao_cmd_status != ao_cmd_success) + return; + } + radio_cmac_send(len); + ao_mutex_put(&ao_radio_cmac_mutex); +} + +static void +radio_cmac_recv_cmd(void) __reentrant +{ + uint8_t len, i; + uint16_t timeout; + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + len = ao_cmd_lex_i; + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + timeout = AO_MS_TO_TICKS(ao_cmd_lex_i); + ao_mutex_get(&ao_radio_cmac_mutex); + i = radio_cmac_recv(len, timeout); + if (i == AO_RADIO_CMAC_OK) { + printf ("PACKET "); + for (i = 0; i < len; i++) + printf("%02x", cmac_data[i]); + printf (" %d\n", ao_radio_cmac_rssi); + } else + printf ("ERROR %d %d\n", i, ao_radio_cmac_rssi); + ao_mutex_put(&ao_radio_cmac_mutex); +} + +static __xdata struct ao_launch_command command; +static __xdata struct ao_launch_query query; +static pdata uint16_t launch_serial; +static pdata uint8_t launch_channel; +static pdata uint16_t tick_offset; + +static void +launch_args(void) __reentrant +{ + ao_cmd_decimal(); + launch_serial = ao_cmd_lex_i; + ao_cmd_decimal(); + launch_channel = ao_cmd_lex_i; +} + +static int8_t +launch_query(void) +{ + uint8_t i; + int8_t r = AO_RADIO_CMAC_OK; + + tick_offset = ao_time(); + for (i = 0; i < 10; i++) { + printf ("."); flush(); + command.tick = ao_time(); + command.serial = launch_serial; + command.cmd = AO_LAUNCH_QUERY; + command.channel = launch_channel; + ao_radio_cmac_send(&command, sizeof (command)); + r = ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500)); + if (r == AO_RADIO_CMAC_OK) + break; + } + tick_offset -= query.tick; + printf("\n"); flush(); + return r; +} + +static void +launch_report_cmd(void) __reentrant +{ + int8_t r; + + launch_args(); + if (ao_cmd_status != ao_cmd_success) + return; + r = launch_query(); + switch (r) { + case AO_RADIO_CMAC_OK: + if (query.valid) { + switch (query.arm_status) { + case ao_igniter_ready: + case ao_igniter_active: + printf ("Armed: "); + break; + default: + printf("Disarmed: "); + } + switch (query.igniter_status) { + default: + printf("unknown\n"); + break; + case ao_igniter_ready: + printf("igniter good\n"); + break; + case ao_igniter_open: + printf("igniter bad\n"); + break; + } + } else { + printf("Invalid channel %d\n", launch_channel); + } + printf("Rssi: %d\n", ao_radio_cmac_rssi); + break; + default: + printf("Error %d\n", r); + break; + } +} + +static void +launch_arm(void) __reentrant +{ + command.tick = ao_time() - tick_offset; + command.serial = launch_serial; + command.cmd = AO_LAUNCH_ARM; + command.channel = launch_channel; + ao_radio_cmac_send(&command, sizeof (command)); +} + +static void +launch_ignite(void) __reentrant +{ + command.tick = ao_time() - tick_offset; + command.serial = launch_serial; + command.cmd = AO_LAUNCH_FIRE; + command.channel = 0; + ao_radio_cmac_send(&command, sizeof (command)); +} + +static void +launch_fire_cmd(void) __reentrant +{ + static __xdata struct ao_launch_command command; + uint8_t secs; + uint8_t i; + int8_t r; + + launch_args(); + ao_cmd_decimal(); + secs = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) + return; + r = launch_query(); + if (r != AO_RADIO_CMAC_OK) { + printf("query failed %d\n", r); + return; + } + + for (i = 0; i < 4; i++) { + printf("arm %d\n", i); flush(); + launch_arm(); + } + + secs = secs * 10 - 5; + if (secs > 100) + secs = 100; + for (i = 0; i < secs; i++) { + printf("fire %d\n", i); flush(); + launch_ignite(); + ao_delay(AO_MS_TO_TICKS(100)); + } +} + +static void +launch_arm_cmd(void) __reentrant +{ + uint8_t i; + int8_t r; + launch_args(); + r = launch_query(); + if (r != AO_RADIO_CMAC_OK) { + printf("query failed %d\n", r); + return; + } + for (i = 0; i < 4; i++) + launch_arm(); +} + +static void +launch_ignite_cmd(void) __reentrant +{ + uint8_t i; + launch_args(); + for (i = 0; i < 4; i++) + launch_ignite(); +} + +static __code struct ao_cmds ao_radio_cmac_cmds[] = { + { radio_cmac_send_cmd, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, + { radio_cmac_recv_cmd, "S \0Receive AES-CMAC packet. Timeout in ms" }, + { launch_report_cmd, "l \0Get remote launch status" }, + { launch_fire_cmd, "f \0Fire remote igniter" }, + { launch_arm_cmd, "a \0Arm remote igniter" }, + { launch_ignite_cmd, "i \0Pulse remote igniter" }, + { 0, NULL }, +}; + +void +ao_radio_cmac_init(void) +{ + ao_cmd_register(&ao_radio_cmac_cmds[0]); +} -- cgit v1.2.3 From 59588ba34159b27c02e1a886b46497ecfa0cf4d3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Jul 2012 16:22:23 -0700 Subject: Add ability to re-play telemetry through TeleDongle This adds a new command to TeleDongle to send arbitrary data, and then creates a new tool, 'ao-send-telem' that replays existing telemetry files through TeleDongle. Signed-off-by: Keith Packard --- ao-tools/Makefile.am | 2 +- ao-tools/ao-send-telem/Makefile.am | 12 ++ ao-tools/ao-send-telem/ao-send-telem.1 | 64 +++++++++ ao-tools/ao-send-telem/ao-send-telem.c | 238 +++++++++++++++++++++++++++++++++ configure.ac | 1 + src/core/ao_send_packet.c | 74 ++++++++++ src/core/ao_send_packet.h | 24 ++++ src/product/Makefile.teledongle | 1 + src/product/ao_teledongle.c | 2 + 9 files changed, 417 insertions(+), 1 deletion(-) create mode 100644 ao-tools/ao-send-telem/Makefile.am create mode 100644 ao-tools/ao-send-telem/ao-send-telem.1 create mode 100644 ao-tools/ao-send-telem/ao-send-telem.c create mode 100644 src/core/ao_send_packet.c create mode 100644 src/core/ao_send_packet.h (limited to 'src') diff --git a/ao-tools/Makefile.am b/ao-tools/Makefile.am index 6c315dd1..257fdaec 100644 --- a/ao-tools/Makefile.am +++ b/ao-tools/Makefile.am @@ -1 +1 @@ -SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list ao-load ao-telem ao-stmload +SUBDIRS=lib ao-rawload ao-dbg ao-bitbang ao-eeprom ao-list ao-load ao-telem ao-stmload ao-send-telem diff --git a/ao-tools/ao-send-telem/Makefile.am b/ao-tools/ao-send-telem/Makefile.am new file mode 100644 index 00000000..bfddf131 --- /dev/null +++ b/ao-tools/ao-send-telem/Makefile.am @@ -0,0 +1,12 @@ +bin_PROGRAMS=ao-send-telem + +AM_CFLAGS=-I$(top_srcdir)/ao-tools/lib $(LIBUSB_CFLAGS) +AO_POSTFLIGHT_LIBS=$(top_builddir)/ao-tools/lib/libao-tools.a + +ao_send_telem_DEPENDENCIES = $(AO_POSTFLIGHT_LIBS) + +ao_send_telem_LDADD=$(AO_POSTFLIGHT_LIBS) $(LIBUSB_LIBS) + +ao_send_telem_SOURCES = ao-send-telem.c + +man_MANS = ao-send-telem.1 diff --git a/ao-tools/ao-send-telem/ao-send-telem.1 b/ao-tools/ao-send-telem/ao-send-telem.1 new file mode 100644 index 00000000..fbdb2fe9 --- /dev/null +++ b/ao-tools/ao-send-telem/ao-send-telem.1 @@ -0,0 +1,64 @@ +.\" +.\" 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; either version 2 of the License, or +.\" (at your option) any later version. +.\" +.\" 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. +.\" +.\" +.TH AO-SEND-TELEM 1 "ao-send-telem" "" +.SH NAME +ao-send-telem \- Re-transmit stored telemetry file +.SH SYNOPSIS +.B "ao-send-telem" +[\-T \fItty-device\fP] +[\--tty \fItty-device\fP] +[\-D \fIaltos-device\fP] +[\--device \fIaltos-device\fP] +[\-F \fIfrequency (kHz)\fP] +[\--frequency \fIfrequency (kHz)\fP] +[\-R] +[\--realtime] + +.SH OPTIONS +.TP +\-T tty-device | --tty tty-device +This selects which tty device ao-dumplog uses to communicate with +the target device. +.TP +\-D AltOS-device | --device AltOS-device +Search for a connected device. This requires an argument of one of the +following forms: +.IP +TeleDongle:2 +.br +TeleDongle +.br +2 +.IP +Leaving out the product name will cause the tool to select a suitable +product, leaving out the serial number will cause the tool to match +one of the available devices. +.TP +\-F kHz | --frequency kHz +This selects which frequency to send the specified packets on. +.TP +\-R | --realtime +This makes the program delay between packets in pad mode. Normally, +pad mode packets are sent as quickly as possible. +.SH DESCRIPTION +.I ao-send-telem +reads the specified flight telemetry log and re-transmits it via the +specified ground station device +.SH AUTHOR +Keith Packard diff --git a/ao-tools/ao-send-telem/ao-send-telem.c b/ao-tools/ao-send-telem/ao-send-telem.c new file mode 100644 index 00000000..c4c354e0 --- /dev/null +++ b/ao-tools/ao-send-telem/ao-send-telem.c @@ -0,0 +1,238 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include "cc.h" +#include "cc-usb.h" + +static const struct option options[] = { + { .name = "tty", .has_arg = 1, .val = 'T' }, + { .name = "device", .has_arg = 1, .val = 'D' }, + { .name = "frequency", .has_arg = 1, .val = 'F' }, + { .name = "realtime", .has_arg = 0, .val = 'R' }, + { 0, 0, 0, 0}, +}; + +static void usage(char *program) +{ + fprintf(stderr, "usage: %s [--tty ] [--device ] [--frequency ] [--realtime] file.telem ...\n", program); + exit(1); +} + +#define bool(b) ((b) ? "true" : "false") + +struct ao_telem_list { + struct ao_telem_list *next; + union ao_telemetry_all telem; +}; + +static struct ao_telem_list *telem_list, **telem_last; + +static void +trim_telem(uint16_t time) +{ + while (telem_list && (int16_t) (time - telem_list->telem.generic.tick) > 0) { + struct ao_telem_list *next = telem_list->next; + free(telem_list); + telem_list = next; + } + if (!telem_list) + telem_last = &telem_list; +} + +static void +add_telem(union ao_telemetry_all *telem) +{ + struct ao_telem_list *new = malloc (sizeof (struct ao_telem_list)); + trim_telem((uint16_t) (telem->generic.tick - 20 * 100)); + new->telem = *telem; + new->next = 0; + *telem_last = new; + telem_last = &new->next; +} + +static enum ao_flight_state cur_state = ao_flight_invalid; +static enum ao_flight_state last_state = ao_flight_invalid; + +static enum ao_flight_state +packet_state(union ao_telemetry_all *telem) +{ + switch (telem->generic.type) { + case AO_TELEMETRY_SENSOR_TELEMETRUM: + case AO_TELEMETRY_SENSOR_TELEMINI: + case AO_TELEMETRY_SENSOR_TELENANO: + cur_state = telem->sensor.state; + break; + case AO_TELEMETRY_MEGA_DATA: + cur_state = telem->mega_data.state; + break; + } + return cur_state; +} + +static const char *state_names[] = { + "startup", + "idle", + "pad", + "boost", + "fast", + "coast", + "drogue", + "main", + "landed", + "invalid" +}; + +static void +send_telem(struct cc_usb *cc, union ao_telemetry_all *telem) +{ + int rssi = (int8_t) telem->generic.rssi / 2 - 74; + int i; + uint8_t *b; + + packet_state(telem); + if (cur_state != last_state) { + if (0 <= cur_state && cur_state < sizeof(state_names) / sizeof (state_names[0])) + printf ("%s\n", state_names[cur_state]); + last_state = cur_state; + } + cc_usb_printf(cc, "S 20\n"); + b = (uint8_t *) telem; + for (i = 0; i < 0x20; i++) + cc_usb_printf(cc, "%02x", b[i]); + cc_usb_sync(cc); +} + +static void +do_delay(uint16_t now, uint16_t then) +{ + int16_t delay = (int16_t) (now - then); + + if (delay > 0 && delay < 1000) + usleep(delay * 10 * 1000); +} + +static uint16_t +send_queued(struct cc_usb *cc, int pause) +{ + struct ao_telem_list *next; + uint16_t tick = 0; + int started = 0; + + while (telem_list) { + if (started && pause) + do_delay(telem_list->telem.generic.tick, tick); + tick = telem_list->telem.generic.tick; + started = 1; + send_telem(cc, &telem_list->telem); + + next = telem_list->next; + free(telem_list); + telem_list = next; + } + return tick; +} + +int +main (int argc, char **argv) +{ + struct cc_usb *cc; + char *tty = NULL; + char *device = NULL; + char line[80]; + int c, i, ret = 0; + int freq = 434550; + char *s; + FILE *file; + int serial; + uint16_t last_tick; + int started; + int realtime = 0; + + + while ((c = getopt_long(argc, argv, "RT:D:F:", options, NULL)) != -1) { + switch (c) { + case 'T': + tty = optarg; + break; + case 'D': + device = optarg; + break; + case 'F': + freq = atoi(optarg); + break; + case 'R': + realtime = 1; + default: + usage(argv[0]); + break; + } + } + if (!tty) + tty = cc_usbdevs_find_by_arg(device, "TeleDongle"); + if (!tty) + tty = getenv("ALTOS_TTY"); + if (!tty) + tty="/dev/ttyACM0"; + cc = cc_usb_open(tty); + if (!cc) + exit (1); + + cc_usb_printf(cc, "m 0\n"); + cc_usb_printf(cc, "F %d\n", freq); + for (i = optind; i < argc; i++) { + file = fopen(argv[i], "r"); + if (!file) { + perror(argv[i]); + ret++; + continue; + } + started = 0; + last_tick = 0; + while (fgets(line, sizeof (line), file)) { + union ao_telemetry_all telem; + + if (cc_telemetry_parse(line, &telem)) { + /* + * Skip packets with CRC errors. + */ + if ((telem.generic.status & (1 << 7)) == 0) + continue; + + if (started) { + do_delay(telem.generic.tick, last_tick); + last_tick = telem.generic.tick; + send_telem(cc, &telem); + } else { + add_telem(&telem); + if (packet_state(&telem) > ao_flight_pad) { + started = 1; + last_tick = send_queued(cc, realtime); + } + } + } + } + fclose (file); + + } + return ret; +} diff --git a/configure.ac b/configure.ac index bcd2dcac..c59261af 100644 --- a/configure.ac +++ b/configure.ac @@ -160,6 +160,7 @@ ao-tools/ao-list/Makefile ao-tools/ao-load/Makefile ao-tools/ao-telem/Makefile ao-tools/ao-stmload/Makefile +ao-tools/ao-send-telem/Makefile ao-utils/Makefile src/Version ]) diff --git a/src/core/ao_send_packet.c b/src/core/ao_send_packet.c new file mode 100644 index 00000000..1a8e74de --- /dev/null +++ b/src/core/ao_send_packet.c @@ -0,0 +1,74 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +#define AO_MAX_SEND 128 + +static __xdata uint8_t ao_send[AO_MAX_SEND]; + +static uint8_t +getnibble(void) +{ + char 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 +ao_send_packet(void) +{ + __pdata uint16_t count; + uint8_t b; + __pdata uint8_t i; + + ao_cmd_hex(); + count = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) + return; + if (count > AO_MAX_SEND - 2) { + ao_cmd_status = ao_cmd_syntax_error; + return; + } + for (i = 0; i < count; i++) { + b = getnibble() << 4; + b |= getnibble(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_send[i] = b; + } + ao_radio_send(ao_send, count); +} + +static __code struct ao_cmds ao_send_packet_cmds[] = { + { ao_send_packet, "S \0Send packet. Data on next line" }, + { 0, NULL } +}; + +void +ao_send_packet_init(void) +{ + ao_cmd_register(&ao_send_packet_cmds[0]); +} diff --git a/src/core/ao_send_packet.h b/src/core/ao_send_packet.h new file mode 100644 index 00000000..526f7b55 --- /dev/null +++ b/src/core/ao_send_packet.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_SEND_PACKET_H_ +#define _AO_SEND_PACKET_H_ + +void +ao_send_packet_init(void); + +#endif /* _AO_SEND_PACKET_H_ */ diff --git a/src/product/Makefile.teledongle b/src/product/Makefile.teledongle index 5105b567..3101b777 100644 --- a/src/product/Makefile.teledongle +++ b/src/product/Makefile.teledongle @@ -43,6 +43,7 @@ CC1111_SRC = \ ao_packet.c \ ao_packet_master.c \ ao_radio.c \ + ao_send_packet.c \ ao_romconfig.c \ ao_string.c \ ao_timer.c \ diff --git a/src/product/ao_teledongle.c b/src/product/ao_teledongle.c index 0c829e97..25ebe73e 100644 --- a/src/product/ao_teledongle.c +++ b/src/product/ao_teledongle.c @@ -16,6 +16,7 @@ */ #include "ao.h" +#include void main(void) @@ -32,6 +33,7 @@ main(void) ao_rssi_init(AO_LED_RED); ao_radio_init(); ao_packet_master_init(); + ao_send_packet_init(); #if HAS_DBG ao_dbg_init(); #endif -- cgit v1.2.3 From 21e39811bd234c6f66ab7644864fcc1b8c316998 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Jul 2012 19:36:50 -0700 Subject: altos/cc1111: Fix serial 0 option 2 pins definitions tx/rx are 4/5, rts/cts are 2/3 Signed-off-by: Keith Packard --- src/cc1111/Makefile.cc1111 | 2 +- src/cc1111/ao_serial.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cc1111/Makefile.cc1111 b/src/cc1111/Makefile.cc1111 index f7ecce33..bfd444dd 100644 --- a/src/cc1111/Makefile.cc1111 +++ b/src/cc1111/Makefile.cc1111 @@ -2,7 +2,7 @@ CC=sdcc CFLAGS=--model-small --debug --opt-code-speed -DCODESIZE=$(CODESIZE) -CFLAGS += $(PRODUCT_DEF) -I. -I.. -I../core -I../cc1111 -I../driver -I../product +CFLAGS += $(PRODUCT_DEF) -I. -I.. -I../core -I../cc1111 -I../drivers -I../product CODESIZE ?= 0x8000 diff --git a/src/cc1111/ao_serial.c b/src/cc1111/ao_serial.c index 00c85ff3..d90103b0 100644 --- a/src/cc1111/ao_serial.c +++ b/src/cc1111/ao_serial.c @@ -236,9 +236,9 @@ ao_serial_init(void) (P2SEL_PRI3P1_USART0 | P2SEL_PRI0P1_USART0); /* Make the USART pins be controlled by the USART */ - P1SEL |= (1 << 2) | (1 << 3); -#if HAS_SERIAL_0_HW_FLOW P1SEL |= (1 << 5) | (1 << 4); +#if HAS_SERIAL_0_HW_FLOW + P1SEL |= (1 << 3) | (1 << 2); #endif #endif -- cgit v1.2.3 From e4d244eefa4c779cd9c8a91389bf998c54705b72 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Jul 2012 19:42:53 -0700 Subject: altos: Add software AES implementation This is untested Signed-off-by: Keith Packard --- src/aes/ao_aes.c | 390 ++++++++++++++++++++++++ src/aes/ao_aes_int.h | 64 ++++ src/aes/ao_aes_tables.c | 768 +++++++++++++++++++++++++++++++++++++++++++++++ src/aes/ao_aes_tables.h | 10 + src/core/ao_aes.h | 2 + src/core/ao_radio_cmac.c | 8 +- src/stm/Makefile.defs | 2 +- 7 files changed, 1239 insertions(+), 5 deletions(-) create mode 100644 src/aes/ao_aes.c create mode 100644 src/aes/ao_aes_int.h create mode 100644 src/aes/ao_aes_tables.c create mode 100644 src/aes/ao_aes_tables.h (limited to 'src') diff --git a/src/aes/ao_aes.c b/src/aes/ao_aes.c new file mode 100644 index 00000000..4977aaf8 --- /dev/null +++ b/src/aes/ao_aes.c @@ -0,0 +1,390 @@ +/* Copyright (C) 2000-2009 Peter Selinger. + This file is part of ccrypt. It is free software and it is covered + by the GNU general public license. See the file COPYING for details. */ + +/* rijndael.c - optimized version of the Rijndeal cipher */ +/* $Id: rijndael.c 258 2009-08-26 17:46:10Z selinger $ */ + +/* derived from original source: rijndael-alg-ref.c v2.0 August '99 + * Reference ANSI C code for NIST competition + * authors: Paulo Barreto + * Vincent Rijmen + */ + +#include +#include +#include "ao_aes_int.h" + +static const int xshifts[3][2][4] = { + {{0, 1, 2, 3}, + {0, 3, 2, 1}}, + + {{0, 1, 2, 3}, + {0, 5, 4, 3}}, + + {{0, 1, 3, 4}, + {0, 7, 5, 4}}, +}; + +/* Exor corresponding text input and round key input bytes */ +/* the result is written to res, which can be the same as a */ +static inline void xKeyAddition(word32 res[MAXBC], word32 a[MAXBC], + word32 rk[MAXBC], int BC) +{ + int j; + + for (j = 0; j < BC; j++) { + res[j] = a[j] ^ rk[j]; + } +} + +#if 0 /* code included for reference */ + +/* shift rows a, return result in res. This avoids having to copy a + tmp array back to a. res must not be a. */ +static inline void xShiftRow(word32 res[MAXBC], word32 a[MAXBC], int shift[4], + int BC) +{ + word8 (*a8)[4] = (word8 (*)[4]) a; + word8 (*res8)[4] = (word8 (*)[4]) res; + + /* Row 0 remains unchanged + * The other three rows are shifted a variable amount + */ + int i, j; + int s; + + for (j = 0; j < BC; j++) { + res8[j][0] = a8[j][0]; + } + for (i = 1; i < 4; i++) { + s = shift[i]; + for (j = 0; j < BC; j++) { + res8[j][i] = a8[(j + s) % BC][i]; + } + } +} + +static inline void xSubstitution(word32 a[MAXBC], word8 box[256], int BC) +{ + word8 (*a8)[4] = (word8 (*)[4]) a; + + /* Replace every byte of the input by the byte at that place + * in the nonlinear S-box + */ + int i, j; + + for (i = 0; i < 4; i++) { + for (j = 0; j < BC; j++) { + a8[j][i] = box[a[j][i]]; + } + } +} + +#endif /* code included for reference */ + +/* profiling shows that the ccrypt program spends about 50% of its + time in the function xShiftSubst. Splitting the inner "for" + statement into two parts - versus using the expensive "%" modulo + operation, makes this function about 44% faster, thereby making the + entire program about 28% faster. With -O3 optimization, the time + savings are even more dramatic - ccrypt runs between 55% and 65% + faster on most platforms. */ + +/* do ShiftRow and Substitution together. res must not be a. */ +static inline void xShiftSubst(word32 res[MAXBC], word32 a[MAXBC], + int shift[4], int BC, const word8 box[256]) +{ + int i, j; + int s; + word8 (*a8)[4] = (word8 (*)[4]) a; + word8 (*res8)[4] = (word8 (*)[4]) res; + + for (j = 0; j < BC; j++) { + res8[j][0] = box[a8[j][0]]; + } + for (i = 1; i < 4; i++) { + s = shift[i]; + for (j = 0; j < BC - s; j++) { + res8[j][i] = box[a8[(j + s)][i]]; + } + for (j = BC - s; j < BC; j++) { + res8[j][i] = box[a8[(j + s) - BC][i]]; + } + } +} + +#if 0 /* code included for reference */ + +/* Mix the four bytes of every column in a linear way */ +/* the result is written to res, which may equal a */ +static inline void xMixColumn(word32 res[MAXBC], word32 a[MAXBC], int BC) +{ + int j; + word32 b; + word8 (*a8)[4] = (word8 (*)[4]) a; + + for (j = 0; j < BC; j++) { + b = M0[0][a8[j][0]].w32; + b ^= M0[1][a8[j][1]].w32; + b ^= M0[2][a8[j][2]].w32; + b ^= M0[3][a8[j][3]].w32; + res[j] = b; + } +} + +#endif /* code included for reference */ + +/* do MixColumn and KeyAddition together */ +static inline void xMixAdd(word32 res[MAXBC], word32 a[MAXBC], + word32 rk[MAXBC], int BC) +{ + int j; + word32 b; + word8 (*a8)[4] = (word8 (*)[4]) a; + + for (j = 0; j < BC; j++) { + b = M0[0][a8[j][0]].w32; + b ^= M0[1][a8[j][1]].w32; + b ^= M0[2][a8[j][2]].w32; + b ^= M0[3][a8[j][3]].w32; + b ^= rk[j]; + res[j] = b; + } +} + +/* Mix the four bytes of every column in a linear way + * This is the opposite operation of xMixColumn */ +/* the result is written to res, which may equal a */ +static inline void xInvMixColumn(word32 res[MAXBC], word32 a[MAXBC], int BC) +{ + int j; + word32 b; + word8 (*a8)[4] = (word8 (*)[4]) a; + + for (j = 0; j < BC; j++) { + b = M1[0][a8[j][0]].w32; + b ^= M1[1][a8[j][1]].w32; + b ^= M1[2][a8[j][2]].w32; + b ^= M1[3][a8[j][3]].w32; + res[j] = b; + } +} + +#if 0 /* code included for reference */ + +/* do KeyAddition and InvMixColumn together */ +static inline void xAddInvMix(word32 res[MAXBC], word32 a[MAXBC], + word32 rk[MAXBC], int BC) +{ + int j; + word32 b; + word8 (*a8)[4] = (word8 (*)[4]) a; + + for (j = 0; j < BC; j++) { + a[j] = a[j] ^ rk[j]; + b = M1[0][a8[j][0]].w32; + b ^= M1[1][a8[j][1]].w32; + b ^= M1[2][a8[j][2]].w32; + b ^= M1[3][a8[j][3]].w32; + res[j] = b; + } +} + +#endif /* code included for reference */ + +int xrijndaelKeySched(word32 key[], int keyBits, int blockBits, + roundkey *rkk) +{ + /* Calculate the necessary round keys + * The number of calculations depends on keyBits and blockBits */ + int KC, BC, ROUNDS; + int i, j, t, rconpointer = 0; + word8 (*k8)[4] = (word8 (*)[4]) key; + + switch (keyBits) { + case 128: + KC = 4; + break; + case 192: + KC = 6; + break; + case 256: + KC = 8; + break; + default: + return -1; + } + + switch (blockBits) { + case 128: + BC = 4; + break; + case 192: + BC = 6; + break; + case 256: + BC = 8; + break; + default: + return -2; + } + + ROUNDS = KC > BC ? KC + 6 : BC + 6; + + t = 0; + /* copy values into round key array */ + for (j = 0; (j < KC) && (t < (ROUNDS + 1) * BC); j++, t++) + rkk->rk[t] = key[j]; + + while (t < (ROUNDS + 1) * BC) { /* while not enough round key material */ + /* calculate new values */ + for (i = 0; i < 4; i++) { + k8[0][i] ^= xS[k8[KC - 1][(i + 1) % 4]]; + } + k8[0][0] ^= xrcon[rconpointer++]; + + if (KC != 8) { + for (j = 1; j < KC; j++) { + key[j] ^= key[j - 1]; + } + } else { + for (j = 1; j < 4; j++) { + key[j] ^= key[j - 1]; + } + for (i = 0; i < 4; i++) { + k8[4][i] ^= xS[k8[3][i]]; + } + for (j = 5; j < 8; j++) { + key[j] ^= key[j - 1]; + } + } + /* copy values into round key array */ + for (j = 0; (j < KC) && (t < (ROUNDS + 1) * BC); j++, t++) { + rkk->rk[t] = key[j]; + } + } + + /* make roundkey structure */ + rkk->BC = BC; + rkk->KC = KC; + rkk->ROUNDS = ROUNDS; + for (i = 0; i < 2; i++) { + for (j = 0; j < 4; j++) { + rkk->shift[i][j] = xshifts[(BC - 4) >> 1][i][j]; + } + } + + return 0; +} + +/* Encryption of one block. */ + +void xrijndaelEncrypt(word32 block[], roundkey *rkk) +{ + word32 block2[MAXBC]; /* hold intermediate result */ + int r; + + int *shift = rkk->shift[0]; + int BC = rkk->BC; + int ROUNDS = rkk->ROUNDS; + word32 *rp = rkk->rk; + + /* begin with a key addition */ + xKeyAddition(block, block, rp, BC); + rp += BC; + + /* ROUNDS-1 ordinary rounds */ + for (r = 1; r < ROUNDS; r++) { + xShiftSubst(block2, block, shift, BC, xS); + xMixAdd(block, block2, rp, BC); + rp += BC; + } + + /* Last round is special: there is no xMixColumn */ + xShiftSubst(block2, block, shift, BC, xS); + xKeyAddition(block, block2, rp, BC); +} + +void xrijndaelDecrypt(word32 block[], roundkey *rkk) +{ + word32 block2[MAXBC]; /* hold intermediate result */ + int r; + + int *shift = rkk->shift[1]; + int BC = rkk->BC; + int ROUNDS = rkk->ROUNDS; + word32 *rp = rkk->rk + ROUNDS * BC; + + /* To decrypt: apply the inverse operations of the encrypt routine, + * in opposite order + * + * (xKeyAddition is an involution: it's equal to its inverse) + * (the inverse of xSubstitution with table S is xSubstitution with the + * inverse table of S) + * (the inverse of xShiftRow is xShiftRow over a suitable distance) + */ + + /* First the special round: + * without xInvMixColumn + * with extra xKeyAddition + */ + xKeyAddition(block2, block, rp, BC); + xShiftSubst(block, block2, shift, BC, xSi); + rp -= BC; + + /* ROUNDS-1 ordinary rounds + */ + for (r = ROUNDS - 1; r > 0; r--) { + xKeyAddition(block, block, rp, BC); + xInvMixColumn(block2, block, BC); + xShiftSubst(block, block2, shift, BC, xSi); + rp -= BC; + } + + /* End with the extra key addition + */ + + xKeyAddition(block, block, rp, BC); +} + +uint8_t ao_aes_mutex; +static roundkey rkk; + +static uint8_t iv[16]; + +void +ao_aes_set_mode(enum ao_aes_mode mode) +{ + /* we only do CBC_MAC anyways... */ +} + +void +ao_aes_set_key(__xdata uint8_t *in) +{ + xrijndaelKeySched((word32 *) in, 128, 128, &rkk); +} + +void +ao_aes_zero_iv(void) +{ + memset(iv, '\0', sizeof (iv)); +} + +void +ao_aes_run(__xdata uint8_t *in, + __xdata uint8_t *out) +{ + uint8_t i; + + for (i = 0; i < 16; i++) + iv[i] ^= in[i]; + xrijndaelEncrypt((word32 *) iv, &rkk); + if (out) + memcpy(out, iv, 16); +} + +void +ao_aes_init(void) +{ +} diff --git a/src/aes/ao_aes_int.h b/src/aes/ao_aes_int.h new file mode 100644 index 00000000..7990a2e1 --- /dev/null +++ b/src/aes/ao_aes_int.h @@ -0,0 +1,64 @@ +/* Copyright (C) 2000-2009 Peter Selinger. + This file is part of ccrypt. It is free software and it is covered + by the GNU general public license. See the file COPYING for details. */ + +/* rijndael.h */ +/* $Id: rijndael.h 258 2009-08-26 17:46:10Z selinger $ */ + +/* derived from original source: rijndael-alg-ref.h v2.0 August '99 + * Reference ANSI C code for NIST competition + * authors: Paulo Barreto + * Vincent Rijmen + */ + +#ifndef __RIJNDAEL_H +#define __RIJNDAEL_H + +#include + +typedef uint8_t word8; +typedef uint32_t word32; + +/* a type to hold 32 bits accessible as 1 integer or 4 bytes */ +union word8x4_u { + word8 w8[4]; + word32 w32; +}; +typedef union word8x4_u word8x4; + +#include "ao_aes_tables.h" + +#define MAXBC (256/32) +#define MAXKC (256/32) +#define MAXROUNDS 14 +#define MAXRK ((MAXROUNDS+1)*MAXBC) + +typedef struct { + int BC; + int KC; + int ROUNDS; + int shift[2][4]; + word32 rk[MAXRK]; +} roundkey; + +/* keys and blocks are externally treated as word32 arrays, to + make sure they are aligned on 4-byte boundaries on architectures + that require it. */ + +/* make a roundkey rkk from key. key must have appropriate size given + by keyBits. keyBits and blockBits may only be 128, 196, or + 256. Returns non-zero if arguments are invalid. */ + +int xrijndaelKeySched(word32 key[], int keyBits, int blockBits, + roundkey *rkk); + +/* encrypt, resp. decrypt, block using rijndael roundkey rkk. rkk must + have been created with xrijndaelKeySched. Size of block, in bits, + must be equal to blockBits parameter that was used to make rkk. In + all other cases, behavior is undefined - for reasons of speed, no + check for error conditions is done. */ + +void xrijndaelEncrypt(word32 block[], roundkey *rkk); +void xrijndaelDecrypt(word32 block[], roundkey *rkk); + +#endif /* __RIJNDAEL_H */ diff --git a/src/aes/ao_aes_tables.c b/src/aes/ao_aes_tables.c new file mode 100644 index 00000000..1bca227c --- /dev/null +++ b/src/aes/ao_aes_tables.c @@ -0,0 +1,768 @@ +/* Copyright (C) 2000-2009 Peter Selinger. + This file is part of ccrypt. It is free software and it is covered + by the GNU general public license. See the file COPYING for details. */ + +/* generated by maketables.c */ + +#include "ao_aes_int.h" + +const word8x4 M0[4][256] = { + { + {{ 0, 0, 0, 0}}, {{ 2, 1, 1, 3}}, {{ 4, 2, 2, 6}}, + {{ 6, 3, 3, 5}}, {{ 8, 4, 4, 12}}, {{ 10, 5, 5, 15}}, + {{ 12, 6, 6, 10}}, {{ 14, 7, 7, 9}}, {{ 16, 8, 8, 24}}, + {{ 18, 9, 9, 27}}, {{ 20, 10, 10, 30}}, {{ 22, 11, 11, 29}}, + {{ 24, 12, 12, 20}}, {{ 26, 13, 13, 23}}, {{ 28, 14, 14, 18}}, + {{ 30, 15, 15, 17}}, {{ 32, 16, 16, 48}}, {{ 34, 17, 17, 51}}, + {{ 36, 18, 18, 54}}, {{ 38, 19, 19, 53}}, {{ 40, 20, 20, 60}}, + {{ 42, 21, 21, 63}}, {{ 44, 22, 22, 58}}, {{ 46, 23, 23, 57}}, + {{ 48, 24, 24, 40}}, {{ 50, 25, 25, 43}}, {{ 52, 26, 26, 46}}, + {{ 54, 27, 27, 45}}, {{ 56, 28, 28, 36}}, {{ 58, 29, 29, 39}}, + {{ 60, 30, 30, 34}}, {{ 62, 31, 31, 33}}, {{ 64, 32, 32, 96}}, + {{ 66, 33, 33, 99}}, {{ 68, 34, 34, 102}}, {{ 70, 35, 35, 101}}, + {{ 72, 36, 36, 108}}, {{ 74, 37, 37, 111}}, {{ 76, 38, 38, 106}}, + {{ 78, 39, 39, 105}}, {{ 80, 40, 40, 120}}, {{ 82, 41, 41, 123}}, + {{ 84, 42, 42, 126}}, {{ 86, 43, 43, 125}}, {{ 88, 44, 44, 116}}, + {{ 90, 45, 45, 119}}, {{ 92, 46, 46, 114}}, {{ 94, 47, 47, 113}}, + {{ 96, 48, 48, 80}}, {{ 98, 49, 49, 83}}, {{100, 50, 50, 86}}, + {{102, 51, 51, 85}}, {{104, 52, 52, 92}}, {{106, 53, 53, 95}}, + {{108, 54, 54, 90}}, {{110, 55, 55, 89}}, {{112, 56, 56, 72}}, + {{114, 57, 57, 75}}, {{116, 58, 58, 78}}, {{118, 59, 59, 77}}, + {{120, 60, 60, 68}}, {{122, 61, 61, 71}}, {{124, 62, 62, 66}}, + {{126, 63, 63, 65}}, {{128, 64, 64, 192}}, {{130, 65, 65, 195}}, + {{132, 66, 66, 198}}, {{134, 67, 67, 197}}, {{136, 68, 68, 204}}, + {{138, 69, 69, 207}}, {{140, 70, 70, 202}}, {{142, 71, 71, 201}}, + {{144, 72, 72, 216}}, {{146, 73, 73, 219}}, {{148, 74, 74, 222}}, + {{150, 75, 75, 221}}, {{152, 76, 76, 212}}, {{154, 77, 77, 215}}, + {{156, 78, 78, 210}}, {{158, 79, 79, 209}}, {{160, 80, 80, 240}}, + {{162, 81, 81, 243}}, {{164, 82, 82, 246}}, {{166, 83, 83, 245}}, + {{168, 84, 84, 252}}, {{170, 85, 85, 255}}, {{172, 86, 86, 250}}, + {{174, 87, 87, 249}}, {{176, 88, 88, 232}}, {{178, 89, 89, 235}}, + {{180, 90, 90, 238}}, {{182, 91, 91, 237}}, {{184, 92, 92, 228}}, + {{186, 93, 93, 231}}, {{188, 94, 94, 226}}, {{190, 95, 95, 225}}, + {{192, 96, 96, 160}}, {{194, 97, 97, 163}}, {{196, 98, 98, 166}}, + {{198, 99, 99, 165}}, {{200, 100, 100, 172}}, {{202, 101, 101, 175}}, + {{204, 102, 102, 170}}, {{206, 103, 103, 169}}, {{208, 104, 104, 184}}, + {{210, 105, 105, 187}}, {{212, 106, 106, 190}}, {{214, 107, 107, 189}}, + {{216, 108, 108, 180}}, {{218, 109, 109, 183}}, {{220, 110, 110, 178}}, + {{222, 111, 111, 177}}, {{224, 112, 112, 144}}, {{226, 113, 113, 147}}, + {{228, 114, 114, 150}}, {{230, 115, 115, 149}}, {{232, 116, 116, 156}}, + {{234, 117, 117, 159}}, {{236, 118, 118, 154}}, {{238, 119, 119, 153}}, + {{240, 120, 120, 136}}, {{242, 121, 121, 139}}, {{244, 122, 122, 142}}, + {{246, 123, 123, 141}}, {{248, 124, 124, 132}}, {{250, 125, 125, 135}}, + {{252, 126, 126, 130}}, {{254, 127, 127, 129}}, {{ 27, 128, 128, 155}}, + {{ 25, 129, 129, 152}}, {{ 31, 130, 130, 157}}, {{ 29, 131, 131, 158}}, + {{ 19, 132, 132, 151}}, {{ 17, 133, 133, 148}}, {{ 23, 134, 134, 145}}, + {{ 21, 135, 135, 146}}, {{ 11, 136, 136, 131}}, {{ 9, 137, 137, 128}}, + {{ 15, 138, 138, 133}}, {{ 13, 139, 139, 134}}, {{ 3, 140, 140, 143}}, + {{ 1, 141, 141, 140}}, {{ 7, 142, 142, 137}}, {{ 5, 143, 143, 138}}, + {{ 59, 144, 144, 171}}, {{ 57, 145, 145, 168}}, {{ 63, 146, 146, 173}}, + {{ 61, 147, 147, 174}}, {{ 51, 148, 148, 167}}, {{ 49, 149, 149, 164}}, + {{ 55, 150, 150, 161}}, {{ 53, 151, 151, 162}}, {{ 43, 152, 152, 179}}, + {{ 41, 153, 153, 176}}, {{ 47, 154, 154, 181}}, {{ 45, 155, 155, 182}}, + {{ 35, 156, 156, 191}}, {{ 33, 157, 157, 188}}, {{ 39, 158, 158, 185}}, + {{ 37, 159, 159, 186}}, {{ 91, 160, 160, 251}}, {{ 89, 161, 161, 248}}, + {{ 95, 162, 162, 253}}, {{ 93, 163, 163, 254}}, {{ 83, 164, 164, 247}}, + {{ 81, 165, 165, 244}}, {{ 87, 166, 166, 241}}, {{ 85, 167, 167, 242}}, + {{ 75, 168, 168, 227}}, {{ 73, 169, 169, 224}}, {{ 79, 170, 170, 229}}, + {{ 77, 171, 171, 230}}, {{ 67, 172, 172, 239}}, {{ 65, 173, 173, 236}}, + {{ 71, 174, 174, 233}}, {{ 69, 175, 175, 234}}, {{123, 176, 176, 203}}, + {{121, 177, 177, 200}}, {{127, 178, 178, 205}}, {{125, 179, 179, 206}}, + {{115, 180, 180, 199}}, {{113, 181, 181, 196}}, {{119, 182, 182, 193}}, + {{117, 183, 183, 194}}, {{107, 184, 184, 211}}, {{105, 185, 185, 208}}, + {{111, 186, 186, 213}}, {{109, 187, 187, 214}}, {{ 99, 188, 188, 223}}, + {{ 97, 189, 189, 220}}, {{103, 190, 190, 217}}, {{101, 191, 191, 218}}, + {{155, 192, 192, 91}}, {{153, 193, 193, 88}}, {{159, 194, 194, 93}}, + {{157, 195, 195, 94}}, {{147, 196, 196, 87}}, {{145, 197, 197, 84}}, + {{151, 198, 198, 81}}, {{149, 199, 199, 82}}, {{139, 200, 200, 67}}, + {{137, 201, 201, 64}}, {{143, 202, 202, 69}}, {{141, 203, 203, 70}}, + {{131, 204, 204, 79}}, {{129, 205, 205, 76}}, {{135, 206, 206, 73}}, + {{133, 207, 207, 74}}, {{187, 208, 208, 107}}, {{185, 209, 209, 104}}, + {{191, 210, 210, 109}}, {{189, 211, 211, 110}}, {{179, 212, 212, 103}}, + {{177, 213, 213, 100}}, {{183, 214, 214, 97}}, {{181, 215, 215, 98}}, + {{171, 216, 216, 115}}, {{169, 217, 217, 112}}, {{175, 218, 218, 117}}, + {{173, 219, 219, 118}}, {{163, 220, 220, 127}}, {{161, 221, 221, 124}}, + {{167, 222, 222, 121}}, {{165, 223, 223, 122}}, {{219, 224, 224, 59}}, + {{217, 225, 225, 56}}, {{223, 226, 226, 61}}, {{221, 227, 227, 62}}, + {{211, 228, 228, 55}}, {{209, 229, 229, 52}}, {{215, 230, 230, 49}}, + {{213, 231, 231, 50}}, {{203, 232, 232, 35}}, {{201, 233, 233, 32}}, + {{207, 234, 234, 37}}, {{205, 235, 235, 38}}, {{195, 236, 236, 47}}, + {{193, 237, 237, 44}}, {{199, 238, 238, 41}}, {{197, 239, 239, 42}}, + {{251, 240, 240, 11}}, {{249, 241, 241, 8}}, {{255, 242, 242, 13}}, + {{253, 243, 243, 14}}, {{243, 244, 244, 7}}, {{241, 245, 245, 4}}, + {{247, 246, 246, 1}}, {{245, 247, 247, 2}}, {{235, 248, 248, 19}}, + {{233, 249, 249, 16}}, {{239, 250, 250, 21}}, {{237, 251, 251, 22}}, + {{227, 252, 252, 31}}, {{225, 253, 253, 28}}, {{231, 254, 254, 25}}, + {{229, 255, 255, 26}}, + }, + { + {{ 0, 0, 0, 0}}, {{ 3, 2, 1, 1}}, {{ 6, 4, 2, 2}}, + {{ 5, 6, 3, 3}}, {{ 12, 8, 4, 4}}, {{ 15, 10, 5, 5}}, + {{ 10, 12, 6, 6}}, {{ 9, 14, 7, 7}}, {{ 24, 16, 8, 8}}, + {{ 27, 18, 9, 9}}, {{ 30, 20, 10, 10}}, {{ 29, 22, 11, 11}}, + {{ 20, 24, 12, 12}}, {{ 23, 26, 13, 13}}, {{ 18, 28, 14, 14}}, + {{ 17, 30, 15, 15}}, {{ 48, 32, 16, 16}}, {{ 51, 34, 17, 17}}, + {{ 54, 36, 18, 18}}, {{ 53, 38, 19, 19}}, {{ 60, 40, 20, 20}}, + {{ 63, 42, 21, 21}}, {{ 58, 44, 22, 22}}, {{ 57, 46, 23, 23}}, + {{ 40, 48, 24, 24}}, {{ 43, 50, 25, 25}}, {{ 46, 52, 26, 26}}, + {{ 45, 54, 27, 27}}, {{ 36, 56, 28, 28}}, {{ 39, 58, 29, 29}}, + {{ 34, 60, 30, 30}}, {{ 33, 62, 31, 31}}, {{ 96, 64, 32, 32}}, + {{ 99, 66, 33, 33}}, {{102, 68, 34, 34}}, {{101, 70, 35, 35}}, + {{108, 72, 36, 36}}, {{111, 74, 37, 37}}, {{106, 76, 38, 38}}, + {{105, 78, 39, 39}}, {{120, 80, 40, 40}}, {{123, 82, 41, 41}}, + {{126, 84, 42, 42}}, {{125, 86, 43, 43}}, {{116, 88, 44, 44}}, + {{119, 90, 45, 45}}, {{114, 92, 46, 46}}, {{113, 94, 47, 47}}, + {{ 80, 96, 48, 48}}, {{ 83, 98, 49, 49}}, {{ 86, 100, 50, 50}}, + {{ 85, 102, 51, 51}}, {{ 92, 104, 52, 52}}, {{ 95, 106, 53, 53}}, + {{ 90, 108, 54, 54}}, {{ 89, 110, 55, 55}}, {{ 72, 112, 56, 56}}, + {{ 75, 114, 57, 57}}, {{ 78, 116, 58, 58}}, {{ 77, 118, 59, 59}}, + {{ 68, 120, 60, 60}}, {{ 71, 122, 61, 61}}, {{ 66, 124, 62, 62}}, + {{ 65, 126, 63, 63}}, {{192, 128, 64, 64}}, {{195, 130, 65, 65}}, + {{198, 132, 66, 66}}, {{197, 134, 67, 67}}, {{204, 136, 68, 68}}, + {{207, 138, 69, 69}}, {{202, 140, 70, 70}}, {{201, 142, 71, 71}}, + {{216, 144, 72, 72}}, {{219, 146, 73, 73}}, {{222, 148, 74, 74}}, + {{221, 150, 75, 75}}, {{212, 152, 76, 76}}, {{215, 154, 77, 77}}, + {{210, 156, 78, 78}}, {{209, 158, 79, 79}}, {{240, 160, 80, 80}}, + {{243, 162, 81, 81}}, {{246, 164, 82, 82}}, {{245, 166, 83, 83}}, + {{252, 168, 84, 84}}, {{255, 170, 85, 85}}, {{250, 172, 86, 86}}, + {{249, 174, 87, 87}}, {{232, 176, 88, 88}}, {{235, 178, 89, 89}}, + {{238, 180, 90, 90}}, {{237, 182, 91, 91}}, {{228, 184, 92, 92}}, + {{231, 186, 93, 93}}, {{226, 188, 94, 94}}, {{225, 190, 95, 95}}, + {{160, 192, 96, 96}}, {{163, 194, 97, 97}}, {{166, 196, 98, 98}}, + {{165, 198, 99, 99}}, {{172, 200, 100, 100}}, {{175, 202, 101, 101}}, + {{170, 204, 102, 102}}, {{169, 206, 103, 103}}, {{184, 208, 104, 104}}, + {{187, 210, 105, 105}}, {{190, 212, 106, 106}}, {{189, 214, 107, 107}}, + {{180, 216, 108, 108}}, {{183, 218, 109, 109}}, {{178, 220, 110, 110}}, + {{177, 222, 111, 111}}, {{144, 224, 112, 112}}, {{147, 226, 113, 113}}, + {{150, 228, 114, 114}}, {{149, 230, 115, 115}}, {{156, 232, 116, 116}}, + {{159, 234, 117, 117}}, {{154, 236, 118, 118}}, {{153, 238, 119, 119}}, + {{136, 240, 120, 120}}, {{139, 242, 121, 121}}, {{142, 244, 122, 122}}, + {{141, 246, 123, 123}}, {{132, 248, 124, 124}}, {{135, 250, 125, 125}}, + {{130, 252, 126, 126}}, {{129, 254, 127, 127}}, {{155, 27, 128, 128}}, + {{152, 25, 129, 129}}, {{157, 31, 130, 130}}, {{158, 29, 131, 131}}, + {{151, 19, 132, 132}}, {{148, 17, 133, 133}}, {{145, 23, 134, 134}}, + {{146, 21, 135, 135}}, {{131, 11, 136, 136}}, {{128, 9, 137, 137}}, + {{133, 15, 138, 138}}, {{134, 13, 139, 139}}, {{143, 3, 140, 140}}, + {{140, 1, 141, 141}}, {{137, 7, 142, 142}}, {{138, 5, 143, 143}}, + {{171, 59, 144, 144}}, {{168, 57, 145, 145}}, {{173, 63, 146, 146}}, + {{174, 61, 147, 147}}, {{167, 51, 148, 148}}, {{164, 49, 149, 149}}, + {{161, 55, 150, 150}}, {{162, 53, 151, 151}}, {{179, 43, 152, 152}}, + {{176, 41, 153, 153}}, {{181, 47, 154, 154}}, {{182, 45, 155, 155}}, + {{191, 35, 156, 156}}, {{188, 33, 157, 157}}, {{185, 39, 158, 158}}, + {{186, 37, 159, 159}}, {{251, 91, 160, 160}}, {{248, 89, 161, 161}}, + {{253, 95, 162, 162}}, {{254, 93, 163, 163}}, {{247, 83, 164, 164}}, + {{244, 81, 165, 165}}, {{241, 87, 166, 166}}, {{242, 85, 167, 167}}, + {{227, 75, 168, 168}}, {{224, 73, 169, 169}}, {{229, 79, 170, 170}}, + {{230, 77, 171, 171}}, {{239, 67, 172, 172}}, {{236, 65, 173, 173}}, + {{233, 71, 174, 174}}, {{234, 69, 175, 175}}, {{203, 123, 176, 176}}, + {{200, 121, 177, 177}}, {{205, 127, 178, 178}}, {{206, 125, 179, 179}}, + {{199, 115, 180, 180}}, {{196, 113, 181, 181}}, {{193, 119, 182, 182}}, + {{194, 117, 183, 183}}, {{211, 107, 184, 184}}, {{208, 105, 185, 185}}, + {{213, 111, 186, 186}}, {{214, 109, 187, 187}}, {{223, 99, 188, 188}}, + {{220, 97, 189, 189}}, {{217, 103, 190, 190}}, {{218, 101, 191, 191}}, + {{ 91, 155, 192, 192}}, {{ 88, 153, 193, 193}}, {{ 93, 159, 194, 194}}, + {{ 94, 157, 195, 195}}, {{ 87, 147, 196, 196}}, {{ 84, 145, 197, 197}}, + {{ 81, 151, 198, 198}}, {{ 82, 149, 199, 199}}, {{ 67, 139, 200, 200}}, + {{ 64, 137, 201, 201}}, {{ 69, 143, 202, 202}}, {{ 70, 141, 203, 203}}, + {{ 79, 131, 204, 204}}, {{ 76, 129, 205, 205}}, {{ 73, 135, 206, 206}}, + {{ 74, 133, 207, 207}}, {{107, 187, 208, 208}}, {{104, 185, 209, 209}}, + {{109, 191, 210, 210}}, {{110, 189, 211, 211}}, {{103, 179, 212, 212}}, + {{100, 177, 213, 213}}, {{ 97, 183, 214, 214}}, {{ 98, 181, 215, 215}}, + {{115, 171, 216, 216}}, {{112, 169, 217, 217}}, {{117, 175, 218, 218}}, + {{118, 173, 219, 219}}, {{127, 163, 220, 220}}, {{124, 161, 221, 221}}, + {{121, 167, 222, 222}}, {{122, 165, 223, 223}}, {{ 59, 219, 224, 224}}, + {{ 56, 217, 225, 225}}, {{ 61, 223, 226, 226}}, {{ 62, 221, 227, 227}}, + {{ 55, 211, 228, 228}}, {{ 52, 209, 229, 229}}, {{ 49, 215, 230, 230}}, + {{ 50, 213, 231, 231}}, {{ 35, 203, 232, 232}}, {{ 32, 201, 233, 233}}, + {{ 37, 207, 234, 234}}, {{ 38, 205, 235, 235}}, {{ 47, 195, 236, 236}}, + {{ 44, 193, 237, 237}}, {{ 41, 199, 238, 238}}, {{ 42, 197, 239, 239}}, + {{ 11, 251, 240, 240}}, {{ 8, 249, 241, 241}}, {{ 13, 255, 242, 242}}, + {{ 14, 253, 243, 243}}, {{ 7, 243, 244, 244}}, {{ 4, 241, 245, 245}}, + {{ 1, 247, 246, 246}}, {{ 2, 245, 247, 247}}, {{ 19, 235, 248, 248}}, + {{ 16, 233, 249, 249}}, {{ 21, 239, 250, 250}}, {{ 22, 237, 251, 251}}, + {{ 31, 227, 252, 252}}, {{ 28, 225, 253, 253}}, {{ 25, 231, 254, 254}}, + {{ 26, 229, 255, 255}}, + }, + { + {{ 0, 0, 0, 0}}, {{ 1, 3, 2, 1}}, {{ 2, 6, 4, 2}}, + {{ 3, 5, 6, 3}}, {{ 4, 12, 8, 4}}, {{ 5, 15, 10, 5}}, + {{ 6, 10, 12, 6}}, {{ 7, 9, 14, 7}}, {{ 8, 24, 16, 8}}, + {{ 9, 27, 18, 9}}, {{ 10, 30, 20, 10}}, {{ 11, 29, 22, 11}}, + {{ 12, 20, 24, 12}}, {{ 13, 23, 26, 13}}, {{ 14, 18, 28, 14}}, + {{ 15, 17, 30, 15}}, {{ 16, 48, 32, 16}}, {{ 17, 51, 34, 17}}, + {{ 18, 54, 36, 18}}, {{ 19, 53, 38, 19}}, {{ 20, 60, 40, 20}}, + {{ 21, 63, 42, 21}}, {{ 22, 58, 44, 22}}, {{ 23, 57, 46, 23}}, + {{ 24, 40, 48, 24}}, {{ 25, 43, 50, 25}}, {{ 26, 46, 52, 26}}, + {{ 27, 45, 54, 27}}, {{ 28, 36, 56, 28}}, {{ 29, 39, 58, 29}}, + {{ 30, 34, 60, 30}}, {{ 31, 33, 62, 31}}, {{ 32, 96, 64, 32}}, + {{ 33, 99, 66, 33}}, {{ 34, 102, 68, 34}}, {{ 35, 101, 70, 35}}, + {{ 36, 108, 72, 36}}, {{ 37, 111, 74, 37}}, {{ 38, 106, 76, 38}}, + {{ 39, 105, 78, 39}}, {{ 40, 120, 80, 40}}, {{ 41, 123, 82, 41}}, + {{ 42, 126, 84, 42}}, {{ 43, 125, 86, 43}}, {{ 44, 116, 88, 44}}, + {{ 45, 119, 90, 45}}, {{ 46, 114, 92, 46}}, {{ 47, 113, 94, 47}}, + {{ 48, 80, 96, 48}}, {{ 49, 83, 98, 49}}, {{ 50, 86, 100, 50}}, + {{ 51, 85, 102, 51}}, {{ 52, 92, 104, 52}}, {{ 53, 95, 106, 53}}, + {{ 54, 90, 108, 54}}, {{ 55, 89, 110, 55}}, {{ 56, 72, 112, 56}}, + {{ 57, 75, 114, 57}}, {{ 58, 78, 116, 58}}, {{ 59, 77, 118, 59}}, + {{ 60, 68, 120, 60}}, {{ 61, 71, 122, 61}}, {{ 62, 66, 124, 62}}, + {{ 63, 65, 126, 63}}, {{ 64, 192, 128, 64}}, {{ 65, 195, 130, 65}}, + {{ 66, 198, 132, 66}}, {{ 67, 197, 134, 67}}, {{ 68, 204, 136, 68}}, + {{ 69, 207, 138, 69}}, {{ 70, 202, 140, 70}}, {{ 71, 201, 142, 71}}, + {{ 72, 216, 144, 72}}, {{ 73, 219, 146, 73}}, {{ 74, 222, 148, 74}}, + {{ 75, 221, 150, 75}}, {{ 76, 212, 152, 76}}, {{ 77, 215, 154, 77}}, + {{ 78, 210, 156, 78}}, {{ 79, 209, 158, 79}}, {{ 80, 240, 160, 80}}, + {{ 81, 243, 162, 81}}, {{ 82, 246, 164, 82}}, {{ 83, 245, 166, 83}}, + {{ 84, 252, 168, 84}}, {{ 85, 255, 170, 85}}, {{ 86, 250, 172, 86}}, + {{ 87, 249, 174, 87}}, {{ 88, 232, 176, 88}}, {{ 89, 235, 178, 89}}, + {{ 90, 238, 180, 90}}, {{ 91, 237, 182, 91}}, {{ 92, 228, 184, 92}}, + {{ 93, 231, 186, 93}}, {{ 94, 226, 188, 94}}, {{ 95, 225, 190, 95}}, + {{ 96, 160, 192, 96}}, {{ 97, 163, 194, 97}}, {{ 98, 166, 196, 98}}, + {{ 99, 165, 198, 99}}, {{100, 172, 200, 100}}, {{101, 175, 202, 101}}, + {{102, 170, 204, 102}}, {{103, 169, 206, 103}}, {{104, 184, 208, 104}}, + {{105, 187, 210, 105}}, {{106, 190, 212, 106}}, {{107, 189, 214, 107}}, + {{108, 180, 216, 108}}, {{109, 183, 218, 109}}, {{110, 178, 220, 110}}, + {{111, 177, 222, 111}}, {{112, 144, 224, 112}}, {{113, 147, 226, 113}}, + {{114, 150, 228, 114}}, {{115, 149, 230, 115}}, {{116, 156, 232, 116}}, + {{117, 159, 234, 117}}, {{118, 154, 236, 118}}, {{119, 153, 238, 119}}, + {{120, 136, 240, 120}}, {{121, 139, 242, 121}}, {{122, 142, 244, 122}}, + {{123, 141, 246, 123}}, {{124, 132, 248, 124}}, {{125, 135, 250, 125}}, + {{126, 130, 252, 126}}, {{127, 129, 254, 127}}, {{128, 155, 27, 128}}, + {{129, 152, 25, 129}}, {{130, 157, 31, 130}}, {{131, 158, 29, 131}}, + {{132, 151, 19, 132}}, {{133, 148, 17, 133}}, {{134, 145, 23, 134}}, + {{135, 146, 21, 135}}, {{136, 131, 11, 136}}, {{137, 128, 9, 137}}, + {{138, 133, 15, 138}}, {{139, 134, 13, 139}}, {{140, 143, 3, 140}}, + {{141, 140, 1, 141}}, {{142, 137, 7, 142}}, {{143, 138, 5, 143}}, + {{144, 171, 59, 144}}, {{145, 168, 57, 145}}, {{146, 173, 63, 146}}, + {{147, 174, 61, 147}}, {{148, 167, 51, 148}}, {{149, 164, 49, 149}}, + {{150, 161, 55, 150}}, {{151, 162, 53, 151}}, {{152, 179, 43, 152}}, + {{153, 176, 41, 153}}, {{154, 181, 47, 154}}, {{155, 182, 45, 155}}, + {{156, 191, 35, 156}}, {{157, 188, 33, 157}}, {{158, 185, 39, 158}}, + {{159, 186, 37, 159}}, {{160, 251, 91, 160}}, {{161, 248, 89, 161}}, + {{162, 253, 95, 162}}, {{163, 254, 93, 163}}, {{164, 247, 83, 164}}, + {{165, 244, 81, 165}}, {{166, 241, 87, 166}}, {{167, 242, 85, 167}}, + {{168, 227, 75, 168}}, {{169, 224, 73, 169}}, {{170, 229, 79, 170}}, + {{171, 230, 77, 171}}, {{172, 239, 67, 172}}, {{173, 236, 65, 173}}, + {{174, 233, 71, 174}}, {{175, 234, 69, 175}}, {{176, 203, 123, 176}}, + {{177, 200, 121, 177}}, {{178, 205, 127, 178}}, {{179, 206, 125, 179}}, + {{180, 199, 115, 180}}, {{181, 196, 113, 181}}, {{182, 193, 119, 182}}, + {{183, 194, 117, 183}}, {{184, 211, 107, 184}}, {{185, 208, 105, 185}}, + {{186, 213, 111, 186}}, {{187, 214, 109, 187}}, {{188, 223, 99, 188}}, + {{189, 220, 97, 189}}, {{190, 217, 103, 190}}, {{191, 218, 101, 191}}, + {{192, 91, 155, 192}}, {{193, 88, 153, 193}}, {{194, 93, 159, 194}}, + {{195, 94, 157, 195}}, {{196, 87, 147, 196}}, {{197, 84, 145, 197}}, + {{198, 81, 151, 198}}, {{199, 82, 149, 199}}, {{200, 67, 139, 200}}, + {{201, 64, 137, 201}}, {{202, 69, 143, 202}}, {{203, 70, 141, 203}}, + {{204, 79, 131, 204}}, {{205, 76, 129, 205}}, {{206, 73, 135, 206}}, + {{207, 74, 133, 207}}, {{208, 107, 187, 208}}, {{209, 104, 185, 209}}, + {{210, 109, 191, 210}}, {{211, 110, 189, 211}}, {{212, 103, 179, 212}}, + {{213, 100, 177, 213}}, {{214, 97, 183, 214}}, {{215, 98, 181, 215}}, + {{216, 115, 171, 216}}, {{217, 112, 169, 217}}, {{218, 117, 175, 218}}, + {{219, 118, 173, 219}}, {{220, 127, 163, 220}}, {{221, 124, 161, 221}}, + {{222, 121, 167, 222}}, {{223, 122, 165, 223}}, {{224, 59, 219, 224}}, + {{225, 56, 217, 225}}, {{226, 61, 223, 226}}, {{227, 62, 221, 227}}, + {{228, 55, 211, 228}}, {{229, 52, 209, 229}}, {{230, 49, 215, 230}}, + {{231, 50, 213, 231}}, {{232, 35, 203, 232}}, {{233, 32, 201, 233}}, + {{234, 37, 207, 234}}, {{235, 38, 205, 235}}, {{236, 47, 195, 236}}, + {{237, 44, 193, 237}}, {{238, 41, 199, 238}}, {{239, 42, 197, 239}}, + {{240, 11, 251, 240}}, {{241, 8, 249, 241}}, {{242, 13, 255, 242}}, + {{243, 14, 253, 243}}, {{244, 7, 243, 244}}, {{245, 4, 241, 245}}, + {{246, 1, 247, 246}}, {{247, 2, 245, 247}}, {{248, 19, 235, 248}}, + {{249, 16, 233, 249}}, {{250, 21, 239, 250}}, {{251, 22, 237, 251}}, + {{252, 31, 227, 252}}, {{253, 28, 225, 253}}, {{254, 25, 231, 254}}, + {{255, 26, 229, 255}}, + }, + { + {{ 0, 0, 0, 0}}, {{ 1, 1, 3, 2}}, {{ 2, 2, 6, 4}}, + {{ 3, 3, 5, 6}}, {{ 4, 4, 12, 8}}, {{ 5, 5, 15, 10}}, + {{ 6, 6, 10, 12}}, {{ 7, 7, 9, 14}}, {{ 8, 8, 24, 16}}, + {{ 9, 9, 27, 18}}, {{ 10, 10, 30, 20}}, {{ 11, 11, 29, 22}}, + {{ 12, 12, 20, 24}}, {{ 13, 13, 23, 26}}, {{ 14, 14, 18, 28}}, + {{ 15, 15, 17, 30}}, {{ 16, 16, 48, 32}}, {{ 17, 17, 51, 34}}, + {{ 18, 18, 54, 36}}, {{ 19, 19, 53, 38}}, {{ 20, 20, 60, 40}}, + {{ 21, 21, 63, 42}}, {{ 22, 22, 58, 44}}, {{ 23, 23, 57, 46}}, + {{ 24, 24, 40, 48}}, {{ 25, 25, 43, 50}}, {{ 26, 26, 46, 52}}, + {{ 27, 27, 45, 54}}, {{ 28, 28, 36, 56}}, {{ 29, 29, 39, 58}}, + {{ 30, 30, 34, 60}}, {{ 31, 31, 33, 62}}, {{ 32, 32, 96, 64}}, + {{ 33, 33, 99, 66}}, {{ 34, 34, 102, 68}}, {{ 35, 35, 101, 70}}, + {{ 36, 36, 108, 72}}, {{ 37, 37, 111, 74}}, {{ 38, 38, 106, 76}}, + {{ 39, 39, 105, 78}}, {{ 40, 40, 120, 80}}, {{ 41, 41, 123, 82}}, + {{ 42, 42, 126, 84}}, {{ 43, 43, 125, 86}}, {{ 44, 44, 116, 88}}, + {{ 45, 45, 119, 90}}, {{ 46, 46, 114, 92}}, {{ 47, 47, 113, 94}}, + {{ 48, 48, 80, 96}}, {{ 49, 49, 83, 98}}, {{ 50, 50, 86, 100}}, + {{ 51, 51, 85, 102}}, {{ 52, 52, 92, 104}}, {{ 53, 53, 95, 106}}, + {{ 54, 54, 90, 108}}, {{ 55, 55, 89, 110}}, {{ 56, 56, 72, 112}}, + {{ 57, 57, 75, 114}}, {{ 58, 58, 78, 116}}, {{ 59, 59, 77, 118}}, + {{ 60, 60, 68, 120}}, {{ 61, 61, 71, 122}}, {{ 62, 62, 66, 124}}, + {{ 63, 63, 65, 126}}, {{ 64, 64, 192, 128}}, {{ 65, 65, 195, 130}}, + {{ 66, 66, 198, 132}}, {{ 67, 67, 197, 134}}, {{ 68, 68, 204, 136}}, + {{ 69, 69, 207, 138}}, {{ 70, 70, 202, 140}}, {{ 71, 71, 201, 142}}, + {{ 72, 72, 216, 144}}, {{ 73, 73, 219, 146}}, {{ 74, 74, 222, 148}}, + {{ 75, 75, 221, 150}}, {{ 76, 76, 212, 152}}, {{ 77, 77, 215, 154}}, + {{ 78, 78, 210, 156}}, {{ 79, 79, 209, 158}}, {{ 80, 80, 240, 160}}, + {{ 81, 81, 243, 162}}, {{ 82, 82, 246, 164}}, {{ 83, 83, 245, 166}}, + {{ 84, 84, 252, 168}}, {{ 85, 85, 255, 170}}, {{ 86, 86, 250, 172}}, + {{ 87, 87, 249, 174}}, {{ 88, 88, 232, 176}}, {{ 89, 89, 235, 178}}, + {{ 90, 90, 238, 180}}, {{ 91, 91, 237, 182}}, {{ 92, 92, 228, 184}}, + {{ 93, 93, 231, 186}}, {{ 94, 94, 226, 188}}, {{ 95, 95, 225, 190}}, + {{ 96, 96, 160, 192}}, {{ 97, 97, 163, 194}}, {{ 98, 98, 166, 196}}, + {{ 99, 99, 165, 198}}, {{100, 100, 172, 200}}, {{101, 101, 175, 202}}, + {{102, 102, 170, 204}}, {{103, 103, 169, 206}}, {{104, 104, 184, 208}}, + {{105, 105, 187, 210}}, {{106, 106, 190, 212}}, {{107, 107, 189, 214}}, + {{108, 108, 180, 216}}, {{109, 109, 183, 218}}, {{110, 110, 178, 220}}, + {{111, 111, 177, 222}}, {{112, 112, 144, 224}}, {{113, 113, 147, 226}}, + {{114, 114, 150, 228}}, {{115, 115, 149, 230}}, {{116, 116, 156, 232}}, + {{117, 117, 159, 234}}, {{118, 118, 154, 236}}, {{119, 119, 153, 238}}, + {{120, 120, 136, 240}}, {{121, 121, 139, 242}}, {{122, 122, 142, 244}}, + {{123, 123, 141, 246}}, {{124, 124, 132, 248}}, {{125, 125, 135, 250}}, + {{126, 126, 130, 252}}, {{127, 127, 129, 254}}, {{128, 128, 155, 27}}, + {{129, 129, 152, 25}}, {{130, 130, 157, 31}}, {{131, 131, 158, 29}}, + {{132, 132, 151, 19}}, {{133, 133, 148, 17}}, {{134, 134, 145, 23}}, + {{135, 135, 146, 21}}, {{136, 136, 131, 11}}, {{137, 137, 128, 9}}, + {{138, 138, 133, 15}}, {{139, 139, 134, 13}}, {{140, 140, 143, 3}}, + {{141, 141, 140, 1}}, {{142, 142, 137, 7}}, {{143, 143, 138, 5}}, + {{144, 144, 171, 59}}, {{145, 145, 168, 57}}, {{146, 146, 173, 63}}, + {{147, 147, 174, 61}}, {{148, 148, 167, 51}}, {{149, 149, 164, 49}}, + {{150, 150, 161, 55}}, {{151, 151, 162, 53}}, {{152, 152, 179, 43}}, + {{153, 153, 176, 41}}, {{154, 154, 181, 47}}, {{155, 155, 182, 45}}, + {{156, 156, 191, 35}}, {{157, 157, 188, 33}}, {{158, 158, 185, 39}}, + {{159, 159, 186, 37}}, {{160, 160, 251, 91}}, {{161, 161, 248, 89}}, + {{162, 162, 253, 95}}, {{163, 163, 254, 93}}, {{164, 164, 247, 83}}, + {{165, 165, 244, 81}}, {{166, 166, 241, 87}}, {{167, 167, 242, 85}}, + {{168, 168, 227, 75}}, {{169, 169, 224, 73}}, {{170, 170, 229, 79}}, + {{171, 171, 230, 77}}, {{172, 172, 239, 67}}, {{173, 173, 236, 65}}, + {{174, 174, 233, 71}}, {{175, 175, 234, 69}}, {{176, 176, 203, 123}}, + {{177, 177, 200, 121}}, {{178, 178, 205, 127}}, {{179, 179, 206, 125}}, + {{180, 180, 199, 115}}, {{181, 181, 196, 113}}, {{182, 182, 193, 119}}, + {{183, 183, 194, 117}}, {{184, 184, 211, 107}}, {{185, 185, 208, 105}}, + {{186, 186, 213, 111}}, {{187, 187, 214, 109}}, {{188, 188, 223, 99}}, + {{189, 189, 220, 97}}, {{190, 190, 217, 103}}, {{191, 191, 218, 101}}, + {{192, 192, 91, 155}}, {{193, 193, 88, 153}}, {{194, 194, 93, 159}}, + {{195, 195, 94, 157}}, {{196, 196, 87, 147}}, {{197, 197, 84, 145}}, + {{198, 198, 81, 151}}, {{199, 199, 82, 149}}, {{200, 200, 67, 139}}, + {{201, 201, 64, 137}}, {{202, 202, 69, 143}}, {{203, 203, 70, 141}}, + {{204, 204, 79, 131}}, {{205, 205, 76, 129}}, {{206, 206, 73, 135}}, + {{207, 207, 74, 133}}, {{208, 208, 107, 187}}, {{209, 209, 104, 185}}, + {{210, 210, 109, 191}}, {{211, 211, 110, 189}}, {{212, 212, 103, 179}}, + {{213, 213, 100, 177}}, {{214, 214, 97, 183}}, {{215, 215, 98, 181}}, + {{216, 216, 115, 171}}, {{217, 217, 112, 169}}, {{218, 218, 117, 175}}, + {{219, 219, 118, 173}}, {{220, 220, 127, 163}}, {{221, 221, 124, 161}}, + {{222, 222, 121, 167}}, {{223, 223, 122, 165}}, {{224, 224, 59, 219}}, + {{225, 225, 56, 217}}, {{226, 226, 61, 223}}, {{227, 227, 62, 221}}, + {{228, 228, 55, 211}}, {{229, 229, 52, 209}}, {{230, 230, 49, 215}}, + {{231, 231, 50, 213}}, {{232, 232, 35, 203}}, {{233, 233, 32, 201}}, + {{234, 234, 37, 207}}, {{235, 235, 38, 205}}, {{236, 236, 47, 195}}, + {{237, 237, 44, 193}}, {{238, 238, 41, 199}}, {{239, 239, 42, 197}}, + {{240, 240, 11, 251}}, {{241, 241, 8, 249}}, {{242, 242, 13, 255}}, + {{243, 243, 14, 253}}, {{244, 244, 7, 243}}, {{245, 245, 4, 241}}, + {{246, 246, 1, 247}}, {{247, 247, 2, 245}}, {{248, 248, 19, 235}}, + {{249, 249, 16, 233}}, {{250, 250, 21, 239}}, {{251, 251, 22, 237}}, + {{252, 252, 31, 227}}, {{253, 253, 28, 225}}, {{254, 254, 25, 231}}, + {{255, 255, 26, 229}}, + }, +}; + +const word8x4 M1[4][256] = { + { + {{ 0, 0, 0, 0}}, {{ 14, 9, 13, 11}}, {{ 28, 18, 26, 22}}, + {{ 18, 27, 23, 29}}, {{ 56, 36, 52, 44}}, {{ 54, 45, 57, 39}}, + {{ 36, 54, 46, 58}}, {{ 42, 63, 35, 49}}, {{112, 72, 104, 88}}, + {{126, 65, 101, 83}}, {{108, 90, 114, 78}}, {{ 98, 83, 127, 69}}, + {{ 72, 108, 92, 116}}, {{ 70, 101, 81, 127}}, {{ 84, 126, 70, 98}}, + {{ 90, 119, 75, 105}}, {{224, 144, 208, 176}}, {{238, 153, 221, 187}}, + {{252, 130, 202, 166}}, {{242, 139, 199, 173}}, {{216, 180, 228, 156}}, + {{214, 189, 233, 151}}, {{196, 166, 254, 138}}, {{202, 175, 243, 129}}, + {{144, 216, 184, 232}}, {{158, 209, 181, 227}}, {{140, 202, 162, 254}}, + {{130, 195, 175, 245}}, {{168, 252, 140, 196}}, {{166, 245, 129, 207}}, + {{180, 238, 150, 210}}, {{186, 231, 155, 217}}, {{219, 59, 187, 123}}, + {{213, 50, 182, 112}}, {{199, 41, 161, 109}}, {{201, 32, 172, 102}}, + {{227, 31, 143, 87}}, {{237, 22, 130, 92}}, {{255, 13, 149, 65}}, + {{241, 4, 152, 74}}, {{171, 115, 211, 35}}, {{165, 122, 222, 40}}, + {{183, 97, 201, 53}}, {{185, 104, 196, 62}}, {{147, 87, 231, 15}}, + {{157, 94, 234, 4}}, {{143, 69, 253, 25}}, {{129, 76, 240, 18}}, + {{ 59, 171, 107, 203}}, {{ 53, 162, 102, 192}}, {{ 39, 185, 113, 221}}, + {{ 41, 176, 124, 214}}, {{ 3, 143, 95, 231}}, {{ 13, 134, 82, 236}}, + {{ 31, 157, 69, 241}}, {{ 17, 148, 72, 250}}, {{ 75, 227, 3, 147}}, + {{ 69, 234, 14, 152}}, {{ 87, 241, 25, 133}}, {{ 89, 248, 20, 142}}, + {{115, 199, 55, 191}}, {{125, 206, 58, 180}}, {{111, 213, 45, 169}}, + {{ 97, 220, 32, 162}}, {{173, 118, 109, 246}}, {{163, 127, 96, 253}}, + {{177, 100, 119, 224}}, {{191, 109, 122, 235}}, {{149, 82, 89, 218}}, + {{155, 91, 84, 209}}, {{137, 64, 67, 204}}, {{135, 73, 78, 199}}, + {{221, 62, 5, 174}}, {{211, 55, 8, 165}}, {{193, 44, 31, 184}}, + {{207, 37, 18, 179}}, {{229, 26, 49, 130}}, {{235, 19, 60, 137}}, + {{249, 8, 43, 148}}, {{247, 1, 38, 159}}, {{ 77, 230, 189, 70}}, + {{ 67, 239, 176, 77}}, {{ 81, 244, 167, 80}}, {{ 95, 253, 170, 91}}, + {{117, 194, 137, 106}}, {{123, 203, 132, 97}}, {{105, 208, 147, 124}}, + {{103, 217, 158, 119}}, {{ 61, 174, 213, 30}}, {{ 51, 167, 216, 21}}, + {{ 33, 188, 207, 8}}, {{ 47, 181, 194, 3}}, {{ 5, 138, 225, 50}}, + {{ 11, 131, 236, 57}}, {{ 25, 152, 251, 36}}, {{ 23, 145, 246, 47}}, + {{118, 77, 214, 141}}, {{120, 68, 219, 134}}, {{106, 95, 204, 155}}, + {{100, 86, 193, 144}}, {{ 78, 105, 226, 161}}, {{ 64, 96, 239, 170}}, + {{ 82, 123, 248, 183}}, {{ 92, 114, 245, 188}}, {{ 6, 5, 190, 213}}, + {{ 8, 12, 179, 222}}, {{ 26, 23, 164, 195}}, {{ 20, 30, 169, 200}}, + {{ 62, 33, 138, 249}}, {{ 48, 40, 135, 242}}, {{ 34, 51, 144, 239}}, + {{ 44, 58, 157, 228}}, {{150, 221, 6, 61}}, {{152, 212, 11, 54}}, + {{138, 207, 28, 43}}, {{132, 198, 17, 32}}, {{174, 249, 50, 17}}, + {{160, 240, 63, 26}}, {{178, 235, 40, 7}}, {{188, 226, 37, 12}}, + {{230, 149, 110, 101}}, {{232, 156, 99, 110}}, {{250, 135, 116, 115}}, + {{244, 142, 121, 120}}, {{222, 177, 90, 73}}, {{208, 184, 87, 66}}, + {{194, 163, 64, 95}}, {{204, 170, 77, 84}}, {{ 65, 236, 218, 247}}, + {{ 79, 229, 215, 252}}, {{ 93, 254, 192, 225}}, {{ 83, 247, 205, 234}}, + {{121, 200, 238, 219}}, {{119, 193, 227, 208}}, {{101, 218, 244, 205}}, + {{107, 211, 249, 198}}, {{ 49, 164, 178, 175}}, {{ 63, 173, 191, 164}}, + {{ 45, 182, 168, 185}}, {{ 35, 191, 165, 178}}, {{ 9, 128, 134, 131}}, + {{ 7, 137, 139, 136}}, {{ 21, 146, 156, 149}}, {{ 27, 155, 145, 158}}, + {{161, 124, 10, 71}}, {{175, 117, 7, 76}}, {{189, 110, 16, 81}}, + {{179, 103, 29, 90}}, {{153, 88, 62, 107}}, {{151, 81, 51, 96}}, + {{133, 74, 36, 125}}, {{139, 67, 41, 118}}, {{209, 52, 98, 31}}, + {{223, 61, 111, 20}}, {{205, 38, 120, 9}}, {{195, 47, 117, 2}}, + {{233, 16, 86, 51}}, {{231, 25, 91, 56}}, {{245, 2, 76, 37}}, + {{251, 11, 65, 46}}, {{154, 215, 97, 140}}, {{148, 222, 108, 135}}, + {{134, 197, 123, 154}}, {{136, 204, 118, 145}}, {{162, 243, 85, 160}}, + {{172, 250, 88, 171}}, {{190, 225, 79, 182}}, {{176, 232, 66, 189}}, + {{234, 159, 9, 212}}, {{228, 150, 4, 223}}, {{246, 141, 19, 194}}, + {{248, 132, 30, 201}}, {{210, 187, 61, 248}}, {{220, 178, 48, 243}}, + {{206, 169, 39, 238}}, {{192, 160, 42, 229}}, {{122, 71, 177, 60}}, + {{116, 78, 188, 55}}, {{102, 85, 171, 42}}, {{104, 92, 166, 33}}, + {{ 66, 99, 133, 16}}, {{ 76, 106, 136, 27}}, {{ 94, 113, 159, 6}}, + {{ 80, 120, 146, 13}}, {{ 10, 15, 217, 100}}, {{ 4, 6, 212, 111}}, + {{ 22, 29, 195, 114}}, {{ 24, 20, 206, 121}}, {{ 50, 43, 237, 72}}, + {{ 60, 34, 224, 67}}, {{ 46, 57, 247, 94}}, {{ 32, 48, 250, 85}}, + {{236, 154, 183, 1}}, {{226, 147, 186, 10}}, {{240, 136, 173, 23}}, + {{254, 129, 160, 28}}, {{212, 190, 131, 45}}, {{218, 183, 142, 38}}, + {{200, 172, 153, 59}}, {{198, 165, 148, 48}}, {{156, 210, 223, 89}}, + {{146, 219, 210, 82}}, {{128, 192, 197, 79}}, {{142, 201, 200, 68}}, + {{164, 246, 235, 117}}, {{170, 255, 230, 126}}, {{184, 228, 241, 99}}, + {{182, 237, 252, 104}}, {{ 12, 10, 103, 177}}, {{ 2, 3, 106, 186}}, + {{ 16, 24, 125, 167}}, {{ 30, 17, 112, 172}}, {{ 52, 46, 83, 157}}, + {{ 58, 39, 94, 150}}, {{ 40, 60, 73, 139}}, {{ 38, 53, 68, 128}}, + {{124, 66, 15, 233}}, {{114, 75, 2, 226}}, {{ 96, 80, 21, 255}}, + {{110, 89, 24, 244}}, {{ 68, 102, 59, 197}}, {{ 74, 111, 54, 206}}, + {{ 88, 116, 33, 211}}, {{ 86, 125, 44, 216}}, {{ 55, 161, 12, 122}}, + {{ 57, 168, 1, 113}}, {{ 43, 179, 22, 108}}, {{ 37, 186, 27, 103}}, + {{ 15, 133, 56, 86}}, {{ 1, 140, 53, 93}}, {{ 19, 151, 34, 64}}, + {{ 29, 158, 47, 75}}, {{ 71, 233, 100, 34}}, {{ 73, 224, 105, 41}}, + {{ 91, 251, 126, 52}}, {{ 85, 242, 115, 63}}, {{127, 205, 80, 14}}, + {{113, 196, 93, 5}}, {{ 99, 223, 74, 24}}, {{109, 214, 71, 19}}, + {{215, 49, 220, 202}}, {{217, 56, 209, 193}}, {{203, 35, 198, 220}}, + {{197, 42, 203, 215}}, {{239, 21, 232, 230}}, {{225, 28, 229, 237}}, + {{243, 7, 242, 240}}, {{253, 14, 255, 251}}, {{167, 121, 180, 146}}, + {{169, 112, 185, 153}}, {{187, 107, 174, 132}}, {{181, 98, 163, 143}}, + {{159, 93, 128, 190}}, {{145, 84, 141, 181}}, {{131, 79, 154, 168}}, + {{141, 70, 151, 163}}, + }, + { + {{ 0, 0, 0, 0}}, {{ 11, 14, 9, 13}}, {{ 22, 28, 18, 26}}, + {{ 29, 18, 27, 23}}, {{ 44, 56, 36, 52}}, {{ 39, 54, 45, 57}}, + {{ 58, 36, 54, 46}}, {{ 49, 42, 63, 35}}, {{ 88, 112, 72, 104}}, + {{ 83, 126, 65, 101}}, {{ 78, 108, 90, 114}}, {{ 69, 98, 83, 127}}, + {{116, 72, 108, 92}}, {{127, 70, 101, 81}}, {{ 98, 84, 126, 70}}, + {{105, 90, 119, 75}}, {{176, 224, 144, 208}}, {{187, 238, 153, 221}}, + {{166, 252, 130, 202}}, {{173, 242, 139, 199}}, {{156, 216, 180, 228}}, + {{151, 214, 189, 233}}, {{138, 196, 166, 254}}, {{129, 202, 175, 243}}, + {{232, 144, 216, 184}}, {{227, 158, 209, 181}}, {{254, 140, 202, 162}}, + {{245, 130, 195, 175}}, {{196, 168, 252, 140}}, {{207, 166, 245, 129}}, + {{210, 180, 238, 150}}, {{217, 186, 231, 155}}, {{123, 219, 59, 187}}, + {{112, 213, 50, 182}}, {{109, 199, 41, 161}}, {{102, 201, 32, 172}}, + {{ 87, 227, 31, 143}}, {{ 92, 237, 22, 130}}, {{ 65, 255, 13, 149}}, + {{ 74, 241, 4, 152}}, {{ 35, 171, 115, 211}}, {{ 40, 165, 122, 222}}, + {{ 53, 183, 97, 201}}, {{ 62, 185, 104, 196}}, {{ 15, 147, 87, 231}}, + {{ 4, 157, 94, 234}}, {{ 25, 143, 69, 253}}, {{ 18, 129, 76, 240}}, + {{203, 59, 171, 107}}, {{192, 53, 162, 102}}, {{221, 39, 185, 113}}, + {{214, 41, 176, 124}}, {{231, 3, 143, 95}}, {{236, 13, 134, 82}}, + {{241, 31, 157, 69}}, {{250, 17, 148, 72}}, {{147, 75, 227, 3}}, + {{152, 69, 234, 14}}, {{133, 87, 241, 25}}, {{142, 89, 248, 20}}, + {{191, 115, 199, 55}}, {{180, 125, 206, 58}}, {{169, 111, 213, 45}}, + {{162, 97, 220, 32}}, {{246, 173, 118, 109}}, {{253, 163, 127, 96}}, + {{224, 177, 100, 119}}, {{235, 191, 109, 122}}, {{218, 149, 82, 89}}, + {{209, 155, 91, 84}}, {{204, 137, 64, 67}}, {{199, 135, 73, 78}}, + {{174, 221, 62, 5}}, {{165, 211, 55, 8}}, {{184, 193, 44, 31}}, + {{179, 207, 37, 18}}, {{130, 229, 26, 49}}, {{137, 235, 19, 60}}, + {{148, 249, 8, 43}}, {{159, 247, 1, 38}}, {{ 70, 77, 230, 189}}, + {{ 77, 67, 239, 176}}, {{ 80, 81, 244, 167}}, {{ 91, 95, 253, 170}}, + {{106, 117, 194, 137}}, {{ 97, 123, 203, 132}}, {{124, 105, 208, 147}}, + {{119, 103, 217, 158}}, {{ 30, 61, 174, 213}}, {{ 21, 51, 167, 216}}, + {{ 8, 33, 188, 207}}, {{ 3, 47, 181, 194}}, {{ 50, 5, 138, 225}}, + {{ 57, 11, 131, 236}}, {{ 36, 25, 152, 251}}, {{ 47, 23, 145, 246}}, + {{141, 118, 77, 214}}, {{134, 120, 68, 219}}, {{155, 106, 95, 204}}, + {{144, 100, 86, 193}}, {{161, 78, 105, 226}}, {{170, 64, 96, 239}}, + {{183, 82, 123, 248}}, {{188, 92, 114, 245}}, {{213, 6, 5, 190}}, + {{222, 8, 12, 179}}, {{195, 26, 23, 164}}, {{200, 20, 30, 169}}, + {{249, 62, 33, 138}}, {{242, 48, 40, 135}}, {{239, 34, 51, 144}}, + {{228, 44, 58, 157}}, {{ 61, 150, 221, 6}}, {{ 54, 152, 212, 11}}, + {{ 43, 138, 207, 28}}, {{ 32, 132, 198, 17}}, {{ 17, 174, 249, 50}}, + {{ 26, 160, 240, 63}}, {{ 7, 178, 235, 40}}, {{ 12, 188, 226, 37}}, + {{101, 230, 149, 110}}, {{110, 232, 156, 99}}, {{115, 250, 135, 116}}, + {{120, 244, 142, 121}}, {{ 73, 222, 177, 90}}, {{ 66, 208, 184, 87}}, + {{ 95, 194, 163, 64}}, {{ 84, 204, 170, 77}}, {{247, 65, 236, 218}}, + {{252, 79, 229, 215}}, {{225, 93, 254, 192}}, {{234, 83, 247, 205}}, + {{219, 121, 200, 238}}, {{208, 119, 193, 227}}, {{205, 101, 218, 244}}, + {{198, 107, 211, 249}}, {{175, 49, 164, 178}}, {{164, 63, 173, 191}}, + {{185, 45, 182, 168}}, {{178, 35, 191, 165}}, {{131, 9, 128, 134}}, + {{136, 7, 137, 139}}, {{149, 21, 146, 156}}, {{158, 27, 155, 145}}, + {{ 71, 161, 124, 10}}, {{ 76, 175, 117, 7}}, {{ 81, 189, 110, 16}}, + {{ 90, 179, 103, 29}}, {{107, 153, 88, 62}}, {{ 96, 151, 81, 51}}, + {{125, 133, 74, 36}}, {{118, 139, 67, 41}}, {{ 31, 209, 52, 98}}, + {{ 20, 223, 61, 111}}, {{ 9, 205, 38, 120}}, {{ 2, 195, 47, 117}}, + {{ 51, 233, 16, 86}}, {{ 56, 231, 25, 91}}, {{ 37, 245, 2, 76}}, + {{ 46, 251, 11, 65}}, {{140, 154, 215, 97}}, {{135, 148, 222, 108}}, + {{154, 134, 197, 123}}, {{145, 136, 204, 118}}, {{160, 162, 243, 85}}, + {{171, 172, 250, 88}}, {{182, 190, 225, 79}}, {{189, 176, 232, 66}}, + {{212, 234, 159, 9}}, {{223, 228, 150, 4}}, {{194, 246, 141, 19}}, + {{201, 248, 132, 30}}, {{248, 210, 187, 61}}, {{243, 220, 178, 48}}, + {{238, 206, 169, 39}}, {{229, 192, 160, 42}}, {{ 60, 122, 71, 177}}, + {{ 55, 116, 78, 188}}, {{ 42, 102, 85, 171}}, {{ 33, 104, 92, 166}}, + {{ 16, 66, 99, 133}}, {{ 27, 76, 106, 136}}, {{ 6, 94, 113, 159}}, + {{ 13, 80, 120, 146}}, {{100, 10, 15, 217}}, {{111, 4, 6, 212}}, + {{114, 22, 29, 195}}, {{121, 24, 20, 206}}, {{ 72, 50, 43, 237}}, + {{ 67, 60, 34, 224}}, {{ 94, 46, 57, 247}}, {{ 85, 32, 48, 250}}, + {{ 1, 236, 154, 183}}, {{ 10, 226, 147, 186}}, {{ 23, 240, 136, 173}}, + {{ 28, 254, 129, 160}}, {{ 45, 212, 190, 131}}, {{ 38, 218, 183, 142}}, + {{ 59, 200, 172, 153}}, {{ 48, 198, 165, 148}}, {{ 89, 156, 210, 223}}, + {{ 82, 146, 219, 210}}, {{ 79, 128, 192, 197}}, {{ 68, 142, 201, 200}}, + {{117, 164, 246, 235}}, {{126, 170, 255, 230}}, {{ 99, 184, 228, 241}}, + {{104, 182, 237, 252}}, {{177, 12, 10, 103}}, {{186, 2, 3, 106}}, + {{167, 16, 24, 125}}, {{172, 30, 17, 112}}, {{157, 52, 46, 83}}, + {{150, 58, 39, 94}}, {{139, 40, 60, 73}}, {{128, 38, 53, 68}}, + {{233, 124, 66, 15}}, {{226, 114, 75, 2}}, {{255, 96, 80, 21}}, + {{244, 110, 89, 24}}, {{197, 68, 102, 59}}, {{206, 74, 111, 54}}, + {{211, 88, 116, 33}}, {{216, 86, 125, 44}}, {{122, 55, 161, 12}}, + {{113, 57, 168, 1}}, {{108, 43, 179, 22}}, {{103, 37, 186, 27}}, + {{ 86, 15, 133, 56}}, {{ 93, 1, 140, 53}}, {{ 64, 19, 151, 34}}, + {{ 75, 29, 158, 47}}, {{ 34, 71, 233, 100}}, {{ 41, 73, 224, 105}}, + {{ 52, 91, 251, 126}}, {{ 63, 85, 242, 115}}, {{ 14, 127, 205, 80}}, + {{ 5, 113, 196, 93}}, {{ 24, 99, 223, 74}}, {{ 19, 109, 214, 71}}, + {{202, 215, 49, 220}}, {{193, 217, 56, 209}}, {{220, 203, 35, 198}}, + {{215, 197, 42, 203}}, {{230, 239, 21, 232}}, {{237, 225, 28, 229}}, + {{240, 243, 7, 242}}, {{251, 253, 14, 255}}, {{146, 167, 121, 180}}, + {{153, 169, 112, 185}}, {{132, 187, 107, 174}}, {{143, 181, 98, 163}}, + {{190, 159, 93, 128}}, {{181, 145, 84, 141}}, {{168, 131, 79, 154}}, + {{163, 141, 70, 151}}, + }, + { + {{ 0, 0, 0, 0}}, {{ 13, 11, 14, 9}}, {{ 26, 22, 28, 18}}, + {{ 23, 29, 18, 27}}, {{ 52, 44, 56, 36}}, {{ 57, 39, 54, 45}}, + {{ 46, 58, 36, 54}}, {{ 35, 49, 42, 63}}, {{104, 88, 112, 72}}, + {{101, 83, 126, 65}}, {{114, 78, 108, 90}}, {{127, 69, 98, 83}}, + {{ 92, 116, 72, 108}}, {{ 81, 127, 70, 101}}, {{ 70, 98, 84, 126}}, + {{ 75, 105, 90, 119}}, {{208, 176, 224, 144}}, {{221, 187, 238, 153}}, + {{202, 166, 252, 130}}, {{199, 173, 242, 139}}, {{228, 156, 216, 180}}, + {{233, 151, 214, 189}}, {{254, 138, 196, 166}}, {{243, 129, 202, 175}}, + {{184, 232, 144, 216}}, {{181, 227, 158, 209}}, {{162, 254, 140, 202}}, + {{175, 245, 130, 195}}, {{140, 196, 168, 252}}, {{129, 207, 166, 245}}, + {{150, 210, 180, 238}}, {{155, 217, 186, 231}}, {{187, 123, 219, 59}}, + {{182, 112, 213, 50}}, {{161, 109, 199, 41}}, {{172, 102, 201, 32}}, + {{143, 87, 227, 31}}, {{130, 92, 237, 22}}, {{149, 65, 255, 13}}, + {{152, 74, 241, 4}}, {{211, 35, 171, 115}}, {{222, 40, 165, 122}}, + {{201, 53, 183, 97}}, {{196, 62, 185, 104}}, {{231, 15, 147, 87}}, + {{234, 4, 157, 94}}, {{253, 25, 143, 69}}, {{240, 18, 129, 76}}, + {{107, 203, 59, 171}}, {{102, 192, 53, 162}}, {{113, 221, 39, 185}}, + {{124, 214, 41, 176}}, {{ 95, 231, 3, 143}}, {{ 82, 236, 13, 134}}, + {{ 69, 241, 31, 157}}, {{ 72, 250, 17, 148}}, {{ 3, 147, 75, 227}}, + {{ 14, 152, 69, 234}}, {{ 25, 133, 87, 241}}, {{ 20, 142, 89, 248}}, + {{ 55, 191, 115, 199}}, {{ 58, 180, 125, 206}}, {{ 45, 169, 111, 213}}, + {{ 32, 162, 97, 220}}, {{109, 246, 173, 118}}, {{ 96, 253, 163, 127}}, + {{119, 224, 177, 100}}, {{122, 235, 191, 109}}, {{ 89, 218, 149, 82}}, + {{ 84, 209, 155, 91}}, {{ 67, 204, 137, 64}}, {{ 78, 199, 135, 73}}, + {{ 5, 174, 221, 62}}, {{ 8, 165, 211, 55}}, {{ 31, 184, 193, 44}}, + {{ 18, 179, 207, 37}}, {{ 49, 130, 229, 26}}, {{ 60, 137, 235, 19}}, + {{ 43, 148, 249, 8}}, {{ 38, 159, 247, 1}}, {{189, 70, 77, 230}}, + {{176, 77, 67, 239}}, {{167, 80, 81, 244}}, {{170, 91, 95, 253}}, + {{137, 106, 117, 194}}, {{132, 97, 123, 203}}, {{147, 124, 105, 208}}, + {{158, 119, 103, 217}}, {{213, 30, 61, 174}}, {{216, 21, 51, 167}}, + {{207, 8, 33, 188}}, {{194, 3, 47, 181}}, {{225, 50, 5, 138}}, + {{236, 57, 11, 131}}, {{251, 36, 25, 152}}, {{246, 47, 23, 145}}, + {{214, 141, 118, 77}}, {{219, 134, 120, 68}}, {{204, 155, 106, 95}}, + {{193, 144, 100, 86}}, {{226, 161, 78, 105}}, {{239, 170, 64, 96}}, + {{248, 183, 82, 123}}, {{245, 188, 92, 114}}, {{190, 213, 6, 5}}, + {{179, 222, 8, 12}}, {{164, 195, 26, 23}}, {{169, 200, 20, 30}}, + {{138, 249, 62, 33}}, {{135, 242, 48, 40}}, {{144, 239, 34, 51}}, + {{157, 228, 44, 58}}, {{ 6, 61, 150, 221}}, {{ 11, 54, 152, 212}}, + {{ 28, 43, 138, 207}}, {{ 17, 32, 132, 198}}, {{ 50, 17, 174, 249}}, + {{ 63, 26, 160, 240}}, {{ 40, 7, 178, 235}}, {{ 37, 12, 188, 226}}, + {{110, 101, 230, 149}}, {{ 99, 110, 232, 156}}, {{116, 115, 250, 135}}, + {{121, 120, 244, 142}}, {{ 90, 73, 222, 177}}, {{ 87, 66, 208, 184}}, + {{ 64, 95, 194, 163}}, {{ 77, 84, 204, 170}}, {{218, 247, 65, 236}}, + {{215, 252, 79, 229}}, {{192, 225, 93, 254}}, {{205, 234, 83, 247}}, + {{238, 219, 121, 200}}, {{227, 208, 119, 193}}, {{244, 205, 101, 218}}, + {{249, 198, 107, 211}}, {{178, 175, 49, 164}}, {{191, 164, 63, 173}}, + {{168, 185, 45, 182}}, {{165, 178, 35, 191}}, {{134, 131, 9, 128}}, + {{139, 136, 7, 137}}, {{156, 149, 21, 146}}, {{145, 158, 27, 155}}, + {{ 10, 71, 161, 124}}, {{ 7, 76, 175, 117}}, {{ 16, 81, 189, 110}}, + {{ 29, 90, 179, 103}}, {{ 62, 107, 153, 88}}, {{ 51, 96, 151, 81}}, + {{ 36, 125, 133, 74}}, {{ 41, 118, 139, 67}}, {{ 98, 31, 209, 52}}, + {{111, 20, 223, 61}}, {{120, 9, 205, 38}}, {{117, 2, 195, 47}}, + {{ 86, 51, 233, 16}}, {{ 91, 56, 231, 25}}, {{ 76, 37, 245, 2}}, + {{ 65, 46, 251, 11}}, {{ 97, 140, 154, 215}}, {{108, 135, 148, 222}}, + {{123, 154, 134, 197}}, {{118, 145, 136, 204}}, {{ 85, 160, 162, 243}}, + {{ 88, 171, 172, 250}}, {{ 79, 182, 190, 225}}, {{ 66, 189, 176, 232}}, + {{ 9, 212, 234, 159}}, {{ 4, 223, 228, 150}}, {{ 19, 194, 246, 141}}, + {{ 30, 201, 248, 132}}, {{ 61, 248, 210, 187}}, {{ 48, 243, 220, 178}}, + {{ 39, 238, 206, 169}}, {{ 42, 229, 192, 160}}, {{177, 60, 122, 71}}, + {{188, 55, 116, 78}}, {{171, 42, 102, 85}}, {{166, 33, 104, 92}}, + {{133, 16, 66, 99}}, {{136, 27, 76, 106}}, {{159, 6, 94, 113}}, + {{146, 13, 80, 120}}, {{217, 100, 10, 15}}, {{212, 111, 4, 6}}, + {{195, 114, 22, 29}}, {{206, 121, 24, 20}}, {{237, 72, 50, 43}}, + {{224, 67, 60, 34}}, {{247, 94, 46, 57}}, {{250, 85, 32, 48}}, + {{183, 1, 236, 154}}, {{186, 10, 226, 147}}, {{173, 23, 240, 136}}, + {{160, 28, 254, 129}}, {{131, 45, 212, 190}}, {{142, 38, 218, 183}}, + {{153, 59, 200, 172}}, {{148, 48, 198, 165}}, {{223, 89, 156, 210}}, + {{210, 82, 146, 219}}, {{197, 79, 128, 192}}, {{200, 68, 142, 201}}, + {{235, 117, 164, 246}}, {{230, 126, 170, 255}}, {{241, 99, 184, 228}}, + {{252, 104, 182, 237}}, {{103, 177, 12, 10}}, {{106, 186, 2, 3}}, + {{125, 167, 16, 24}}, {{112, 172, 30, 17}}, {{ 83, 157, 52, 46}}, + {{ 94, 150, 58, 39}}, {{ 73, 139, 40, 60}}, {{ 68, 128, 38, 53}}, + {{ 15, 233, 124, 66}}, {{ 2, 226, 114, 75}}, {{ 21, 255, 96, 80}}, + {{ 24, 244, 110, 89}}, {{ 59, 197, 68, 102}}, {{ 54, 206, 74, 111}}, + {{ 33, 211, 88, 116}}, {{ 44, 216, 86, 125}}, {{ 12, 122, 55, 161}}, + {{ 1, 113, 57, 168}}, {{ 22, 108, 43, 179}}, {{ 27, 103, 37, 186}}, + {{ 56, 86, 15, 133}}, {{ 53, 93, 1, 140}}, {{ 34, 64, 19, 151}}, + {{ 47, 75, 29, 158}}, {{100, 34, 71, 233}}, {{105, 41, 73, 224}}, + {{126, 52, 91, 251}}, {{115, 63, 85, 242}}, {{ 80, 14, 127, 205}}, + {{ 93, 5, 113, 196}}, {{ 74, 24, 99, 223}}, {{ 71, 19, 109, 214}}, + {{220, 202, 215, 49}}, {{209, 193, 217, 56}}, {{198, 220, 203, 35}}, + {{203, 215, 197, 42}}, {{232, 230, 239, 21}}, {{229, 237, 225, 28}}, + {{242, 240, 243, 7}}, {{255, 251, 253, 14}}, {{180, 146, 167, 121}}, + {{185, 153, 169, 112}}, {{174, 132, 187, 107}}, {{163, 143, 181, 98}}, + {{128, 190, 159, 93}}, {{141, 181, 145, 84}}, {{154, 168, 131, 79}}, + {{151, 163, 141, 70}}, + }, + { + {{ 0, 0, 0, 0}}, {{ 9, 13, 11, 14}}, {{ 18, 26, 22, 28}}, + {{ 27, 23, 29, 18}}, {{ 36, 52, 44, 56}}, {{ 45, 57, 39, 54}}, + {{ 54, 46, 58, 36}}, {{ 63, 35, 49, 42}}, {{ 72, 104, 88, 112}}, + {{ 65, 101, 83, 126}}, {{ 90, 114, 78, 108}}, {{ 83, 127, 69, 98}}, + {{108, 92, 116, 72}}, {{101, 81, 127, 70}}, {{126, 70, 98, 84}}, + {{119, 75, 105, 90}}, {{144, 208, 176, 224}}, {{153, 221, 187, 238}}, + {{130, 202, 166, 252}}, {{139, 199, 173, 242}}, {{180, 228, 156, 216}}, + {{189, 233, 151, 214}}, {{166, 254, 138, 196}}, {{175, 243, 129, 202}}, + {{216, 184, 232, 144}}, {{209, 181, 227, 158}}, {{202, 162, 254, 140}}, + {{195, 175, 245, 130}}, {{252, 140, 196, 168}}, {{245, 129, 207, 166}}, + {{238, 150, 210, 180}}, {{231, 155, 217, 186}}, {{ 59, 187, 123, 219}}, + {{ 50, 182, 112, 213}}, {{ 41, 161, 109, 199}}, {{ 32, 172, 102, 201}}, + {{ 31, 143, 87, 227}}, {{ 22, 130, 92, 237}}, {{ 13, 149, 65, 255}}, + {{ 4, 152, 74, 241}}, {{115, 211, 35, 171}}, {{122, 222, 40, 165}}, + {{ 97, 201, 53, 183}}, {{104, 196, 62, 185}}, {{ 87, 231, 15, 147}}, + {{ 94, 234, 4, 157}}, {{ 69, 253, 25, 143}}, {{ 76, 240, 18, 129}}, + {{171, 107, 203, 59}}, {{162, 102, 192, 53}}, {{185, 113, 221, 39}}, + {{176, 124, 214, 41}}, {{143, 95, 231, 3}}, {{134, 82, 236, 13}}, + {{157, 69, 241, 31}}, {{148, 72, 250, 17}}, {{227, 3, 147, 75}}, + {{234, 14, 152, 69}}, {{241, 25, 133, 87}}, {{248, 20, 142, 89}}, + {{199, 55, 191, 115}}, {{206, 58, 180, 125}}, {{213, 45, 169, 111}}, + {{220, 32, 162, 97}}, {{118, 109, 246, 173}}, {{127, 96, 253, 163}}, + {{100, 119, 224, 177}}, {{109, 122, 235, 191}}, {{ 82, 89, 218, 149}}, + {{ 91, 84, 209, 155}}, {{ 64, 67, 204, 137}}, {{ 73, 78, 199, 135}}, + {{ 62, 5, 174, 221}}, {{ 55, 8, 165, 211}}, {{ 44, 31, 184, 193}}, + {{ 37, 18, 179, 207}}, {{ 26, 49, 130, 229}}, {{ 19, 60, 137, 235}}, + {{ 8, 43, 148, 249}}, {{ 1, 38, 159, 247}}, {{230, 189, 70, 77}}, + {{239, 176, 77, 67}}, {{244, 167, 80, 81}}, {{253, 170, 91, 95}}, + {{194, 137, 106, 117}}, {{203, 132, 97, 123}}, {{208, 147, 124, 105}}, + {{217, 158, 119, 103}}, {{174, 213, 30, 61}}, {{167, 216, 21, 51}}, + {{188, 207, 8, 33}}, {{181, 194, 3, 47}}, {{138, 225, 50, 5}}, + {{131, 236, 57, 11}}, {{152, 251, 36, 25}}, {{145, 246, 47, 23}}, + {{ 77, 214, 141, 118}}, {{ 68, 219, 134, 120}}, {{ 95, 204, 155, 106}}, + {{ 86, 193, 144, 100}}, {{105, 226, 161, 78}}, {{ 96, 239, 170, 64}}, + {{123, 248, 183, 82}}, {{114, 245, 188, 92}}, {{ 5, 190, 213, 6}}, + {{ 12, 179, 222, 8}}, {{ 23, 164, 195, 26}}, {{ 30, 169, 200, 20}}, + {{ 33, 138, 249, 62}}, {{ 40, 135, 242, 48}}, {{ 51, 144, 239, 34}}, + {{ 58, 157, 228, 44}}, {{221, 6, 61, 150}}, {{212, 11, 54, 152}}, + {{207, 28, 43, 138}}, {{198, 17, 32, 132}}, {{249, 50, 17, 174}}, + {{240, 63, 26, 160}}, {{235, 40, 7, 178}}, {{226, 37, 12, 188}}, + {{149, 110, 101, 230}}, {{156, 99, 110, 232}}, {{135, 116, 115, 250}}, + {{142, 121, 120, 244}}, {{177, 90, 73, 222}}, {{184, 87, 66, 208}}, + {{163, 64, 95, 194}}, {{170, 77, 84, 204}}, {{236, 218, 247, 65}}, + {{229, 215, 252, 79}}, {{254, 192, 225, 93}}, {{247, 205, 234, 83}}, + {{200, 238, 219, 121}}, {{193, 227, 208, 119}}, {{218, 244, 205, 101}}, + {{211, 249, 198, 107}}, {{164, 178, 175, 49}}, {{173, 191, 164, 63}}, + {{182, 168, 185, 45}}, {{191, 165, 178, 35}}, {{128, 134, 131, 9}}, + {{137, 139, 136, 7}}, {{146, 156, 149, 21}}, {{155, 145, 158, 27}}, + {{124, 10, 71, 161}}, {{117, 7, 76, 175}}, {{110, 16, 81, 189}}, + {{103, 29, 90, 179}}, {{ 88, 62, 107, 153}}, {{ 81, 51, 96, 151}}, + {{ 74, 36, 125, 133}}, {{ 67, 41, 118, 139}}, {{ 52, 98, 31, 209}}, + {{ 61, 111, 20, 223}}, {{ 38, 120, 9, 205}}, {{ 47, 117, 2, 195}}, + {{ 16, 86, 51, 233}}, {{ 25, 91, 56, 231}}, {{ 2, 76, 37, 245}}, + {{ 11, 65, 46, 251}}, {{215, 97, 140, 154}}, {{222, 108, 135, 148}}, + {{197, 123, 154, 134}}, {{204, 118, 145, 136}}, {{243, 85, 160, 162}}, + {{250, 88, 171, 172}}, {{225, 79, 182, 190}}, {{232, 66, 189, 176}}, + {{159, 9, 212, 234}}, {{150, 4, 223, 228}}, {{141, 19, 194, 246}}, + {{132, 30, 201, 248}}, {{187, 61, 248, 210}}, {{178, 48, 243, 220}}, + {{169, 39, 238, 206}}, {{160, 42, 229, 192}}, {{ 71, 177, 60, 122}}, + {{ 78, 188, 55, 116}}, {{ 85, 171, 42, 102}}, {{ 92, 166, 33, 104}}, + {{ 99, 133, 16, 66}}, {{106, 136, 27, 76}}, {{113, 159, 6, 94}}, + {{120, 146, 13, 80}}, {{ 15, 217, 100, 10}}, {{ 6, 212, 111, 4}}, + {{ 29, 195, 114, 22}}, {{ 20, 206, 121, 24}}, {{ 43, 237, 72, 50}}, + {{ 34, 224, 67, 60}}, {{ 57, 247, 94, 46}}, {{ 48, 250, 85, 32}}, + {{154, 183, 1, 236}}, {{147, 186, 10, 226}}, {{136, 173, 23, 240}}, + {{129, 160, 28, 254}}, {{190, 131, 45, 212}}, {{183, 142, 38, 218}}, + {{172, 153, 59, 200}}, {{165, 148, 48, 198}}, {{210, 223, 89, 156}}, + {{219, 210, 82, 146}}, {{192, 197, 79, 128}}, {{201, 200, 68, 142}}, + {{246, 235, 117, 164}}, {{255, 230, 126, 170}}, {{228, 241, 99, 184}}, + {{237, 252, 104, 182}}, {{ 10, 103, 177, 12}}, {{ 3, 106, 186, 2}}, + {{ 24, 125, 167, 16}}, {{ 17, 112, 172, 30}}, {{ 46, 83, 157, 52}}, + {{ 39, 94, 150, 58}}, {{ 60, 73, 139, 40}}, {{ 53, 68, 128, 38}}, + {{ 66, 15, 233, 124}}, {{ 75, 2, 226, 114}}, {{ 80, 21, 255, 96}}, + {{ 89, 24, 244, 110}}, {{102, 59, 197, 68}}, {{111, 54, 206, 74}}, + {{116, 33, 211, 88}}, {{125, 44, 216, 86}}, {{161, 12, 122, 55}}, + {{168, 1, 113, 57}}, {{179, 22, 108, 43}}, {{186, 27, 103, 37}}, + {{133, 56, 86, 15}}, {{140, 53, 93, 1}}, {{151, 34, 64, 19}}, + {{158, 47, 75, 29}}, {{233, 100, 34, 71}}, {{224, 105, 41, 73}}, + {{251, 126, 52, 91}}, {{242, 115, 63, 85}}, {{205, 80, 14, 127}}, + {{196, 93, 5, 113}}, {{223, 74, 24, 99}}, {{214, 71, 19, 109}}, + {{ 49, 220, 202, 215}}, {{ 56, 209, 193, 217}}, {{ 35, 198, 220, 203}}, + {{ 42, 203, 215, 197}}, {{ 21, 232, 230, 239}}, {{ 28, 229, 237, 225}}, + {{ 7, 242, 240, 243}}, {{ 14, 255, 251, 253}}, {{121, 180, 146, 167}}, + {{112, 185, 153, 169}}, {{107, 174, 132, 187}}, {{ 98, 163, 143, 181}}, + {{ 93, 128, 190, 159}}, {{ 84, 141, 181, 145}}, {{ 79, 154, 168, 131}}, + {{ 70, 151, 163, 141}}, + }, +}; + +const int xrcon[30] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, + 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, + 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, +}; + +const word8 xS[256] = { + 99, 124, 119, 123, 242, 107, 111, 197, 48, 1, 103, 43, 254, 215, + 171, 118, 202, 130, 201, 125, 250, 89, 71, 240, 173, 212, 162, 175, + 156, 164, 114, 192, 183, 253, 147, 38, 54, 63, 247, 204, 52, 165, + 229, 241, 113, 216, 49, 21, 4, 199, 35, 195, 24, 150, 5, 154, + 7, 18, 128, 226, 235, 39, 178, 117, 9, 131, 44, 26, 27, 110, + 90, 160, 82, 59, 214, 179, 41, 227, 47, 132, 83, 209, 0, 237, + 32, 252, 177, 91, 106, 203, 190, 57, 74, 76, 88, 207, 208, 239, + 170, 251, 67, 77, 51, 133, 69, 249, 2, 127, 80, 60, 159, 168, + 81, 163, 64, 143, 146, 157, 56, 245, 188, 182, 218, 33, 16, 255, + 243, 210, 205, 12, 19, 236, 95, 151, 68, 23, 196, 167, 126, 61, + 100, 93, 25, 115, 96, 129, 79, 220, 34, 42, 144, 136, 70, 238, + 184, 20, 222, 94, 11, 219, 224, 50, 58, 10, 73, 6, 36, 92, + 194, 211, 172, 98, 145, 149, 228, 121, 231, 200, 55, 109, 141, 213, + 78, 169, 108, 86, 244, 234, 101, 122, 174, 8, 186, 120, 37, 46, + 28, 166, 180, 198, 232, 221, 116, 31, 75, 189, 139, 138, 112, 62, + 181, 102, 72, 3, 246, 14, 97, 53, 87, 185, 134, 193, 29, 158, + 225, 248, 152, 17, 105, 217, 142, 148, 155, 30, 135, 233, 206, 85, + 40, 223, 140, 161, 137, 13, 191, 230, 66, 104, 65, 153, 45, 15, + 176, 84, 187, 22, +}; + +const word8 xSi[256] = { + 82, 9, 106, 213, 48, 54, 165, 56, 191, 64, 163, 158, 129, 243, + 215, 251, 124, 227, 57, 130, 155, 47, 255, 135, 52, 142, 67, 68, + 196, 222, 233, 203, 84, 123, 148, 50, 166, 194, 35, 61, 238, 76, + 149, 11, 66, 250, 195, 78, 8, 46, 161, 102, 40, 217, 36, 178, + 118, 91, 162, 73, 109, 139, 209, 37, 114, 248, 246, 100, 134, 104, + 152, 22, 212, 164, 92, 204, 93, 101, 182, 146, 108, 112, 72, 80, + 253, 237, 185, 218, 94, 21, 70, 87, 167, 141, 157, 132, 144, 216, + 171, 0, 140, 188, 211, 10, 247, 228, 88, 5, 184, 179, 69, 6, + 208, 44, 30, 143, 202, 63, 15, 2, 193, 175, 189, 3, 1, 19, + 138, 107, 58, 145, 17, 65, 79, 103, 220, 234, 151, 242, 207, 206, + 240, 180, 230, 115, 150, 172, 116, 34, 231, 173, 53, 133, 226, 249, + 55, 232, 28, 117, 223, 110, 71, 241, 26, 113, 29, 41, 197, 137, + 111, 183, 98, 14, 170, 24, 190, 27, 252, 86, 62, 75, 198, 210, + 121, 32, 154, 219, 192, 254, 120, 205, 90, 244, 31, 221, 168, 51, + 136, 7, 199, 49, 177, 18, 16, 89, 39, 128, 236, 95, 96, 81, + 127, 169, 25, 181, 74, 13, 45, 229, 122, 159, 147, 201, 156, 239, + 160, 224, 59, 77, 174, 42, 245, 176, 200, 235, 187, 60, 131, 83, + 153, 97, 23, 43, 4, 126, 186, 119, 214, 38, 225, 105, 20, 99, + 85, 33, 12, 125, +}; + diff --git a/src/aes/ao_aes_tables.h b/src/aes/ao_aes_tables.h new file mode 100644 index 00000000..73bcf3fb --- /dev/null +++ b/src/aes/ao_aes_tables.h @@ -0,0 +1,10 @@ +/* Copyright (C) 2000-2009 Peter Selinger. + This file is part of ccrypt. It is free software and it is covered + by the GNU general public license. See the file COPYING for details. */ + +extern const word8x4 M0[4][256]; +extern const word8x4 M1[4][256]; +extern const int xrcon[30]; +extern const word8 xS[256]; +extern const word8 xSi[256]; + diff --git a/src/core/ao_aes.h b/src/core/ao_aes.h index 7f67374d..ab3e367e 100644 --- a/src/core/ao_aes.h +++ b/src/core/ao_aes.h @@ -29,9 +29,11 @@ enum ao_aes_mode { }; #if HAS_AES +#ifdef SDCC void ao_aes_isr(void) __interrupt 4; #endif +#endif void ao_aes_set_mode(enum ao_aes_mode mode); diff --git a/src/core/ao_radio_cmac.c b/src/core/ao_radio_cmac.c index e263f0db..7a377002 100644 --- a/src/core/ao_radio_cmac.c +++ b/src/core/ao_radio_cmac.c @@ -121,7 +121,7 @@ radio_cmac_recv(uint8_t len, uint16_t timeout) __reentrant } ao_radio_cmac_rssi = (int16_t) (((int8_t) cmac_data[len + AO_CMAC_KEY_LEN]) >> 1) - 74; - if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & PKT_APPEND_STATUS_1_CRC_OK)) + if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & AO_RADIO_STATUS_CRC_OK)) return AO_RADIO_CMAC_CRC_ERROR; ao_config_get(); @@ -233,9 +233,9 @@ radio_cmac_recv_cmd(void) __reentrant static __xdata struct ao_launch_command command; static __xdata struct ao_launch_query query; -static pdata uint16_t launch_serial; -static pdata uint8_t launch_channel; -static pdata uint16_t tick_offset; +static __pdata uint16_t launch_serial; +static __pdata uint8_t launch_channel; +static __pdata uint16_t tick_offset; static void launch_args(void) __reentrant diff --git a/src/stm/Makefile.defs b/src/stm/Makefile.defs index 3edfa41d..04404cdc 100644 --- a/src/stm/Makefile.defs +++ b/src/stm/Makefile.defs @@ -1,4 +1,4 @@ -vpath % ../stm:../product:../drivers:../core:../util:../kalman:.. +vpath % ../stm:../product:../drivers:../core:../util:../kalman:../aes:.. vpath make-altitude ../util vpath make-kalman ../util vpath kalman.5c ../kalman -- cgit v1.2.3 From 843fcab46d633e5bb6959286adeb68e41a4c30a3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Jul 2012 19:44:56 -0700 Subject: altos: Add telefire-v0.1 Signed-off-by: Keith Packard --- src/Makefile | 3 +- src/cc1111/ao_adc.c | 20 ++++ src/cc1111/ao_arch.h | 12 --- src/cc1111/ao_pins.h | 12 +++ src/core/ao.h | 7 ++ src/core/ao_config.c | 3 + src/core/ao_storage.c | 1 + src/drivers/ao_74hc497.c | 40 +++++++ src/drivers/ao_74hc497.h | 27 +++++ src/drivers/ao_pad.c | 227 ++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_pad.h | 67 ++++++++++++ src/drivers/ao_pca9922.c | 78 ++++++++++++++ src/telefire-v0.1/Makefile | 101 ++++++++++++++++++ src/telefire-v0.1/ao_pins.h | 94 +++++++++++++++++ src/telefire-v0.1/ao_telefire.c | 41 ++++++++ 15 files changed, 720 insertions(+), 13 deletions(-) create mode 100644 src/drivers/ao_74hc497.c create mode 100644 src/drivers/ao_74hc497.h create mode 100644 src/drivers/ao_pad.c create mode 100644 src/drivers/ao_pad.h create mode 100644 src/drivers/ao_pca9922.c create mode 100644 src/telefire-v0.1/Makefile create mode 100644 src/telefire-v0.1/ao_pins.h create mode 100644 src/telefire-v0.1/ao_telefire.c (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 491618f6..99ea8f85 100644 --- a/src/Makefile +++ b/src/Makefile @@ -21,7 +21,8 @@ ifneq ($(shell which sdcc),) telebt-v0.0 telebt-v0.1 \ telemetrum-v0.1-sky telemetrum-v0.1-sirf \ telelaunch-v0.1 tidongle test \ - teleterra-v0.2 teleshield-v0.1 + teleterra-v0.2 teleshield-v0.1 \ + telefire-v0.1 endif ifneq ($(shell which avr-gcc),) diff --git a/src/cc1111/ao_adc.c b/src/cc1111/ao_adc.c index ce827e25..f7b52281 100644 --- a/src/cc1111/ao_adc.c +++ b/src/cc1111/ao_adc.c @@ -140,6 +140,15 @@ ao_adc_isr(void) __interrupt 1 } #endif /* telemini || telenano */ +#ifdef TELEFIRE_V_0_1 + a = (uint8_t __xdata *) (&ao_data_ring[ao_data_head].adc.sense[0] + sequence); + a[0] = ADCL; + a[1] = ADCH; + if (sequence < 5) + ADCCON3 = ADCCON3_EREF_VDD | ADCCON3_EDIV_512 | (sequence + 1); +#define GOT_ADC +#endif /* TELEFIRE_V_0_1 */ + #ifndef GOT_ADC #error No known ADC configuration set #endif @@ -157,9 +166,13 @@ ao_adc_dump(void) __reentrant { static __xdata struct ao_data packet; ao_data_get(&packet); +#ifndef AO_ADC_DUMP printf("tick: %5u accel: %5d pres: %5d temp: %5d batt: %5d drogue: %5d main: %5d\n", packet.tick, packet.adc.accel, packet.adc.pres, packet.adc.temp, packet.adc.v_batt, packet.adc.sense_d, packet.adc.sense_m); +#else + AO_ADC_DUMP(&packet); +#endif } __code struct ao_cmds ao_adc_cmds[] = { @@ -170,6 +183,11 @@ __code struct ao_cmds ao_adc_cmds[] = { void ao_adc_init(void) { +#ifdef AO_ADC_PINS + ADCCFG = AO_ADC_PINS; + +#else + #if IGNITE_ON_P2 /* TeleMetrum configuration */ ADCCFG = ((1 << 0) | /* acceleration */ @@ -190,6 +208,8 @@ ao_adc_init(void) (1 << 3)); /* battery voltage */ #endif +#endif /* else AO_ADC_PINS */ + /* enable interrupts */ ADCIF = 0; IEN0 |= IEN0_ADCIE; diff --git a/src/cc1111/ao_arch.h b/src/cc1111/ao_arch.h index 06b04b93..a97515a7 100644 --- a/src/cc1111/ao_arch.h +++ b/src/cc1111/ao_arch.h @@ -200,18 +200,6 @@ extern AO_ROMCONFIG_SYMBOL(0x00a6) uint32_t ao_radio_cal; #define ao_arch_critical(b) __critical { b } -struct ao_adc { - int16_t accel; /* accelerometer */ - int16_t pres; /* pressure sensor */ - int16_t temp; /* temperature sensor */ - int16_t v_batt; /* battery voltage */ - int16_t sense_d; /* drogue continuity sense */ - int16_t sense_m; /* main continuity sense */ -#if HAS_ACCEL_REF - uint16_t accel_ref; /* acceleration reference */ -#endif -}; - #define AO_DATA_RING 32 /* ao_button.c */ diff --git a/src/cc1111/ao_pins.h b/src/cc1111/ao_pins.h index fc6ed3ec..2f0e2884 100644 --- a/src/cc1111/ao_pins.h +++ b/src/cc1111/ao_pins.h @@ -560,4 +560,16 @@ #define AO_IGNITER_FIRE_TIME AO_MS_TO_TICKS(50) #define AO_IGNITER_CHARGE_TIME AO_MS_TO_TICKS(2000) +struct ao_adc { + int16_t accel; /* accelerometer */ + int16_t pres; /* pressure sensor */ + int16_t temp; /* temperature sensor */ + int16_t v_batt; /* battery voltage */ + int16_t sense_d; /* drogue continuity sense */ + int16_t sense_m; /* main continuity sense */ +#if HAS_ACCEL_REF + uint16_t accel_ref; /* acceleration reference */ +#endif +}; + #endif /* _AO_PINS_H_ */ diff --git a/src/core/ao.h b/src/core/ao.h index 65b9eb18..1032dd33 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -432,6 +432,7 @@ ao_gps_report_mega_init(void); * ao_telemetry_orig.c */ +#if LEGACY_MONITOR struct ao_adc_orig { uint16_t tick; /* tick when the sample was read */ int16_t accel; /* accelerometer */ @@ -489,6 +490,8 @@ struct ao_telemetry_tiny_recv { uint8_t status; }; +#endif /* LEGACY_MONITOR */ + /* Unfortunately, we've exposed the CC1111 rssi units as the 'usual' method * for reporting RSSI. So, now we use these values everywhere */ @@ -582,6 +585,8 @@ ao_radio_init(void); * ao_monitor.c */ +#if HAS_MONITOR + extern const char const * const ao_state_names[]; #define AO_MONITOR_RING 8 @@ -618,6 +623,8 @@ ao_monitor_enable(void); void ao_monitor_init(void) __reentrant; +#endif + /* * ao_stdio.c */ diff --git a/src/core/ao_config.c b/src/core/ao_config.c index e2095e65..f19dd9cd 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -17,8 +17,11 @@ #include "ao.h" #include "ao_log.h" +#include +#if HAS_FLIGHT #include #include +#endif __xdata struct ao_config ao_config; __pdata uint8_t ao_config_loaded; diff --git a/src/core/ao_storage.c b/src/core/ao_storage.c index b2dd435b..adf7e4d4 100644 --- a/src/core/ao_storage.c +++ b/src/core/ao_storage.c @@ -16,6 +16,7 @@ */ #include +#include uint8_t ao_storage_read(ao_pos_t pos, __xdata void *buf, uint16_t len) __reentrant diff --git a/src/drivers/ao_74hc497.c b/src/drivers/ao_74hc497.c new file mode 100644 index 00000000..93c544c3 --- /dev/null +++ b/src/drivers/ao_74hc497.c @@ -0,0 +1,40 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +/* + * 74HC597 driver. + * Reads a single byte from the shift register + */ + +#include +#include + +uint8_t +ao_74hc497_read(void) +{ + static __xdata state; + ao_spi_get_bit(AO_74HC497_CS_PORT, AO_74HC497_CS_PIN, AO_74HC497_CS, AO_74HC497_SPI_BUS, AO_SPI_SPEED_FAST); + ao_spi_send(&state, 1, AO_74HC497_SPI_BUS); + ao_spi_put_bit(AO_74HC497_CS_PORT, AO_74HC497_CS_PIN, AO_74HC497_CS, AO_74HC497_SPI_BUS); + return state; +} + +void +ao_74hc497_init(void) +{ + ao_enable_output(AO_74HC497_CS_PORT, AO_74HC497_CS_PIN, AO_74HC497_CS, 1); +} diff --git a/src/drivers/ao_74hc497.h b/src/drivers/ao_74hc497.h new file mode 100644 index 00000000..6df7bcae --- /dev/null +++ b/src/drivers/ao_74hc497.h @@ -0,0 +1,27 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_74HC497_H_ +#define _AO_74HC497_H_ + +uint8_t +ao_74hc497_read(void); + +void +ao_74hc497_init(void); + +#endif /* _AO_74HC497_H_ */ diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c new file mode 100644 index 00000000..21aa788d --- /dev/null +++ b/src/drivers/ao_pad.c @@ -0,0 +1,227 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include + +__xdata uint8_t ao_pad_ignite; + +#define ao_pad_igniter_status(c) AO_PAD_IGNITER_STATUS_UNKNOWN +#define ao_pad_arm_status() AO_PAD_ARM_STATUS_UNKNOWN + +#if 0 +#define PRINTD(...) printf(__VA_ARGS__) +#else +#define PRINTD(...) +#endif + +static void +ao_pad_run(void) +{ + for (;;) { + while (!ao_pad_ignite) + ao_sleep(&ao_pad_ignite); + /* + * Actually set the pad bits + */ + AO_PAD_PORT = (AO_PAD_PORT & (~AO_PAD_ALL_PINS)) | ao_pad_ignite; + while (ao_pad_ignite) { + ao_pad_ignite = 0; + ao_delay(AO_PAD_FIRE_TIME); + } + AO_PAD_PORT &= ~(AO_PAD_ALL_PINS); + } +} + +static void +ao_pad_status(void) +{ + for (;;) { + ao_delay(AO_SEC_TO_TICKS(1)); +#if 0 + if (ao_igniter_status(ao_igniter_drogue) == ao_igniter_ready) { + if (ao_igniter_status(ao_igniter_main) == ao_igniter_ready) { + for (i = 0; i < 5; i++) { + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(50)); + ao_delay(AO_MS_TO_TICKS(100)); + } + } else { + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + } + } +#endif + } +} + +static __pdata uint8_t ao_pad_armed; +static __pdata uint16_t ao_pad_arm_time; +static __pdata uint8_t ao_pad_box; + +static void +ao_pad(void) +{ + static __xdata struct ao_pad_command command; + static __xdata struct ao_pad_query query; + int16_t time_difference; + uint8_t c; + + ao_led_off(AO_LED_RED); + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + ao_pad_box = ao_74hc497_read(); + for (;;) { + flush(); + if (ao_radio_cmac_recv(&command, sizeof (command), 0) != AO_RADIO_CMAC_OK) + continue; + + PRINTD ("tick %d serial %d cmd %d channel %d\n", + command.tick, command.serial, command.cmd, command.channel); + + switch (command.cmd) { + case AO_LAUNCH_ARM: + if (command.box != ao_pad_box) { + PRINTD ("box number mismatch\n"); + break; + } + + if (command.channels & ~(AO_PAD_ALL_PINS)) + break; + + time_difference = command.tick - ao_time(); + PRINTD ("arm tick %d local tick %d\n", command.tick, ao_time()); + if (time_difference < 0) + time_difference = -time_difference; + if (time_difference > 10) { + PRINTD ("time difference too large %d\n", time_difference); + break; + } + PRINTD ("armed\n"); + ao_pad_armed = command.channels; + ao_pad_arm_time = ao_time(); + + /* fall through ... */ + + case AO_LAUNCH_QUERY: + if (command.box != ao_pad_box) { + PRINTD ("box number mismatch\n"); + break; + } + + query.tick = ao_time(); + query.box = ao_pad_box; + query.channels = AO_PAD_ALL_PINS; + query.armed = ao_pad_armed; + query.arm_status = ao_pad_arm_status(); + for (c = 0; c < AO_PAD_NUM; c++) + query.igniter_status[c] = ao_pad_igniter_status(c); + PRINTD ("query tick %d serial %d channel %d valid %d arm %d igniter %d\n", + query.tick, query.serial, query.channel, query.valid, query.arm_status, + query.igniter_status); + ao_radio_cmac_send(&query, sizeof (query)); + break; + case AO_LAUNCH_FIRE: + if (!ao_pad_armed) { + PRINTD ("not armed\n"); + break; + } + if ((uint16_t) (ao_time() - ao_pad_arm_time) > AO_SEC_TO_TICKS(20)) { + PRINTD ("late pad arm_time %d time %d\n", + ao_pad_arm_time, ao_time()); + break; + } + time_difference = command.tick - ao_time(); + if (time_difference < 0) + time_difference = -time_difference; + if (time_difference > 10) { + PRINTD ("time different too large %d\n", time_difference); + break; + } + PRINTD ("ignite\n"); + ao_pad_ignite = ao_pad_armed; + ao_wakeup(&ao_pad_ignite); + break; + } + } +} + +void +ao_pad_test(void) +{ +#if 0 + switch (ao_igniter_status(ao_igniter_drogue)) { + case ao_igniter_ready: + case ao_igniter_active: + printf ("Armed: "); + switch (ao_igniter_status(ao_igniter_main)) { + default: + printf("unknown status\n"); + break; + case ao_igniter_ready: + printf("igniter good\n"); + break; + case ao_igniter_open: + printf("igniter bad\n"); + break; + } + break; + default: + printf("Disarmed\n"); + } +#endif +} + +void +ao_pad_manual(void) +{ + ao_cmd_white(); + if (!ao_match_word("DoIt")) + return; + ao_cmd_white(); + ao_pad_ignite = 1; + ao_wakeup(&ao_pad_ignite); +} + +static __xdata struct ao_task ao_pad_task; +static __xdata struct ao_task ao_pad_ignite_task; +static __xdata struct ao_task ao_pad_status_task; + +__code struct ao_cmds ao_pad_cmds[] = { + { ao_pad_test, "t\0Test pad continuity" }, + { ao_pad_manual, "i \0Fire igniter. is doit with D&I" }, + { 0, NULL } +}; + +void +ao_pad_init(void) +{ +#if AO_PAD_NUM > 0 + ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_0, AO_PAD_0, 0); +#endif +#if AO_PAD_NUM > 1 + ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_1, AO_PAD_1, 0); +#endif +#if AO_PAD_NUM > 2 + ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_2, AO_PAD_2, 0); +#endif +#if AO_PAD_NUM > 3 + ao_enable_output(AO_PAD_PORT, AO_PAD_PIN_3, AO_PAD_3, 0); +#endif + ao_cmd_register(&ao_pad_cmds[0]); + ao_add_task(&ao_pad_task, ao_pad, "pad listener"); + ao_add_task(&ao_pad_ignite_task, ao_pad_run, "pad igniter"); + ao_add_task(&ao_pad_status_task, ao_pad_status, "pad status"); +} diff --git a/src/drivers/ao_pad.h b/src/drivers/ao_pad.h new file mode 100644 index 00000000..9ea016ff --- /dev/null +++ b/src/drivers/ao_pad.h @@ -0,0 +1,67 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PAD_H_ +#define _AO_PAD_H_ + +#define AO_PAD_MAX_CHANNELS 8 + +struct ao_pad_command { + uint16_t tick; + uint16_t box; + uint8_t cmd; + uint8_t channels; +}; + +/* Report current telefire status. + */ + +#define AO_PAD_QUERY 1 + +struct ao_pad_query { + uint16_t tick; /* telefire tick */ + uint16_t box; /* telefire box number */ + uint8_t channels; /* which chanels are present */ + uint8_t armed; /* which channels are armed */ + uint8_t arm_status; /* status of arming switch */ + uint8_t igniter_status[AO_PAD_MAX_CHANNELS]; /* status for each igniter */ +}; + +/* Set current armed pads, report back status + */ + +#define AO_PAD_ARM 2 + +/* Fire current armed pads for 200ms, no report + */ +#define AO_PAD_FIRE 3 + +#define AO_PAD_FIRE_TIME AO_MS_TO_TICKS(200) + +#define AO_PAD_ARM_STATUS_DISARMED 0 +#define AO_PAD_ARM_STATUS_ARMED 1 +#define AO_PAD_ARM_STATUS_UNKNOWN 2 + +#define AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN 0 +#define AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN 1 +#define AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED 2 +#define AO_PAD_IGNITER_STATUS_UNKNOWN 3 + +void +ao_pad_init(void); + +#endif /* _AO_PAD_H_ */ diff --git a/src/drivers/ao_pca9922.c b/src/drivers/ao_pca9922.c new file mode 100644 index 00000000..dc006f55 --- /dev/null +++ b/src/drivers/ao_pca9922.c @@ -0,0 +1,78 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +/* + * PCA9922 LED driver. This uses SPI to send a single byte to the device to + * set the current state of the LEDs using the existing LED interface + */ + +#include + +static __xdata uint8_t ao_led_state; + +static void +ao_led_apply(void) +{ + /* Don't try the SPI bus during initialization */ + if (!ao_cur_task) + return; + ao_spi_get_bit(AO_PCA9922_CS_PORT, AO_PCA9922_CS_PIN, AO_PCA9922_CS, AO_PCA9922_SPI_BUS, AO_SPI_SPEED_FAST); + ao_spi_send(&ao_led_state, 1, AO_PCA9922_SPI_BUS); + ao_spi_put_bit(AO_PCA9922_CS_PORT, AO_PCA9922_CS_PIN, AO_PCA9922_CS, AO_PCA9922_SPI_BUS); +} + +void +ao_led_on(uint8_t colors) +{ + ao_led_state |= colors; + ao_led_apply(); +} + +void +ao_led_off(uint8_t colors) +{ + ao_led_state &= ~colors; + ao_led_apply(); +} + +void +ao_led_set(uint8_t colors) +{ + ao_led_state = colors; + ao_led_apply(); +} + +void +ao_led_toggle(uint8_t colors) +{ + ao_led_state ^= colors; + ao_led_apply(); +} + +void +ao_led_for(uint8_t colors, uint16_t ticks) __reentrant +{ + ao_led_on(colors); + ao_delay(ticks); + ao_led_off(colors); +} + +void +ao_led_init(uint8_t enable) +{ + ao_enable_output(AO_PCA9922_CS_PORT, AO_PCA9922_CS_PIN, AO_PCA9922_CS, 1); +} diff --git a/src/telefire-v0.1/Makefile b/src/telefire-v0.1/Makefile new file mode 100644 index 00000000..09cb88fb --- /dev/null +++ b/src/telefire-v0.1/Makefile @@ -0,0 +1,101 @@ +# +# TeleFire build file +# + +TELEFIRE_VER=0.1 +TELEFIRE_DEF=0_1 + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ + cc1111.h \ + ao_product.h + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_convert.c \ + ao_mutex.c \ + ao_panic.c \ + ao_stdio.c \ + ao_storage.c \ + ao_task.c \ + ao_freq.c + +CC1111_SRC = \ + ao_adc.c \ + ao_aes.c \ + ao_beep.c \ + ao_dma.c \ + ao_intflash.c \ + ao_radio.c \ + ao_radio_cmac.c \ + ao_romconfig.c \ + ao_serial.c \ + ao_spi.c \ + ao_string.c \ + ao_timer.c \ + ao_usb.c \ + _bp.c + +DRIVER_SRC = \ + ao_pca9922.c \ + ao_74hc497.c \ + ao_pad.c + +PRODUCT_SRC = \ + ao_telefire.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(DRIVER_SRC) \ + $(PRODUCT_SRC) + +PROGNAME = telefire-v$(TELEFIRE_VER) +PROG = $(PROGNAME)-$(VERSION).ihx +PRODUCT=TeleFire-v$(TELEFIRE_VER) +PRODUCT_DEF=-DTELEFIRE_V_$(TELEFIRE_DEF) +IDPRODUCT=0x000f +CODESIZE=0x6700 + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: clean-cc1111 + +install: + +uninstall: + diff --git a/src/telefire-v0.1/ao_pins.h b/src/telefire-v0.1/ao_pins.h new file mode 100644 index 00000000..4cf523fc --- /dev/null +++ b/src/telefire-v0.1/ao_pins.h @@ -0,0 +1,94 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_RADIO 1 + +#define HAS_FLIGHT 0 +#define HAS_USB 1 +#define HAS_BEEP 1 +#define HAS_GPS 0 +#define HAS_SERIAL_1 0 +#define HAS_ADC 1 +#define HAS_DBG 0 +#define HAS_EEPROM 1 +#define HAS_LOG 0 +#define USE_INTERNAL_FLASH 1 +#define DBG_ON_P1 0 +#define IGNITE_ON_P2 0 +#define IGNITE_ON_P1 1 +#define IGNITE_ON_P0 0 +#define PACKET_HAS_MASTER 0 +#define PACKET_HAS_SLAVE 0 +#define AO_LED_RED 2 +#define AO_LED_GREEN 1 +#define LEDS_AVAILABLE (0xff) +#define HAS_EXTERNAL_TEMP 0 +#define HAS_ACCEL_REF 0 +#define SPI_CS_ON_P1 1 +#define HAS_AES 1 + +#define SPI_CS_PORT P1 +#define SPI_CS_SEL P1SEL +#define SPI_CS_DIR P1DIR + +#define AO_74HC497_CS_PORT P1 +#define AO_74HC497_CS_PIN 4 +#define AO_74HC497_CS P1_4 + +#define AO_PCA9922_CS_PORT P1 +#define AO_PCA9922_CS_PIN 4 +#define AO_PCA9922_CS P1_4 + +#define AO_PAD_NUM 4 +#define AO_PAD_PORT P1 +#define AO_PAD_DIR P1DIR +#define AO_PAD_PIN_0 0 +#define AO_PAD_0 P1_0 +#define AO_PAD_PIN_1 1 +#define AO_PAD_1 P1_1 +#define AO_PAD_PIN_2 2 +#define AO_PAD_2 P1_2 +#define AO_PAD_PIN_3 3 +#define AO_PAD_3 P1_3 +#define AO_PAD_ALL_PINS ((1 << AO_PAD_PIN_0) | (1 << AO_PAD_PIN_1) | (1 << AO_PAD_PIN_2) | (1 << AO_PAD_PIN_3)) + +/* test these values with real igniters */ +#define AO_PAD_RELAY_CLOSED 3524 +#define AO_PAD_NO_IGNITER 16904 +#define AO_PAD_GOOD_IGNITER 22514 + +struct ao_adc { + int16_t sense[4]; + int16_t pyro; + int16_t batt; +}; + +#define AO_ADC_DUMP(p) \ + printf ("tick: %5u 0: %5d 1: %5d 2: %5d 3: %5d pyro: %5d batt %5d\n", \ + (p)->adc.sense[0], \ + (p)->adc.sense[1], \ + (p)->adc.sense[2], \ + (p)->adc.sense[3], \ + (p)->adc.pyro, \ + (p)->adc.batt) + +#define AO_ADC_PINS ((1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5)) + +#endif /* _AO_PINS_H_ */ diff --git a/src/telefire-v0.1/ao_telefire.c b/src/telefire-v0.1/ao_telefire.c new file mode 100644 index 00000000..96413a63 --- /dev/null +++ b/src/telefire-v0.1/ao_telefire.c @@ -0,0 +1,41 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" +#include "ao_pins.h" + +void +main(void) +{ + ao_clock_init(); + + ao_led_init(LEDS_AVAILABLE); + + ao_timer_init(); + ao_adc_init(); + ao_beep_init(); + ao_cmd_init(); + ao_spi_init(); + ao_storage_init(); + ao_usb_init(); + ao_radio_init(); + ao_aes_init(); + ao_radio_cmac_init(); + ao_pad_init(); + ao_config_init(); + ao_start_scheduler(); +} -- cgit v1.2.3 From 2e7e304e67bc1e094282c8668fa8cccf09f9c9b4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 29 Jul 2012 19:48:08 -0700 Subject: altos: Add driver for STM internal flash Signed-off-by: Keith Packard --- src/stm/ao_eeprom_stm.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++++ src/stm/stm32l.h | 24 ++++++ 2 files changed, 215 insertions(+) create mode 100644 src/stm/ao_eeprom_stm.c (limited to 'src') diff --git a/src/stm/ao_eeprom_stm.c b/src/stm/ao_eeprom_stm.c new file mode 100644 index 00000000..1e51b417 --- /dev/null +++ b/src/stm/ao_eeprom_stm.c @@ -0,0 +1,191 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +/* Total bytes of available storage */ +ao_pos_t ao_storage_total = 4096; + +/* Block size - device is erased in these units. */ +ao_pos_t ao_storage_block = 1024; + +/* Byte offset of config block. Will be ao_storage_block bytes long */ +ao_pos_t ao_storage_config = 0; + +/* Storage unit size - device reads and writes must be within blocks of this size. */ +uint16_t ao_storage_unit = 1024; + +/* Location of eeprom in address space */ +#define stm_eeprom ((uint8_t *) 0x08080000) + +/* + * The internal flash chip is arranged in 8 byte sectors; the + * chip cannot erase in units smaller than that. + * + * Writing happens in units of 2 bytes and + * can only change bits from 1 to 0. So, you can rewrite + * the same contents, or append to an existing page easily enough + */ + +/* + * Erase the specified sector + */ +uint8_t +ao_storage_erase(ao_pos_t pos) __reentrant +{ + /* Not necessary */ + return 1; +} + +static void +ao_intflash_unlock(void) +{ + /* Unlock Data EEPROM and FLASH_PECR register */ + stm_flash.pekeyr = STM_FLASH_PEKEYR_PEKEY1; + stm_flash.pekeyr = STM_FLASH_PEKEYR_PEKEY2; + + /* Configure the FTDW bit (FLASH_PECR[8]) to execute + * word write, whatever the previous value of the word + * being written to + */ + stm_flash.pecr = ((0 << STM_FLASH_PECR_OBL_LAUNCH) | + (0 << STM_FLASH_PECR_ERRIE) | + (0 << STM_FLASH_PECR_EOPIE) | + (0 << STM_FLASH_PECR_FPRG) | + (0 << STM_FLASH_PECR_ERASE) | + (0 << STM_FLASH_PECR_FTDW) | + (1 << STM_FLASH_PECR_DATA) | + (0 << STM_FLASH_PECR_PROG) | + (0 << STM_FLASH_PECR_OPTLOCK) | + (0 << STM_FLASH_PECR_PRGLOCK) | + (0 << STM_FLASH_PECR_PELOCK)); +} + +static void +ao_intflash_lock(void) +{ + stm_flash.pecr |= (1 << STM_FLASH_PECR_PELOCK); +} + +static void +ao_intflash_write32(uint16_t pos, uint32_t w) +{ + uint32_t *addr; + + addr = (uint32_t *) (stm_eeprom + pos); + + /* Write a word to a valid address in the data EEPROM */ + *addr = w; + + /* Wait for the flash unit to go idle */ + while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)) + ; +} + +static void +ao_intflash_write8(uint16_t pos, uint8_t d) +{ + uint32_t w, *addr, mask; + uint8_t shift; + + addr = (uint32_t *) (stm_eeprom + (pos & ~3)); + + /* Compute word to be written */ + shift = (pos & 3) << 3; + mask = 0xff << shift; + w = (*addr & ~mask) | (d << shift); + + ao_intflash_write32(pos & ~3, w); +} + +static uint8_t +ao_intflash_read(uint16_t pos) +{ + return stm_eeprom[pos]; +} + +/* + * Write to flash + */ + +uint8_t +ao_storage_device_write(ao_pos_t pos32, __xdata void *v, uint16_t len) __reentrant +{ + uint16_t pos = pos32; + __xdata uint8_t *d = v; + + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + + ao_intflash_unlock(); + while (len) { + if ((pos & 3) == 0 && len >= 4) { + uint32_t w; + + w = d[0] | (d[1] << 8) | (d[2] << 16) | (d[3] << 24); + ao_intflash_write32(pos, w); + pos += 4; + d += 4; + len -= 4; + } else { + ao_intflash_write8(pos, *d); + pos += 1; + d += 1; + len -= 1; + } + } + ao_intflash_lock(); + + return 1; +} + +/* + * Read from flash + */ +uint8_t +ao_storage_device_read(ao_pos_t pos, __xdata void *v, uint16_t len) __reentrant +{ + uint8_t *d = v; + + if (pos >= ao_storage_total || pos + len > ao_storage_total) + return 0; + while (len--) + *d++ = ao_intflash_read(pos++); + return 1; +} + +void +ao_storage_flush(void) __reentrant +{ +} + +void +ao_storage_setup(void) +{ +} + +void +ao_storage_device_info(void) __reentrant +{ + printf ("Using internal flash\n"); +} + +void +ao_storage_device_init(void) +{ +} diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index ff8dddff..4d665e8b 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -281,6 +281,30 @@ extern struct stm_flash stm_flash; #define STM_FLASH_ACR_PRFEN (1) #define STM_FLASH_ACR_LATENCY (0) +#define STM_FLASH_PECR_OBL_LAUNCH 18 +#define STM_FLASH_PECR_ERRIE 17 +#define STM_FLASH_PECR_EOPIE 16 +#define STM_FLASH_PECR_FPRG 10 +#define STM_FLASH_PECR_ERASE 9 +#define STM_FLASH_PECR_FTDW 8 +#define STM_FLASH_PECR_DATA 4 +#define STM_FLASH_PECR_PROG 3 +#define STM_FLASH_PECR_OPTLOCK 2 +#define STM_FLASH_PECR_PRGLOCK 1 +#define STM_FLASH_PECR_PELOCK 0 + +#define STM_FLASH_SR_OPTVERR 11 +#define STM_FLASH_SR_SIZERR 10 +#define STM_FLASH_SR_PGAERR 9 +#define STM_FLASH_SR_WRPERR 8 +#define STM_FLASH_SR_READY 3 +#define STM_FLASH_SR_ENDHV 2 +#define STM_FLASH_SR_EOP 1 +#define STM_FLASH_SR_BSY 0 + +#define STM_FLASH_PEKEYR_PEKEY1 0x89ABCDEF +#define STM_FLASH_PEKEYR_PEKEY2 0x02030405 + struct stm_rcc { vuint32_t cr; vuint32_t icscr; -- cgit v1.2.3 From 2610b316eb939c1532061646b05207fcd54d984f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Aug 2012 12:15:36 -0700 Subject: src/cc1111: Add ao_gpio_set macro Allows general GPIO-using code to run on cc1111 Signed-off-by: Keith Packard --- src/cc1111/ao_arch_funcs.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/cc1111/ao_arch_funcs.h b/src/cc1111/ao_arch_funcs.h index 0737e7ab..29755b5c 100644 --- a/src/cc1111/ao_arch_funcs.h +++ b/src/cc1111/ao_arch_funcs.h @@ -88,3 +88,4 @@ ao_spi_init(void); #define token_paster(x,y) x ## y #define token_evaluator(x,y) token_paster(x,y) #define ao_enable_output(port,bit,pin,v) cc1111_enable_output(port,token_evaluator(port,DIR), token_evaluator(port,SEL), pin, bit, v) +#define ao_gpio_set(port, bit, pin, v) ((pin) = (v)) -- cgit v1.2.3 From 39594fdb3e30a1a25dd894c217e3d9d773bab972 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Aug 2012 12:16:25 -0700 Subject: src/cc1111: Allow serial0 without serial1 The ao_serial_speed structure is needed by serial0 too. Signed-off-by: Keith Packard --- src/cc1111/ao_serial.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_serial.c b/src/cc1111/ao_serial.c index d90103b0..d5431070 100644 --- a/src/cc1111/ao_serial.c +++ b/src/cc1111/ao_serial.c @@ -17,6 +17,25 @@ #include "ao.h" +const __code struct ao_serial_speed ao_serial_speeds[] = { + /* [AO_SERIAL_SPEED_4800] = */ { + /* .baud = */ 163, + /* .gcr = */ (7 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB + }, + /* [AO_SERIAL_SPEED_9600] = */ { + /* .baud = */ 163, + /* .gcr = */ (8 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB + }, + /* [AO_SERIAL_SPEED_19200] = */ { + /* .baud = */ 163, + /* .gcr = */ (9 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB + }, + /* [AO_SERIAL_SPEED_57600] = */ { + /* .baud = */ 59, + /* .gcr = */ (11 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB + }, +}; + #if HAS_SERIAL_0 volatile __xdata struct ao_fifo ao_serial0_rx_fifo; @@ -181,25 +200,6 @@ ao_serial1_drain(void) __critical ao_sleep(&ao_serial1_tx_fifo); } -const __code struct ao_serial_speed ao_serial_speeds[] = { - /* [AO_SERIAL_SPEED_4800] = */ { - /* .baud = */ 163, - /* .gcr = */ (7 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB - }, - /* [AO_SERIAL_SPEED_9600] = */ { - /* .baud = */ 163, - /* .gcr = */ (8 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB - }, - /* [AO_SERIAL_SPEED_19200] = */ { - /* .baud = */ 163, - /* .gcr = */ (9 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB - }, - /* [AO_SERIAL_SPEED_57600] = */ { - /* .baud = */ 59, - /* .gcr = */ (11 << UxGCR_BAUD_E_SHIFT) | UxGCR_ORDER_LSB - }, -}; - void ao_serial1_set_speed(uint8_t speed) { -- cgit v1.2.3 From 0f82021186565fda10df7893b95deae4a1f32778 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Aug 2012 12:17:25 -0700 Subject: src/cc1111: Enable SPI slave mode This is untested... Signed-off-by: Keith Packard --- src/cc1111/ao_spi.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_spi.c b/src/cc1111/ao_spi.c index 1bf5e155..88cff9dd 100644 --- a/src/cc1111/ao_spi.c +++ b/src/cc1111/ao_spi.c @@ -40,6 +40,7 @@ static __xdata uint8_t ao_spi_const; void ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant { +#if !AO_SPI_SLAVE ao_dma_set_transfer(ao_spi_dma_in_id, &U0DBUFXADDR, &ao_spi_const, @@ -50,7 +51,7 @@ ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant DMA_CFG1_SRCINC_0 | DMA_CFG1_DESTINC_0 | DMA_CFG1_PRIORITY_NORMAL); - +#endif ao_dma_set_transfer(ao_spi_dma_out_id, block, &U0DBUFXADDR, @@ -62,11 +63,18 @@ ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant DMA_CFG1_DESTINC_0 | DMA_CFG1_PRIORITY_NORMAL); +#if !AO_SPI_SLAVE ao_dma_start(ao_spi_dma_in_id); +#endif ao_dma_start(ao_spi_dma_out_id); ao_dma_trigger(ao_spi_dma_out_id); +#if AO_SPI_SLAVE + __critical while (!ao_spi_dma_out_done) + ao_sleep(&ao_spi_dma_out_done); +#else __critical while (!ao_spi_dma_in_done) ao_sleep(&ao_spi_dma_in_done); +#endif } /* Receive bytes over SPI. @@ -115,10 +123,19 @@ ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant * MO P1_5 * MI P1_4 * CLK P1_3 + * CSS P1_2 * - * Chip select is the responsibility of the caller + * Chip select is the responsibility of the caller in master mode */ +#if AO_SPI_SLAVE +#define CSS (1 << 2) +#define UxCSR_DIRECTION UxCSR_SLAVE +#else +#define CSS 0 +#define UxCSR_DIRECTION UxCSR_MASTER +#endif + void ao_spi_init(void) { @@ -131,7 +148,7 @@ ao_spi_init(void) P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | P2SEL_PRI3P1_USART0; /* Make the SPI pins be controlled by the USART peripheral */ - P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3)); + P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3) | CSS); /* Set up OUT DMA */ ao_spi_dma_out_id = ao_dma_alloc(&ao_spi_dma_out_done); @@ -143,7 +160,7 @@ ao_spi_init(void) * * SPI master mode */ - U0CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_MASTER); + U0CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_DIRECTION); /* Set the baud rate and signal parameters * -- cgit v1.2.3 From de701d5a234cd21930cf92c9cabebb0e230da9b5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 5 Aug 2012 14:58:40 -0700 Subject: altos: Build ao_kalman.h from cc1111 subdirs as needed Signed-off-by: Keith Packard --- src/cc1111/Makefile.cc1111 | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/cc1111/Makefile.cc1111 b/src/cc1111/Makefile.cc1111 index bfd444dd..0e19603b 100644 --- a/src/cc1111/Makefile.cc1111 +++ b/src/cc1111/Makefile.cc1111 @@ -33,3 +33,6 @@ clean-cc1111: rm -f $(PROGNAME)-* rm -f ao_product.h rm -f ../$(PROGNAME)-* + +../ao_kalman.h: + +(cd .. && make ao_kalman.h) -- cgit v1.2.3 From 6171892fa32e8a662a494ec6ba28a82fddc68589 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 6 Aug 2012 19:33:44 -0700 Subject: altos: Add ao_gpio_get and ao_exti_set_mode Needed to support general GPIO interrupts Signed-off-by: Keith Packard --- src/stm/ao_arch_funcs.h | 13 +++++++++++++ src/stm/ao_exti.h | 3 +++ src/stm/ao_exti_stm.c | 14 ++++++++++++++ src/stm/stm32l.h | 2 +- 4 files changed, 31 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index d2c973f5..3d8ca1f2 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -78,12 +78,25 @@ ao_spi_init(void); #define ao_gpio_set(port, bit, pin, v) stm_gpio_set(port, bit, v) +#define ao_gpio_get(port, bit, pin) stm_gpio_get(port, bit) + #define ao_enable_output(port,bit,pin,v) do { \ ao_enable_port(port); \ ao_gpio_set(port, bit, pin, v); \ stm_moder_set(port, bit, STM_MODER_OUTPUT);\ } while (0) +#define ao_enable_input(port,bit,mode) do { \ + ao_enable_port(port); \ + stm_moder_set(port, bit, STM_MODER_INPUT); \ + if (mode == AO_EXTI_MODE_PULL_UP) \ + stm_pupdr_set(port, bit, STM_PUPDR_PULL_UP); \ + else if (mode == AO_EXTI_MODE_PULL_DOWN) \ + stm_pupdr_set(port, bit, STM_PUPDR_PULL_DOWN); \ + else \ + stm_pupdr_set(port, bit, STM_PUPDR_NONE); \ + } while (0) + #define ao_enable_cs(port,bit) do { \ stm_gpio_set((port), bit, 1); \ stm_moder_set((port), bit, STM_MODER_OUTPUT); \ diff --git a/src/stm/ao_exti.h b/src/stm/ao_exti.h index b579ad9f..35b56b57 100644 --- a/src/stm/ao_exti.h +++ b/src/stm/ao_exti.h @@ -29,6 +29,9 @@ void ao_exti_setup(struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback)()); +void +ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode); + void ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)()); diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c index d54e6ee6..11099b02 100644 --- a/src/stm/ao_exti_stm.c +++ b/src/stm/ao_exti_stm.c @@ -115,6 +115,20 @@ ao_exti_setup (struct stm_gpio *gpio, uint8_t pin, uint8_t mode, void (*callback stm_nvic_set_enable(irq); } +void +ao_exti_set_mode(struct stm_gpio *gpio, uint8_t pin, uint8_t mode) { + uint32_t mask = 1 << pin; + + if (mode & AO_EXTI_MODE_RISING) + stm_exti.rtsr |= mask; + else + stm_exti.rtsr &= ~mask; + if (mode & AO_EXTI_MODE_FALLING) + stm_exti.ftsr |= mask; + else + stm_exti.ftsr &= ~mask; +} + void ao_exti_set_callback(struct stm_gpio *gpio, uint8_t pin, void (*callback)()) { ao_exti_callback[pin] = callback; diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 4d665e8b..3a498a0a 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -167,7 +167,7 @@ stm_gpio_set(struct stm_gpio *gpio, int pin, uint8_t value) { } static inline uint8_t -stm_gpio_isset(struct stm_gpio *gpio, int pin) { +stm_gpio_get(struct stm_gpio *gpio, int pin) { return (gpio->idr >> pin) & 1; } -- cgit v1.2.3 From b0b52ca73bc836336ecc70247a9ed1dd633920d9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 6 Aug 2012 19:34:34 -0700 Subject: altos: Add quadrature driver Signed-off-by: Keith Packard --- src/drivers/ao_quadrature.c | 108 ++++++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_quadrature.h | 30 ++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 src/drivers/ao_quadrature.c create mode 100644 src/drivers/ao_quadrature.h (limited to 'src') diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c new file mode 100644 index 00000000..1cde32e7 --- /dev/null +++ b/src/drivers/ao_quadrature.c @@ -0,0 +1,108 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include + +__xdata int32_t ao_quadrature_count; + +static uint8_t wait_clear; + +static void +ao_quadrature_isr(void) +{ + if (wait_clear) { + wait_clear = 0; + ao_exti_set_mode(AO_QUADRATURE_PORT, AO_QUADRATURE_A, AO_EXTI_MODE_RISING); + } else { + wait_clear = 1; + ao_exti_set_mode(AO_QUADRATURE_PORT, AO_QUADRATURE_A, AO_EXTI_MODE_FALLING); + if (ao_gpio_get(AO_QUADRATURE_PORT, AO_QUADRATURE_B, AO_QUADRATURE_B_PIN)) + ao_quadrature_count++; + else + ao_quadrature_count--; + ao_wakeup(&ao_quadrature_count); + } +} + +int32_t +ao_quadrature_poll(void) +{ + int32_t ret; + ao_arch_critical(ret = ao_quadrature_count;); + return ret; +} + +int32_t +ao_quadrature_wait(void) +{ + ao_sleep(&ao_quadrature_count); + return ao_quadrature_poll(); +} + +static void +ao_quadrature_test(void) +{ +#if 0 + for (;;) { + int32_t c; + printf ("waiting...\n"); + flush(); + c = ao_quadrature_wait(); + printf ("new count %d\n", c); + if (ao_stdin_ready) + break; + } +#endif + uint8_t a, old_a, b, old_b; + + old_a = 2; old_b = 2; + for (;;) { + a = ao_gpio_get(AO_QUADRATURE_PORT, AO_QUADRATURE_A, AO_QUADRATURE_A_PIN); + b = ao_gpio_get(AO_QUADRATURE_PORT, AO_QUADRATURE_B, AO_QUADRATURE_B_PIN); + if (a != old_a || b != old_b) { + printf ("A %d B %d\n", a, b); + flush(); + ao_yield(); + old_a = a; + old_b = b; + } + if (ao_stdin_ready) + break; + } + +} + +static const struct ao_cmds ao_quadrature_cmds[] = { + { ao_quadrature_test, "q\0Test quadrature" }, + { 0, NULL } +}; + +void +ao_quadrature_init(void) +{ + ao_quadrature_count = 0; + + ao_enable_port(AO_QUADRATURE_PORT); + ao_exti_setup(AO_QUADRATURE_PORT, AO_QUADRATURE_A, + AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, + ao_quadrature_isr); + ao_exti_enable(AO_QUADRATURE_PORT, AO_QUADRATURE_A); + ao_enable_input(AO_QUADRATURE_PORT, AO_QUADRATURE_B, AO_EXTI_MODE_PULL_UP); + ao_cmd_register(&ao_quadrature_cmds[0]); +} diff --git a/src/drivers/ao_quadrature.h b/src/drivers/ao_quadrature.h new file mode 100644 index 00000000..7e1048bc --- /dev/null +++ b/src/drivers/ao_quadrature.h @@ -0,0 +1,30 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_QUADRATURE_H_ +#define _AO_QUADRATURE_H_ + +int32_t +ao_quadrature_wait(void); + +int32_t +ao_quadrature_poll(void); + +void +ao_quadrature_init(void); + +#endif /* _AO_QUADRATURE_H_ */ -- cgit v1.2.3 From ab379493dbe9923db8e458d2f4e0344df17d331c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 6 Aug 2012 19:35:02 -0700 Subject: Signed-off-by: Keith Packard altos: Test quadrature driver --- src/stm-demo/Makefile | 4 +++- src/stm-demo/ao_demo.c | 4 ++++ src/stm-demo/ao_pins.h | 4 ++++ 3 files changed, 11 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 055a73af..52bb7b51 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -33,7 +33,9 @@ ALTOS_SRC = \ ao_spi_stm.c \ ao_adc_stm.c \ ao_i2c_stm.c \ - ao_usb_stm.c + ao_usb_stm.c \ + ao_exti_stm.c \ + ao_quadrature.c PRODUCT=StmDemo-v0.0 PRODUCT_DEF=-DSTM_DEMO diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 9a581ff9..1b9813fe 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -16,6 +16,8 @@ */ #include "ao.h" +#include +#include struct ao_task demo_task; @@ -170,6 +172,8 @@ main(void) // ao_lcd_font_init(); ao_spi_init(); ao_i2c_init(); + ao_exti_init(); + ao_quadrature_init(); ao_timer_set_adc_interval(100); diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 7e222122..17a76bd0 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -170,4 +170,8 @@ struct ao_adc { #define HAS_I2C_2 0 #define I2C_2_PB10_PB11 0 +#define AO_QUADRATURE_PORT &stm_gpioc +#define AO_QUADRATURE_A 0 +#define AO_QUADRATURE_B 1 + #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 5f7e61c749b02ed16e368502062e39b0471e9257 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 6 Aug 2012 20:20:32 -0700 Subject: altos: Fix up quadrature driver Mostly works now, should work reliably with a bit of input filtering. Signed-off-by: Keith Packard --- src/drivers/ao_quadrature.c | 49 +++++++++++++++++++++++++++------------------ src/stm-demo/ao_pins.h | 4 ++-- 2 files changed, 31 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c index 1cde32e7..1f94aa44 100644 --- a/src/drivers/ao_quadrature.c +++ b/src/drivers/ao_quadrature.c @@ -21,23 +21,29 @@ __xdata int32_t ao_quadrature_count; -static uint8_t wait_clear; +static uint8_t ao_quadrature_state; + +#define BIT(a,b) ((a) | ((b) << 1)) +#define STATE(old_a, old_b, new_a, new_b) (((BIT(old_a, old_b) << 2) | BIT(new_a, new_b))) static void ao_quadrature_isr(void) { - if (wait_clear) { - wait_clear = 0; - ao_exti_set_mode(AO_QUADRATURE_PORT, AO_QUADRATURE_A, AO_EXTI_MODE_RISING); - } else { - wait_clear = 1; - ao_exti_set_mode(AO_QUADRATURE_PORT, AO_QUADRATURE_A, AO_EXTI_MODE_FALLING); - if (ao_gpio_get(AO_QUADRATURE_PORT, AO_QUADRATURE_B, AO_QUADRATURE_B_PIN)) - ao_quadrature_count++; - else - ao_quadrature_count--; - ao_wakeup(&ao_quadrature_count); + ao_quadrature_state = ((ao_quadrature_state & 3) << 2); + ao_quadrature_state |= ao_gpio_get(AO_QUADRATURE_PORT, AO_QUADRATURE_A, AO_QUADRATURE_A_PIN); + ao_quadrature_state |= ao_gpio_get(AO_QUADRATURE_PORT, AO_QUADRATURE_B, AO_QUADRATURE_B_PIN) << 1; + + switch (ao_quadrature_state) { + case STATE(0, 1, 0, 0): + ao_quadrature_count++; + break; + case STATE(1, 0, 0, 0): + ao_quadrature_count--; + break; + default: + return; } + ao_wakeup(&ao_quadrature_count); } int32_t @@ -58,17 +64,17 @@ ao_quadrature_wait(void) static void ao_quadrature_test(void) { -#if 0 +#if 1 for (;;) { int32_t c; - printf ("waiting...\n"); flush(); c = ao_quadrature_wait(); - printf ("new count %d\n", c); - if (ao_stdin_ready) + printf ("new count %6d\n", c); + if (c == 100) break; } #endif +#if 0 uint8_t a, old_a, b, old_b; old_a = 2; old_b = 2; @@ -76,7 +82,7 @@ ao_quadrature_test(void) a = ao_gpio_get(AO_QUADRATURE_PORT, AO_QUADRATURE_A, AO_QUADRATURE_A_PIN); b = ao_gpio_get(AO_QUADRATURE_PORT, AO_QUADRATURE_B, AO_QUADRATURE_B_PIN); if (a != old_a || b != old_b) { - printf ("A %d B %d\n", a, b); + printf ("A %d B %d count %ld\n", a, b, ao_quadrature_count); flush(); ao_yield(); old_a = a; @@ -85,7 +91,7 @@ ao_quadrature_test(void) if (ao_stdin_ready) break; } - +#endif } static const struct ao_cmds ao_quadrature_cmds[] = { @@ -100,9 +106,12 @@ ao_quadrature_init(void) ao_enable_port(AO_QUADRATURE_PORT); ao_exti_setup(AO_QUADRATURE_PORT, AO_QUADRATURE_A, - AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_FALLING|AO_EXTI_PRIORITY_MED, + AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, ao_quadrature_isr); ao_exti_enable(AO_QUADRATURE_PORT, AO_QUADRATURE_A); - ao_enable_input(AO_QUADRATURE_PORT, AO_QUADRATURE_B, AO_EXTI_MODE_PULL_UP); + ao_exti_setup(AO_QUADRATURE_PORT, AO_QUADRATURE_B, + AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, + ao_quadrature_isr); + ao_exti_enable(AO_QUADRATURE_PORT, AO_QUADRATURE_B); ao_cmd_register(&ao_quadrature_cmds[0]); } diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 17a76bd0..1f5ef4ff 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -171,7 +171,7 @@ struct ao_adc { #define I2C_2_PB10_PB11 0 #define AO_QUADRATURE_PORT &stm_gpioc -#define AO_QUADRATURE_A 0 -#define AO_QUADRATURE_B 1 +#define AO_QUADRATURE_A 1 +#define AO_QUADRATURE_B 0 #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 11046bc89b3ce6386f1005fc8476b08f54d6f5fb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 6 Aug 2012 21:54:58 -0700 Subject: altos: Support multiple quadrature encoders. Signed-off-by: Keith Packard --- src/drivers/ao_quadrature.c | 90 +++++++++++++++++++++++++++++---------------- src/drivers/ao_quadrature.h | 4 +- src/stm-demo/ao_pins.h | 13 +++++-- 3 files changed, 70 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c index 1f94aa44..aed4999e 100644 --- a/src/drivers/ao_quadrature.c +++ b/src/drivers/ao_quadrature.c @@ -19,46 +19,63 @@ #include #include -__xdata int32_t ao_quadrature_count; +__xdata int32_t ao_quadrature_count[AO_QUADRATURE_COUNT]; -static uint8_t ao_quadrature_state; +static uint8_t ao_quadrature_state[AO_QUADRATURE_COUNT]; #define BIT(a,b) ((a) | ((b) << 1)) #define STATE(old_a, old_b, new_a, new_b) (((BIT(old_a, old_b) << 2) | BIT(new_a, new_b))) +#define port(q) AO_QUADRATURE_ ## q ## _PORT +#define bita(q) AO_QUADRATURE_ ## q ## _A +#define bitb(q) AO_QUADRATURE_ ## q ## _B + +#define ao_quadrature_update(q) do { \ + ao_quadrature_state[q] = ((ao_quadrature_state[q] & 3) << 2); \ + ao_quadrature_state[q] |= ao_gpio_get(port(q), bita(q), 0); \ + ao_quadrature_state[q] |= ao_gpio_get(port(q), bitb(q), 0) << 1; \ + } while (0) + + static void ao_quadrature_isr(void) { - ao_quadrature_state = ((ao_quadrature_state & 3) << 2); - ao_quadrature_state |= ao_gpio_get(AO_QUADRATURE_PORT, AO_QUADRATURE_A, AO_QUADRATURE_A_PIN); - ao_quadrature_state |= ao_gpio_get(AO_QUADRATURE_PORT, AO_QUADRATURE_B, AO_QUADRATURE_B_PIN) << 1; + uint8_t q; +#if AO_QUADRATURE_COUNT > 0 + ao_quadrature_update(0); +#endif +#if AO_QUADRATURE_COUNT > 1 + ao_quadrature_update(1); +#endif - switch (ao_quadrature_state) { - case STATE(0, 1, 0, 0): - ao_quadrature_count++; - break; - case STATE(1, 0, 0, 0): - ao_quadrature_count--; - break; - default: - return; + for (q = 0; q < AO_QUADRATURE_COUNT; q++) { + switch (ao_quadrature_state[q]) { + case STATE(0, 1, 0, 0): + ao_quadrature_count[q]++; + break; + case STATE(1, 0, 0, 0): + ao_quadrature_count[q]--; + break; + default: + continue; + } + ao_wakeup(&ao_quadrature_count[q]); } - ao_wakeup(&ao_quadrature_count); } int32_t -ao_quadrature_poll(void) +ao_quadrature_poll(uint8_t q) { int32_t ret; - ao_arch_critical(ret = ao_quadrature_count;); + ao_arch_critical(ret = ao_quadrature_count[q];); return ret; } int32_t -ao_quadrature_wait(void) +ao_quadrature_wait(uint8_t q) { - ao_sleep(&ao_quadrature_count); - return ao_quadrature_poll(); + ao_sleep(&ao_quadrature_count[q]); + return ao_quadrature_poll(q); } static void @@ -68,7 +85,7 @@ ao_quadrature_test(void) for (;;) { int32_t c; flush(); - c = ao_quadrature_wait(); + c = ao_quadrature_wait(0); printf ("new count %6d\n", c); if (c == 100) break; @@ -99,19 +116,28 @@ static const struct ao_cmds ao_quadrature_cmds[] = { { 0, NULL } }; +#define init(q) do { \ + ao_enable_port(port(q)); \ + \ + ao_exti_setup(port(q), bita(q), \ + AO_QUADRATURE_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \ + ao_quadrature_isr); \ + ao_exti_enable(port(q), bita(q)); \ + \ + ao_exti_setup(port(q), bitb(q), \ + AO_QUADRATURE_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \ + ao_quadrature_isr); \ + ao_exti_enable(port(q), bitb(q)); \ + } while (0) + void ao_quadrature_init(void) { - ao_quadrature_count = 0; - - ao_enable_port(AO_QUADRATURE_PORT); - ao_exti_setup(AO_QUADRATURE_PORT, AO_QUADRATURE_A, - AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, - ao_quadrature_isr); - ao_exti_enable(AO_QUADRATURE_PORT, AO_QUADRATURE_A); - ao_exti_setup(AO_QUADRATURE_PORT, AO_QUADRATURE_B, - AO_EXTI_MODE_PULL_UP|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, - ao_quadrature_isr); - ao_exti_enable(AO_QUADRATURE_PORT, AO_QUADRATURE_B); +#if AO_QUADRATURE_COUNT > 0 + init(0); +#endif +#if AO_QUADRATURE_COUNT > 1 + init(1); +#endif ao_cmd_register(&ao_quadrature_cmds[0]); } diff --git a/src/drivers/ao_quadrature.h b/src/drivers/ao_quadrature.h index 7e1048bc..f0b73b68 100644 --- a/src/drivers/ao_quadrature.h +++ b/src/drivers/ao_quadrature.h @@ -19,10 +19,10 @@ #define _AO_QUADRATURE_H_ int32_t -ao_quadrature_wait(void); +ao_quadrature_wait(uint8_t q); int32_t -ao_quadrature_poll(void); +ao_quadrature_poll(uint8_t q); void ao_quadrature_init(void); diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 1f5ef4ff..0c1ed8fc 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -170,8 +170,15 @@ struct ao_adc { #define HAS_I2C_2 0 #define I2C_2_PB10_PB11 0 -#define AO_QUADRATURE_PORT &stm_gpioc -#define AO_QUADRATURE_A 1 -#define AO_QUADRATURE_B 0 +#define AO_QUADRATURE_COUNT 2 +#define AO_QUADRATURE_MODE AO_EXTI_MODE_PULL_UP + +#define AO_QUADRATURE_0_PORT &stm_gpioc +#define AO_QUADRATURE_0_A 1 +#define AO_QUADRATURE_0_B 0 + +#define AO_QUADRATURE_1_PORT &stm_gpioc +#define AO_QUADRATURE_1_A 3 +#define AO_QUADRATURE_1_B 2 #endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 46f87373bc8c28442273ee4f8da3a352223150f5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 6 Aug 2012 22:53:52 -0700 Subject: altos: Add button driver and event queue With this, a single task can wait for any button or quadrature input device. Signed-off-by: Keith Packard --- src/core/ao.h | 7 ++++++- src/drivers/ao_quadrature.c | 7 +++++++ src/stm-demo/Makefile | 4 +++- src/stm-demo/ao_demo.c | 20 ++++++++++++++++++++ src/stm-demo/ao_pins.h | 14 ++++++++++++++ src/stm/ao_timer.c | 2 +- 6 files changed, 51 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 1032dd33..5e1fbb9d 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -125,7 +125,12 @@ ao_panic(uint8_t reason); * ao_timer.c */ -extern volatile __data uint16_t ao_tick_count; +#ifndef AO_TICK_TYPE +#define AO_TICK_TYPE uint16_t +#define AO_TICK_SIGNED int16_t +#endif + +extern volatile __data AO_TICK_TYPE ao_tick_count; /* Our timer runs at 100Hz */ #define AO_HERTZ 100 diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c index aed4999e..6a2c1bba 100644 --- a/src/drivers/ao_quadrature.c +++ b/src/drivers/ao_quadrature.c @@ -18,6 +18,12 @@ #include #include #include +#if AO_EVENT +#include +#define ao_quadrature_queue(q) ao_event_put_isr(AO_EVENT_QUADRATURE, q, ao_quadrature_count[q]) +#else +#define ao_quadrature_queue(q) +#endif __xdata int32_t ao_quadrature_count[AO_QUADRATURE_COUNT]; @@ -59,6 +65,7 @@ ao_quadrature_isr(void) default: continue; } + ao_quadrature_queue(q); ao_wakeup(&ao_quadrature_count[q]); } } diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 52bb7b51..340967fc 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -35,7 +35,9 @@ ALTOS_SRC = \ ao_i2c_stm.c \ ao_usb_stm.c \ ao_exti_stm.c \ - ao_quadrature.c + ao_event.c \ + ao_quadrature.c \ + ao_button.c PRODUCT=StmDemo-v0.0 PRODUCT_DEF=-DSTM_DEMO diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c index 1b9813fe..fe7c69f2 100644 --- a/src/stm-demo/ao_demo.c +++ b/src/stm-demo/ao_demo.c @@ -17,7 +17,9 @@ #include "ao.h" #include +#include #include +#include struct ao_task demo_task; @@ -150,12 +152,29 @@ ao_temp (void) printf ("temp: %d\n", temp); } +static void +ao_event(void) +{ + struct ao_event event; + + for (;;) { + flush(); + ao_event_get(&event); + printf ("type %1d unit %1d tick %5u value %ld\n", + event.type, event.unit, event.tick, event.value); + if (event.value == 100) + break; + } + +} + __code struct ao_cmds ao_demo_cmds[] = { { ao_dma_test, "D\0DMA test" }, { ao_spi_write, "W\0SPI write" }, { ao_spi_read, "R\0SPI read" }, { ao_i2c_write, "i\0I2C write" }, { ao_temp, "t\0Show temp" }, + { ao_event, "e\0Monitor event queue" }, { 0, NULL } }; @@ -174,6 +193,7 @@ main(void) ao_i2c_init(); ao_exti_init(); ao_quadrature_init(); + ao_button_init(); ao_timer_set_adc_interval(100); diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 0c1ed8fc..77e42a28 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -170,6 +170,8 @@ struct ao_adc { #define HAS_I2C_2 0 #define I2C_2_PB10_PB11 0 +#define AO_EVENT 1 + #define AO_QUADRATURE_COUNT 2 #define AO_QUADRATURE_MODE AO_EXTI_MODE_PULL_UP @@ -181,4 +183,16 @@ struct ao_adc { #define AO_QUADRATURE_1_A 3 #define AO_QUADRATURE_1_B 2 +#define AO_BUTTON_COUNT 2 +#define AO_BUTTON_MODE AO_EXTI_MODE_PULL_UP + +#define AO_BUTTON_0_PORT &stm_gpioc +#define AO_BUTTON_0 6 + +#define AO_BUTTON_1_PORT &stm_gpioc +#define AO_BUTTON_1 7 + +#define AO_TICK_TYPE uint32_t +#define AO_TICK_SIGNED int32_t + #endif /* _AO_PINS_H_ */ diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index ebe75366..adec7aad 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -17,7 +17,7 @@ #include "ao.h" -volatile __data uint16_t ao_tick_count; +volatile __data AO_TICK_TYPE ao_tick_count; uint16_t ao_time(void) { -- cgit v1.2.3 From c58f3d1a373b20fac3f51037008bcc40955f1348 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 7 Aug 2012 11:30:47 -0700 Subject: altos: Oops. Serial 1 stdin was busted by typo A typo in the symbol used to enable stdin wakeups from serial1 caused the input to pend until some other wakeup occurred. This also makes the serial1 hw flow control pin selects in config 2 work right, although those aren't used by any current product Signed-off-by: Keith Packard --- src/cc1111/ao_serial.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cc1111/ao_serial.c b/src/cc1111/ao_serial.c index d5431070..48383802 100644 --- a/src/cc1111/ao_serial.c +++ b/src/cc1111/ao_serial.c @@ -135,7 +135,7 @@ ao_serial1_rx_isr(void) __interrupt 3 if (!ao_fifo_full(ao_serial1_rx_fifo)) ao_fifo_insert(ao_serial1_rx_fifo, U1DBUF); ao_wakeup(&ao_serial1_rx_fifo); -#if USE_SERIAL1_STDIN +#if USE_SERIAL_1_STDIN ao_wakeup(&ao_stdin_ready); #endif } @@ -292,7 +292,9 @@ ao_serial_init(void) /* Make the USART pins be controlled by the USART */ P1SEL |= (1 << 6) | (1 << 7); +#if HAS_SERIAL_1_HW_FLOW P1SEL |= (1 << 5) | (1 << 4); +#endif #endif /* UART mode with receiver enabled */ -- cgit v1.2.3 From c7f228503870c44dfd278ede8b0980dbac73d3c7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 7 Aug 2012 11:32:16 -0700 Subject: altos: Fix .sdcdbrc file for telebt-v0.1 Signed-off-by: Keith Packard --- src/telebt-v0.1/.sdcdbrc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/telebt-v0.1/.sdcdbrc b/src/telebt-v0.1/.sdcdbrc index 710b4a2f..b9f6129c 100644 --- a/src/telebt-v0.1/.sdcdbrc +++ b/src/telebt-v0.1/.sdcdbrc @@ -1 +1,2 @@ ---directory=.. +--directory=../cc1111:../product:../core:../drivers:. + -- cgit v1.2.3 From a1a48aa9ee0bf7fa6720b34c0f544485caea7cac Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 Aug 2012 21:21:58 -0700 Subject: altos: Allow STM SPI bus on multiple pin sets This allows multiple STM pin groups to be used for each SPI bus. Useful for the MS5607 sensor which signals conversion complete on the MISO line. Signed-off-by: Keith Packard --- src/megametrum-v0.1/ao_pins.h | 16 +++-- src/stm/ao_arch_funcs.h | 27 ++++++- src/stm/ao_spi_stm.c | 162 +++++++++++++++++++++++++++++------------- 3 files changed, 148 insertions(+), 57 deletions(-) (limited to 'src') diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 6b0f9832..42715968 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -69,13 +69,14 @@ #define HAS_TELEMETRY 1 #define HAS_SPI_1 1 -#define SPI_1_PA5_PA6_PA7 1 +#define SPI_1_PA5_PA6_PA7 1 /* Barometer */ #define SPI_1_PB3_PB4_PB5 0 -#define SPI_1_PE13_PE14_PE15 0 +#define SPI_1_PE13_PE14_PE15 1 /* Accelerometer */ #define HAS_SPI_2 1 -#define SPI_2_PB13_PB14_PB15 1 +#define SPI_2_PB13_PB14_PB15 1 /* Flash, Companion */ #define SPI_2_PD1_PD3_PD4 0 + #define SPI_2_GPIO (&stm_gpiob) #define SPI_2_SCK 13 #define SPI_2_MISO 14 @@ -247,13 +248,14 @@ struct ao_adc { * Pressure sensor settings */ #define HAS_MS5607 1 +#define AO_MS5607_PRIVATE_PINS 1 #define AO_MS5607_CS_GPIO (&stm_gpioc) #define AO_MS5607_CS 4 #define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) #define AO_MS5607_MISO_GPIO (&stm_gpioa) #define AO_MS5607_MISO 6 #define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO) -#define AO_MS5607_SPI_INDEX (STM_SPI_INDEX(1)) +#define AO_MS5607_SPI_INDEX AO_SPI_1_PA5_PA6_PA7 /* * SPI Flash memory @@ -262,7 +264,7 @@ struct ao_adc { #define M25_MAX_CHIPS 1 #define AO_M25_SPI_CS_PORT (&stm_gpiod) #define AO_M25_SPI_CS_MASK (1 << 3) -#define AO_M25_SPI_BUS STM_SPI_INDEX(2) +#define AO_M25_SPI_BUS AO_SPI_2_PB13_PB14_PB15 /* * Radio (cc1120) @@ -275,7 +277,7 @@ struct ao_adc { #define AO_FEC_DEBUG 0 #define AO_CC1120_SPI_CS_PORT (&stm_gpioc) #define AO_CC1120_SPI_CS_PIN 5 -#define AO_CC1120_SPI_BUS STM_SPI_INDEX(2) +#define AO_CC1120_SPI_BUS AO_SPI_2_PB13_PB14_PB15 #define AO_CC1120_INT_PORT (&stm_gpioc) #define AO_CC1120_INT_PIN 14 @@ -311,7 +313,7 @@ struct ao_adc { #define AO_COMPANION_CS_PORT (&stm_gpiod) #define AO_COMPANION_CS_PIN (0) -#define AO_COMPANION_SPI_BUS STM_SPI_INDEX(2) +#define AO_COMPANION_SPI_BUS AO_SPI_2_PB13_PB14_PB15 /* * Monitor diff --git a/src/stm/ao_arch_funcs.h b/src/stm/ao_arch_funcs.h index 3d8ca1f2..d4fbea37 100644 --- a/src/stm/ao_arch_funcs.h +++ b/src/stm/ao_arch_funcs.h @@ -20,12 +20,37 @@ /* ao_spi_stm.c */ -extern uint8_t ao_spi_mutex[STM_NUM_SPI]; #define AO_SPI_SPEED_FAST STM_SPI_CR1_BR_PCLK_4 #define AO_SPI_SPEED_1MHz STM_SPI_CR1_BR_PCLK_16 #define AO_SPI_SPEED_200kHz STM_SPI_CR1_BR_PCLK_256 +#define AO_SPI_CONFIG_1 0x00 +#define AO_SPI_1_CONFIG_PA5_PA6_PA7 AO_SPI_CONFIG_1 +#define AO_SPI_2_CONFIG_PB13_PB14_PB15 AO_SPI_CONFIG_1 + +#define AO_SPI_CONFIG_2 0x04 +#define AO_SPI_1_CONFIG_PB3_PB4_PB5 AO_SPI_CONFIG_2 +#define AO_SPI_2_CONFIG_PD1_PD3_PD4 AO_SPI_CONFIG_2 + +#define AO_SPI_CONFIG_3 0x08 +#define AO_SPI_1_CONFIG_PE13_PE14_PE15 AO_SPI_CONFIG_3 + +#define AO_SPI_CONFIG_NONE 0x0c + +#define AO_SPI_INDEX_MASK 0x01 +#define AO_SPI_CONFIG_MASK 0x0c + +#define AO_SPI_1_PA5_PA6_PA7 (STM_SPI_INDEX(1) | AO_SPI_1_CONFIG_PA5_PA6_PA7) +#define AO_SPI_1_PB3_PB4_PB5 (STM_SPI_INDEX(1) | AO_SPI_1_CONFIG_PB3_PB4_PB5) +#define AO_SPI_1_PE13_PE14_PE15 (STM_SPI_INDEX(1) | AO_SPI_1_CONFIG_PE13_PE14_PE15) + +#define AO_SPI_2_PB13_PB14_PB15 (STM_SPI_INDEX(2) | AO_SPI_2_CONFIG_PB13_PB14_PB15) +#define AO_SPI_2_PD1_PD3_PD4 (STM_SPI_INDEX(2) | AO_SPI_2_CONFIG_PD1_PD3_PD4) + +#define AO_SPI_INDEX(id) ((id) & AO_SPI_INDEX_MASK) +#define AO_SPI_CONFIG(id) ((id) & AO_SPI_CONFIG_MASK) + void ao_spi_get(uint8_t spi_index, uint32_t speed); diff --git a/src/stm/ao_spi_stm.c b/src/stm/ao_spi_stm.c index 547de9e5..ade86a27 100644 --- a/src/stm/ao_spi_stm.c +++ b/src/stm/ao_spi_stm.c @@ -23,7 +23,8 @@ struct ao_spi_stm_info { struct stm_spi *stm_spi; }; -uint8_t ao_spi_mutex[STM_NUM_SPI]; +static uint8_t ao_spi_mutex[STM_NUM_SPI]; +static uint8_t ao_spi_config[STM_NUM_SPI]; static const struct ao_spi_stm_info ao_spi_stm_info[STM_NUM_SPI] = { { @@ -43,9 +44,9 @@ static uint8_t spi_dev_null; void ao_spi_send(void *block, uint16_t len, uint8_t spi_index) { - struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; - uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; - uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; + uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index; /* Set up the transmit DMA to deliver data */ ao_dma_set_transfer(mosi_dma_index, @@ -99,9 +100,9 @@ ao_spi_send(void *block, uint16_t len, uint8_t spi_index) void ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index) { - struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; - uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; - uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; + uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index; /* Set up the transmit DMA to deliver data */ ao_dma_set_transfer(mosi_dma_index, @@ -155,9 +156,9 @@ ao_spi_send_fixed(uint8_t value, uint16_t len, uint8_t spi_index) void ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) { - struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; - uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; - uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; + uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index; /* Set up transmit DMA to make the SPI hardware actually run */ ao_dma_set_transfer(mosi_dma_index, @@ -212,9 +213,9 @@ ao_spi_recv(void *block, uint16_t len, uint8_t spi_index) void ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index) { - struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; - uint8_t mosi_dma_index = ao_spi_stm_info[spi_index].mosi_dma_index; - uint8_t miso_dma_index = ao_spi_stm_info[spi_index].miso_dma_index; + struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; + uint8_t mosi_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].mosi_dma_index; + uint8_t miso_dma_index = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].miso_dma_index; /* Set up transmit DMA to send data */ ao_dma_set_transfer(mosi_dma_index, @@ -269,9 +270,94 @@ ao_spi_duplex(void *out, void *in, uint16_t len, uint8_t spi_index) void ao_spi_get(uint8_t spi_index, uint32_t speed) { - struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; - - ao_mutex_get(&ao_spi_mutex[spi_index]); + struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; + uint8_t config = AO_SPI_CONFIG(spi_index); + + ao_mutex_get(&ao_spi_mutex[AO_SPI_INDEX(spi_index)]); + if (config != ao_spi_config[AO_SPI_INDEX(spi_index)]) { + + /* Disable current config + */ + switch (AO_SPI_INDEX(spi_index)) { + case STM_SPI_INDEX(1): + switch (ao_spi_config[AO_SPI_INDEX(spi_index)]) { + case AO_SPI_1_CONFIG_PA5_PA6_PA7: + stm_gpio_set(&stm_gpioa, 5, 0); + stm_moder_set(&stm_gpioa, 5, STM_MODER_OUTPUT); + stm_moder_set(&stm_gpioa, 6, STM_MODER_INPUT); + stm_moder_set(&stm_gpioa, 7, STM_MODER_OUTPUT); + break; + case AO_SPI_1_CONFIG_PB3_PB4_PB5: + stm_gpio_set(&stm_gpiob, 3, 0); + stm_moder_set(&stm_gpiob, 3, STM_MODER_OUTPUT); + stm_moder_set(&stm_gpiob, 4, STM_MODER_INPUT); + stm_moder_set(&stm_gpiob, 5, STM_MODER_OUTPUT); + break; + case AO_SPI_1_CONFIG_PE13_PE14_PE15: + stm_gpio_set(&stm_gpioe, 13, 0); + stm_moder_set(&stm_gpioe, 13, STM_MODER_OUTPUT); + stm_moder_set(&stm_gpioe, 14, STM_MODER_INPUT); + stm_moder_set(&stm_gpioe, 15, STM_MODER_OUTPUT); + break; + } + break; + case STM_SPI_INDEX(2): + switch (ao_spi_config[AO_SPI_INDEX(spi_index)]) { + case AO_SPI_2_CONFIG_PB13_PB14_PB15: + stm_gpio_set(&stm_gpiob, 13, 0); + stm_moder_set(&stm_gpiob, 13, STM_MODER_OUTPUT); + stm_moder_set(&stm_gpiob, 14, STM_MODER_INPUT); + stm_moder_set(&stm_gpiob, 15, STM_MODER_OUTPUT); + break; + case AO_SPI_2_CONFIG_PD1_PD3_PD4: + stm_gpio_set(&stm_gpiod, 1, 0); + stm_moder_set(&stm_gpiod, 1, STM_MODER_OUTPUT); + stm_moder_set(&stm_gpiod, 3, STM_MODER_INPUT); + stm_moder_set(&stm_gpiod, 4, STM_MODER_OUTPUT); + break; + } + break; + } + + /* Enable new config + */ + switch (AO_SPI_INDEX(spi_index)) { + case 0: + switch (AO_SPI_CONFIG(spi_index)) { + case AO_SPI_1_CONFIG_PA5_PA6_PA7: + stm_afr_set(&stm_gpioa, 5, STM_AFR_AF5); + stm_afr_set(&stm_gpioa, 6, STM_AFR_AF5); + stm_afr_set(&stm_gpioa, 7, STM_AFR_AF5); + break; + case AO_SPI_1_CONFIG_PB3_PB4_PB5: + stm_afr_set(&stm_gpiob, 3, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 4, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 5, STM_AFR_AF5); + break; + case AO_SPI_1_CONFIG_PE13_PE14_PE15: + stm_afr_set(&stm_gpioe, 13, STM_AFR_AF5); + stm_afr_set(&stm_gpioe, 14, STM_AFR_AF5); + stm_afr_set(&stm_gpioe, 15, STM_AFR_AF5); + break; + } + break; + case 1: + switch (AO_SPI_CONFIG(spi_index)) { + case AO_SPI_2_CONFIG_PB13_PB14_PB15: + stm_afr_set(&stm_gpiob, 13, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 14, STM_AFR_AF5); + stm_afr_set(&stm_gpiob, 15, STM_AFR_AF5); + break; + case AO_SPI_2_CONFIG_PD1_PD3_PD4: + stm_afr_set(&stm_gpiod, 1, STM_AFR_AF5); + stm_afr_set(&stm_gpiod, 3, STM_AFR_AF5); + stm_afr_set(&stm_gpiod, 4, STM_AFR_AF5); + break; + } + break; + } + ao_spi_config[AO_SPI_INDEX(spi_index)] = AO_SPI_CONFIG(spi_index); + } stm_spi->cr1 = ((0 << STM_SPI_CR1_BIDIMODE) | /* Three wire mode */ (0 << STM_SPI_CR1_BIDIOE) | (0 << STM_SPI_CR1_CRCEN) | /* CRC disabled */ @@ -291,16 +377,16 @@ ao_spi_get(uint8_t spi_index, uint32_t speed) void ao_spi_put(uint8_t spi_index) { - struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; + struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; stm_spi->cr1 = 0; - ao_mutex_put(&ao_spi_mutex[spi_index]); + ao_mutex_put(&ao_spi_mutex[AO_SPI_INDEX(spi_index)]); } static void ao_spi_channel_init(uint8_t spi_index) { - struct stm_spi *stm_spi = ao_spi_stm_info[spi_index].stm_spi; + struct stm_spi *stm_spi = ao_spi_stm_info[AO_SPI_INDEX(spi_index)].stm_spi; stm_spi->cr1 = 0; (void) stm_spi->sr; @@ -318,50 +404,28 @@ ao_spi_init(void) #if HAS_SPI_1 # if SPI_1_PA5_PA6_PA7 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); - stm_afr_set(&stm_gpioa, 5, STM_AFR_AF5); - stm_afr_set(&stm_gpioa, 6, STM_AFR_AF5); - stm_afr_set(&stm_gpioa, 7, STM_AFR_AF5); -# else -# if SPI_1_PB3_PB4_PB5 +# endif +# if SPI_1_PB3_PB4_PB5 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); - stm_afr_set(&stm_gpiob, 3, STM_AFR_AF5); - stm_afr_set(&stm_gpiob, 4, STM_AFR_AF5); - stm_afr_set(&stm_gpiob, 5, STM_AFR_AF5); -# else -# if SPI_1_PE13_PE14_PE15 +# endif +# if SPI_1_PE13_PE14_PE15 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOEEN); - stm_afr_set(&stm_gpioe, 13, STM_AFR_AF5); - stm_afr_set(&stm_gpioe, 14, STM_AFR_AF5); - stm_afr_set(&stm_gpioe, 15, STM_AFR_AF5); -# else -# error "No SPI_1 port configuration specified" -# endif -# endif # endif - stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SPI1EN); - + ao_spi_config[0] = AO_SPI_CONFIG_NONE; ao_spi_channel_init(0); #endif #if HAS_SPI_2 # if SPI_2_PB13_PB14_PB15 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); - stm_afr_set(&stm_gpiob, 13, STM_AFR_AF5); - stm_afr_set(&stm_gpiob, 14, STM_AFR_AF5); - stm_afr_set(&stm_gpiob, 15, STM_AFR_AF5); -# else -# if SPI_2_PPD1_PD3_PD4 +# endif +# if SPI_2_PD1_PD3_PD4 stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN); - stm_afr_set(&stm_gpiod, 1, STM_AFR_AF5); - stm_afr_set(&stm_gpiod, 3, STM_AFR_AF5); - stm_afr_set(&stm_gpiod, 4, STM_AFR_AF5); -# else -# error "No SPI_2 port configuration specified" -# endif # endif stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_SPI2EN); + ao_spi_config[1] = AO_SPI_CONFIG_NONE; ao_spi_channel_init(1); #endif -- cgit v1.2.3 From f46d94ca5c969c88dd307d1b684d6fafa2157020 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 Aug 2012 21:24:16 -0700 Subject: altos: Use split SPI bus for MS5607 sensor Leave CS low while releasing the SPI bus when waiting for conversion complete -- other SPI bus users will use another set of pins. Signed-off-by: Keith Packard --- src/drivers/ao_ms5607.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 17fe853b..1b55b7fd 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -134,11 +134,18 @@ ao_ms5607_get_sample(uint8_t cmd) { ao_ms5607_start(); ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); ao_exti_enable(AO_MS5607_MISO_GPIO, AO_MS5607_MISO); +#if AO_MS5607_PRIVATE_PINS + ao_spi_put(AO_MS5607_SPI_INDEX); +#endif cli(); while (!ao_ms5607_done) ao_sleep(&ao_ms5607_done); sei(); +#if AO_MS5607_PRIVATE_PINS + stm_gpio_set(AO_MS5607_CS_GPIO, AO_MS5607_CS, 1); +#else ao_ms5607_stop(); +#endif ao_ms5607_start(); read = AO_MS5607_ADC_READ; -- cgit v1.2.3 From 8457ca81adc9d62a7ffe56a7c0c36f2fcadaa682 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 Aug 2012 21:25:34 -0700 Subject: altos/cc1111: Document SPI bus pin options Just a comment in the source code about which pins each option selects. Signed-off-by: Keith Packard --- src/cc1111/ao_spi.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cc1111/ao_spi.c b/src/cc1111/ao_spi.c index 88cff9dd..52087fb4 100644 --- a/src/cc1111/ao_spi.c +++ b/src/cc1111/ao_spi.c @@ -118,13 +118,34 @@ ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant } /* - * Initialize USART0 for SPI using config alt 2 + * USART0 SPI config alt 2 (using this one) * * MO P1_5 * MI P1_4 * CLK P1_3 * CSS P1_2 * + * USART0 SPI config alt 1 + * + * MO P0_3 + * MI P0_2 + * CLK P0_5 + * SS P0_4 + * + * USART1 SPI config alt 2 + * + * MO P1_6 + * MI P1_7 + * CLK P1_5 + * SS P1_4 + * + * USART1 SPI config alt 1 + * + * MO P0_4 + * MI P0_5 + * CLK P0_3 + * SS P0_2 + * * Chip select is the responsibility of the caller in master mode */ -- cgit v1.2.3 From 93db8febda03d9a02c5c1ccdc6ad44eaf00a433b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 Aug 2012 21:26:34 -0700 Subject: altos: Add MMA655X driver Just debug code at this point, will complete on real hardware Signed-off-by: Keith Packard --- src/drivers/ao_mma655x.c | 210 ++++++++++++++++++++++++++++++++++++ src/drivers/ao_mma655x.h | 85 +++++++++++++++ src/megametrum-v0.1/Makefile | 2 + src/megametrum-v0.1/ao_megametrum.c | 4 + src/megametrum-v0.1/ao_pins.h | 9 ++ 5 files changed, 310 insertions(+) create mode 100644 src/drivers/ao_mma655x.c create mode 100644 src/drivers/ao_mma655x.h (limited to 'src') diff --git a/src/drivers/ao_mma655x.c b/src/drivers/ao_mma655x.c new file mode 100644 index 00000000..e4e41627 --- /dev/null +++ b/src/drivers/ao_mma655x.c @@ -0,0 +1,210 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +static uint8_t mma655x_configured; +uint8_t ao_mma655x_valid; + +static void +ao_mma655x_start(void) { + ao_spi_get_bit(AO_MMA655X_CS_GPIO, + AO_MMA655X_CS, + AO_MMA655X_CS_PIN, + AO_MMA655X_SPI_INDEX, + AO_SPI_SPEED_FAST); +} + +static void +ao_mma655x_stop(void) { + ao_spi_put_bit(AO_MMA655X_CS_GPIO, + AO_MMA655X_CS, + AO_MMA655X_CS_PIN, + AO_MMA655X_SPI_INDEX); +} + +static uint8_t +ao_parity(uint8_t v) +{ + /* down to four bits */ + v = (v ^ (v >> 4)) & 0xf; + + /* Cute lookup hack -- 0x6996 encodes the sixteen + * even parity values in order. + */ + return (~0x6996 >> v) & 1; +} + +static void +ao_mma655x_cmd(uint8_t d[2]) +{ + ao_mma655x_start(); + ao_spi_send(d, 2, AO_MMA655X_SPI_INDEX); + ao_spi_recv(d, 2, AO_MMA655X_SPI_INDEX); + ao_mma655x_stop(); +} + +static uint8_t +ao_mma655x_reg_write(uint8_t addr, uint8_t value) +{ + uint8_t d[2]; + + addr |= (1 << 6); /* write mode */ + d[0] = addr | (ao_parity(addr^value) << 7); + d[1] = value; + ao_mma655x_cmd(d); + return d[1]; +} + +static uint8_t +ao_mma655x_reg_read(uint8_t addr) +{ + uint8_t d[2]; + + d[0] = addr | (ao_parity(addr) << 7); + d[1] = 0; + ao_mma655x_cmd(d); + return d[1]; +} + +static uint16_t +ao_mma655x_value(void) +{ + uint8_t d[2]; + uint16_t v; + + d[0] = ((0 << 7) | /* Axis selection (X) */ + (1 << 6) | /* Acceleration operation */ + (1 << 5)); /* Raw data */ + d[1] = ((1 << 3) | /* must be one */ + (1 << 2) | /* Unsigned data */ + (0 << 1) | /* Arm disabled */ + (1 << 0)); /* Odd parity */ + ao_mma655x_cmd(d); + v = (uint16_t) d[1] << 2; + v |= d[0] >> 6; + v |= (uint16_t) (d[0] & 3) << 10; + return v; +} + +static void +ao_mma655x_reset(void) { + ao_mma655x_reg_write(AO_MMA655X_DEVCTL, + (0 << AO_MMA655X_DEVCTL_RES_1) | + (0 << AO_MMA655X_DEVCTL_RES_1)); + ao_mma655x_reg_write(AO_MMA655X_DEVCTL, + (1 << AO_MMA655X_DEVCTL_RES_1) | + (1 << AO_MMA655X_DEVCTL_RES_1)); + ao_mma655x_reg_write(AO_MMA655X_DEVCTL, + (0 << AO_MMA655X_DEVCTL_RES_1) | + (1 << AO_MMA655X_DEVCTL_RES_1)); +} + +#define DEVCFG_VALUE (\ + (1 << AO_MMA655X_DEVCFG_OC) | /* Disable offset cancelation */ \ + (1 << AO_MMA655X_DEVCFG_SD) | /* Receive unsigned data */ \ + (0 << AO_MMA655X_DEVCFG_OFMON) | /* Disable offset monitor */ \ + (AO_MMA655X_DEVCFG_A_CFG_DISABLE << AO_MMA655X_DEVCFG_A_CFG)) + +#define AXISCFG_VALUE (\ + (0 << AO_MMA655X_AXISCFG_LPF)) /* 100Hz 4-pole filter */ + + +static void +ao_mma655x_setup(void) +{ + uint8_t v; + uint16_t a, a_st; + uint8_t stdefl; + + if (mma655x_configured) + return; + mma655x_configured = 1; + ao_delay(AO_MS_TO_TICKS(10)); /* Top */ + ao_mma655x_reset(); + ao_delay(AO_MS_TO_TICKS(10)); /* Top */ + (void) ao_mma655x_reg_read(AO_MMA655X_DEVSTAT); + v = ao_mma655x_reg_read(AO_MMA655X_DEVSTAT); + + /* Configure R/W register values. + * Most of them relate to the arming feature, which + * we don't use, so the only registers we need to + * write are DEVCFG and AXISCFG + */ + + ao_mma655x_reg_write(AO_MMA655X_DEVCFG, + DEVCFG_VALUE | (0 << AO_MMA655X_DEVCFG_ENDINIT)); + + /* Test X axis + */ + + ao_mma655x_reg_write(AO_MMA655X_AXISCFG, + AXISCFG_VALUE | + (1 << AO_MMA655X_AXISCFG_ST)); + a_st = ao_mma655x_value(); + + stdefl = ao_mma655x_reg_read(AO_MMA655X_STDEFL); + + ao_mma655x_reg_write(AO_MMA655X_AXISCFG, + AXISCFG_VALUE | + (0 << AO_MMA655X_AXISCFG_ST)); + a = ao_mma655x_value(); + printf ("normal: %u self_test: %u stdefl: %u\n", + a, a_st, stdefl); + + ao_mma655x_reg_write(AO_MMA655X_DEVCFG, + DEVCFG_VALUE | (1 << AO_MMA655X_DEVCFG_ENDINIT)); +} + +static void +ao_mma655x_dump(void) +{ + uint8_t s0, s1, s2, s3; + uint32_t lot; + uint16_t serial; + + ao_mma655x_setup(); + + s0 = ao_mma655x_reg_read(AO_MMA655X_SN0); + s1 = ao_mma655x_reg_read(AO_MMA655X_SN1); + s2 = ao_mma655x_reg_read(AO_MMA655X_SN2); + s3 = ao_mma655x_reg_read(AO_MMA655X_SN3); + lot = ((uint32_t) s3 << 24) | ((uint32_t) s2 << 16) | + ((uint32_t) s1 << 8) | ((uint32_t) s0); + serial = lot & 0x1fff; + lot >>= 12; + printf ("MMA655X lot %d serial %d\n", lot, serial); + mma655x_configured = 0; +} + +__code struct ao_cmds ao_mma655x_cmds[] = { + { ao_mma655x_dump, "A\0Display MMA655X data" }, + { 0, NULL }, +}; + +void +ao_mma655x_init(void) +{ + mma655x_configured = 0; + ao_mma655x_valid = 0; + + ao_cmd_register(&ao_mma655x_cmds[0]); + ao_spi_init_cs(AO_MMA655X_CS_GPIO, (1 << AO_MMA655X_CS)); + +// ao_add_task(&ao_mma655x_task, ao_mma655x, "mma655x"); +} diff --git a/src/drivers/ao_mma655x.h b/src/drivers/ao_mma655x.h new file mode 100644 index 00000000..9c0c59dc --- /dev/null +++ b/src/drivers/ao_mma655x.h @@ -0,0 +1,85 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_MMA655X_H_ +#define _AO_MMA655X_H_ + + +#define AO_MMA655X_SN0 0x00 +#define AO_MMA655X_SN1 0x01 +#define AO_MMA655X_SN2 0x02 +#define AO_MMA655X_SN3 0x03 +#define AO_MMA655X_SN3 0x03 +#define AO_MMA655X_STDEFL 0x04 +#define AO_MMA655X_FCTCFG 0x06 +# define AO_MMA655X_FCTCFG_STMAG 7 + +#define AO_MMA655X_PN 0x08 +#define AO_MMA655X_DEVCTL 0x0a +#define AO_MMA655X_DEVCTL_RES_1 7 +#define AO_MMA655X_DEVCTL_RES_0 6 +#define AO_MMA655X_DEVCTL_OCPHASE 4 +#define AO_MMA655X_DEVCTL_OCPHASE_MASK 3 +#define AO_MMA655X_DEVCTL_OFFCFG_EN 3 + +#define AO_MMA655X_DEVCFG 0x0b +#define AO_MMA655X_DEVCFG_OC 7 +#define AO_MMA655X_DEVCFG_ENDINIT 5 +#define AO_MMA655X_DEVCFG_SD 4 +#define AO_MMA655X_DEVCFG_OFMON 3 +#define AO_MMA655X_DEVCFG_A_CFG 0 +#define AO_MMA655X_DEVCFG_A_CFG_DISABLE 0 +#define AO_MMA655X_DEVCFG_A_CFG_PCM 1 +#define AO_MMA655X_DEVCFG_A_CFG_MOVING_AVG_HIGH 2 +#define AO_MMA655X_DEVCFG_A_CFG_MOVING_AVG_LOW 3 +#define AO_MMA655X_DEVCFG_A_CFG_COUNT_HIGH 4 +#define AO_MMA655X_DEVCFG_A_CFG_COUNT_LOW 5 +#define AO_MMA655X_DEVCFG_A_CFG_UNFILTERED_HIGH 6 +#define AO_MMA655X_DEVCFG_A_CFG_UNFILTERED_LOW 7 +#define AO_MMA655X_DEVCFG_A_CFG_MASK 7 + +#define AO_MMA655X_AXISCFG 0x0c +#define AO_MMA655X_AXISCFG_ST 7 +#define AO_MMA655X_AXISCFG_LPF 0 +#define AO_MMA655X_AXISCFG_LPF_MASK 0xf + +#define AO_MMA655X_ARMCFG 0x0e +#define AO_MMA655X_ARMCFG_APS 4 +#define AO_MMA655X_ARMCFG_APS_MASK 3 +#define AO_MMA655X_ARMCFG_AWS_N 2 +#define AO_MMA655X_ARMCFG_AWS_N_MASK 3 +#define AO_MMA655X_ARMCFG_AWS_P 0 +#define AO_MMA655X_ARMCFG_AWS_P_MASK 3 + +#define AO_MMA655X_ARMT_P 0x10 +#define AO_MMA655X_ARMT_N 0x12 + +#define AO_MMA655X_DEVSTAT 0x14 +#define AO_MMA655X_DEVSTAT_IDE 6 +#define AO_MMA655X_DEVSTAT_DEVINIT 4 +#define AO_MMA655X_DEVSTAT_MISOERR 3 +#define AO_MMA655X_DEVSTAT_OFFSET 1 +#define AO_MMA655X_DEVSTAT_DEVRES 0 + +#define AO_MMA655X_COUNT 0x15 +#define AO_MMA655X_OFFCORR 0x16 + + +void +ao_mma655x_init(void); + +#endif /* _AO_MMA655X_H_ */ diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 4a4c983a..1dfebca0 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -19,6 +19,7 @@ INC = \ ao_ms5607.h \ ao_hmc5883.h \ ao_mpu6000.h \ + ao_mma655x.h \ ao_cc1120_CC1120.h \ ao_profile.h \ ao_whiten.h \ @@ -56,6 +57,7 @@ ALTOS_SRC = \ ao_fec_tx.c \ ao_fec_rx.c \ ao_ms5607.c \ + ao_mma655x.c \ ao_adc_stm.c \ ao_beep_stm.c \ ao_storage.c \ diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index 55324514..d3ae4690 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -53,6 +54,9 @@ main(void) #if HAS_MPU6000 ao_mpu6000_init(); #endif +#if HAS_MMA655X + ao_mma655x_init(); +#endif ao_storage_init(); diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 42715968..6256d2f6 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -305,6 +305,15 @@ struct ao_adc { #define HAS_HIGHG_ACCEL 0 +/* + * mma655x + */ + +#define HAS_MMA655X 1 +#define AO_MMA655X_SPI_INDEX AO_SPI_1_PA5_PA6_PA7 +#define AO_MMA655X_CS_GPIO (&stm_gpiod) +#define AO_MMA655X_CS 4 + #define NUM_CMDS 16 /* -- cgit v1.2.3 From ab1279cc6a683595631d7ac8bed7b36e0c8a691c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 18 Aug 2012 22:51:47 -0700 Subject: Here's the button driver and event queue logic These were neglected in the commit which was supposed to include them Signed-off-by: Keith Packard --- src/drivers/ao_button.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_button.h | 24 +++++++++++++ src/drivers/ao_event.c | 77 ++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_event.h | 41 +++++++++++++++++++++ 4 files changed, 236 insertions(+) create mode 100644 src/drivers/ao_button.c create mode 100644 src/drivers/ao_button.h create mode 100644 src/drivers/ao_event.c create mode 100644 src/drivers/ao_event.h (limited to 'src') diff --git a/src/drivers/ao_button.c b/src/drivers/ao_button.c new file mode 100644 index 00000000..a507c909 --- /dev/null +++ b/src/drivers/ao_button.c @@ -0,0 +1,94 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#if AO_EVENT +#include +#define ao_button_queue(b,v) ao_event_put_isr(AO_EVENT_BUTTON, b, v) +#else +#define ao_button_queue(b,v) +#endif + +static uint8_t ao_button[AO_BUTTON_COUNT]; +static AO_TICK_TYPE ao_button_time[AO_BUTTON_COUNT]; + +#define AO_DEBOUNCE AO_MS_TO_TICKS(20) + +#define port(q) AO_BUTTON_ ## q ## _PORT +#define bit(q) AO_BUTTON_ ## q +#define pin(q) AO_BUTTON_ ## q ## _PIN + +static void +ao_button_do(uint8_t b, uint8_t v) +{ + /* Debounce */ + if ((AO_TICK_SIGNED) (ao_tick_count - ao_button_time[b]) < AO_DEBOUNCE) + return; + + /* pins are inverted */ + v = !v; + if (ao_button[b] != v) { + ao_button[b] = v; + ao_button_time[b] = ao_tick_count; + ao_button_queue(b, v); + ao_wakeup(&ao_button[b]); + } +} + +#define ao_button_update(b) ao_button_do(b, ao_gpio_get(port(b), bit(b), pin(b))) + +static void +ao_button_isr(void) +{ +#if AO_BUTTON_COUNT > 0 + ao_button_update(0); +#endif +#if AO_BUTTON_COUNT > 1 + ao_button_update(1); +#endif +#if AO_BUTTON_COUNT > 2 + ao_button_update(2); +#endif +#if AO_BUTTON_COUNT > 3 + ao_button_update(3); +#endif +#if AO_BUTTON_COUNT > 4 + ao_button_update(4); +#endif +} + +#define init(b) do { \ + ao_enable_port(port(b)); \ + \ + ao_exti_setup(port(b), bit(b), \ + AO_BUTTON_MODE|AO_EXTI_MODE_FALLING|AO_EXTI_MODE_RISING|AO_EXTI_PRIORITY_MED, \ + ao_button_isr); \ + ao_exti_enable(port(b), bit(b)); \ + } while (0) + +void +ao_button_init(void) +{ +#if AO_BUTTON_COUNT > 0 + init(0); +#endif +#if AO_BUTTON_COUNT > 1 + init(1); +#endif +} diff --git a/src/drivers/ao_button.h b/src/drivers/ao_button.h new file mode 100644 index 00000000..ce349d65 --- /dev/null +++ b/src/drivers/ao_button.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_BUTTON_H_ +#define _AO_BUTTON_H_ + +void +ao_button_init(void); + +#endif /* _AO_BUTTON_H_ */ diff --git a/src/drivers/ao_event.c b/src/drivers/ao_event.c new file mode 100644 index 00000000..440ef2de --- /dev/null +++ b/src/drivers/ao_event.c @@ -0,0 +1,77 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +#define AO_EVENT_QUEUE 64 + +#define ao_event_queue_next(n) (((n) + 1) & (AO_EVENT_QUEUE - 1)) +#define ao_event_queue_prev(n) (((n) - 1) & (AO_EVENT_QUEUE - 1)) +#define ao_event_queue_empty() (ao_event_queue_insert == ao_event_queue_remove) +#define ao_event_queue_full() (ao_event_queue_next(ao_event_queue_insert) == ao_event_queue_remove) + +/* + * Whether a sequence of events from the same device should be collapsed + */ +#define ao_event_can_collapse(type) ((type) == AO_EVENT_QUADRATURE) + +struct ao_event ao_event_queue[AO_EVENT_QUEUE]; +uint8_t ao_event_queue_insert; +uint8_t ao_event_queue_remove; + + +uint8_t +ao_event_get(struct ao_event *ev) +{ + ao_arch_critical( + while (ao_event_queue_empty()) + ao_sleep(&ao_event_queue); + *ev = ao_event_queue[ao_event_queue_remove]; + ao_event_queue_remove = ao_event_queue_next(ao_event_queue_remove); + ); +} + +/* called with interrupts disabled */ +void +ao_event_put_isr(uint8_t type, uint8_t unit, uint32_t value) +{ + if (!ao_event_queue_full()) { + + if (ao_event_can_collapse(type) && !ao_event_queue_empty()) { + uint8_t prev = ao_event_queue_prev(ao_event_queue_insert); + + if (ao_event_queue[prev].type == type && + ao_event_queue[prev].unit == unit) + ao_event_queue_insert = prev; + } + ao_event_queue[ao_event_queue_insert] = (struct ao_event) { + .type = type, + .unit = unit, + .tick = ao_tick_count, + .value = value + }; + ao_event_queue_insert = ao_event_queue_next(ao_event_queue_insert); + ao_wakeup(&ao_event_queue); + } +} + +void +ao_event_put(uint8_t type, uint8_t unit, uint32_t value) +{ + ao_arch_critical(ao_event_put_isr(type, unit, value);); +} diff --git a/src/drivers/ao_event.h b/src/drivers/ao_event.h new file mode 100644 index 00000000..25c49c35 --- /dev/null +++ b/src/drivers/ao_event.h @@ -0,0 +1,41 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_EVENT_H_ +#define _AO_EVENT_H_ + +#define AO_EVENT_NONE 0 +#define AO_EVENT_QUADRATURE 1 +#define AO_EVENT_BUTTON 2 + +struct ao_event { + uint8_t type; + uint8_t unit; + uint16_t tick; + uint32_t value; +}; + +uint8_t +ao_event_get(struct ao_event *ev); + +void +ao_event_put_isr(uint8_t type, uint8_t unit, uint32_t value); + +void +ao_event_put(uint8_t type, uint8_t unit, uint32_t value); + +#endif /* _AO_EVENT_H_ */ -- cgit v1.2.3 From 7a0ed0ff4192060854d69e640de2c30105eb2f62 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 24 Aug 2012 00:27:13 -0700 Subject: altos: Disable telefire 'pad' listener when testing radio Ensures that the radio testing won't block waiting for a firing mode packet to arrive. Signed-off-by: Keith Packard --- src/cc1111/ao_radio.c | 9 +++++++++ src/drivers/ao_pad.c | 19 +++++++++++++++++++ src/drivers/ao_pad.h | 6 ++++++ 3 files changed, 34 insertions(+) (limited to 'src') diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index 2071c47a..46b2362d 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -16,6 +16,9 @@ */ #include "ao.h" +#if HAS_PAD +#include +#endif /* Values from SmartRF® Studio for: * @@ -484,6 +487,9 @@ ao_radio_test(void) #endif #if PACKET_HAS_SLAVE ao_packet_slave_stop(); +#endif +#if HAS_PAD + ao_pad_disable(); #endif ao_radio_get(0xff); RFST = RFST_STX; @@ -500,6 +506,9 @@ ao_radio_test(void) radio_on = 0; #if HAS_MONITOR ao_monitor_enable(); +#endif +#if HAS_PAD + ao_pad_enable(); #endif } } diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index 21aa788d..b6dbcefe 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -71,6 +71,23 @@ ao_pad_status(void) static __pdata uint8_t ao_pad_armed; static __pdata uint16_t ao_pad_arm_time; static __pdata uint8_t ao_pad_box; +static __xdata uint8_t ao_pad_disabled; + +void +ao_pad_disable(void) +{ + if (!ao_pad_disabled) { + ao_pad_disabled = 1; + ao_radio_recv_abort(); + } +} + +void +ao_pad_enable(void) +{ + ao_pad_disabled = 0; + ao_wakeup (&ao_pad_disabled); +} static void ao_pad(void) @@ -85,6 +102,8 @@ ao_pad(void) ao_pad_box = ao_74hc497_read(); for (;;) { flush(); + while (ao_pad_disabled) + ao_sleep(&ao_pad_disabled); if (ao_radio_cmac_recv(&command, sizeof (command), 0) != AO_RADIO_CMAC_OK) continue; diff --git a/src/drivers/ao_pad.h b/src/drivers/ao_pad.h index 9ea016ff..d5ca3a88 100644 --- a/src/drivers/ao_pad.h +++ b/src/drivers/ao_pad.h @@ -64,4 +64,10 @@ struct ao_pad_query { void ao_pad_init(void); +void +ao_pad_disable(void); + +void +ao_pad_enable(void); + #endif /* _AO_PAD_H_ */ -- cgit v1.2.3 From 50b58d703b8b48005a3ca9ad4e3603d6f7ac1430 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 24 Aug 2012 00:33:38 -0700 Subject: altos: Make cc1111 SPI pins configurable Allow either USART in any configuration. Still only supports one SPI bus though. Signed-off-by: Keith Packard --- src/cc1111/ao_spi.c | 188 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 128 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_spi.c b/src/cc1111/ao_spi.c index 52087fb4..e7480fd7 100644 --- a/src/cc1111/ao_spi.c +++ b/src/cc1111/ao_spi.c @@ -17,6 +17,109 @@ #include "ao.h" +/* Default pin usage for existing Altus Metrum devices */ +#if !HAS_SPI_0 && !HAS_SPI_1 +#define HAS_SPI_0 1 +#define SPI_0_ALT_2 1 +#endif + +#ifndef SPI_CONST +#define SPI_CONST 0xff +#endif + +/* + * USART0 SPI config alt 1 + * + * MO P0_3 + * MI P0_2 + * CLK P0_5 + * SS P0_4 + * + * USART0 SPI config alt 2 + * + * MO P1_5 + * MI P1_4 + * CLK P1_3 + * CSS P1_2 + * + * USART1 SPI config alt 1 + * + * MO P0_4 + * MI P0_5 + * CLK P0_3 + * SS P0_2 + * + * USART1 SPI config alt 2 + * + * MO P1_6 + * MI P1_7 + * CLK P1_5 + * SS P1_4 + * + * + * Chip select is the responsibility of the caller in master mode + */ + +#if HAS_SPI_0 +#define SPI_CSR U0CSR +#define SPI_BUF U0DBUFXADDR +#define SPI_BAUD U0BAUD +#define SPI_GCR U0GCR +#define SPI_CFG_MASK PERCFG_U0CFG_ALT_MASK +#define SPI_DMA_TX DMA_CFG0_TRIGGER_UTX0 +#define SPI_DMA_RX DMA_CFG0_TRIGGER_URX0 + +#if SPI_0_ALT_1 +#define SPI_CFG PERCFG_U0CFG_ALT_1 +#define SPI_SEL P0SEL +#define SPI_BITS (1 << 3) | (1 << 2) | (1 << 5) +#define SPI_CSS_BIT (1 << 4) +#endif + +#if SPI_0_ALT_2 +#define SPI_CFG PERCFG_U0CFG_ALT_2 +#define SPI_SEL P1SEL +#define SPI_PRI P2SEL_PRI3P1_USART0 +#define SPI_BITS (1 << 5) | (1 << 4) | (1 << 3) +#define SPI_CSS_BIT (1 << 2) +#endif + +#endif + +#if HAS_SPI_1 +#define SPI_CSR U1CSR +#define SPI_BUF U1DBUFXADDR +#define SPI_BAUD U1BAUD +#define SPI_GCR U1GCR +#define SPI_CFG_MASK PERCFG_U1CFG_ALT_MASK +#define SPI_DMA_TX DMA_CFG0_TRIGGER_UTX1 +#define SPI_DMA_RX DMA_CFG0_TRIGGER_URX1 + +#if SPI_1_ALT_1 +#define SPI_CFG PERCFG_U1CFG_ALT_1 +#define SPI_SEL P0SEL +#define SPI_BITS (1 << 4) | (1 << 5) | (1 << 3) +#define SPI_CSS_BIT (1 << 2) +#endif + +#if SPI_1_ALT_2 +#define SPI_CFG PERCFG_U1CFG_ALT_2 +#define SPI_SEL P1SEL +#define SPI_PRI P2SEL_PRI3P1_USART1 +#define SPI_BITS (1 << 6) | (1 << 7) | (1 << 5) +#define SPI_CSS_BIT (1 << 4) +#endif + +#endif + +#if AO_SPI_SLAVE +#define CSS SPI_CSS_BIT +#define UxCSR_DIRECTION UxCSR_SLAVE +#else +#define CSS 0 +#define UxCSR_DIRECTION UxCSR_MASTER +#endif + /* Shared mutex to protect SPI bus, must cover the entire * operation, from CS low to CS high. This means that any SPI * user must protect the SPI bus with this mutex @@ -42,23 +145,23 @@ ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant { #if !AO_SPI_SLAVE ao_dma_set_transfer(ao_spi_dma_in_id, - &U0DBUFXADDR, + &SPI_BUF, &ao_spi_const, len, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_URX0, + SPI_DMA_RX, DMA_CFG1_SRCINC_0 | DMA_CFG1_DESTINC_0 | DMA_CFG1_PRIORITY_NORMAL); #endif ao_dma_set_transfer(ao_spi_dma_out_id, block, - &U0DBUFXADDR, + &SPI_BUF, len, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_UTX0, + SPI_DMA_TX, DMA_CFG1_SRCINC_1 | DMA_CFG1_DESTINC_0 | DMA_CFG1_PRIORITY_NORMAL); @@ -77,6 +180,8 @@ ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant #endif } + + /* Receive bytes over SPI. * * This sets up tow DMA engines, one reading the data and another @@ -87,25 +192,25 @@ void ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant { ao_dma_set_transfer(ao_spi_dma_in_id, - &U0DBUFXADDR, + &SPI_BUF, block, len, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_URX0, + SPI_DMA_RX, DMA_CFG1_SRCINC_0 | DMA_CFG1_DESTINC_1 | DMA_CFG1_PRIORITY_NORMAL); - ao_spi_const = 0xff; + ao_spi_const = SPI_CONST; ao_dma_set_transfer(ao_spi_dma_out_id, &ao_spi_const, - &U0DBUFXADDR, + &SPI_BUF, len, DMA_CFG0_WORDSIZE_8 | DMA_CFG0_TMODE_SINGLE | - DMA_CFG0_TRIGGER_UTX0, + SPI_DMA_TX, DMA_CFG1_SRCINC_0 | DMA_CFG1_DESTINC_0 | DMA_CFG1_PRIORITY_NORMAL); @@ -117,59 +222,22 @@ ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant ao_sleep(&ao_spi_dma_in_done); } -/* - * USART0 SPI config alt 2 (using this one) - * - * MO P1_5 - * MI P1_4 - * CLK P1_3 - * CSS P1_2 - * - * USART0 SPI config alt 1 - * - * MO P0_3 - * MI P0_2 - * CLK P0_5 - * SS P0_4 - * - * USART1 SPI config alt 2 - * - * MO P1_6 - * MI P1_7 - * CLK P1_5 - * SS P1_4 - * - * USART1 SPI config alt 1 - * - * MO P0_4 - * MI P0_5 - * CLK P0_3 - * SS P0_2 - * - * Chip select is the responsibility of the caller in master mode - */ - -#if AO_SPI_SLAVE -#define CSS (1 << 2) -#define UxCSR_DIRECTION UxCSR_SLAVE -#else -#define CSS 0 -#define UxCSR_DIRECTION UxCSR_MASTER -#endif void ao_spi_init(void) { /* Set up the USART pin assignment */ - PERCFG = (PERCFG & ~PERCFG_U0CFG_ALT_MASK) | PERCFG_U0CFG_ALT_2; + PERCFG = (PERCFG & ~SPI_CFG_MASK) | SPI_CFG; - /* Ensure that USART0 takes precidence over USART1 for pins that - * they share + /* Ensure that SPI USART takes precidence over the other USART + * for pins that they share */ - P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | P2SEL_PRI3P1_USART0; +#ifdef SPI_PRI + P2SEL = (P2SEL & ~P2SEL_PRI3P1_MASK) | SPI_PRI; +#endif /* Make the SPI pins be controlled by the USART peripheral */ - P1SEL |= ((1 << 5) | (1 << 4) | (1 << 3) | CSS); + SPI_SEL |= SPI_BITS | CSS; /* Set up OUT DMA */ ao_spi_dma_out_id = ao_dma_alloc(&ao_spi_dma_out_done); @@ -179,9 +247,9 @@ ao_spi_init(void) /* Set up the USART. * - * SPI master mode + * SPI master/slave mode */ - U0CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_DIRECTION); + SPI_CSR = (UxCSR_MODE_SPI | UxCSR_RE | UxCSR_DIRECTION); /* Set the baud rate and signal parameters * @@ -189,9 +257,9 @@ ao_spi_init(void) * Every peripheral I've ever seen goes faster than that, * so set the clock to 3MHz (BAUD_E 17, BAUD_M 0) */ - U0BAUD = 0; - U0GCR = (UxGCR_CPOL_NEGATIVE | - UxGCR_CPHA_FIRST_EDGE | - UxGCR_ORDER_MSB | - (17 << UxGCR_BAUD_E_SHIFT)); + SPI_BAUD = 0; + SPI_GCR = (UxGCR_CPOL_NEGATIVE | + UxGCR_CPHA_FIRST_EDGE | + UxGCR_ORDER_MSB | + (17 << UxGCR_BAUD_E_SHIFT)); } -- cgit v1.2.3 From a8e9906513227600599da12b268ff5f807ae98c7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 24 Aug 2012 00:34:55 -0700 Subject: altos: Add 'ao_led_set_mask' in the PCA9922 driver This lets a subset of the LEDs be controlled independent of other LED settings. Signed-off-by: Keith Packard --- src/core/ao_led.h | 4 ++++ src/drivers/ao_pca9922.c | 8 ++++++++ 2 files changed, 12 insertions(+) (limited to 'src') diff --git a/src/core/ao_led.h b/src/core/ao_led.h index edc5fd1f..d9a0914a 100644 --- a/src/core/ao_led.h +++ b/src/core/ao_led.h @@ -40,6 +40,10 @@ ao_led_off(AO_LED_TYPE colors); void ao_led_set(AO_LED_TYPE colors); +/* Set all LEDs in 'mask' to the specified state */ +void +ao_led_set_mask(uint8_t colors, uint8_t mask); + /* Toggle the specified LEDs */ void ao_led_toggle(AO_LED_TYPE colors); diff --git a/src/drivers/ao_pca9922.c b/src/drivers/ao_pca9922.c index dc006f55..6d8d18d8 100644 --- a/src/drivers/ao_pca9922.c +++ b/src/drivers/ao_pca9922.c @@ -56,6 +56,13 @@ ao_led_set(uint8_t colors) ao_led_apply(); } +void +ao_led_set_mask(uint8_t colors, uint8_t mask) +{ + ao_led_state = (ao_led_state & ~mask) | (colors & mask); + ao_led_apply(); +} + void ao_led_toggle(uint8_t colors) { @@ -74,5 +81,6 @@ ao_led_for(uint8_t colors, uint16_t ticks) __reentrant void ao_led_init(uint8_t enable) { + (void) enable; ao_enable_output(AO_PCA9922_CS_PORT, AO_PCA9922_CS_PIN, AO_PCA9922_CS, 1); } -- cgit v1.2.3 From c64999c39d6d9242f98bdc9312436c3333115bfd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 24 Aug 2012 00:39:46 -0700 Subject: altos: Have radio_cmac turn on LEDs as appropriate Use AO_LED_RX and AO_LED_TX defines if present to control LEDs during radio operations. Signed-off-by: Keith Packard --- src/core/ao_radio_cmac.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/ao_radio_cmac.c b/src/core/ao_radio_cmac.c index 7a377002..32ce8793 100644 --- a/src/core/ao_radio_cmac.c +++ b/src/core/ao_radio_cmac.c @@ -159,8 +159,14 @@ ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant if (len > AO_CMAC_MAX_LEN) return AO_RADIO_CMAC_LEN_ERROR; ao_mutex_get(&ao_radio_cmac_mutex); - memcpy(cmac_data, packet, len); + ao_xmemcpy(cmac_data, packet, len); +#if AO_LED_TX + ao_led_on(AO_LED_TX); +#endif radio_cmac_send(len); +#if AO_LED_TX + ao_led_off(AO_LED_TX); +#endif ao_mutex_put(&ao_radio_cmac_mutex); return AO_RADIO_CMAC_OK; } @@ -172,9 +178,15 @@ ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentr if (len > AO_CMAC_MAX_LEN) return AO_RADIO_CMAC_LEN_ERROR; ao_mutex_get(&ao_radio_cmac_mutex); +#if AO_LED_RX + ao_led_on(AO_LED_RX); +#endif i = radio_cmac_recv(len, timeout); +#if AO_LED_RX + ao_led_off(AO_LED_RX); +#endif if (i == AO_RADIO_CMAC_OK) - memcpy(packet, cmac_data, len); + ao_xmemcpy(packet, cmac_data, len); ao_mutex_put(&ao_radio_cmac_mutex); return i; } -- cgit v1.2.3 From 83e0d4352041b3964ea7a133b0f67da9ebaa1c77 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 24 Aug 2012 00:40:27 -0700 Subject: altos: Split out LCO functions from ao_radio_cmac.c to ao_lco.c These functions are not used in the telelaunch or telefire nodes, so don't force them to be included. Signed-off-by: Keith Packard --- src/core/ao_radio_cmac.c | 173 ------------------------------------------ src/drivers/ao_lco.c | 193 +++++++++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_lco.h | 24 ++++++ 3 files changed, 217 insertions(+), 173 deletions(-) create mode 100644 src/drivers/ao_lco.c create mode 100644 src/drivers/ao_lco.h (limited to 'src') diff --git a/src/core/ao_radio_cmac.c b/src/core/ao_radio_cmac.c index 32ce8793..3e8dce53 100644 --- a/src/core/ao_radio_cmac.c +++ b/src/core/ao_radio_cmac.c @@ -243,176 +243,3 @@ radio_cmac_recv_cmd(void) __reentrant ao_mutex_put(&ao_radio_cmac_mutex); } -static __xdata struct ao_launch_command command; -static __xdata struct ao_launch_query query; -static __pdata uint16_t launch_serial; -static __pdata uint8_t launch_channel; -static __pdata uint16_t tick_offset; - -static void -launch_args(void) __reentrant -{ - ao_cmd_decimal(); - launch_serial = ao_cmd_lex_i; - ao_cmd_decimal(); - launch_channel = ao_cmd_lex_i; -} - -static int8_t -launch_query(void) -{ - uint8_t i; - int8_t r = AO_RADIO_CMAC_OK; - - tick_offset = ao_time(); - for (i = 0; i < 10; i++) { - printf ("."); flush(); - command.tick = ao_time(); - command.serial = launch_serial; - command.cmd = AO_LAUNCH_QUERY; - command.channel = launch_channel; - ao_radio_cmac_send(&command, sizeof (command)); - r = ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500)); - if (r == AO_RADIO_CMAC_OK) - break; - } - tick_offset -= query.tick; - printf("\n"); flush(); - return r; -} - -static void -launch_report_cmd(void) __reentrant -{ - int8_t r; - - launch_args(); - if (ao_cmd_status != ao_cmd_success) - return; - r = launch_query(); - switch (r) { - case AO_RADIO_CMAC_OK: - if (query.valid) { - switch (query.arm_status) { - case ao_igniter_ready: - case ao_igniter_active: - printf ("Armed: "); - break; - default: - printf("Disarmed: "); - } - switch (query.igniter_status) { - default: - printf("unknown\n"); - break; - case ao_igniter_ready: - printf("igniter good\n"); - break; - case ao_igniter_open: - printf("igniter bad\n"); - break; - } - } else { - printf("Invalid channel %d\n", launch_channel); - } - printf("Rssi: %d\n", ao_radio_cmac_rssi); - break; - default: - printf("Error %d\n", r); - break; - } -} - -static void -launch_arm(void) __reentrant -{ - command.tick = ao_time() - tick_offset; - command.serial = launch_serial; - command.cmd = AO_LAUNCH_ARM; - command.channel = launch_channel; - ao_radio_cmac_send(&command, sizeof (command)); -} - -static void -launch_ignite(void) __reentrant -{ - command.tick = ao_time() - tick_offset; - command.serial = launch_serial; - command.cmd = AO_LAUNCH_FIRE; - command.channel = 0; - ao_radio_cmac_send(&command, sizeof (command)); -} - -static void -launch_fire_cmd(void) __reentrant -{ - static __xdata struct ao_launch_command command; - uint8_t secs; - uint8_t i; - int8_t r; - - launch_args(); - ao_cmd_decimal(); - secs = ao_cmd_lex_i; - if (ao_cmd_status != ao_cmd_success) - return; - r = launch_query(); - if (r != AO_RADIO_CMAC_OK) { - printf("query failed %d\n", r); - return; - } - - for (i = 0; i < 4; i++) { - printf("arm %d\n", i); flush(); - launch_arm(); - } - - secs = secs * 10 - 5; - if (secs > 100) - secs = 100; - for (i = 0; i < secs; i++) { - printf("fire %d\n", i); flush(); - launch_ignite(); - ao_delay(AO_MS_TO_TICKS(100)); - } -} - -static void -launch_arm_cmd(void) __reentrant -{ - uint8_t i; - int8_t r; - launch_args(); - r = launch_query(); - if (r != AO_RADIO_CMAC_OK) { - printf("query failed %d\n", r); - return; - } - for (i = 0; i < 4; i++) - launch_arm(); -} - -static void -launch_ignite_cmd(void) __reentrant -{ - uint8_t i; - launch_args(); - for (i = 0; i < 4; i++) - launch_ignite(); -} - -static __code struct ao_cmds ao_radio_cmac_cmds[] = { - { radio_cmac_send_cmd, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, - { radio_cmac_recv_cmd, "S \0Receive AES-CMAC packet. Timeout in ms" }, - { launch_report_cmd, "l \0Get remote launch status" }, - { launch_fire_cmd, "f \0Fire remote igniter" }, - { launch_arm_cmd, "a \0Arm remote igniter" }, - { launch_ignite_cmd, "i \0Pulse remote igniter" }, - { 0, NULL }, -}; - -void -ao_radio_cmac_init(void) -{ - ao_cmd_register(&ao_radio_cmac_cmds[0]); -} diff --git a/src/drivers/ao_lco.c b/src/drivers/ao_lco.c new file mode 100644 index 00000000..f30f3379 --- /dev/null +++ b/src/drivers/ao_lco.c @@ -0,0 +1,193 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +static __xdata struct ao_launch_command command; +static __xdata struct ao_launch_query query; +static __pdata uint16_t launch_serial; +static __pdata uint8_t launch_channel; +static __pdata uint16_t tick_offset; + +static void +launch_args(void) __reentrant +{ + ao_cmd_decimal(); + launch_serial = ao_cmd_lex_i; + ao_cmd_decimal(); + launch_channel = ao_cmd_lex_i; +} + +static int8_t +launch_query(void) +{ + uint8_t i; + int8_t r = AO_RADIO_CMAC_OK; + + tick_offset = ao_time(); + for (i = 0; i < 10; i++) { + printf ("."); flush(); + command.tick = ao_time(); + command.serial = launch_serial; + command.cmd = AO_LAUNCH_QUERY; + command.channel = launch_channel; + ao_radio_cmac_send(&command, sizeof (command)); + r = ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500)); + if (r == AO_RADIO_CMAC_OK) + break; + } + tick_offset -= query.tick; + printf("\n"); flush(); + return r; +} + +static void +launch_report_cmd(void) __reentrant +{ + int8_t r; + + launch_args(); + if (ao_cmd_status != ao_cmd_success) + return; + r = launch_query(); + switch (r) { + case AO_RADIO_CMAC_OK: + if (query.valid) { + switch (query.arm_status) { + case ao_igniter_ready: + case ao_igniter_active: + printf ("Armed: "); + break; + default: + printf("Disarmed: "); + } + switch (query.igniter_status) { + default: + printf("unknown\n"); + break; + case ao_igniter_ready: + printf("igniter good\n"); + break; + case ao_igniter_open: + printf("igniter bad\n"); + break; + } + } else { + printf("Invalid channel %d\n", launch_channel); + } + printf("Rssi: %d\n", ao_radio_cmac_rssi); + break; + default: + printf("Error %d\n", r); + break; + } +} + +static void +launch_arm(void) __reentrant +{ + command.tick = ao_time() - tick_offset; + command.serial = launch_serial; + command.cmd = AO_LAUNCH_ARM; + command.channel = launch_channel; + ao_radio_cmac_send(&command, sizeof (command)); +} + +static void +launch_ignite(void) __reentrant +{ + command.tick = ao_time() - tick_offset; + command.serial = launch_serial; + command.cmd = AO_LAUNCH_FIRE; + command.channel = 0; + ao_radio_cmac_send(&command, sizeof (command)); +} + +static void +launch_fire_cmd(void) __reentrant +{ + static __xdata struct ao_launch_command command; + uint8_t secs; + uint8_t i; + int8_t r; + + launch_args(); + ao_cmd_decimal(); + secs = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) + return; + r = launch_query(); + if (r != AO_RADIO_CMAC_OK) { + printf("query failed %d\n", r); + return; + } + + for (i = 0; i < 4; i++) { + printf("arm %d\n", i); flush(); + launch_arm(); + } + + secs = secs * 10 - 5; + if (secs > 100) + secs = 100; + for (i = 0; i < secs; i++) { + printf("fire %d\n", i); flush(); + launch_ignite(); + ao_delay(AO_MS_TO_TICKS(100)); + } +} + +static void +launch_arm_cmd(void) __reentrant +{ + uint8_t i; + int8_t r; + launch_args(); + r = launch_query(); + if (r != AO_RADIO_CMAC_OK) { + printf("query failed %d\n", r); + return; + } + for (i = 0; i < 4; i++) + launch_arm(); +} + +static void +launch_ignite_cmd(void) __reentrant +{ + uint8_t i; + launch_args(); + for (i = 0; i < 4; i++) + launch_ignite(); +} + +static __code struct ao_cmds ao_lco_cmds[] = { + { radio_cmac_send_cmd, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, + { radio_cmac_recv_cmd, "S \0Receive AES-CMAC packet. Timeout in ms" }, + { launch_report_cmd, "l \0Get remote launch status" }, + { launch_fire_cmd, "f \0Fire remote igniter" }, + { launch_arm_cmd, "a \0Arm remote igniter" }, + { launch_ignite_cmd, "i \0Pulse remote igniter" }, + { 0, NULL }, +}; + +void +ao_lco_init(void) +{ + ao_cmd_register(&ao_lco_cmds[0]); +} diff --git a/src/drivers/ao_lco.h b/src/drivers/ao_lco.h new file mode 100644 index 00000000..253f9702 --- /dev/null +++ b/src/drivers/ao_lco.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_LCO_H_ +#define _AO_LCO_H_ + +void +ao_lco_init(void); + +#endif /* _AO_LCO_H_ */ -- cgit v1.2.3 From 6581fa1641882198c870c2f7b1340794b9d47f29 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 24 Aug 2012 00:42:32 -0700 Subject: altos: Get ao_pad.c working on telefire v0.1 Monitor all four channels, allow any channel to be fired. Turn on power LED at startup time. Signed-off-by: Keith Packard --- src/drivers/ao_pad.c | 61 +++++++++++++++++++++++++++++++++++++++------------- src/drivers/ao_pad.h | 2 +- 2 files changed, 47 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index b6dbcefe..dfa5f9f5 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -51,20 +51,48 @@ ao_pad_run(void) static void ao_pad_status(void) { + uint8_t c; + uint8_t sample; + __pdata uint8_t prev = 0, cur = 0; + __pdata uint8_t beeping = 0; + __xdata struct ao_data *packet; + + sample = ao_data_head; for (;;) { - ao_delay(AO_SEC_TO_TICKS(1)); -#if 0 - if (ao_igniter_status(ao_igniter_drogue) == ao_igniter_ready) { - if (ao_igniter_status(ao_igniter_main) == ao_igniter_ready) { - for (i = 0; i < 5; i++) { - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(50)); - ao_delay(AO_MS_TO_TICKS(100)); - } - } else { - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + __pdata int16_t pyro; + ao_arch_critical( + while (sample == ao_data_head) + ao_sleep((void *) DATA_TO_XDATA(&ao_data_head)); + ); + + packet = &ao_data_ring[sample]; + sample = ao_data_ring_next(sample); + + pyro = packet->adc.pyro; + +#define VOLTS_TO_PYRO(x) ((int16_t) ((x) * 27.0 / 127.0 / 3.3 * 32767.0)) + + cur = 0; + if (pyro > VOLTS_TO_PYRO(4)) { + for (c = 0; c < AO_PAD_NUM; c++) { + int16_t sense = packet->adc.sense[c]; + + if (sense >= pyro / 4 * 3) + cur |= AO_LED_CONTINUITY(c); } } -#endif + if (cur != prev) { + ao_led_set_mask(cur, AO_LED_CONTINUITY_MASK); + prev = cur; + } + + if (pyro > VOLTS_TO_PYRO(9) && sample == 0) { + beeping = 1; + ao_beep(AO_BEEP_HIGH); + } else if (beeping) { + beeping = 0; + ao_beep(0); + } } } @@ -97,9 +125,10 @@ ao_pad(void) int16_t time_difference; uint8_t c; - ao_led_off(AO_LED_RED); ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); ao_pad_box = ao_74hc497_read(); + ao_led_set(0); + ao_led_on(AO_LED_POWER); for (;;) { flush(); while (ao_pad_disabled) @@ -209,8 +238,10 @@ ao_pad_manual(void) ao_cmd_white(); if (!ao_match_word("DoIt")) return; - ao_cmd_white(); - ao_pad_ignite = 1; + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + ao_pad_ignite = 1 << ao_cmd_lex_i; ao_wakeup(&ao_pad_ignite); } @@ -220,7 +251,7 @@ static __xdata struct ao_task ao_pad_status_task; __code struct ao_cmds ao_pad_cmds[] = { { ao_pad_test, "t\0Test pad continuity" }, - { ao_pad_manual, "i \0Fire igniter. is doit with D&I" }, + { ao_pad_manual, "i \0Fire igniter. is doit with D&I" }, { 0, NULL } }; diff --git a/src/drivers/ao_pad.h b/src/drivers/ao_pad.h index d5ca3a88..3b0cf1fe 100644 --- a/src/drivers/ao_pad.h +++ b/src/drivers/ao_pad.h @@ -50,7 +50,7 @@ struct ao_pad_query { */ #define AO_PAD_FIRE 3 -#define AO_PAD_FIRE_TIME AO_MS_TO_TICKS(200) +#define AO_PAD_FIRE_TIME AO_MS_TO_TICKS(1000) #define AO_PAD_ARM_STATUS_DISARMED 0 #define AO_PAD_ARM_STATUS_ARMED 1 -- cgit v1.2.3 From 310c1d0bf83448eb12e5d64ac09a4279c25fd258 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 24 Aug 2012 00:44:35 -0700 Subject: altos: telelaunch doesn't need ao_radio_cmac_init This function was used to initialize the LCO functions, which were moved to ao_lco.c a few commits back, so ao_radio_cmac_init doesn't even exist anymore. Signed-off-by: Keith Packard --- src/product/ao_telelaunch.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/product/ao_telelaunch.c b/src/product/ao_telelaunch.c index 506431de..b6e4bfc1 100644 --- a/src/product/ao_telelaunch.c +++ b/src/product/ao_telelaunch.c @@ -39,7 +39,6 @@ main(void) ao_dbg_init(); #endif ao_aes_init(); - ao_radio_cmac_init(); ao_launch_init(); ao_config_init(); ao_start_scheduler(); -- cgit v1.2.3 From 7ecb429fe4682faf209452b1738ff3c8096fc5d5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 24 Aug 2012 00:46:55 -0700 Subject: altos: Configure telefire SPI and LEDs correctly This places the telefire SPI bus on USART1 option 2 and marks the various LED functions with symbolic names. Signed-off-by: Keith Packard --- src/telefire-v0.1/Makefile | 1 + src/telefire-v0.1/ao_pins.h | 22 ++++++++++++++++++++-- src/telefire-v0.1/ao_telefire.c | 9 +++++---- 3 files changed, 26 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/telefire-v0.1/Makefile b/src/telefire-v0.1/Makefile index 09cb88fb..cfa4b3ed 100644 --- a/src/telefire-v0.1/Makefile +++ b/src/telefire-v0.1/Makefile @@ -18,6 +18,7 @@ INC = \ ao_pins.h \ ao_arch.h \ ao_arch_funcs.h \ + ao_pad.h \ cc1111.h \ ao_product.h diff --git a/src/telefire-v0.1/ao_pins.h b/src/telefire-v0.1/ao_pins.h index 4cf523fc..d3a9e9e3 100644 --- a/src/telefire-v0.1/ao_pins.h +++ b/src/telefire-v0.1/ao_pins.h @@ -29,6 +29,7 @@ #define HAS_DBG 0 #define HAS_EEPROM 1 #define HAS_LOG 0 +#define HAS_PAD 1 #define USE_INTERNAL_FLASH 1 #define DBG_ON_P1 0 #define IGNITE_ON_P2 0 @@ -36,8 +37,17 @@ #define IGNITE_ON_P0 0 #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 0 -#define AO_LED_RED 2 -#define AO_LED_GREEN 1 + +#define AO_LED_CONTINUITY(c) (1 << (c)) +#define AO_LED_CONTINUITY_MASK (0xf) +#define AO_LED_RX 0x10 +#define AO_LED_TX 0x20 +#define AO_LED_ARMED 0x40 +#define AO_LED_POWER 0x80 + +#define AO_LED_RED AO_LED_TX +#define AO_LED_GREEN AO_LED_RX + #define LEDS_AVAILABLE (0xff) #define HAS_EXTERNAL_TEMP 0 #define HAS_ACCEL_REF 0 @@ -48,6 +58,13 @@ #define SPI_CS_SEL P1SEL #define SPI_CS_DIR P1DIR +#define SPI_CONST 0x00 + +#define HAS_SPI_0 0 +#define HAS_SPI_1 1 +#define SPI_1_ALT_1 0 +#define SPI_1_ALT_2 1 + #define AO_74HC497_CS_PORT P1 #define AO_74HC497_CS_PIN 4 #define AO_74HC497_CS P1_4 @@ -82,6 +99,7 @@ struct ao_adc { #define AO_ADC_DUMP(p) \ printf ("tick: %5u 0: %5d 1: %5d 2: %5d 3: %5d pyro: %5d batt %5d\n", \ + (p)->tick, \ (p)->adc.sense[0], \ (p)->adc.sense[1], \ (p)->adc.sense[2], \ diff --git a/src/telefire-v0.1/ao_telefire.c b/src/telefire-v0.1/ao_telefire.c index 96413a63..c1335d66 100644 --- a/src/telefire-v0.1/ao_telefire.c +++ b/src/telefire-v0.1/ao_telefire.c @@ -15,8 +15,9 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" -#include "ao_pins.h" +#include +#include +#include void main(void) @@ -30,11 +31,11 @@ main(void) ao_beep_init(); ao_cmd_init(); ao_spi_init(); + ao_74hc497_init(); ao_storage_init(); ao_usb_init(); ao_radio_init(); - ao_aes_init(); - ao_radio_cmac_init(); +// ao_aes_init(); ao_pad_init(); ao_config_init(); ao_start_scheduler(); -- cgit v1.2.3 From 89f1a685a02c7808cf03853aa9a5ee50c6baf49e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 26 Aug 2012 09:43:34 -0700 Subject: altos: Allow sharing of radio DMA with aes engine otherwise, telefire doesn't have enough DMA channels. Signed-off-by: Keith Packard --- src/cc1111/ao_aes.c | 4 ++++ src/telefire-v0.1/ao_pins.h | 1 + src/telefire-v0.1/ao_telefire.c | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/cc1111/ao_aes.c b/src/cc1111/ao_aes.c index d50fecfb..0e32abf6 100644 --- a/src/cc1111/ao_aes.c +++ b/src/cc1111/ao_aes.c @@ -136,7 +136,11 @@ void ao_aes_init(void) { ao_aes_dma_in = ao_dma_alloc(&ao_aes_dma_in_done); +#if DMA_SHARE_AES_RADIO + ao_aes_dma_out = ao_radio_dma; +#else ao_aes_dma_out = ao_dma_alloc(&ao_aes_dma_out_done); +#endif S0CON = 0; ENCIE = 1; } diff --git a/src/telefire-v0.1/ao_pins.h b/src/telefire-v0.1/ao_pins.h index d3a9e9e3..eecf783e 100644 --- a/src/telefire-v0.1/ao_pins.h +++ b/src/telefire-v0.1/ao_pins.h @@ -53,6 +53,7 @@ #define HAS_ACCEL_REF 0 #define SPI_CS_ON_P1 1 #define HAS_AES 1 +#define DMA_SHARE_AES_RADIO 1 #define SPI_CS_PORT P1 #define SPI_CS_SEL P1SEL diff --git a/src/telefire-v0.1/ao_telefire.c b/src/telefire-v0.1/ao_telefire.c index c1335d66..210be08b 100644 --- a/src/telefire-v0.1/ao_telefire.c +++ b/src/telefire-v0.1/ao_telefire.c @@ -35,7 +35,7 @@ main(void) ao_storage_init(); ao_usb_init(); ao_radio_init(); -// ao_aes_init(); + ao_aes_init(); ao_pad_init(); ao_config_init(); ao_start_scheduler(); -- cgit v1.2.3 From ea4db73328e865fd658b573da256ca0004c69c61 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 26 Aug 2012 09:45:03 -0700 Subject: altos: Add debug command for 74hc597 driver This dumps the current state of the 74hc597 chip. Note that this shows that the 74hc597 driver doesn't work, and that the circuit used in telefire v0.1 can't work. Signed-off-by: Keith Packard --- src/drivers/ao_74hc497.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/drivers/ao_74hc497.c b/src/drivers/ao_74hc497.c index 93c544c3..4c13ee71 100644 --- a/src/drivers/ao_74hc497.c +++ b/src/drivers/ao_74hc497.c @@ -28,13 +28,28 @@ ao_74hc497_read(void) { static __xdata state; ao_spi_get_bit(AO_74HC497_CS_PORT, AO_74HC497_CS_PIN, AO_74HC497_CS, AO_74HC497_SPI_BUS, AO_SPI_SPEED_FAST); - ao_spi_send(&state, 1, AO_74HC497_SPI_BUS); + ao_spi_recv(&state, 1, AO_74HC497_SPI_BUS); ao_spi_put_bit(AO_74HC497_CS_PORT, AO_74HC497_CS_PIN, AO_74HC497_CS, AO_74HC497_SPI_BUS); return state; } +static void +ao_74hc497_cmd(void) +{ + uint8_t v; + + v = ao_74hc497_read(); + printf ("Switches: 0x%02x\n", v); +} + +static const struct ao_cmds ao_74hc497_cmds[] = { + { ao_74hc497_cmd, "L\0Show 74hc497" }, + { 0, NULL } +}; + void ao_74hc497_init(void) { ao_enable_output(AO_74HC497_CS_PORT, AO_74HC497_CS_PIN, AO_74HC497_CS, 1); + ao_cmd_register(&ao_74hc497_cmds[0]); } -- cgit v1.2.3 From 1c9baa88d6cd931c66d453674322908eb267ba4c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 26 Aug 2012 09:47:05 -0700 Subject: altos: Make 'pad' driver useful with telefire v0.1 This reports correct status bits over the radio and to the LEDs for all four channels, and also makes the firing test command control all four relays. Signed-off-by: Keith Packard --- src/drivers/ao_pad.c | 108 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 69 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index dfa5f9f5..791c9a47 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -19,15 +19,16 @@ #include #include -__xdata uint8_t ao_pad_ignite; - -#define ao_pad_igniter_status(c) AO_PAD_IGNITER_STATUS_UNKNOWN -#define ao_pad_arm_status() AO_PAD_ARM_STATUS_UNKNOWN +static __xdata uint8_t ao_pad_ignite; +static __xdata struct ao_pad_command command; +static __xdata struct ao_pad_query query; #if 0 #define PRINTD(...) printf(__VA_ARGS__) +#define FLUSHD() flush() #else #define PRINTD(...) +#define FLUSHD() #endif static void @@ -49,12 +50,12 @@ ao_pad_run(void) } static void -ao_pad_status(void) +ao_pad_monitor(void) { uint8_t c; uint8_t sample; - __pdata uint8_t prev = 0, cur = 0; - __pdata uint8_t beeping = 0; + __pdata uint8_t prev = 0, cur = 0; + __pdata uint8_t beeping = 0; __xdata struct ao_data *packet; sample = ao_data_head; @@ -73,13 +74,45 @@ ao_pad_status(void) #define VOLTS_TO_PYRO(x) ((int16_t) ((x) * 27.0 / 127.0 / 3.3 * 32767.0)) cur = 0; - if (pyro > VOLTS_TO_PYRO(4)) { - for (c = 0; c < AO_PAD_NUM; c++) { - int16_t sense = packet->adc.sense[c]; + if (pyro > VOLTS_TO_PYRO(4)) + query.arm_status = AO_PAD_ARM_STATUS_ARMED; + else if (pyro < VOLTS_TO_PYRO(1)) + query.arm_status = AO_PAD_ARM_STATUS_DISARMED; + else + query.arm_status = AO_PAD_ARM_STATUS_UNKNOWN; + + for (c = 0; c < AO_PAD_NUM; c++) { + int16_t sense = packet->adc.sense[c]; + uint8_t status = AO_PAD_IGNITER_STATUS_UNKNOWN; + + if (query.arm_status == AO_PAD_ARM_STATUS_ARMED) { + /* + * pyro is run through a divider, so pyro = v_pyro * 27 / 127 ~= v_pyro / 20 + * v_pyro = pyro * 127 / 27 + * + * v_pyro \ + * 100k igniter + * output / + * 100k \ + * sense relay + * 27k / + * gnd --- + * + * If the relay is closed, then sense will be 0 + * If no igniter is present, then sense will be v_pyro * 27k/227k = pyro * 127 / 227 ~= pyro/2 + * If igniter is present, then sense will be v_pyro * 27k/127k ~= v_pyro / 20 = pyro + */ - if (sense >= pyro / 4 * 3) + if (sense <= pyro / 8) + status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED; + else if (pyro / 8 * 3 <= sense && sense <= pyro / 8 * 5) + status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN; + else if (pyro / 8 * 7 <= sense) { + status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN; cur |= AO_LED_CONTINUITY(c); + } } + query.igniter_status[c] = status; } if (cur != prev) { ao_led_set_mask(cur, AO_LED_CONTINUITY_MASK); @@ -120,17 +153,14 @@ ao_pad_enable(void) static void ao_pad(void) { - static __xdata struct ao_pad_command command; - static __xdata struct ao_pad_query query; int16_t time_difference; - uint8_t c; ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); ao_pad_box = ao_74hc497_read(); ao_led_set(0); ao_led_on(AO_LED_POWER); for (;;) { - flush(); + FLUSHD(); while (ao_pad_disabled) ao_sleep(&ao_pad_disabled); if (ao_radio_cmac_recv(&command, sizeof (command), 0) != AO_RADIO_CMAC_OK) @@ -173,9 +203,6 @@ ao_pad(void) query.box = ao_pad_box; query.channels = AO_PAD_ALL_PINS; query.armed = ao_pad_armed; - query.arm_status = ao_pad_arm_status(); - for (c = 0; c < AO_PAD_NUM; c++) - query.igniter_status[c] = ao_pad_igniter_status(c); PRINTD ("query tick %d serial %d channel %d valid %d arm %d igniter %d\n", query.tick, query.serial, query.channel, query.valid, query.arm_status, query.igniter_status); @@ -209,27 +236,30 @@ ao_pad(void) void ao_pad_test(void) { -#if 0 - switch (ao_igniter_status(ao_igniter_drogue)) { - case ao_igniter_ready: - case ao_igniter_active: - printf ("Armed: "); - switch (ao_igniter_status(ao_igniter_main)) { - default: - printf("unknown status\n"); - break; - case ao_igniter_ready: - printf("igniter good\n"); - break; - case ao_igniter_open: - printf("igniter bad\n"); - break; - } + uint8_t c; + + printf ("Arm switch: "); + switch (query.arm_status) { + case AO_PAD_ARM_STATUS_ARMED: + printf ("Armed\n"); + break; + case AO_PAD_ARM_STATUS_DISARMED: + printf ("Disarmed\n"); + break; + case AO_PAD_ARM_STATUS_UNKNOWN: + printf ("Unknown\n"); break; - default: - printf("Disarmed\n"); } -#endif + + for (c = 0; c < AO_PAD_NUM; c++) { + printf ("Pad %d: "); + switch (query.igniter_status[c]) { + case AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED: printf ("No igniter. Relay closed\n"); break; + case AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN: printf ("No igniter. Relay open\n"); break; + case AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN: printf ("Good igniter. Relay open\n"); break; + case AO_PAD_IGNITER_STATUS_UNKNOWN: printf ("Unknown\n"); break; + } + } } void @@ -247,7 +277,7 @@ ao_pad_manual(void) static __xdata struct ao_task ao_pad_task; static __xdata struct ao_task ao_pad_ignite_task; -static __xdata struct ao_task ao_pad_status_task; +static __xdata struct ao_task ao_pad_monitor_task; __code struct ao_cmds ao_pad_cmds[] = { { ao_pad_test, "t\0Test pad continuity" }, @@ -273,5 +303,5 @@ ao_pad_init(void) ao_cmd_register(&ao_pad_cmds[0]); ao_add_task(&ao_pad_task, ao_pad, "pad listener"); ao_add_task(&ao_pad_ignite_task, ao_pad_run, "pad igniter"); - ao_add_task(&ao_pad_status_task, ao_pad_status, "pad status"); + ao_add_task(&ao_pad_monitor_task, ao_pad_monitor, "pad monitor"); } -- cgit v1.2.3 From d13d0fbfcb0fd6d8a1af46f6270a968d746c830e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 26 Aug 2012 09:49:34 -0700 Subject: altos: Make ao_cur_task_index track ao_cur_task in ao_yield This keeps the two main task references (index and pointer) in agreement during task switching, avoiding an extra assignment at the end of the task switching loop. Signed-off-by: Keith Packard --- src/core/ao_task.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/core/ao_task.c b/src/core/ao_task.c index 4011a36e..4593bd79 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -82,39 +82,36 @@ ao_yield(void) ao_arch_naked_define ao_arch_isr_stack(); -#if CHECK_STACK +#if AO_CHECK_STACK in_yield = 1; #endif /* Find a task to run. If there isn't any runnable task, * this loop will run forever, which is just fine */ { - __pdata uint8_t ao_next_task_index = ao_cur_task_index; + __pdata uint8_t ao_last_task_index = ao_cur_task_index; for (;;) { - ++ao_next_task_index; - if (ao_next_task_index == ao_num_tasks) - ao_next_task_index = 0; + ++ao_cur_task_index; + if (ao_cur_task_index == ao_num_tasks) + ao_cur_task_index = 0; + + ao_cur_task = ao_tasks[ao_cur_task_index]; - ao_cur_task = ao_tasks[ao_next_task_index]; - if (ao_cur_task->wchan == NULL) { - ao_cur_task_index = ao_next_task_index; + /* Check for ready task */ + if (ao_cur_task->wchan == NULL) break; - } /* Check if the alarm is set for a time which has passed */ if (ao_cur_task->alarm && - (int16_t) (ao_time() - ao_cur_task->alarm) >= 0) { - ao_cur_task_index = ao_next_task_index; + (int16_t) (ao_time() - ao_cur_task->alarm) >= 0) break; - } /* Enter lower power mode when there isn't anything to do */ - if (ao_next_task_index == ao_cur_task_index) { + if (ao_cur_task_index == ao_last_task_index) ao_arch_cpu_idle(); - } } } -#if CHECK_STACK +#if AO_CHECK_STACK cli(); in_yield = 0; #endif @@ -177,7 +174,7 @@ ao_exit(void) void ao_task_info(void) { - uint8_t i; + uint8_t i; __xdata struct ao_task *task; for (i = 0; i < ao_num_tasks; i++) { -- cgit v1.2.3 From dec1481786ad54e22634e32109b5ed6e5483938e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 26 Aug 2012 09:52:27 -0700 Subject: altos: Shrink STM stack size 512 bytes should be enough for anybody. Signed-off-by: Keith Packard --- src/stm/ao_arch.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index 484ce89e..d0dd3c79 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -25,10 +25,14 @@ * STM32L definitions and code fragments for AltOS */ -#define AO_STACK_SIZE 668 +#define AO_STACK_SIZE 512 #define AO_LED_TYPE uint16_t +#ifndef AO_TICK_TYPE +#define AO_TICK_TYPE uint16_t +#endif + /* Various definitions to make GCC look more like SDCC */ #define ao_arch_naked_declare __attribute__((naked)) -- cgit v1.2.3 From f89e7de20374141b367205aa517a08ee203bfaf3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 26 Aug 2012 09:53:16 -0700 Subject: altos: Trigger sample complete when all data are ready This has each sensor mark a bit in the current data record which is then sent for processing when all of the data are present. Signed-off-by: Keith Packard --- src/core/ao_data.h | 50 +++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_hmc5883.c | 23 ++++++++----------- src/drivers/ao_hmc5883.h | 4 ---- src/drivers/ao_mma655x.c | 23 ++++++++++++++++--- src/drivers/ao_mpu6000.c | 30 +++++++++---------------- src/drivers/ao_mpu6000.h | 3 --- src/drivers/ao_ms5607.c | 26 ++++++++++----------- src/drivers/ao_ms5607.h | 3 --- src/megametrum-v0.1/Makefile | 2 ++ src/megametrum-v0.1/ao_pins.h | 2 +- src/megametrum-v0.1/stlink-pins | 8 +++++++ src/stm-demo/Makefile | 1 + src/stm/ao_adc_stm.c | 42 +--------------------------------- src/stm/ao_timer.c | 19 +++++++++------- 14 files changed, 126 insertions(+), 110 deletions(-) (limited to 'src') diff --git a/src/core/ao_data.h b/src/core/ao_data.h index fdc49ca2..3b66ef5d 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -18,18 +18,42 @@ #ifndef _AO_DATA_H_ #define _AO_DATA_H_ +#if HAS_ADC +#define AO_DATA_ADC (1 << 0) +#else +#define AO_DATA_ADC 0 +#endif + #if HAS_MS5607 #include +#define AO_DATA_MS5607 (1 << 1) +#else +#define AO_DATA_MS5607 (1 << 1) #endif #if HAS_MPU6000 #include +#define AO_DATA_MPU6000 (1 << 2) +#else +#define AO_DATA_MPU6000 0 #endif #if HAS_HMC5883 #include +#define AO_DATA_HMC5883 (1 << 3) +#else +#define AO_DATA_HMC5883 0 +#endif + +#if HAS_MMA655X +#include +#define AO_DATA_MMA655X (1 << 4) +#else +#define AO_DATA_MMA655X 0 #endif +#define AO_DATA_ALL (AO_DATA_ADC|AO_DATA_MS5607|AO_DATA_MPU6000|AO_DATA_HMC5883|AO_DATA_MMA655X) + struct ao_data { uint16_t tick; #if HAS_ADC @@ -45,6 +69,9 @@ struct ao_data { #if HAS_HMC5883 struct ao_hmc5883_sample hmc5883; #endif +#if HAS_MMA655X + uint16_t mma655x; +#endif }; #define ao_data_ring_next(n) (((n) + 1) & (AO_DATA_RING - 1)) @@ -52,6 +79,29 @@ struct ao_data { extern volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; extern volatile __data uint8_t ao_data_head; +extern volatile __data uint8_t ao_data_present; +extern volatile __data uint8_t ao_data_count; + +/* + * Mark a section of data as ready, check for data complete + */ +#define AO_DATA_PRESENT(bit) do { \ + if ((ao_data_present |= (bit)) == AO_DATA_ALL) { \ + ao_data_ring[ao_data_head].tick = ao_tick_count; \ + ao_data_head = ao_data_ring_next(ao_data_head); \ + ao_data_present = 0; \ + ao_wakeup((void *) &ao_data_head); \ + } \ + } while (0); + +/* + * Wait for data to be completed by looking at the + * indicated bit + */ +#define AO_DATA_WAIT() do { \ + ao_sleep((void *) &ao_data_count); \ + } while (0) + #if HAS_MS5607 diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c index dbeb66b8..ade6c263 100644 --- a/src/drivers/ao_hmc5883.c +++ b/src/drivers/ao_hmc5883.c @@ -19,7 +19,7 @@ #include #include -uint8_t ao_hmc5883_valid; +#if HAS_HMC5883 static uint8_t ao_hmc5883_configured; @@ -123,21 +123,16 @@ ao_hmc5883_setup(void) return 1; } -struct ao_hmc5883_sample ao_hmc5883_current; - static void ao_hmc5883(void) { ao_hmc5883_setup(); for (;;) { - struct ao_hmc5883_sample ao_hmc5883_next; - - ao_hmc5883_sample(&ao_hmc5883_next); + ao_hmc5883_sample((struct ao_hmc5883_sample *) &ao_data_ring[ao_data_head].hmc5883); ao_arch_critical( - ao_hmc5883_current = ao_hmc5883_next; - ao_hmc5883_valid = 1; + AO_DATA_PRESENT(AO_DATA_HMC5883); + AO_DATA_WAIT(); ); - ao_delay(0); } } @@ -146,11 +141,10 @@ static struct ao_task ao_hmc5883_task; static void ao_hmc5883_show(void) { - struct ao_hmc5883_sample sample; - - sample = ao_hmc5883_current; + struct ao_data sample; + ao_data_get(&sample); printf ("X: %d Y: %d Z: %d missed irq: %lu\n", - sample.x, sample.y, sample.z, ao_hmc5883_missed_irq); + sample.hmc5883.x, sample.hmc5883.y, sample.hmc5883.z, ao_hmc5883_missed_irq); } static const struct ao_cmds ao_hmc5883_cmds[] = { @@ -162,7 +156,6 @@ void ao_hmc5883_init(void) { ao_hmc5883_configured = 0; - ao_hmc5883_valid = 0; ao_enable_port(AO_HMC5883_INT_PORT); ao_exti_setup(AO_HMC5883_INT_PORT, @@ -173,3 +166,5 @@ ao_hmc5883_init(void) ao_add_task(&ao_hmc5883_task, ao_hmc5883, "hmc5883"); ao_cmd_register(&ao_hmc5883_cmds[0]); } + +#endif diff --git a/src/drivers/ao_hmc5883.h b/src/drivers/ao_hmc5883.h index 8d726510..55690978 100644 --- a/src/drivers/ao_hmc5883.h +++ b/src/drivers/ao_hmc5883.h @@ -75,14 +75,10 @@ #define HMC5883_ID_B 11 #define HMC5883_ID_C 12 -extern uint8_t ao_hmc5883_valid; - struct ao_hmc5883_sample { int16_t x, y, z; }; -extern struct ao_hmc5883_sample ao_hmc5883_current; - void ao_hmc5883_init(void); diff --git a/src/drivers/ao_mma655x.c b/src/drivers/ao_mma655x.c index e4e41627..cd304d80 100644 --- a/src/drivers/ao_mma655x.c +++ b/src/drivers/ao_mma655x.c @@ -18,8 +18,9 @@ #include #include +#if HAS_MMA655X + static uint8_t mma655x_configured; -uint8_t ao_mma655x_valid; static void ao_mma655x_start(void) { @@ -197,14 +198,30 @@ __code struct ao_cmds ao_mma655x_cmds[] = { { 0, NULL }, }; +static void +ao_mma655x(void) +{ + ao_mma655x_setup(); + for (;;) { + ao_data_ring[ao_data_head].mma655x = ao_mma655x_value(); + ao_arch_critical( + AO_DATA_PRESENT(AO_DATA_MMA655X); + AO_DATA_WAIT(); + ); + } +} + +static __xdata struct ao_task ao_mma655x_task; + void ao_mma655x_init(void) { mma655x_configured = 0; - ao_mma655x_valid = 0; ao_cmd_register(&ao_mma655x_cmds[0]); ao_spi_init_cs(AO_MMA655X_CS_GPIO, (1 << AO_MMA655X_CS)); -// ao_add_task(&ao_mma655x_task, ao_mma655x, "mma655x"); + ao_add_task(&ao_mma655x_task, ao_mma655x, "mma655x"); } + +#endif diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index a1c32d4d..e8c80f12 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -240,22 +240,17 @@ ao_mpu6000_setup(void) ao_mpu6000_configured = 1; } -struct ao_mpu6000_sample ao_mpu6000_current; -uint8_t ao_mpu6000_valid; - static void ao_mpu6000(void) { ao_mpu6000_setup(); for (;;) { - struct ao_mpu6000_sample ao_mpu6000_next; - ao_mpu6000_sample(&ao_mpu6000_next); + ao_mpu6000_sample((struct ao_mpu6000_sample *) &ao_data_ring[ao_data_head].mpu6000); ao_arch_critical( - ao_mpu6000_current = ao_mpu6000_next; - ao_mpu6000_valid = 1; + AO_DATA_PRESENT(AO_DATA_MPU6000); + AO_DATA_WAIT(); ); - ao_delay(0); } } @@ -264,18 +259,16 @@ static struct ao_task ao_mpu6000_task; static void ao_mpu6000_show(void) { - struct ao_mpu6000_sample sample; + struct ao_data sample; - ao_arch_critical( - sample = ao_mpu6000_current; - ); + ao_data_get(&sample); printf ("Accel: %7d %7d %7d Gyro: %7d %7d %7d\n", - sample.accel_x, - sample.accel_y, - sample.accel_z, - sample.gyro_x, - sample.gyro_y, - sample.gyro_z); + sample.mpu6000.accel_x, + sample.mpu6000.accel_y, + sample.mpu6000.accel_z, + sample.mpu6000.gyro_x, + sample.mpu6000.gyro_y, + sample.mpu6000.gyro_z); } static const struct ao_cmds ao_mpu6000_cmds[] = { @@ -287,7 +280,6 @@ void ao_mpu6000_init(void) { ao_mpu6000_configured = 0; - ao_mpu6000_valid = 0; ao_add_task(&ao_mpu6000_task, ao_mpu6000, "mpu6000"); ao_cmd_register(&ao_mpu6000_cmds[0]); diff --git a/src/drivers/ao_mpu6000.h b/src/drivers/ao_mpu6000.h index fc7af1e0..ca76b081 100644 --- a/src/drivers/ao_mpu6000.h +++ b/src/drivers/ao_mpu6000.h @@ -155,9 +155,6 @@ struct ao_mpu6000_sample { int16_t gyro_z; }; -extern struct ao_mpu6000_sample ao_mpu6000_current; -extern uint8_t ao_mpu6000_valid; - void ao_mpu6000_init(void); diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index 1b55b7fd..ec0d2202 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -19,6 +19,8 @@ #include #include "ao_ms5607.h" +#if HAS_MS5607 + static struct ao_ms5607_prom ms5607_prom; static uint8_t ms5607_configured; @@ -201,22 +203,17 @@ ao_ms5607_convert(struct ao_ms5607_sample *sample, struct ao_ms5607_value *value value->temp = TEMP; } -struct ao_ms5607_sample ao_ms5607_current; -uint8_t ao_ms5607_valid; - static void ao_ms5607(void) { ao_ms5607_setup(); for (;;) { - static struct ao_ms5607_sample ao_ms5607_next; - ao_ms5607_sample(&ao_ms5607_next); + ao_ms5607_sample((struct ao_ms5607_sample *) &ao_data_ring[ao_data_head].ms5607_raw); ao_arch_critical( - ao_ms5607_current = ao_ms5607_next; - ao_ms5607_valid = 1; + AO_DATA_PRESENT(AO_DATA_MS5607); + AO_DATA_WAIT(); ); - ao_delay(0); } } @@ -238,13 +235,13 @@ ao_ms5607_info(void) static void ao_ms5607_dump(void) { - struct ao_ms5607_sample sample; + struct ao_data sample; struct ao_ms5607_value value; - sample = ao_ms5607_current; - ao_ms5607_convert(&sample, &value); - printf ("Pressure: %8u %8d\n", sample.pres, value.pres); - printf ("Temperature: %8u %8d\n", sample.temp, value.temp); + ao_data_get(&sample); + ao_ms5607_convert(&sample.ms5607_raw, &value); + printf ("Pressure: %8u %8d\n", sample.ms5607_raw.pres, value.pres); + printf ("Temperature: %8u %8d\n", sample.ms5607_raw.temp, value.temp); printf ("Altitude: %ld\n", ao_pa_to_altitude(value.pres)); } @@ -257,7 +254,6 @@ void ao_ms5607_init(void) { ms5607_configured = 0; - ao_ms5607_valid = 0; ao_cmd_register(&ao_ms5607_cmds[0]); ao_spi_init_cs(AO_MS5607_CS_GPIO, (1 << AO_MS5607_CS)); @@ -279,3 +275,5 @@ ao_ms5607_init(void) AO_MS5607_MISO, STM_MODER_ALTERNATE); } + +#endif diff --git a/src/drivers/ao_ms5607.h b/src/drivers/ao_ms5607.h index fa3b1c5b..e9c364d9 100644 --- a/src/drivers/ao_ms5607.h +++ b/src/drivers/ao_ms5607.h @@ -51,9 +51,6 @@ struct ao_ms5607_sample { uint32_t temp; /* raw 24 bit sensor */ }; -extern uint8_t ao_ms5607_valid; -extern struct ao_ms5607_sample ao_ms5607_current; - struct ao_ms5607_value { int32_t pres; /* in Pa * 10 */ int32_t temp; /* in °C * 100 */ diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 1dfebca0..a93f6f17 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -56,8 +56,10 @@ ALTOS_SRC = \ ao_cc1120.c \ ao_fec_tx.c \ ao_fec_rx.c \ + ao_data.c \ ao_ms5607.c \ ao_mma655x.c \ + ao_hmc5883.c \ ao_adc_stm.c \ ao_beep_stm.c \ ao_storage.c \ diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 6256d2f6..8b631ae9 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -309,7 +309,7 @@ struct ao_adc { * mma655x */ -#define HAS_MMA655X 1 +#define HAS_MMA655X 0 #define AO_MMA655X_SPI_INDEX AO_SPI_1_PA5_PA6_PA7 #define AO_MMA655X_CS_GPIO (&stm_gpiod) #define AO_MMA655X_CS 4 diff --git a/src/megametrum-v0.1/stlink-pins b/src/megametrum-v0.1/stlink-pins index 71042acc..e6094372 100644 --- a/src/megametrum-v0.1/stlink-pins +++ b/src/megametrum-v0.1/stlink-pins @@ -34,6 +34,14 @@ GND 3 7 JTMS 4 8 NRST 5 2 +TL debug connector: + + TL ST +GND 1 3 +NRST 2 5 +SWDIO 3 4 +SWCLK 4 2 + MegaAccel: Jumpers diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile index 340967fc..09c9c3ca 100644 --- a/src/stm-demo/Makefile +++ b/src/stm-demo/Makefile @@ -32,6 +32,7 @@ ALTOS_SRC = \ ao_dma_stm.c \ ao_spi_stm.c \ ao_adc_stm.c \ + ao_data.c \ ao_i2c_stm.c \ ao_usb_stm.c \ ao_exti_stm.c \ diff --git a/src/stm/ao_adc_stm.c b/src/stm/ao_adc_stm.c index 7564c7fa..18ca6ea0 100644 --- a/src/stm/ao_adc_stm.c +++ b/src/stm/ao_adc_stm.c @@ -17,15 +17,6 @@ #include #include -#if HAS_MPU6000 -#include -#endif -#if HAS_MS5607 -#include -#endif - -volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; -volatile __data uint8_t ao_data_head; static uint8_t ao_adc_ready; @@ -50,27 +41,7 @@ static uint8_t ao_adc_ready; */ static void ao_adc_done(int index) { - uint8_t step = 1; - ao_data_ring[ao_data_head].tick = ao_time(); -#if HAS_MPU6000 - if (!ao_mpu6000_valid) - step = 0; - ao_data_ring[ao_data_head].mpu6000 = ao_mpu6000_current; -#endif -#if HAS_MS5607 - if (!ao_ms5607_valid) - step = 0; - ao_data_ring[ao_data_head].ms5607_raw = ao_ms5607_current; -#endif -#if HAS_HMC5883 - if (!ao_hmc5883_valid) - step = 0; - ao_data_ring[ao_data_head].hmc5883 = ao_hmc5883_current; -#endif - if (step) { - ao_data_head = ao_data_ring_next(ao_data_head); - ao_wakeup((void *) &ao_data_head); - } + AO_DATA_PRESENT(AO_DATA_ADC); ao_dma_done_transfer(STM_DMA_INDEX(STM_DMA_CHANNEL_ADC1)); ao_adc_ready = 1; } @@ -117,17 +88,6 @@ ao_adc_get(__xdata struct ao_adc *packet) memcpy(packet, (void *) &ao_data_ring[i].adc, sizeof (struct ao_adc)); } -void -ao_data_get(__xdata struct ao_data *packet) -{ -#if HAS_FLIGHT - uint8_t i = ao_data_ring_prev(ao_sample_data); -#else - uint8_t i = ao_data_ring_prev(ao_data_head); -#endif - memcpy(packet, (void *) &ao_data_ring[i], sizeof (struct ao_data)); -} - static void ao_adc_dump(void) __reentrant { diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index adec7aad..78228e65 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -37,9 +37,9 @@ ao_delay(uint16_t ticks) ao_sleep(&ao_forever); } -#if HAS_ADC -volatile __data uint8_t ao_adc_interval = 1; -volatile __data uint8_t ao_adc_count; +#if AO_DATA_ALL +volatile __data uint8_t ao_data_interval = 1; +volatile __data uint8_t ao_data_count; #endif void @@ -51,10 +51,13 @@ void stm_tim6_isr(void) if (stm_tim6.sr & (1 << STM_TIM67_SR_UIF)) { stm_tim6.sr = 0; ++ao_tick_count; -#if HAS_ADC - if (++ao_adc_count == ao_adc_interval) { - ao_adc_count = 0; +#if AO_DATA_ALL + if (++ao_data_count == ao_data_interval) { + ao_data_count = 0; ao_adc_poll(); +#if (AO_DATA_ALL & ~(AO_DATA_ADC)) + ao_wakeup((void *) &ao_data_count); +#endif } #endif } @@ -64,8 +67,8 @@ void stm_tim6_isr(void) void ao_timer_set_adc_interval(uint8_t interval) __critical { - ao_adc_interval = interval; - ao_adc_count = 0; + ao_data_interval = interval; + ao_data_count = 0; } #endif -- cgit v1.2.3 From c1168f40223ca09df23215f2e2fc445a8a03aea9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Aug 2012 13:32:41 -0700 Subject: altos: Rename drivers/ao_lco to drivers/ao_lco_cmd These contain command line functions for testing the cmac and lco features. Now that there's a telelco-specific ao_lco interface file, it's useful to have both for testing. Signed-off-by: Keith Packard --- src/drivers/ao_lco.c | 193 ---------------------------------- src/drivers/ao_lco.h | 24 ----- src/drivers/ao_lco_cmd.c | 266 +++++++++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_lco_cmd.h | 24 +++++ 4 files changed, 290 insertions(+), 217 deletions(-) delete mode 100644 src/drivers/ao_lco.c delete mode 100644 src/drivers/ao_lco.h create mode 100644 src/drivers/ao_lco_cmd.c create mode 100644 src/drivers/ao_lco_cmd.h (limited to 'src') diff --git a/src/drivers/ao_lco.c b/src/drivers/ao_lco.c deleted file mode 100644 index f30f3379..00000000 --- a/src/drivers/ao_lco.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include -#include - -static __xdata struct ao_launch_command command; -static __xdata struct ao_launch_query query; -static __pdata uint16_t launch_serial; -static __pdata uint8_t launch_channel; -static __pdata uint16_t tick_offset; - -static void -launch_args(void) __reentrant -{ - ao_cmd_decimal(); - launch_serial = ao_cmd_lex_i; - ao_cmd_decimal(); - launch_channel = ao_cmd_lex_i; -} - -static int8_t -launch_query(void) -{ - uint8_t i; - int8_t r = AO_RADIO_CMAC_OK; - - tick_offset = ao_time(); - for (i = 0; i < 10; i++) { - printf ("."); flush(); - command.tick = ao_time(); - command.serial = launch_serial; - command.cmd = AO_LAUNCH_QUERY; - command.channel = launch_channel; - ao_radio_cmac_send(&command, sizeof (command)); - r = ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500)); - if (r == AO_RADIO_CMAC_OK) - break; - } - tick_offset -= query.tick; - printf("\n"); flush(); - return r; -} - -static void -launch_report_cmd(void) __reentrant -{ - int8_t r; - - launch_args(); - if (ao_cmd_status != ao_cmd_success) - return; - r = launch_query(); - switch (r) { - case AO_RADIO_CMAC_OK: - if (query.valid) { - switch (query.arm_status) { - case ao_igniter_ready: - case ao_igniter_active: - printf ("Armed: "); - break; - default: - printf("Disarmed: "); - } - switch (query.igniter_status) { - default: - printf("unknown\n"); - break; - case ao_igniter_ready: - printf("igniter good\n"); - break; - case ao_igniter_open: - printf("igniter bad\n"); - break; - } - } else { - printf("Invalid channel %d\n", launch_channel); - } - printf("Rssi: %d\n", ao_radio_cmac_rssi); - break; - default: - printf("Error %d\n", r); - break; - } -} - -static void -launch_arm(void) __reentrant -{ - command.tick = ao_time() - tick_offset; - command.serial = launch_serial; - command.cmd = AO_LAUNCH_ARM; - command.channel = launch_channel; - ao_radio_cmac_send(&command, sizeof (command)); -} - -static void -launch_ignite(void) __reentrant -{ - command.tick = ao_time() - tick_offset; - command.serial = launch_serial; - command.cmd = AO_LAUNCH_FIRE; - command.channel = 0; - ao_radio_cmac_send(&command, sizeof (command)); -} - -static void -launch_fire_cmd(void) __reentrant -{ - static __xdata struct ao_launch_command command; - uint8_t secs; - uint8_t i; - int8_t r; - - launch_args(); - ao_cmd_decimal(); - secs = ao_cmd_lex_i; - if (ao_cmd_status != ao_cmd_success) - return; - r = launch_query(); - if (r != AO_RADIO_CMAC_OK) { - printf("query failed %d\n", r); - return; - } - - for (i = 0; i < 4; i++) { - printf("arm %d\n", i); flush(); - launch_arm(); - } - - secs = secs * 10 - 5; - if (secs > 100) - secs = 100; - for (i = 0; i < secs; i++) { - printf("fire %d\n", i); flush(); - launch_ignite(); - ao_delay(AO_MS_TO_TICKS(100)); - } -} - -static void -launch_arm_cmd(void) __reentrant -{ - uint8_t i; - int8_t r; - launch_args(); - r = launch_query(); - if (r != AO_RADIO_CMAC_OK) { - printf("query failed %d\n", r); - return; - } - for (i = 0; i < 4; i++) - launch_arm(); -} - -static void -launch_ignite_cmd(void) __reentrant -{ - uint8_t i; - launch_args(); - for (i = 0; i < 4; i++) - launch_ignite(); -} - -static __code struct ao_cmds ao_lco_cmds[] = { - { radio_cmac_send_cmd, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, - { radio_cmac_recv_cmd, "S \0Receive AES-CMAC packet. Timeout in ms" }, - { launch_report_cmd, "l \0Get remote launch status" }, - { launch_fire_cmd, "f \0Fire remote igniter" }, - { launch_arm_cmd, "a \0Arm remote igniter" }, - { launch_ignite_cmd, "i \0Pulse remote igniter" }, - { 0, NULL }, -}; - -void -ao_lco_init(void) -{ - ao_cmd_register(&ao_lco_cmds[0]); -} diff --git a/src/drivers/ao_lco.h b/src/drivers/ao_lco.h deleted file mode 100644 index 253f9702..00000000 --- a/src/drivers/ao_lco.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright © 2012 Keith Packard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#ifndef _AO_LCO_H_ -#define _AO_LCO_H_ - -void -ao_lco_init(void); - -#endif /* _AO_LCO_H_ */ diff --git a/src/drivers/ao_lco_cmd.c b/src/drivers/ao_lco_cmd.c new file mode 100644 index 00000000..3fe0d9cc --- /dev/null +++ b/src/drivers/ao_lco_cmd.c @@ -0,0 +1,266 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include + +static __xdata struct ao_launch_command command; +static __xdata struct ao_launch_query query; +static __pdata uint16_t launch_serial; +static __pdata uint8_t launch_channel; +static __pdata uint16_t tick_offset; + +static void +launch_args(void) __reentrant +{ + ao_cmd_decimal(); + launch_serial = ao_cmd_lex_i; + ao_cmd_decimal(); + launch_channel = ao_cmd_lex_i; +} + +static int8_t +launch_query(void) +{ + uint8_t i; + int8_t r = AO_RADIO_CMAC_OK; + + tick_offset = ao_time(); + for (i = 0; i < 10; i++) { + printf ("."); flush(); + command.tick = ao_time(); + command.serial = launch_serial; + command.cmd = AO_LAUNCH_QUERY; + command.channel = launch_channel; + ao_radio_cmac_send(&command, sizeof (command)); + r = ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500)); + if (r == AO_RADIO_CMAC_OK) + break; + } + tick_offset -= query.tick; + printf("\n"); flush(); + return r; +} + +static void +launch_report_cmd(void) __reentrant +{ + int8_t r; + + launch_args(); + if (ao_cmd_status != ao_cmd_success) + return; + r = launch_query(); + switch (r) { + case AO_RADIO_CMAC_OK: + if (query.valid) { + switch (query.arm_status) { + case ao_igniter_ready: + case ao_igniter_active: + printf ("Armed: "); + break; + default: + printf("Disarmed: "); + } + switch (query.igniter_status) { + default: + printf("unknown\n"); + break; + case ao_igniter_ready: + printf("igniter good\n"); + break; + case ao_igniter_open: + printf("igniter bad\n"); + break; + } + } else { + printf("Invalid channel %d\n", launch_channel); + } + printf("Rssi: %d\n", ao_radio_cmac_rssi); + break; + default: + printf("Error %d\n", r); + break; + } +} + +static void +launch_arm(void) __reentrant +{ + command.tick = ao_time() - tick_offset; + command.serial = launch_serial; + command.cmd = AO_LAUNCH_ARM; + command.channel = launch_channel; + ao_radio_cmac_send(&command, sizeof (command)); +} + +static void +launch_ignite(void) __reentrant +{ + command.tick = ao_time() - tick_offset; + command.serial = launch_serial; + command.cmd = AO_LAUNCH_FIRE; + command.channel = 0; + ao_radio_cmac_send(&command, sizeof (command)); +} + +static void +launch_fire_cmd(void) __reentrant +{ + static __xdata struct ao_launch_command command; + uint8_t secs; + uint8_t i; + int8_t r; + + launch_args(); + ao_cmd_decimal(); + secs = ao_cmd_lex_i; + if (ao_cmd_status != ao_cmd_success) + return; + r = launch_query(); + if (r != AO_RADIO_CMAC_OK) { + printf("query failed %d\n", r); + return; + } + + for (i = 0; i < 4; i++) { + printf("arm %d\n", i); flush(); + launch_arm(); + } + + secs = secs * 10 - 5; + if (secs > 100) + secs = 100; + for (i = 0; i < secs; i++) { + printf("fire %d\n", i); flush(); + launch_ignite(); + ao_delay(AO_MS_TO_TICKS(100)); + } +} + +static void +launch_arm_cmd(void) __reentrant +{ + uint8_t i; + int8_t r; + launch_args(); + r = launch_query(); + if (r != AO_RADIO_CMAC_OK) { + printf("query failed %d\n", r); + return; + } + for (i = 0; i < 4; i++) + launch_arm(); +} + +static void +launch_ignite_cmd(void) __reentrant +{ + uint8_t i; + launch_args(); + for (i = 0; i < 4; i++) + launch_ignite(); +} + +static uint8_t +getnibble(void) +{ + int8_t b; + + b = ao_cmd_hexchar(getchar()); + if (b < 0) { + ao_cmd_status = ao_cmd_lex_error; + return 0; + } + return (uint8_t) b; +} + +static uint8_t +getbyte(void) +{ + uint8_t b; + b = getnibble() << 4; + b |= getnibble(); + return b; +} + +static __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN]; + +static void +radio_cmac_send_cmd(void) __reentrant +{ + uint8_t i; + uint8_t len; + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + len = ao_cmd_lex_i; + if (len > AO_CMAC_MAX_LEN) { + ao_cmd_status = ao_cmd_syntax_error; + return; + } + flush(); + len = ao_cmd_lex_i; + for (i = 0; i < len; i++) { + cmac_data[i] = getbyte(); + if (ao_cmd_status != ao_cmd_success) + return; + } + ao_radio_cmac_send(cmac_data, len); +} + +static void +radio_cmac_recv_cmd(void) __reentrant +{ + uint8_t len, i; + uint16_t timeout; + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + len = ao_cmd_lex_i; + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + timeout = AO_MS_TO_TICKS(ao_cmd_lex_i); + i = ao_radio_cmac_recv(cmac_data, len, timeout); + if (i == AO_RADIO_CMAC_OK) { + printf ("PACKET "); + for (i = 0; i < len; i++) + printf("%02x", cmac_data[i]); + printf (" %d\n", ao_radio_cmac_rssi); + } else + printf ("ERROR %d %d\n", i, ao_radio_cmac_rssi); +} + +static __code struct ao_cmds ao_lco_cmds[] = { + { radio_cmac_send_cmd, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, + { radio_cmac_recv_cmd, "S \0Receive AES-CMAC packet. Timeout in ms" }, + { launch_report_cmd, "l \0Get remote launch status" }, + { launch_fire_cmd, "f \0Fire remote igniter" }, + { launch_arm_cmd, "a \0Arm remote igniter" }, + { launch_ignite_cmd, "i \0Pulse remote igniter" }, + { 0, NULL }, +}; + +void +ao_lco_cmd_init(void) +{ + ao_cmd_register(&ao_lco_cmds[0]); +} diff --git a/src/drivers/ao_lco_cmd.h b/src/drivers/ao_lco_cmd.h new file mode 100644 index 00000000..c55448cd --- /dev/null +++ b/src/drivers/ao_lco_cmd.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_LCO_CMD_H_ +#define _AO_LCO_CMD_H_ + +void +ao_lco_cmd_init(void); + +#endif /* _AO_LCO_CMD_H_ */ -- cgit v1.2.3 From 304909b7534768bfc8da62954effb37ba86806ea Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Aug 2012 13:34:12 -0700 Subject: altos: Provide interface for STM LCD driver. This provides a simple function interface for driving the LCD segments in the STM chip. It also uses the update complete interrupt to block LCD users during flush. Signed-off-by: Keith Packard --- src/stm/ao_lcd_stm.c | 109 ++++++++++++++++++++++++++++++++++----------------- src/stm/ao_lcd_stm.h | 30 ++++++++++++++ 2 files changed, 102 insertions(+), 37 deletions(-) create mode 100644 src/stm/ao_lcd_stm.h (limited to 'src') diff --git a/src/stm/ao_lcd_stm.c b/src/stm/ao_lcd_stm.c index b1909444..0f9a8eb5 100644 --- a/src/stm/ao_lcd_stm.c +++ b/src/stm/ao_lcd_stm.c @@ -16,6 +16,7 @@ */ #include +#include struct ao_lcd_segment { uint8_t reg; @@ -88,7 +89,7 @@ static inline int ao_lcd_stm_com_enabled(int com) { (1 << 31)) #else -#define AO_LCD_STM_GPIOC_28_C_SEGS 0 +#define AO_LCD_STM_GPIOC_28_SEGS 0 #define AO_LCD_STM_GPIOD_28_SEGS ( \ (1 << 28) | \ @@ -227,6 +228,21 @@ static const struct ao_lcd_segment coms[] = { #define NSEG (sizeof segs/sizeof segs[0]) #define NCOM (sizeof coms/sizeof coms[0]) +static uint8_t ao_lcd_update_active; + +void +stm_lcd_isr(void) +{ + if (stm_lcd.sr & (1 << STM_LCD_SR_UDD)) { + stm_lcd.clr = (1 << STM_LCD_CLR_UDDC); + if (ao_lcd_update_active) { + ao_lcd_update_active = 0; + ao_wakeup(&ao_lcd_update_active); + } + } +} + + static void ao_lcd_stm_fcr_sync(void) { @@ -234,6 +250,45 @@ ao_lcd_stm_fcr_sync(void) asm("nop"); } +void +ao_lcd_flush(void) +{ + cli(); + ao_lcd_update_active = 1; + stm_lcd.sr = (1 << STM_LCD_SR_UDR); + while (ao_lcd_update_active) + ao_sleep(&ao_lcd_update_active); + sei(); +} + +void +ao_lcd_clear(void) +{ + uint8_t i; + + for (i = 0; i < sizeof (stm_lcd.ram) / 4; i++) + stm_lcd.ram[i] = 0; + ao_lcd_flush(); +} + +void +ao_lcd_set(uint8_t digit, uint8_t segment, uint8_t value) +{ + uint8_t n; + + if (digit >= NCOM) + digit = NCOM-1; + if (segment >= NSEG) + segment = NSEG-1; + + n = (segment >> 5) & 1; + if (value) + stm_lcd.ram[digit * 2 + n] |= (1 << (segment & 0x1f)); + else + stm_lcd.ram[digit * 2 + n] &= ~(1 << (segment & 0x1f)); +} + +#if 0 static void ao_lcd_stm_seg_set(void) { @@ -246,34 +301,16 @@ ao_lcd_stm_seg_set(void) ao_cmd_decimal(); val = ao_cmd_lex_i; printf ("com: %d seg: %d val: %d\n", com, seg, val); - n = (seg >> 5) & 1; - if (com >= NCOM) - com = NCOM-1; - if (seg >= NSEG) - seg = NSEG-1; - if (val) - stm_lcd.ram[com * 2 + n] |= (1 << (seg & 0x1f)); - else - stm_lcd.ram[com * 2 + n] &= ~(1 << (seg & 0x1f)); - stm_lcd.sr = (1 << STM_LCD_SR_UDR); + ao_lcd_set(com, seg, val); + ao_lcd_flush(); } -static void -ao_lcd_stm_clear(void) -{ - int i; - - for (i = 0; i < sizeof (stm_lcd.ram) / 4; i++) - stm_lcd.ram[i] = 0; - stm_lcd.sr = (1 << STM_LCD_SR_UDR); -} - - -const struct ao_cmds ao_lcd_stm_cmds[] = { +static const struct ao_cmds ao_lcd_stm_cmds[] = { { ao_lcd_stm_seg_set, "s \0Set LCD segment" }, - { ao_lcd_stm_clear, "C\0Clear LCD" }, + { ao_lcd_clear, "C\0Clear LCD" }, { 0, NULL }, }; +#endif void ao_lcd_stm_init(void) @@ -332,14 +369,14 @@ ao_lcd_stm_init(void) stm_lcd.cr = 0; /* duty cycle 1/3, radio 352, frame rate about 33Hz */ - stm_lcd.fcr = ((STM_LCD_FCR_PS_16 << STM_LCD_FCR_PS) | + stm_lcd.fcr = ((STM_LCD_FCR_PS_8 << STM_LCD_FCR_PS) | (STM_LCD_FCR_DIV_20 << STM_LCD_FCR_DIV) | - (4 << STM_LCD_FCR_CC) | + (7 << STM_LCD_FCR_CC) | (0 << STM_LCD_FCR_DEAD) | - (4 << STM_LCD_FCR_PON) | - (0 << STM_LCD_FCR_UDDIE) | + (1 << STM_LCD_FCR_PON) | + (1 << STM_LCD_FCR_UDDIE) | (0 << STM_LCD_FCR_SOFIE) | - (0 << STM_LCD_FCR_HD)); + (1 << STM_LCD_FCR_HD)); ao_lcd_stm_fcr_sync(); @@ -347,10 +384,10 @@ ao_lcd_stm_init(void) /* Program desired BIAS in LCD_CR */ /* Enable mux seg */ /* Internal voltage source */ - stm_lcd.cr = ((STM_LCD_CR_DUTY_STATIC << STM_LCD_CR_DUTY) | + stm_lcd.cr = ((AO_LCD_DUTY << STM_LCD_CR_DUTY) | (STM_LCD_CR_BIAS_1_2 << STM_LCD_CR_BIAS) | (0 << STM_LCD_CR_VSEL) | - (1 << STM_LCD_CR_MUX_SEG)); + (0 << STM_LCD_CR_MUX_SEG)); ao_lcd_stm_fcr_sync(); @@ -362,12 +399,6 @@ ao_lcd_stm_init(void) /* Load initial data into LCD_RAM and set the * UDR bit in the LCD_SR register */ - for (r = 0; r < NCOM; r++) { - stm_lcd.ram[r*2] = 0; - stm_lcd.ram[r*2 + 1] = 0; - } - - stm_lcd.sr = (1 << STM_LCD_SR_UDR); /* Program desired frame rate (PS and DIV bits in LCD_FCR) */ @@ -376,7 +407,11 @@ ao_lcd_stm_init(void) /* Program optional features (BLINK, BLINKF, PON, DEAD, HD) */ /* Program the required interrupts */ + stm_nvic_set_enable(STM_ISR_LCD_POS); + stm_nvic_set_priority(STM_ISR_LCD_POS, AO_STM_NVIC_LOW_PRIORITY); /* All done */ +#if 0 ao_cmd_register(ao_lcd_stm_cmds); +#endif } diff --git a/src/stm/ao_lcd_stm.h b/src/stm/ao_lcd_stm.h new file mode 100644 index 00000000..14667546 --- /dev/null +++ b/src/stm/ao_lcd_stm.h @@ -0,0 +1,30 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_LCD_STM_H_ +#define _AO_LCD_STM_H_ + +void +ao_lcd_set(uint8_t digit, uint8_t segment, uint8_t value); + +void +ao_lcd_clear(void); + +void +ao_lcd_flush(void); + +#endif /* _AO_LCD_STM_H_ */ -- cgit v1.2.3 From a27b9b5c36cf748e415ba210c8d8ae72d8227a98 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Aug 2012 13:35:39 -0700 Subject: altos: Add SPI slave get/put macros to cc1111 Theese don't try to drive the chip select line Signed-off-by: Keith Packard --- src/cc1111/ao_arch_funcs.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/cc1111/ao_arch_funcs.h b/src/cc1111/ao_arch_funcs.h index 29755b5c..5e2fc13d 100644 --- a/src/cc1111/ao_arch_funcs.h +++ b/src/cc1111/ao_arch_funcs.h @@ -29,6 +29,15 @@ extern __xdata uint8_t ao_spi_mutex; UxGCR_ORDER_MSB | \ ((speed) << UxGCR_BAUD_E_SHIFT))) +#define ao_spi_get_slave(bus) do { \ + ao_mutex_get(&ao_spi_mutex); \ + ao_spi_set_speed(AO_SPI_SPEED_FAST); \ + } while (0) + +#define ao_spi_put_slave(bus) do { \ + ao_mutex_put(&ao_spi_mutex); \ + } while (0) + #define ao_spi_get_mask(reg,mask,bus,speed) do { \ ao_mutex_get(&ao_spi_mutex); \ ao_spi_set_speed(speed); \ -- cgit v1.2.3 From 28c3923b6180e24a77aecc7162bb2852cec7d770 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Aug 2012 13:37:14 -0700 Subject: altos: More SPI slave changes for cc1111 driver Don't enable DMA in the other direction when doing slave transfers. Signed-off-by: Keith Packard --- src/cc1111/ao_spi.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/cc1111/ao_spi.c b/src/cc1111/ao_spi.c index e7480fd7..2b4fd186 100644 --- a/src/cc1111/ao_spi.c +++ b/src/cc1111/ao_spi.c @@ -204,6 +204,7 @@ ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant ao_spi_const = SPI_CONST; +#if !AO_SPI_SLAVE ao_dma_set_transfer(ao_spi_dma_out_id, &ao_spi_const, &SPI_BUF, @@ -214,10 +215,13 @@ ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant DMA_CFG1_SRCINC_0 | DMA_CFG1_DESTINC_0 | DMA_CFG1_PRIORITY_NORMAL); +#endif ao_dma_start(ao_spi_dma_in_id); +#if !AO_SPI_SLAVE ao_dma_start(ao_spi_dma_out_id); ao_dma_trigger(ao_spi_dma_out_id); +#endif __critical while (!ao_spi_dma_in_done) ao_sleep(&ao_spi_dma_in_done); } -- cgit v1.2.3 From 8bfe8157cd9fe488d1ee961f200ffa0866322f2c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Aug 2012 13:38:44 -0700 Subject: altos: Seven segment display driver Hex numbers and the decimal point. Signed-off-by: Keith Packard --- src/drivers/ao_seven_segment.c | 216 +++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_seven_segment.h | 34 +++++++ 2 files changed, 250 insertions(+) create mode 100644 src/drivers/ao_seven_segment.c create mode 100644 src/drivers/ao_seven_segment.h (limited to 'src') diff --git a/src/drivers/ao_seven_segment.c b/src/drivers/ao_seven_segment.c new file mode 100644 index 00000000..1a643eff --- /dev/null +++ b/src/drivers/ao_seven_segment.c @@ -0,0 +1,216 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include + +/* + * 0 + * ------- + * | | + * 1 | | 2 + * | 3 | + * ------- + * | | + * 4 | | 5 + * | 6 | + * ------- + * [] 7 + * + */ + +static const uint8_t ao_segments[] = { + (1 << AO_SEGMENT_0) | + (1 << AO_SEGMENT_1) | + (1 << AO_SEGMENT_2) | + (0 << AO_SEGMENT_3) | + (1 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (1 << AO_SEGMENT_6), /* 0 */ + + (0 << AO_SEGMENT_0) | + (0 << AO_SEGMENT_1) | + (1 << AO_SEGMENT_2) | + (0 << AO_SEGMENT_3) | + (0 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (0 << AO_SEGMENT_6), /* 1 */ + + (1 << AO_SEGMENT_0) | + (0 << AO_SEGMENT_1) | + (1 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (1 << AO_SEGMENT_4) | + (0 << AO_SEGMENT_5) | + (1 << AO_SEGMENT_6), /* 2 */ + + (1 << AO_SEGMENT_0) | + (0 << AO_SEGMENT_1) | + (1 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (0 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (1 << AO_SEGMENT_6), /* 3 */ + + (0 << AO_SEGMENT_0) | + (1 << AO_SEGMENT_1) | + (1 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (0 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (0 << AO_SEGMENT_6), /* 4 */ + + (1 << AO_SEGMENT_0) | + (1 << AO_SEGMENT_1) | + (0 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (0 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (1 << AO_SEGMENT_6), /* 5 */ + + (1 << AO_SEGMENT_0) | + (1 << AO_SEGMENT_1) | + (0 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (1 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (1 << AO_SEGMENT_6), /* 6 */ + + (1 << AO_SEGMENT_0) | + (0 << AO_SEGMENT_1) | + (1 << AO_SEGMENT_2) | + (0 << AO_SEGMENT_3) | + (0 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (0 << AO_SEGMENT_6), /* 7 */ + + (1 << AO_SEGMENT_0) | + (1 << AO_SEGMENT_1) | + (1 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (1 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (1 << AO_SEGMENT_6), /* 8 */ + + (1 << AO_SEGMENT_0) | + (1 << AO_SEGMENT_1) | + (1 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (0 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (1 << AO_SEGMENT_6), /* 9 */ + + (1 << AO_SEGMENT_0) | + (1 << AO_SEGMENT_1) | + (1 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (1 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (0 << AO_SEGMENT_6), /* A */ + + (0 << AO_SEGMENT_0) | + (1 << AO_SEGMENT_1) | + (0 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (1 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (1 << AO_SEGMENT_6), /* b */ + + (1 << AO_SEGMENT_0) | + (1 << AO_SEGMENT_1) | + (0 << AO_SEGMENT_2) | + (0 << AO_SEGMENT_3) | + (1 << AO_SEGMENT_4) | + (0 << AO_SEGMENT_5) | + (1 << AO_SEGMENT_6), /* c */ + + (0 << AO_SEGMENT_0) | + (0 << AO_SEGMENT_1) | + (1 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (1 << AO_SEGMENT_4) | + (1 << AO_SEGMENT_5) | + (1 << AO_SEGMENT_6), /* d */ + + (1 << AO_SEGMENT_0) | + (1 << AO_SEGMENT_1) | + (0 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (1 << AO_SEGMENT_4) | + (0 << AO_SEGMENT_5) | + (1 << AO_SEGMENT_6), /* E */ + + (1 << AO_SEGMENT_0) | + (1 << AO_SEGMENT_1) | + (0 << AO_SEGMENT_2) | + (1 << AO_SEGMENT_3) | + (1 << AO_SEGMENT_4) | + (0 << AO_SEGMENT_5) | + (0 << AO_SEGMENT_6), /* F */ +}; + +void +ao_seven_segment_set(uint8_t digit, uint8_t value) +{ + uint8_t s; + uint8_t segments; + + if (value == AO_SEVEN_SEGMENT_CLEAR) + segments = 0; + else { + segments = ao_segments[value & 0xf]; + + /* Check for decimal point */ + if (value & 0x10) + segments |= (1 << AO_SEGMENT_7); + } + + for (s = 0; s <= 7; s++) + ao_lcd_set(digit, s, !!(segments & (1 << s))); + ao_lcd_flush(); +} + +void +ao_seven_segment_clear(void) +{ + ao_lcd_clear(); +} + + +static void +ao_seven_segment_show(void) +{ + uint8_t digit, value; + ao_cmd_decimal(); + digit = ao_cmd_lex_i; + ao_cmd_decimal(); + value = ao_cmd_lex_i; + ao_seven_segment_set(digit, value); +} + + +static const struct ao_cmds ao_seven_segment_cmds[] = { + { ao_seven_segment_show, "S \0Set LCD digit" }, + { 0, NULL }, +}; + +void +ao_seven_segment_init(void) +{ + ao_cmd_register(ao_seven_segment_cmds); +} diff --git a/src/drivers/ao_seven_segment.h b/src/drivers/ao_seven_segment.h new file mode 100644 index 00000000..5b29deaf --- /dev/null +++ b/src/drivers/ao_seven_segment.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_SEVEN_SEGMENT_H_ +#define _AO_SEVEN_SEGMENT_H_ + +#define AO_SEVEN_SEGMENT_DECIMAL 0x10 + +#define AO_SEVEN_SEGMENT_CLEAR 0xff + +void +ao_seven_segment_set(uint8_t digit, uint8_t value); + +void +ao_seven_segment_clear(void); + +void +ao_seven_segment_init(void); + +#endif /* _AO_SEVEN_SEGMENT_H_ */ -- cgit v1.2.3 From 708d49e498bbdc59bb5af9bf4ca5fcea5689547a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Aug 2012 13:41:13 -0700 Subject: altos: Test multiple quadrature devices. Export quadrature count. Signed-off-by: Keith Packard --- src/drivers/ao_quadrature.c | 28 ++++++---------------------- src/drivers/ao_quadrature.h | 2 ++ 2 files changed, 8 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_quadrature.c b/src/drivers/ao_quadrature.c index 6a2c1bba..6cc2467a 100644 --- a/src/drivers/ao_quadrature.c +++ b/src/drivers/ao_quadrature.c @@ -88,38 +88,22 @@ ao_quadrature_wait(uint8_t q) static void ao_quadrature_test(void) { -#if 1 + uint8_t q; + + ao_cmd_decimal(); + q = ao_cmd_lex_i; for (;;) { int32_t c; flush(); - c = ao_quadrature_wait(0); + c = ao_quadrature_wait(q); printf ("new count %6d\n", c); if (c == 100) break; } -#endif -#if 0 - uint8_t a, old_a, b, old_b; - - old_a = 2; old_b = 2; - for (;;) { - a = ao_gpio_get(AO_QUADRATURE_PORT, AO_QUADRATURE_A, AO_QUADRATURE_A_PIN); - b = ao_gpio_get(AO_QUADRATURE_PORT, AO_QUADRATURE_B, AO_QUADRATURE_B_PIN); - if (a != old_a || b != old_b) { - printf ("A %d B %d count %ld\n", a, b, ao_quadrature_count); - flush(); - ao_yield(); - old_a = a; - old_b = b; - } - if (ao_stdin_ready) - break; - } -#endif } static const struct ao_cmds ao_quadrature_cmds[] = { - { ao_quadrature_test, "q\0Test quadrature" }, + { ao_quadrature_test, "q \0Test quadrature" }, { 0, NULL } }; diff --git a/src/drivers/ao_quadrature.h b/src/drivers/ao_quadrature.h index f0b73b68..d7dda682 100644 --- a/src/drivers/ao_quadrature.h +++ b/src/drivers/ao_quadrature.h @@ -18,6 +18,8 @@ #ifndef _AO_QUADRATURE_H_ #define _AO_QUADRATURE_H_ +extern __xdata int32_t ao_quadrature_count[AO_QUADRATURE_COUNT]; + int32_t ao_quadrature_wait(uint8_t q); -- cgit v1.2.3 From e7443bf350afe273e87a884915ea1e7662630cd3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Aug 2012 13:42:38 -0700 Subject: altos: Specify the LCD duty cycle for stm-demo This is the demo for the large 7-segment displays and needs static drive Signed-off-by: Keith Packard --- src/stm-demo/ao_pins.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h index 77e42a28..c9c7446e 100644 --- a/src/stm-demo/ao_pins.h +++ b/src/stm-demo/ao_pins.h @@ -135,6 +135,8 @@ #define AO_LCD_28_ON_C 1 +#define AO_LCD_DUTY STM_LCD_CR_DUTY_STATIC + #define HAS_ADC 1 #define AO_ADC_RING 32 -- cgit v1.2.3 From 467acda662de8b96e7d0df729c2e4761686b82a1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Aug 2012 13:44:35 -0700 Subject: altos: Expose a signed version of the tick count Useful when doing time comparisons. Signed-off-by: Keith Packard --- src/stm/ao_arch.h | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/stm/ao_arch.h b/src/stm/ao_arch.h index d0dd3c79..87eda18b 100644 --- a/src/stm/ao_arch.h +++ b/src/stm/ao_arch.h @@ -31,6 +31,7 @@ #ifndef AO_TICK_TYPE #define AO_TICK_TYPE uint16_t +#define AO_TICK_SIGNED int16_t #endif /* Various definitions to make GCC look more like SDCC */ -- cgit v1.2.3 From 85fd7ab504a9fac1de90bbe7df8ea477a092c2b0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Aug 2012 13:45:56 -0700 Subject: altos: Build telelco and spiradio when possible Signed-off-by: Keith Packard --- src/Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 99ea8f85..b8828d46 100644 --- a/src/Makefile +++ b/src/Makefile @@ -22,7 +22,8 @@ ifneq ($(shell which sdcc),) telemetrum-v0.1-sky telemetrum-v0.1-sirf \ telelaunch-v0.1 tidongle test \ teleterra-v0.2 teleshield-v0.1 \ - telefire-v0.1 + telefire-v0.1 \ + spiradio-v0.1 endif ifneq ($(shell which avr-gcc),) @@ -30,7 +31,7 @@ ifneq ($(shell which avr-gcc),) endif ifneq ($(shell which arm-none-eabi-gcc),) - SUBDIRS += megametrum-v0.1 stm-bringup stm-demo + SUBDIRS += megametrum-v0.1 stm-bringup stm-demo telelco-v0.1 endif all: all-local all-recursive -- cgit v1.2.3 From 0f3483f93137f41a61f3fcbe06afcaffb1b9e17b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Aug 2012 13:47:16 -0700 Subject: altos: Clean up radio APIs Move api to ao_radio_cmac.h include file. Expose ao_radio_test as standard API. Signed-off-by: Keith Packard --- src/cc1111/ao_launch.c | 3 +- src/cc1111/ao_radio.c | 69 +++++++++++++++++++++++---------------- src/core/ao.h | 6 ++-- src/core/ao_aes.h | 17 ---------- src/core/ao_radio_cmac.c | 84 +++--------------------------------------------- src/core/ao_radio_cmac.h | 43 +++++++++++++++++++++++++ src/drivers/ao_cc1120.c | 4 +-- src/drivers/ao_pad.c | 1 + 8 files changed, 97 insertions(+), 130 deletions(-) create mode 100644 src/core/ao_radio_cmac.h (limited to 'src') diff --git a/src/cc1111/ao_launch.c b/src/cc1111/ao_launch.c index a593d0b2..420f7568 100644 --- a/src/cc1111/ao_launch.c +++ b/src/cc1111/ao_launch.c @@ -15,7 +15,8 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" +#include +#include __xdata uint16_t ao_launch_ignite; diff --git a/src/cc1111/ao_radio.c b/src/cc1111/ao_radio.c index 46b2362d..cb2c2fdd 100644 --- a/src/cc1111/ao_radio.c +++ b/src/cc1111/ao_radio.c @@ -470,8 +470,44 @@ ao_radio_rdf_abort(void) /* Output carrier */ + +static __xdata ao_radio_test_on; + void -ao_radio_test(void) +ao_radio_test(uint8_t on) +{ + if (on) { + if (!ao_radio_test_on) { +#if HAS_MONITOR + ao_monitor_disable(); +#endif +#if PACKET_HAS_SLAVE + ao_packet_slave_stop(); +#endif +#if HAS_PAD + ao_pad_disable(); +#endif + ao_radio_get(0xff); + RFST = RFST_STX; + ao_radio_test_on = 1; + } + } else { + if (ao_radio_test_on) { + ao_radio_idle(); + ao_radio_put(); + ao_radio_test_on = 0; +#if HAS_MONITOR + ao_monitor_enable(); +#endif +#if HAS_PAD + ao_pad_enable(); +#endif + } + } +} + +static void +ao_radio_test_cmd(void) { uint8_t mode = 2; static __xdata radio_on; @@ -481,40 +517,19 @@ ao_radio_test(void) mode = (uint8_t) ao_cmd_lex_u32; } mode++; - if ((mode & 2) && !radio_on) { -#if HAS_MONITOR - ao_monitor_disable(); -#endif -#if PACKET_HAS_SLAVE - ao_packet_slave_stop(); -#endif -#if HAS_PAD - ao_pad_disable(); -#endif - ao_radio_get(0xff); - RFST = RFST_STX; - radio_on = 1; - } + if ((mode & 2)) + ao_radio_test(1); if (mode == 3) { printf ("Hit a character to stop..."); flush(); getchar(); putchar('\n'); } - if ((mode & 1) && radio_on) { - ao_radio_idle(); - ao_radio_put(); - radio_on = 0; -#if HAS_MONITOR - ao_monitor_enable(); -#endif -#if HAS_PAD - ao_pad_enable(); -#endif - } + if ((mode & 1)) + ao_radio_test(0); } __code struct ao_cmds ao_radio_cmds[] = { - { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" }, + { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" }, { 0, NULL }, }; diff --git a/src/core/ao.h b/src/core/ao.h index 5e1fbb9d..b8bedd85 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -543,9 +543,6 @@ ao_telemetry_tiny_init(void); */ extern __xdata uint8_t ao_radio_dma; -extern __xdata uint8_t ao_radio_dma_done; -extern __xdata uint8_t ao_radio_done; -extern __xdata uint8_t ao_radio_mutex; #ifdef PKT_APPEND_STATUS_1_CRC_OK #define AO_RADIO_STATUS_CRC_OK PKT_APPEND_STATUS_1_CRC_OK @@ -566,6 +563,9 @@ ao_radio_recv(__xdata void *d, uint8_t size) __reentrant; void ao_radio_recv_abort(void); +void +ao_radio_test(uint8_t on); + /* * Compute the packet length as follows: * diff --git a/src/core/ao_aes.h b/src/core/ao_aes.h index ab3e367e..c47bc2db 100644 --- a/src/core/ao_aes.h +++ b/src/core/ao_aes.h @@ -51,21 +51,4 @@ ao_aes_run(__xdata uint8_t *in, void ao_aes_init(void); -/* ao_radio_cmac.c */ - -int8_t -ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant; - -#define AO_RADIO_CMAC_OK 0 -#define AO_RADIO_CMAC_LEN_ERROR -1 -#define AO_RADIO_CMAC_CRC_ERROR -2 -#define AO_RADIO_CMAC_MAC_ERROR -3 -#define AO_RADIO_CMAC_TIMEOUT -4 - -int8_t -ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant; - -void -ao_radio_cmac_init(void); - #endif /* _AO_AES_H_ */ diff --git a/src/core/ao_radio_cmac.c b/src/core/ao_radio_cmac.c index 3e8dce53..fc0ca8b1 100644 --- a/src/core/ao_radio_cmac.c +++ b/src/core/ao_radio_cmac.c @@ -15,38 +15,14 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -#include "ao.h" - -#define AO_CMAC_KEY_LEN AO_AES_LEN -#define AO_CMAC_MAX_LEN (128 - AO_CMAC_KEY_LEN) +#include +#include static __xdata uint8_t ao_radio_cmac_mutex; -__pdata int16_t ao_radio_cmac_rssi; +__pdata int8_t ao_radio_cmac_rssi; static __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN + AO_CMAC_KEY_LEN + 2 + AO_CMAC_KEY_LEN]; static __pdata uint8_t ao_radio_cmac_len; -static uint8_t -getnibble(void) -{ - int8_t b; - - b = ao_cmd_hexchar(getchar()); - if (b < 0) { - ao_cmd_status = ao_cmd_lex_error; - return 0; - } - return (uint8_t) b; -} - -static uint8_t -getbyte(void) -{ - uint8_t b; - b = getnibble() << 4; - b |= getnibble(); - return b; -} - static uint8_t round_len(uint8_t len) { @@ -120,7 +96,7 @@ radio_cmac_recv(uint8_t len, uint16_t timeout) __reentrant return AO_RADIO_CMAC_TIMEOUT; } - ao_radio_cmac_rssi = (int16_t) (((int8_t) cmac_data[len + AO_CMAC_KEY_LEN]) >> 1) - 74; + ao_radio_cmac_rssi = (int8_t) (((int8_t) cmac_data[len + AO_CMAC_KEY_LEN]) >> 1) - 74; if (!(cmac_data[len + AO_CMAC_KEY_LEN +1] & AO_RADIO_STATUS_CRC_OK)) return AO_RADIO_CMAC_CRC_ERROR; @@ -191,55 +167,3 @@ ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentr return i; } -static void -radio_cmac_send_cmd(void) __reentrant -{ - uint8_t i; - uint8_t len; - - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - len = ao_cmd_lex_i; - if (len > AO_CMAC_MAX_LEN) { - ao_cmd_status = ao_cmd_syntax_error; - return; - } - flush(); - ao_mutex_get(&ao_radio_cmac_mutex); - len = ao_cmd_lex_i; - for (i = 0; i < len; i++) { - cmac_data[i] = getbyte(); - if (ao_cmd_status != ao_cmd_success) - return; - } - radio_cmac_send(len); - ao_mutex_put(&ao_radio_cmac_mutex); -} - -static void -radio_cmac_recv_cmd(void) __reentrant -{ - uint8_t len, i; - uint16_t timeout; - - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - len = ao_cmd_lex_i; - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - timeout = AO_MS_TO_TICKS(ao_cmd_lex_i); - ao_mutex_get(&ao_radio_cmac_mutex); - i = radio_cmac_recv(len, timeout); - if (i == AO_RADIO_CMAC_OK) { - printf ("PACKET "); - for (i = 0; i < len; i++) - printf("%02x", cmac_data[i]); - printf (" %d\n", ao_radio_cmac_rssi); - } else - printf ("ERROR %d %d\n", i, ao_radio_cmac_rssi); - ao_mutex_put(&ao_radio_cmac_mutex); -} - diff --git a/src/core/ao_radio_cmac.h b/src/core/ao_radio_cmac.h new file mode 100644 index 00000000..e86f31e9 --- /dev/null +++ b/src/core/ao_radio_cmac.h @@ -0,0 +1,43 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_RADIO_CMAC_H_ +#define _AO_RADIO_CMAC_H_ + +#include + +#define AO_CMAC_KEY_LEN AO_AES_LEN +#define AO_CMAC_MAX_LEN (128 - AO_CMAC_KEY_LEN) + +extern __pdata int8_t ao_radio_cmac_rssi; + +int8_t +ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant; + +#define AO_RADIO_CMAC_OK 0 +#define AO_RADIO_CMAC_LEN_ERROR -1 +#define AO_RADIO_CMAC_CRC_ERROR -2 +#define AO_RADIO_CMAC_MAC_ERROR -3 +#define AO_RADIO_CMAC_TIMEOUT -4 + +int8_t +ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant; + +void +ao_radio_cmac_init(void); + +#endif /* _AO_RADIO_CMAC_H_ */ diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 97a434d8..4df931b5 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -515,7 +515,7 @@ ao_radio_rdf_abort(void) } static void -ao_radio_test(void) +ao_radio_test_cmd(void) { uint8_t mode = 2; uint8_t radio_on; @@ -1008,7 +1008,7 @@ ao_radio_test_recv() #endif static const struct ao_cmds ao_radio_cmds[] = { - { ao_radio_test, "C <1 start, 0 stop, none both>\0Radio carrier test" }, + { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" }, #if CC1120_DEBUG { ao_radio_show, "R\0Show CC1120 status" }, { ao_radio_beep, "b\0Emit an RDF beacon" }, diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index 791c9a47..b33a5ffd 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -18,6 +18,7 @@ #include #include #include +#include static __xdata uint8_t ao_pad_ignite; static __xdata struct ao_pad_command command; -- cgit v1.2.3 From c31d07fb35a5b4d283facf649bed3f0f9802d1fc Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Aug 2012 13:49:07 -0700 Subject: altos: Add SPI linked radio API Forward the necessary radio functions over the SPI link Signed-off-by: Keith Packard --- src/drivers/ao_radio_master.c | 266 ++++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_radio_slave.c | 127 ++++++++++++++++++++ src/drivers/ao_radio_spi.h | 58 +++++++++ 3 files changed, 451 insertions(+) create mode 100644 src/drivers/ao_radio_master.c create mode 100644 src/drivers/ao_radio_slave.c create mode 100644 src/drivers/ao_radio_spi.h (limited to 'src') diff --git a/src/drivers/ao_radio_master.c b/src/drivers/ao_radio_master.c new file mode 100644 index 00000000..6edea66d --- /dev/null +++ b/src/drivers/ao_radio_master.c @@ -0,0 +1,266 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include + +static __xdata struct ao_radio_spi_reply ao_radio_spi_reply; +static __xdata struct ao_radio_spi_request ao_radio_spi_request; +static __xdata uint8_t ao_radio_done; +static __xdata uint8_t ao_radio_mutex; + +__xdata int8_t ao_radio_cmac_rssi; + +static void +ao_radio_isr(void) +{ + ao_exti_disable(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN); + ao_radio_done = 1; + ao_wakeup(&ao_radio_done); +} + +static void +ao_radio_master_start(void) +{ + ao_spi_get_bit(AO_RADIO_CS_PORT, AO_RADIO_CS_PIN, AO_RADIO_CS, + AO_RADIO_SPI_BUS, + AO_SPI_SPEED_1MHz); +} + +static void +ao_radio_master_stop(void) +{ + ao_spi_put_bit(AO_RADIO_CS_PORT, AO_RADIO_CS_PIN, AO_RADIO_CS, + AO_RADIO_SPI_BUS); +} + + +static uint8_t +ao_radio_master_send(void) +{ + ao_radio_done = 0; + ao_exti_enable(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN); + ao_radio_master_start(); + ao_spi_send(&ao_radio_spi_request, + ao_radio_spi_request.len, + AO_RADIO_SPI_BUS); + ao_radio_master_stop(); + cli(); + while (!ao_radio_done) + if (ao_sleep(&ao_radio_done)) + break; + sei(); + return ao_radio_done; +} + +static void +ao_radio_master_recv(uint16_t len) +{ + ao_radio_master_start(); + ao_spi_recv(&ao_radio_spi_reply, + len, + AO_RADIO_SPI_BUS); + ao_radio_master_stop(); +} + +static void +ao_radio_get(uint8_t req, uint8_t len) +{ + ao_config_get(); + ao_mutex_get(&ao_radio_mutex); + ao_radio_spi_request.len = AO_RADIO_SPI_REQUEST_HEADER_LEN + len; + ao_radio_spi_request.request = req; + ao_radio_spi_request.setting = ao_config.radio_setting; +} + +static void +ao_radio_put(void) +{ + ao_mutex_put(&ao_radio_mutex); +} + +static void +ao_radio_get_data(__xdata void *d, uint8_t size) +{ + ao_radio_master_start(); + ao_spi_recv(&ao_radio_spi_reply, + AO_RADIO_SPI_REPLY_HEADER_LEN + size, + AO_RADIO_SPI_BUS); + ao_radio_master_stop(); + ao_xmemcpy(d, ao_radio_spi_reply.payload, size); +} + +void +ao_radio_recv_abort(void) +{ + ao_radio_get(AO_RADIO_SPI_RECV_ABORT, 0); + ao_radio_master_send(); + ao_radio_put(); +} + +void +ao_radio_send(const void *d, uint8_t size) +{ + ao_radio_get(AO_RADIO_SPI_SEND, size); + ao_xmemcpy(&ao_radio_spi_request.payload, d, size); + ao_radio_master_send(); + ao_radio_put(); +} + + +uint8_t +ao_radio_recv(__xdata void *d, uint8_t size) +{ + int8_t ret; + uint8_t recv; + + /* Recv the data + */ + + ao_radio_get(AO_RADIO_SPI_RECV, 0); + ao_radio_spi_request.recv_len = size; + recv = ao_radio_master_send(); + if (!recv) { + ao_radio_put(); + ao_radio_recv_abort(); + return 0; + } + ao_radio_get_data(d, size); + recv = ao_radio_spi_reply.status; + ao_radio_put(); + return recv; +} + +int8_t +ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant +{ + if (len > AO_CMAC_MAX_LEN) + return AO_RADIO_CMAC_LEN_ERROR; + + /* Set the key. + */ + ao_radio_get(AO_RADIO_SPI_CMAC_KEY, AO_AES_LEN); + ao_xmemcpy(&ao_radio_spi_request.payload, &ao_config.aes_key, AO_AES_LEN); + ao_radio_master_send(); + ao_radio_put(); + + /* Send the data + */ + + ao_radio_get(AO_RADIO_SPI_CMAC_SEND, len); + ao_xmemcpy(&ao_radio_spi_request.payload, packet, len); + ao_radio_master_send(); + ao_radio_put(); + return AO_RADIO_CMAC_OK; +} + +int8_t +ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant +{ + int8_t ret; + uint8_t recv; + + if (len > AO_CMAC_MAX_LEN) + return AO_RADIO_CMAC_LEN_ERROR; + + /* Set the key. + */ + ao_radio_get(AO_RADIO_SPI_CMAC_KEY, AO_AES_LEN); + ao_radio_spi_request.timeout = timeout; + ao_xmemcpy(&ao_radio_spi_request.payload, &ao_config.aes_key, AO_AES_LEN); + ao_radio_master_send(); + ao_radio_put(); + + /* Recv the data + */ + + ao_radio_get(AO_RADIO_SPI_CMAC_RECV, 0); + ao_radio_spi_request.recv_len = len; + recv = ao_radio_master_send(); + if (!recv) { + ao_radio_put(); + ao_radio_recv_abort(); + return AO_RADIO_CMAC_TIMEOUT; + } + ao_radio_get_data(packet, len); + recv = ao_radio_spi_reply.status; + ao_radio_put(); + return recv; +} + +static uint8_t ao_radio_test_on; + +void +ao_radio_test(uint8_t on) +{ + if (on) { + if (!ao_radio_test_on) { + ao_radio_get(AO_RADIO_SPI_TEST_ON, 0); + ao_radio_test_on = 1; + ao_radio_master_send(); + } + } else { + if (ao_radio_test_on) { + ao_radio_spi_request.len = AO_RADIO_SPI_REQUEST_HEADER_LEN; + ao_radio_spi_request.request = AO_RADIO_SPI_TEST_OFF; + ao_radio_master_send(); + ao_radio_test_on = 0; + ao_radio_put(); + } + } +} + +static void +ao_radio_test_cmd(void) +{ + uint8_t mode = 2; + ao_cmd_white(); + if (ao_cmd_lex_c != '\n') { + ao_cmd_decimal(); + mode = (uint8_t) ao_cmd_lex_u32; + } + mode++; + if ((mode & 2)) + ao_radio_test(1); + if (mode == 3) { + printf ("Hit a character to stop..."); flush(); + getchar(); + putchar('\n'); + } + if ((mode & 1)) + ao_radio_test(0); +} + +__code struct ao_cmds ao_radio_cmds[] = { + { ao_radio_test_cmd, "C <1 start, 0 stop, none both>\0Radio carrier test" }, + { 0, NULL }, +}; + +void +ao_radio_init(void) +{ + ao_spi_init_cs(AO_RADIO_CS_PORT, (1 << AO_RADIO_CS_PIN)); + + ao_enable_port(AO_RADIO_INT_PORT); + ao_exti_setup(AO_RADIO_INT_PORT, + AO_RADIO_INT_PIN, + AO_EXTI_MODE_FALLING, + ao_radio_isr); + ao_cmd_register(&ao_radio_cmds[0]); +} diff --git a/src/drivers/ao_radio_slave.c b/src/drivers/ao_radio_slave.c new file mode 100644 index 00000000..9dff511b --- /dev/null +++ b/src/drivers/ao_radio_slave.c @@ -0,0 +1,127 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include + +static __xdata struct ao_radio_spi_reply ao_radio_spi_reply; + +static __xdata struct ao_radio_spi_request ao_radio_spi_request; + +static __xdata uint8_t ao_radio_spi_recv_request; +static __xdata uint8_t ao_radio_spi_recv_len; +static __xdata uint16_t ao_radio_spi_recv_timeout; + +static void +ao_radio_slave_signal(void) +{ + ao_gpio_set(AO_RADIO_SLAVE_INT_PORT, AO_RADIO_SLAVE_INT_BIT, AO_RADIO_SLAVE_INT_PIN, 0); + ao_arch_nop(); + ao_arch_nop(); + ao_arch_nop(); + ao_gpio_set(AO_RADIO_SLAVE_INT_PORT, AO_RADIO_SLAVE_INT_BIT, AO_RADIO_SLAVE_INT_PIN, 0); +} + +static void +ao_radio_slave_spi(void) +{ + for (;;) { + ao_spi_get_slave(AO_RADIO_SLAVE_BUS); + ao_spi_recv(&ao_radio_spi_request, (2 << 13) | sizeof (ao_radio_spi_request), AO_RADIO_SLAVE_BUS); + ao_spi_put_slave(AO_RADIO_SLAVE_BUS); + ao_led_for(AO_LED_RED, AO_MS_TO_TICKS(1000)); + switch (ao_radio_spi_request.request) { + case AO_RADIO_SPI_RECV: + case AO_RADIO_SPI_CMAC_RECV: + ao_config.radio_setting = ao_radio_spi_request.setting; + ao_radio_spi_recv_request = ao_radio_spi_request.request; + ao_radio_spi_recv_len = ao_radio_spi_request.recv_len; + ao_radio_spi_recv_timeout = ao_radio_spi_request.timeout; + ao_wakeup(&ao_radio_spi_recv_len); + break; + case AO_RADIO_SPI_RECV_FETCH: + ao_spi_get_slave(AO_RADIO_SLAVE_BUS); + ao_spi_send(&ao_radio_spi_reply, + ao_radio_spi_request.recv_len + AO_RADIO_SPI_REPLY_HEADER_LEN, + AO_RADIO_SLAVE_BUS); + ao_spi_put_slave(AO_RADIO_SLAVE_BUS); + break; + case AO_RADIO_SPI_RECV_ABORT: + ao_radio_recv_abort(); + break; + case AO_RADIO_SPI_SEND: + ao_config.radio_setting = ao_radio_spi_request.setting; + ao_radio_send(&ao_radio_spi_request.payload, ao_radio_spi_request.len - AO_RADIO_SPI_REQUEST_HEADER_LEN); + ao_radio_slave_signal(); + break; + + case AO_RADIO_SPI_CMAC_SEND: + ao_config.radio_setting = ao_radio_spi_request.setting; + ao_radio_cmac_send(&ao_radio_spi_request.payload, ao_radio_spi_request.len - AO_RADIO_SPI_REQUEST_HEADER_LEN); + ao_radio_slave_signal(); + break; + + case AO_RADIO_SPI_CMAC_KEY: + ao_xmemcpy(&ao_config.aes_key, ao_radio_spi_request.payload, AO_AES_LEN); + ao_radio_slave_signal(); + break; + + case AO_RADIO_SPI_TEST_ON: + ao_radio_test(1); + ao_radio_slave_signal(); + break; + + case AO_RADIO_SPI_TEST_OFF: + ao_radio_test(0); + ao_radio_slave_signal(); + break; + } + } +} + +static void +ao_radio_slave_recv(void) +{ + uint8_t len; + for (;;) { + while (!ao_radio_spi_recv_len) + ao_sleep(&ao_radio_spi_recv_len); + len = ao_radio_spi_recv_len; + ao_radio_spi_recv_len = 0; + if (ao_radio_spi_recv_request == AO_RADIO_SPI_RECV) { + ao_radio_spi_reply.status = ao_radio_recv(&ao_radio_spi_reply.payload, len); + ao_radio_spi_reply.rssi = 0; + } else { + ao_radio_spi_reply.status = ao_radio_cmac_recv(&ao_radio_spi_reply.payload, len, + ao_radio_spi_recv_timeout); + ao_radio_spi_reply.rssi = ao_radio_cmac_rssi; + } + ao_radio_slave_signal(); + } +} + +static __xdata struct ao_task ao_radio_slave_spi_task; +static __xdata struct ao_task ao_radio_slave_recv_task; + +void +ao_radio_slave_init(void) +{ + ao_add_task(&ao_radio_slave_spi_task, ao_radio_slave_spi, "radio_spi"); + ao_add_task(&ao_radio_slave_recv_task, ao_radio_slave_recv, "radio_recv"); + ao_enable_output(AO_RADIO_SLAVE_INT_PORT, AO_RADIO_SLAVE_INT_BIT, AO_RADIO_SLAVE_INT_PIN, 1); +} diff --git a/src/drivers/ao_radio_spi.h b/src/drivers/ao_radio_spi.h new file mode 100644 index 00000000..2957f70d --- /dev/null +++ b/src/drivers/ao_radio_spi.h @@ -0,0 +1,58 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_RADIO_SPI_H_ +#define _AO_RADIO_SPI_H_ + +#define AO_RADIO_SPI_RECV 0 +#define AO_RADIO_SPI_RECV_ABORT 1 +#define AO_RADIO_SPI_RECV_FETCH 2 +#define AO_RADIO_SPI_SEND 3 + +#define AO_RADIO_SPI_CMAC_KEY 4 +#define AO_RADIO_SPI_CMAC_RECV 5 +#define AO_RADIO_SPI_CMAC_SEND 6 + +#define AO_RADIO_SPI_TEST_ON 7 +#define AO_RADIO_SPI_TEST_OFF 8 + +#define AO_RADIO_SPI_MAX_PAYLOAD 128 + +struct ao_radio_spi_request { + uint8_t len; /* required to be first by cc1111 DMA engine */ + uint8_t request; + uint8_t recv_len; + uint8_t pad; + uint32_t setting; + uint16_t timeout; + uint8_t payload[AO_RADIO_SPI_MAX_PAYLOAD]; +}; + +#define AO_RADIO_SPI_REQUEST_HEADER_LEN (sizeof (struct ao_radio_spi_request) - AO_RADIO_SPI_MAX_PAYLOAD) + +struct ao_radio_spi_reply { + uint8_t status; + int8_t rssi; + uint8_t payload[AO_RADIO_SPI_MAX_PAYLOAD]; +}; + +#define AO_RADIO_SPI_REPLY_HEADER_LEN (sizeof (struct ao_radio_spi_reply) - AO_RADIO_SPI_MAX_PAYLOAD) + +void +ao_radio_slave_init(void); + +#endif /* _AO_RADIO_SPI_H_ */ -- cgit v1.2.3 From 61d094f281431e9f11f806454981da8e1245fb5c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Aug 2012 13:51:53 -0700 Subject: altos: sdcdb rc file for telefire Signed-off-by: Keith Packard --- src/telefire-v0.1/.sdcdbrc | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/telefire-v0.1/.sdcdbrc (limited to 'src') diff --git a/src/telefire-v0.1/.sdcdbrc b/src/telefire-v0.1/.sdcdbrc new file mode 100644 index 00000000..b9f6129c --- /dev/null +++ b/src/telefire-v0.1/.sdcdbrc @@ -0,0 +1,2 @@ +--directory=../cc1111:../product:../core:../drivers:. + -- cgit v1.2.3 From 621d0930244f25165d2ac5da596dcc87e253b965 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Aug 2012 13:52:11 -0700 Subject: altos: Add spiradio product Implements the SPI radio protocol Signed-off-by: Keith Packard --- src/spiradio-v0.1/.sdcdbrc | 2 ++ src/spiradio-v0.1/ao_pins.h | 61 +++++++++++++++++++++++++++++++++++++++++ src/spiradio-v0.1/ao_spiradio.c | 37 +++++++++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 src/spiradio-v0.1/.sdcdbrc create mode 100644 src/spiradio-v0.1/ao_pins.h create mode 100644 src/spiradio-v0.1/ao_spiradio.c (limited to 'src') diff --git a/src/spiradio-v0.1/.sdcdbrc b/src/spiradio-v0.1/.sdcdbrc new file mode 100644 index 00000000..b9f6129c --- /dev/null +++ b/src/spiradio-v0.1/.sdcdbrc @@ -0,0 +1,2 @@ +--directory=../cc1111:../product:../core:../drivers:. + diff --git a/src/spiradio-v0.1/ao_pins.h b/src/spiradio-v0.1/ao_pins.h new file mode 100644 index 00000000..363eafa4 --- /dev/null +++ b/src/spiradio-v0.1/ao_pins.h @@ -0,0 +1,61 @@ +/* + * Copyright © 2010 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +#define HAS_RADIO 1 + +#define HAS_FLIGHT 0 +#define HAS_USB 0 +#define HAS_BEEP 0 +#define HAS_GPS 0 +#define HAS_SERIAL_0 1 +#define HAS_SERIAL_0_ALT_1 1 +#define HAS_SERIAL_0_HW_FLOW 0 +#define USE_SERIAL_0_STDIN 1 +#define DELAY_SERIAL_0_STDIN 0 +#define HAS_SERIAL_1 0 +#define HAS_ADC 0 +#define HAS_DBG 0 +#define HAS_EEPROM 0 +#define HAS_LOG 0 +#define USE_INTERNAL_FLASH 0 +#define DBG_ON_P1 0 +#define PACKET_HAS_MASTER 0 +#define PACKET_HAS_SLAVE 0 +#define AO_LED_RED 2 +#define AO_LED_GREEN 1 +#define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) +#define HAS_EXTERNAL_TEMP 0 +#define HAS_ACCEL_REF 0 +#define SPI_CS_ON_P1 1 +#define HAS_AES 1 + +#define SPI_CS_PORT P1 +#define SPI_CS_SEL P1SEL +#define SPI_CS_DIR P1DIR +#define AO_SPI_SLAVE 1 +#define HAS_SPI_0 1 +#define SPI_0_ALT_2 1 +#define HAS_SPI_1 0 + +#define AO_RADIO_SLAVE_INT_PORT P1 +#define AO_RADIO_SLAVE_INT_BIT 6 +#define AO_RADIO_SLAVE_INT_PIN P1_6 + +#endif /* _AO_PINS_H_ */ diff --git a/src/spiradio-v0.1/ao_spiradio.c b/src/spiradio-v0.1/ao_spiradio.c new file mode 100644 index 00000000..d3647cc7 --- /dev/null +++ b/src/spiradio-v0.1/ao_spiradio.c @@ -0,0 +1,37 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +void +main(void) +{ + ao_clock_init(); + + ao_led_init(LEDS_AVAILABLE); + + ao_serial_init(); + ao_timer_init(); + ao_cmd_init(); + ao_spi_init(); + ao_radio_init(); + ao_aes_init(); + ao_config_init(); + ao_radio_slave_init(); + ao_start_scheduler(); +} -- cgit v1.2.3 From c677f26852b70bcbb303382c306ce06664fde028 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Aug 2012 22:45:20 -0700 Subject: altos: No need to initialize EXTI priorities at startup time They all get set to the correct value when enabled. Signed-off-by: Keith Packard --- src/stm/ao_exti_stm.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'src') diff --git a/src/stm/ao_exti_stm.c b/src/stm/ao_exti_stm.c index 11099b02..1361d0d4 100644 --- a/src/stm/ao_exti_stm.c +++ b/src/stm/ao_exti_stm.c @@ -151,10 +151,4 @@ ao_exti_disable(struct stm_gpio *gpio, uint8_t pin) { void ao_exti_init(void) { - stm_nvic_set_priority(STM_ISR_EXTI1_POS, AO_STM_NVIC_MED_PRIORITY); - stm_nvic_set_priority(STM_ISR_EXTI2_POS, AO_STM_NVIC_MED_PRIORITY); - stm_nvic_set_priority(STM_ISR_EXTI3_POS, AO_STM_NVIC_MED_PRIORITY); - stm_nvic_set_priority(STM_ISR_EXTI4_POS, AO_STM_NVIC_MED_PRIORITY); - stm_nvic_set_priority(STM_ISR_EXTI9_5_POS, AO_STM_NVIC_MED_PRIORITY); - stm_nvic_set_priority(STM_ISR_EXTI15_10_POS, AO_STM_NVIC_MED_PRIORITY); } -- cgit v1.2.3 From 68df2b1173e82d48f7857ad2e9325e6a9cbbedfd Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 27 Aug 2012 22:45:47 -0700 Subject: altos: Enable STM SYSCFG when routing EXTI The EXTI routing information is in the syscfg unit, so that needs to be powered up or writes to its registers will be lost. Signed-off-by: Keith Packard --- src/stm/stm32l.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/stm/stm32l.h b/src/stm/stm32l.h index 3a498a0a..25f5af07 100644 --- a/src/stm/stm32l.h +++ b/src/stm/stm32l.h @@ -905,6 +905,9 @@ stm_exticr_set(struct stm_gpio *gpio, int pin) { uint8_t shift = (pin & 3) << 2; uint8_t val = 0; + /* Enable SYSCFG */ + stm_rcc.apb2enr |= (1 << STM_RCC_APB2ENR_SYSCFGEN); + if (gpio == &stm_gpioa) val = STM_SYSCFG_EXTICR_PA; else if (gpio == &stm_gpiob) -- cgit v1.2.3 From 31b42b99edbb976534ac432c07e218f13d1f5f9b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Aug 2012 18:03:52 -0700 Subject: altos: Fix ao_delay function and move from per-chip code to ao_task.c ao_delay hasn't been chip-specific for a long time, and it had a bug in not calling ao_clear_alarm. Signed-off-by: Keith Packard --- src/avr/ao_timer.c | 9 --------- src/cc1111/ao_timer.c | 10 ---------- src/core/ao_task.c | 11 +++++++++++ src/stm/ao_timer.c | 9 --------- 4 files changed, 11 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/avr/ao_timer.c b/src/avr/ao_timer.c index cd81b163..d2ea2be7 100644 --- a/src/avr/ao_timer.c +++ b/src/avr/ao_timer.c @@ -28,15 +28,6 @@ uint16_t ao_time(void) return v; } -static __xdata uint8_t ao_forever; - -void -ao_delay(uint16_t ticks) -{ - ao_alarm(ticks); - ao_sleep(&ao_forever); -} - #define T1_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ #define T1_SAMPLE_TIME 30000 /* 3e6/30000 = 100 */ diff --git a/src/cc1111/ao_timer.c b/src/cc1111/ao_timer.c index 602f98c8..a64b5aba 100644 --- a/src/cc1111/ao_timer.c +++ b/src/cc1111/ao_timer.c @@ -24,16 +24,6 @@ uint16_t ao_time(void) __critical return ao_tick_count; } -static __xdata uint8_t ao_forever; - -void -ao_delay(uint16_t ticks) -{ - ao_alarm(ticks); - ao_sleep(&ao_forever); - ao_clear_alarm(); -} - #define T1_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ #define T1_SAMPLE_TIME 30000 /* 3e6/30000 = 100 */ diff --git a/src/core/ao_task.c b/src/core/ao_task.c index 4593bd79..65654731 100644 --- a/src/core/ao_task.c +++ b/src/core/ao_task.c @@ -125,6 +125,7 @@ ao_sleep(__xdata void *wchan) ao_yield(); if (ao_cur_task->wchan) { ao_cur_task->wchan = NULL; + ao_cur_task->alarm = 0; return 1; } return 0; @@ -157,6 +158,16 @@ ao_clear_alarm(void) ao_cur_task->alarm = 0; } +static __xdata uint8_t ao_forever; + +void +ao_delay(uint16_t ticks) +{ + ao_alarm(ticks); + ao_sleep(&ao_forever); + ao_clear_alarm(); +} + void ao_exit(void) { diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index 78228e65..f561e6b5 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -28,15 +28,6 @@ uint16_t ao_time(void) return v; } -static __xdata uint8_t ao_forever; - -void -ao_delay(uint16_t ticks) -{ - ao_alarm(ticks); - ao_sleep(&ao_forever); -} - #if AO_DATA_ALL volatile __data uint8_t ao_data_interval = 1; volatile __data uint8_t ao_data_count; -- cgit v1.2.3 From f2d919a2147025daa332957cda6d91959e4731ab Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Aug 2012 18:05:10 -0700 Subject: altos: When sharing radio DMA for AES, use it for in instead of out We look at the out_done value, but not the in_done value; if we use the radio DMA for out, we would have to use ao_radio_dma_done to check for completion. This way, we can ignore that value and use the existing ao_aes_dma_out_done value. Signed-off-by: Keith Packard --- src/cc1111/ao_aes.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_aes.c b/src/cc1111/ao_aes.c index 0e32abf6..b1f305ec 100644 --- a/src/cc1111/ao_aes.c +++ b/src/cc1111/ao_aes.c @@ -135,12 +135,12 @@ ao_aes_run(__xdata uint8_t *in, void ao_aes_init(void) { - ao_aes_dma_in = ao_dma_alloc(&ao_aes_dma_in_done); #if DMA_SHARE_AES_RADIO - ao_aes_dma_out = ao_radio_dma; + ao_aes_dma_in = ao_radio_dma; #else - ao_aes_dma_out = ao_dma_alloc(&ao_aes_dma_out_done); + ao_aes_dma_in = ao_dma_alloc(&ao_aes_dma_in_done); #endif + ao_aes_dma_out = ao_dma_alloc(&ao_aes_dma_out_done); S0CON = 0; ENCIE = 1; } -- cgit v1.2.3 From 78cd26eec77adda23ef1b5ca2d91027f1e059868 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Aug 2012 18:07:05 -0700 Subject: altos: Move radio_cmac test funcs from ao_lco_cmd.c to new file These are useful in the firing node for testing as well, so move them to be shared. Signed-off-by: Keith Packard --- src/core/ao_radio_cmac_cmd.c | 104 +++++++++++++++++++++++++++++++++++++++++++ src/core/ao_radio_cmac_cmd.h | 24 ++++++++++ src/drivers/ao_lco_cmd.c | 74 ------------------------------ 3 files changed, 128 insertions(+), 74 deletions(-) create mode 100644 src/core/ao_radio_cmac_cmd.c create mode 100644 src/core/ao_radio_cmac_cmd.h (limited to 'src') diff --git a/src/core/ao_radio_cmac_cmd.c b/src/core/ao_radio_cmac_cmd.c new file mode 100644 index 00000000..64410921 --- /dev/null +++ b/src/core/ao_radio_cmac_cmd.c @@ -0,0 +1,104 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include + +static __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN]; + +static uint8_t +getnibble(void) +{ + int8_t b; + + b = ao_cmd_hexchar(getchar()); + if (b < 0) { + ao_cmd_status = ao_cmd_lex_error; + return 0; + } + return (uint8_t) b; +} + +static uint8_t +getbyte(void) +{ + uint8_t b; + b = getnibble() << 4; + b |= getnibble(); + return b; +} + +static void +radio_cmac_send_cmd(void) __reentrant +{ + uint8_t i; + uint8_t len; + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + len = ao_cmd_lex_i; + if (len > AO_CMAC_MAX_LEN) { + ao_cmd_status = ao_cmd_syntax_error; + return; + } + flush(); + len = ao_cmd_lex_i; + for (i = 0; i < len; i++) { + cmac_data[i] = getbyte(); + if (ao_cmd_status != ao_cmd_success) + return; + } + ao_radio_cmac_send(cmac_data, len); +} + +static void +radio_cmac_recv_cmd(void) __reentrant +{ + uint8_t len, i; + uint16_t timeout; + + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + len = ao_cmd_lex_i; + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + timeout = AO_MS_TO_TICKS(ao_cmd_lex_i); + i = ao_radio_cmac_recv(cmac_data, len, timeout); + if (i == AO_RADIO_CMAC_OK) { + printf ("PACKET "); + for (i = 0; i < len; i++) + printf("%02x", cmac_data[i]); + printf (" %d\n", ao_radio_cmac_rssi); + } else + printf ("ERROR %d %d\n", i, ao_radio_cmac_rssi); +} + +static __code struct ao_cmds ao_radio_cmac_cmds[] = { + { radio_cmac_send_cmd, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, + { radio_cmac_recv_cmd, "S \0Receive AES-CMAC packet. Timeout in ms" }, + { 0, NULL }, +}; + +void +ao_radio_cmac_cmd_init(void) +{ + ao_cmd_register(&ao_radio_cmac_cmds[0]); +} diff --git a/src/core/ao_radio_cmac_cmd.h b/src/core/ao_radio_cmac_cmd.h new file mode 100644 index 00000000..6b8782de --- /dev/null +++ b/src/core/ao_radio_cmac_cmd.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_RADIO_CMAC_CMD_H_ +#define _AO_RADIO_CMAC_CMD_H_ + +void +ao_radio_cmac_cmd_init(void); + +#endif /* _AO_RADIO_CMAC_CMD_H_ */ diff --git a/src/drivers/ao_lco_cmd.c b/src/drivers/ao_lco_cmd.c index 3fe0d9cc..cce7a259 100644 --- a/src/drivers/ao_lco_cmd.c +++ b/src/drivers/ao_lco_cmd.c @@ -177,81 +177,7 @@ launch_ignite_cmd(void) __reentrant launch_ignite(); } -static uint8_t -getnibble(void) -{ - int8_t b; - - b = ao_cmd_hexchar(getchar()); - if (b < 0) { - ao_cmd_status = ao_cmd_lex_error; - return 0; - } - return (uint8_t) b; -} - -static uint8_t -getbyte(void) -{ - uint8_t b; - b = getnibble() << 4; - b |= getnibble(); - return b; -} - -static __xdata uint8_t cmac_data[AO_CMAC_MAX_LEN]; - -static void -radio_cmac_send_cmd(void) __reentrant -{ - uint8_t i; - uint8_t len; - - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - len = ao_cmd_lex_i; - if (len > AO_CMAC_MAX_LEN) { - ao_cmd_status = ao_cmd_syntax_error; - return; - } - flush(); - len = ao_cmd_lex_i; - for (i = 0; i < len; i++) { - cmac_data[i] = getbyte(); - if (ao_cmd_status != ao_cmd_success) - return; - } - ao_radio_cmac_send(cmac_data, len); -} - -static void -radio_cmac_recv_cmd(void) __reentrant -{ - uint8_t len, i; - uint16_t timeout; - - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - len = ao_cmd_lex_i; - ao_cmd_decimal(); - if (ao_cmd_status != ao_cmd_success) - return; - timeout = AO_MS_TO_TICKS(ao_cmd_lex_i); - i = ao_radio_cmac_recv(cmac_data, len, timeout); - if (i == AO_RADIO_CMAC_OK) { - printf ("PACKET "); - for (i = 0; i < len; i++) - printf("%02x", cmac_data[i]); - printf (" %d\n", ao_radio_cmac_rssi); - } else - printf ("ERROR %d %d\n", i, ao_radio_cmac_rssi); -} - static __code struct ao_cmds ao_lco_cmds[] = { - { radio_cmac_send_cmd, "s \0Send AES-CMAC packet. Bytes to send follow on next line" }, - { radio_cmac_recv_cmd, "S \0Receive AES-CMAC packet. Timeout in ms" }, { launch_report_cmd, "l \0Get remote launch status" }, { launch_fire_cmd, "f \0Fire remote igniter" }, { launch_arm_cmd, "a \0Arm remote igniter" }, -- cgit v1.2.3 From 18b5021e99c1eef32d2d85f619c84e89cecae7a7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Aug 2012 18:07:55 -0700 Subject: altos: Stop providing debug commands in seven-segment driver The radio_cmac debug commands use the same letter, and this code works now... Signed-off-by: Keith Packard --- src/drivers/ao_seven_segment.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/drivers/ao_seven_segment.c b/src/drivers/ao_seven_segment.c index 1a643eff..b3b5f878 100644 --- a/src/drivers/ao_seven_segment.c +++ b/src/drivers/ao_seven_segment.c @@ -192,6 +192,7 @@ ao_seven_segment_clear(void) } +#if 0 static void ao_seven_segment_show(void) { @@ -208,9 +209,12 @@ static const struct ao_cmds ao_seven_segment_cmds[] = { { ao_seven_segment_show, "S \0Set LCD digit" }, { 0, NULL }, }; +#endif void ao_seven_segment_init(void) { +#if 0 ao_cmd_register(ao_seven_segment_cmds); +#endif } -- cgit v1.2.3 From 3fe5a70d9ac2114ee554813b1dbb3019a3e4aff7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Aug 2012 18:08:59 -0700 Subject: altos: Track protocol changes to ao_pad debug messages Make the debug output build again. Signed-off-by: Keith Packard --- src/drivers/ao_pad.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index b33a5ffd..94dc5787 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -24,7 +24,7 @@ static __xdata uint8_t ao_pad_ignite; static __xdata struct ao_pad_command command; static __xdata struct ao_pad_query query; -#if 0 +#if 1 #define PRINTD(...) printf(__VA_ARGS__) #define FLUSHD() flush() #else @@ -155,20 +155,23 @@ static void ao_pad(void) { int16_t time_difference; + int8_t ret; ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); - ao_pad_box = ao_74hc497_read(); + ao_pad_box = 0; ao_led_set(0); ao_led_on(AO_LED_POWER); for (;;) { FLUSHD(); while (ao_pad_disabled) ao_sleep(&ao_pad_disabled); - if (ao_radio_cmac_recv(&command, sizeof (command), 0) != AO_RADIO_CMAC_OK) + ret = ao_radio_cmac_recv(&command, sizeof (command), 0); + PRINTD ("cmac_recv %d\n", ret); + if (ret != AO_RADIO_CMAC_OK) continue; - PRINTD ("tick %d serial %d cmd %d channel %d\n", - command.tick, command.serial, command.cmd, command.channel); + PRINTD ("tick %d box %d cmd %d channels %02x\n", + command.tick, command.box, command.cmd, command.channels); switch (command.cmd) { case AO_LAUNCH_ARM: @@ -204,9 +207,9 @@ ao_pad(void) query.box = ao_pad_box; query.channels = AO_PAD_ALL_PINS; query.armed = ao_pad_armed; - PRINTD ("query tick %d serial %d channel %d valid %d arm %d igniter %d\n", - query.tick, query.serial, query.channel, query.valid, query.arm_status, - query.igniter_status); + PRINTD ("query tick %d box %d channels %02x arm %d arm_status %d igniter %d\n", + query.tick, query.box, query.channels, query.armed, + query.arm_status, query.igniter_status); ao_radio_cmac_send(&query, sizeof (query)); break; case AO_LAUNCH_FIRE: -- cgit v1.2.3 From eb1a9a8c3f3d3993d5986925bc4ad112c2bbc119 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Aug 2012 18:10:34 -0700 Subject: altos: Explicitly erase memory in STM eeprom driver. This seems to make the STM32L152 happier Signed-off-by: Keith Packard --- src/stm/ao_eeprom_stm.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/stm/ao_eeprom_stm.c b/src/stm/ao_eeprom_stm.c index 1e51b417..5a75a97d 100644 --- a/src/stm/ao_eeprom_stm.c +++ b/src/stm/ao_eeprom_stm.c @@ -82,19 +82,30 @@ ao_intflash_lock(void) stm_flash.pecr |= (1 << STM_FLASH_PECR_PELOCK); } +static void +ao_intflash_wait(void) +{ + /* Wait for the flash unit to go idle */ + while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)) + ; +} + static void ao_intflash_write32(uint16_t pos, uint32_t w) { - uint32_t *addr; + volatile uint32_t *addr; addr = (uint32_t *) (stm_eeprom + pos); - /* Write a word to a valid address in the data EEPROM */ - *addr = w; + /* Erase previous word */ + *addr = 0; + ao_intflash_wait(); - /* Wait for the flash unit to go idle */ - while (stm_flash.sr & (1 << STM_FLASH_SR_BSY)) - ; + if (w) { + /* Write a word to a valid address in the data EEPROM */ + *addr = w; + ao_intflash_wait(); + } } static void @@ -182,6 +193,7 @@ ao_storage_setup(void) void ao_storage_device_info(void) __reentrant { + uint8_t i; printf ("Using internal flash\n"); } -- cgit v1.2.3 From 27a879b4069ccedf8bbe39d7dbecf45000f29d8c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Aug 2012 18:12:27 -0700 Subject: altos: Include the radio_cmac debug commands in telefire Just temporary debugging Signed-off-by: Keith Packard --- src/telefire-v0.1/Makefile | 3 ++- src/telefire-v0.1/ao_telefire.c | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/telefire-v0.1/Makefile b/src/telefire-v0.1/Makefile index cfa4b3ed..712b2e8b 100644 --- a/src/telefire-v0.1/Makefile +++ b/src/telefire-v0.1/Makefile @@ -52,7 +52,8 @@ CC1111_SRC = \ DRIVER_SRC = \ ao_pca9922.c \ ao_74hc497.c \ - ao_pad.c + ao_pad.c \ + ao_radio_cmac_cmd.c PRODUCT_SRC = \ ao_telefire.c diff --git a/src/telefire-v0.1/ao_telefire.c b/src/telefire-v0.1/ao_telefire.c index 210be08b..cc0f668f 100644 --- a/src/telefire-v0.1/ao_telefire.c +++ b/src/telefire-v0.1/ao_telefire.c @@ -18,6 +18,7 @@ #include #include #include +#include void main(void) @@ -37,6 +38,7 @@ main(void) ao_radio_init(); ao_aes_init(); ao_pad_init(); +// ao_radio_cmac_cmd_init(); ao_config_init(); ao_start_scheduler(); } -- cgit v1.2.3 From fc9841ee5e92318471b6bec09b7075a788ab8872 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Aug 2012 18:13:02 -0700 Subject: altos: Mostly working SPI radio link This includes long delays to avoid overrunning the cc1111 input, otherwise it works pretty well. The delays mean that we can't capture the reply to a cmac command though, so more work is needed. Signed-off-by: Keith Packard --- src/cc1111/ao_arch_funcs.h | 8 +++++ src/cc1111/ao_spi.c | 24 ++++++++++---- src/drivers/ao_radio_master.c | 76 +++++++++++++++++++++++++++++++++---------- src/drivers/ao_radio_slave.c | 40 +++++++++++++---------- 4 files changed, 107 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_arch_funcs.h b/src/cc1111/ao_arch_funcs.h index 5e2fc13d..8f1cc094 100644 --- a/src/cc1111/ao_arch_funcs.h +++ b/src/cc1111/ao_arch_funcs.h @@ -77,6 +77,14 @@ ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant; #define ao_spi_send(block, len, bus) ao_spi_send_bus(block, len) #define ao_spi_recv(block, len, bus) ao_spi_recv_bus(block, len) +#if AO_SPI_SLAVE +void +ao_spi_send_wait(void); + +void +ao_spi_recv_wait(void); +#endif + void ao_spi_init(void); diff --git a/src/cc1111/ao_spi.c b/src/cc1111/ao_spi.c index 2b4fd186..39d459f1 100644 --- a/src/cc1111/ao_spi.c +++ b/src/cc1111/ao_spi.c @@ -171,16 +171,20 @@ ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant #endif ao_dma_start(ao_spi_dma_out_id); ao_dma_trigger(ao_spi_dma_out_id); -#if AO_SPI_SLAVE - __critical while (!ao_spi_dma_out_done) - ao_sleep(&ao_spi_dma_out_done); -#else +#if !AO_SPI_SLAVE __critical while (!ao_spi_dma_in_done) ao_sleep(&ao_spi_dma_in_done); #endif } - +#if AO_SPI_SLAVE +void +ao_spi_send_wait(void) +{ + __critical while (!ao_spi_dma_out_done) + ao_sleep(&ao_spi_dma_out_done); +} +#endif /* Receive bytes over SPI. * @@ -221,11 +225,19 @@ ao_spi_recv_bus(void __xdata *block, uint16_t len) __reentrant #if !AO_SPI_SLAVE ao_dma_start(ao_spi_dma_out_id); ao_dma_trigger(ao_spi_dma_out_id); -#endif __critical while (!ao_spi_dma_in_done) ao_sleep(&ao_spi_dma_in_done); +#endif } +#if AO_SPI_SLAVE +void +ao_spi_recv_wait(void) +{ + __critical while (!ao_spi_dma_in_done) + ao_sleep(&ao_spi_dma_in_done); +} +#endif void ao_spi_init(void) diff --git a/src/drivers/ao_radio_master.c b/src/drivers/ao_radio_master.c index 6edea66d..bfbcb1f8 100644 --- a/src/drivers/ao_radio_master.c +++ b/src/drivers/ao_radio_master.c @@ -22,25 +22,41 @@ static __xdata struct ao_radio_spi_reply ao_radio_spi_reply; static __xdata struct ao_radio_spi_request ao_radio_spi_request; -static __xdata uint8_t ao_radio_done; +static volatile __xdata uint8_t ao_radio_done = 1; static __xdata uint8_t ao_radio_mutex; __xdata int8_t ao_radio_cmac_rssi; +#if 0 +#define PRINTD(...) do { printf ("\r%s: ", __func__); printf(__VA_ARGS__); flush(); } while(0) +#else +#define PRINTD(...) +#endif + static void ao_radio_isr(void) { ao_exti_disable(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN); ao_radio_done = 1; - ao_wakeup(&ao_radio_done); + ao_wakeup((void *) &ao_radio_done); +} + +static void +ao_radio_master_delay(void) +{ +// uint16_t i; +// for (i = 0; i < 1000; i++) +// ao_arch_nop(); + ao_delay(1); } static void ao_radio_master_start(void) { + ao_radio_master_delay(); ao_spi_get_bit(AO_RADIO_CS_PORT, AO_RADIO_CS_PIN, AO_RADIO_CS, AO_RADIO_SPI_BUS, - AO_SPI_SPEED_1MHz); + AO_SPI_SPEED_200kHz); } static void @@ -48,12 +64,15 @@ ao_radio_master_stop(void) { ao_spi_put_bit(AO_RADIO_CS_PORT, AO_RADIO_CS_PIN, AO_RADIO_CS, AO_RADIO_SPI_BUS); +// ao_delay(1); } - static uint8_t ao_radio_master_send(void) { + if (!ao_radio_done) + printf ("radio not done in ao_radio_master_send\n"); + PRINTD("send %d\n", ao_radio_spi_request.len); ao_radio_done = 0; ao_exti_enable(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN); ao_radio_master_start(); @@ -63,22 +82,17 @@ ao_radio_master_send(void) ao_radio_master_stop(); cli(); while (!ao_radio_done) - if (ao_sleep(&ao_radio_done)) + if (ao_sleep((void *) &ao_radio_done)) { + printf ("ao_radio_master awoken\n"); break; + } sei(); + PRINTD ("sent, radio done %d\n", ao_radio_done); + if (!ao_radio_done) + printf ("radio didn't finish after ao_radio_master_send\n"); return ao_radio_done; } -static void -ao_radio_master_recv(uint16_t len) -{ - ao_radio_master_start(); - ao_spi_recv(&ao_radio_spi_reply, - len, - AO_RADIO_SPI_BUS); - ao_radio_master_stop(); -} - static void ao_radio_get(uint8_t req, uint8_t len) { @@ -98,12 +112,23 @@ ao_radio_put(void) static void ao_radio_get_data(__xdata void *d, uint8_t size) { + uint8_t ret; + + PRINTD ("send fetch req\n"); + ao_radio_spi_request.len = AO_RADIO_SPI_REQUEST_HEADER_LEN; + ao_radio_spi_request.request = AO_RADIO_SPI_RECV_FETCH; + ao_radio_spi_request.recv_len = size; + ret = ao_radio_master_send(); + PRINTD ("fetch req sent %d\n", ret); + + PRINTD ("fetch\n"); ao_radio_master_start(); ao_spi_recv(&ao_radio_spi_reply, AO_RADIO_SPI_REPLY_HEADER_LEN + size, AO_RADIO_SPI_BUS); ao_radio_master_stop(); ao_xmemcpy(d, ao_radio_spi_reply.payload, size); + PRINTD ("fetched %d\n", size); } void @@ -142,8 +167,11 @@ ao_radio_recv(__xdata void *d, uint8_t size) return 0; } ao_radio_get_data(d, size); + recv = ao_radio_spi_reply.status; + ao_radio_put(); + return recv; } @@ -153,20 +181,25 @@ ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant if (len > AO_CMAC_MAX_LEN) return AO_RADIO_CMAC_LEN_ERROR; + PRINTD ("cmac_send: send %d\n", len); /* Set the key. */ + PRINTD ("set key\n"); ao_radio_get(AO_RADIO_SPI_CMAC_KEY, AO_AES_LEN); ao_xmemcpy(&ao_radio_spi_request.payload, &ao_config.aes_key, AO_AES_LEN); ao_radio_master_send(); ao_radio_put(); + PRINTD ("key set\n"); /* Send the data */ + PRINTD ("sending packet\n"); ao_radio_get(AO_RADIO_SPI_CMAC_SEND, len); ao_xmemcpy(&ao_radio_spi_request.payload, packet, len); ao_radio_master_send(); ao_radio_put(); + PRINTD ("packet sent\n"); return AO_RADIO_CMAC_OK; } @@ -174,33 +207,40 @@ int8_t ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentrant { int8_t ret; - uint8_t recv; + int8_t recv; if (len > AO_CMAC_MAX_LEN) return AO_RADIO_CMAC_LEN_ERROR; /* Set the key. */ + PRINTD ("setting key\n"); ao_radio_get(AO_RADIO_SPI_CMAC_KEY, AO_AES_LEN); ao_radio_spi_request.timeout = timeout; ao_xmemcpy(&ao_radio_spi_request.payload, &ao_config.aes_key, AO_AES_LEN); - ao_radio_master_send(); + recv = ao_radio_master_send(); ao_radio_put(); + PRINTD ("key set: %d\n", recv); /* Recv the data */ - + PRINTD ("queuing recv\n"); ao_radio_get(AO_RADIO_SPI_CMAC_RECV, 0); ao_radio_spi_request.recv_len = len; recv = ao_radio_master_send(); + PRINTD ("recv queued: %d\n", recv); if (!recv) { ao_radio_put(); ao_radio_recv_abort(); return AO_RADIO_CMAC_TIMEOUT; } + + PRINTD ("fetching data\n"); ao_radio_get_data(packet, len); recv = ao_radio_spi_reply.status; + ao_radio_cmac_rssi = ao_radio_spi_reply.rssi; ao_radio_put(); + PRINTD ("data fetched: %d %d\n", recv, ao_radio_cmac_rssi); return recv; } diff --git a/src/drivers/ao_radio_slave.c b/src/drivers/ao_radio_slave.c index 9dff511b..ab23894f 100644 --- a/src/drivers/ao_radio_slave.c +++ b/src/drivers/ao_radio_slave.c @@ -34,17 +34,24 @@ ao_radio_slave_signal(void) ao_arch_nop(); ao_arch_nop(); ao_arch_nop(); - ao_gpio_set(AO_RADIO_SLAVE_INT_PORT, AO_RADIO_SLAVE_INT_BIT, AO_RADIO_SLAVE_INT_PIN, 0); + ao_gpio_set(AO_RADIO_SLAVE_INT_PORT, AO_RADIO_SLAVE_INT_BIT, AO_RADIO_SLAVE_INT_PIN, 1); } static void ao_radio_slave_spi(void) { + uint8_t need_signal = 0; + + ao_spi_get_slave(AO_RADIO_SLAVE_BUS); for (;;) { - ao_spi_get_slave(AO_RADIO_SLAVE_BUS); - ao_spi_recv(&ao_radio_spi_request, (2 << 13) | sizeof (ao_radio_spi_request), AO_RADIO_SLAVE_BUS); - ao_spi_put_slave(AO_RADIO_SLAVE_BUS); - ao_led_for(AO_LED_RED, AO_MS_TO_TICKS(1000)); + ao_spi_recv(&ao_radio_spi_request, + (2 << 13) | sizeof (ao_radio_spi_request), + AO_RADIO_SLAVE_BUS); + if (need_signal) { + ao_radio_slave_signal(); + need_signal = 0; + } + ao_spi_recv_wait(); switch (ao_radio_spi_request.request) { case AO_RADIO_SPI_RECV: case AO_RADIO_SPI_CMAC_RECV: @@ -53,44 +60,43 @@ ao_radio_slave_spi(void) ao_radio_spi_recv_len = ao_radio_spi_request.recv_len; ao_radio_spi_recv_timeout = ao_radio_spi_request.timeout; ao_wakeup(&ao_radio_spi_recv_len); - break; + continue; case AO_RADIO_SPI_RECV_FETCH: - ao_spi_get_slave(AO_RADIO_SLAVE_BUS); ao_spi_send(&ao_radio_spi_reply, - ao_radio_spi_request.recv_len + AO_RADIO_SPI_REPLY_HEADER_LEN, + ao_radio_spi_request.recv_len, AO_RADIO_SLAVE_BUS); - ao_spi_put_slave(AO_RADIO_SLAVE_BUS); - break; + ao_radio_slave_signal(); + ao_spi_send_wait(); + continue; case AO_RADIO_SPI_RECV_ABORT: ao_radio_recv_abort(); break; case AO_RADIO_SPI_SEND: ao_config.radio_setting = ao_radio_spi_request.setting; - ao_radio_send(&ao_radio_spi_request.payload, ao_radio_spi_request.len - AO_RADIO_SPI_REQUEST_HEADER_LEN); - ao_radio_slave_signal(); + ao_radio_send(&ao_radio_spi_request.payload, + ao_radio_spi_request.len - AO_RADIO_SPI_REQUEST_HEADER_LEN); break; case AO_RADIO_SPI_CMAC_SEND: ao_config.radio_setting = ao_radio_spi_request.setting; - ao_radio_cmac_send(&ao_radio_spi_request.payload, ao_radio_spi_request.len - AO_RADIO_SPI_REQUEST_HEADER_LEN); - ao_radio_slave_signal(); + ao_radio_cmac_send(&ao_radio_spi_request.payload, + ao_radio_spi_request.len - AO_RADIO_SPI_REQUEST_HEADER_LEN); break; case AO_RADIO_SPI_CMAC_KEY: ao_xmemcpy(&ao_config.aes_key, ao_radio_spi_request.payload, AO_AES_LEN); - ao_radio_slave_signal(); break; case AO_RADIO_SPI_TEST_ON: + ao_config.radio_setting = ao_radio_spi_request.setting; ao_radio_test(1); - ao_radio_slave_signal(); break; case AO_RADIO_SPI_TEST_OFF: ao_radio_test(0); - ao_radio_slave_signal(); break; } + need_signal = 1; } } -- cgit v1.2.3 From 3a3982ceb721910c6a4f75badebb62baa6c6568e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Aug 2012 22:43:10 -0700 Subject: altos: Add spiradio Makefile git add doesn't add Makefile by default. Signed-off-by: Keith Packard --- src/spiradio-v0.1/Makefile | 92 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/spiradio-v0.1/Makefile (limited to 'src') diff --git a/src/spiradio-v0.1/Makefile b/src/spiradio-v0.1/Makefile new file mode 100644 index 00000000..a207d34f --- /dev/null +++ b/src/spiradio-v0.1/Makefile @@ -0,0 +1,92 @@ +# +# SpiRadio build file +# + +SPIRADIO_VER=0.1 +SPIRADIO_DEF=0_1 + +vpath %.c ..:../core:../cc1111:../drivers:../product +vpath %.h ..:../core:../cc1111:../drivers:../product +vpath ao-make-product.5c ../util + +ifndef VERSION +include ../Version +endif + +INC = \ + ao.h \ + ao_pins.h \ + ao_arch.h \ + ao_arch_funcs.h \ + cc1111.h \ + ao_product.h \ + ao_radio_spi.h + +CORE_SRC = \ + ao_cmd.c \ + ao_config.c \ + ao_mutex.c \ + ao_panic.c \ + ao_stdio.c \ + ao_task.c \ + ao_freq.c + +CC1111_SRC = \ + ao_aes.c \ + ao_dma.c \ + ao_led.c \ + ao_radio.c \ + ao_radio_cmac.c \ + ao_radio_slave.c \ + ao_romconfig.c \ + ao_serial.c \ + ao_spi.c \ + ao_string.c \ + ao_timer.c \ + _bp.c + +PRODUCT_SRC = \ + ao_spiradio.c + +SRC = \ + $(CORE_SRC) \ + $(CC1111_SRC) \ + $(PRODUCT_SRC) + +PROGNAME = spiradio-v$(SPIRADIO_VER) +PROG = $(PROGNAME)-$(VERSION).ihx +PRODUCT=SpiRadio-v$(SPIRADIO_VER) +PRODUCT_DEF=-DSPIRADIO_V_$(SPIRADIO_DEF) +IDPRODUCT=0x000f +CODESIZE=0x6700 + +include ../cc1111/Makefile.cc1111 + +NICKLE=nickle +CHECK_STACK=sh ../util/check-stack + +V=0 +# The user has explicitly enabled quiet compilation. +ifeq ($(V),0) +quiet = @printf " $1 $2 $@\n"; $($1) +endif +# Otherwise, print the full command line. +quiet ?= $($1) + +all: ../$(PROG) + +../$(PROG): $(REL) Makefile + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(REL) && cp $(PROG) $(PMAP) .. + $(call quiet,CHECK_STACK) ../cc1111/ao_arch.h $(PMEM) || rm $@ + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: clean-cc1111 + +install: + +uninstall: + -- cgit v1.2.3 From 98f65994ee547feb8cca63ff4ed0fefd3fb2d37d Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 28 Aug 2012 23:05:02 -0700 Subject: altos: Oops. forgot ao_data.c Signed-off-by: Keith Packard --- src/stm/ao_data.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/stm/ao_data.c (limited to 'src') diff --git a/src/stm/ao_data.c b/src/stm/ao_data.c new file mode 100644 index 00000000..38d2f7ff --- /dev/null +++ b/src/stm/ao_data.c @@ -0,0 +1,34 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include + +volatile __xdata struct ao_data ao_data_ring[AO_DATA_RING]; +volatile __data uint8_t ao_data_head; +volatile __data uint8_t ao_data_present; + +void +ao_data_get(__xdata struct ao_data *packet) +{ +#if HAS_FLIGHT + uint8_t i = ao_data_ring_prev(ao_sample_data); +#else + uint8_t i = ao_data_ring_prev(ao_data_head); +#endif + memcpy(packet, (void *) &ao_data_ring[i], sizeof (struct ao_data)); +} -- cgit v1.2.3 From 1a7d2faf76a46271532102e217c2dd5515e38b72 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 29 Aug 2012 11:16:42 -0700 Subject: altos: Wait for IN dma complete on slave SPI send SPI send double buffered, so the DMA completes one byte too early. Use the recv DMA to know when the SPI transfer is complete. Signed-off-by: Keith Packard --- src/cc1111/ao_spi.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/cc1111/ao_spi.c b/src/cc1111/ao_spi.c index 39d459f1..cdef6bda 100644 --- a/src/cc1111/ao_spi.c +++ b/src/cc1111/ao_spi.c @@ -143,7 +143,6 @@ static __xdata uint8_t ao_spi_const; void ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant { -#if !AO_SPI_SLAVE ao_dma_set_transfer(ao_spi_dma_in_id, &SPI_BUF, &ao_spi_const, @@ -154,7 +153,6 @@ ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant DMA_CFG1_SRCINC_0 | DMA_CFG1_DESTINC_0 | DMA_CFG1_PRIORITY_NORMAL); -#endif ao_dma_set_transfer(ao_spi_dma_out_id, block, &SPI_BUF, @@ -166,9 +164,7 @@ ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant DMA_CFG1_DESTINC_0 | DMA_CFG1_PRIORITY_NORMAL); -#if !AO_SPI_SLAVE ao_dma_start(ao_spi_dma_in_id); -#endif ao_dma_start(ao_spi_dma_out_id); ao_dma_trigger(ao_spi_dma_out_id); #if !AO_SPI_SLAVE @@ -181,8 +177,8 @@ ao_spi_send_bus(void __xdata *block, uint16_t len) __reentrant void ao_spi_send_wait(void) { - __critical while (!ao_spi_dma_out_done) - ao_sleep(&ao_spi_dma_out_done); + __critical while (!ao_spi_dma_in_done) + ao_sleep(&ao_spi_dma_in_done); } #endif -- cgit v1.2.3 From 7f64e62356bcfcd6ba8a88b09251793481bcd56c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 29 Aug 2012 11:19:17 -0700 Subject: altos: Note changes to configured AES key for SPI radio convenience Keep a sequence number to mark when the AES key is changed so that the radio code can avoid sending the key before every CMAC radio operation. Signed-off-by: Keith Packard --- src/core/ao.h | 2 ++ src/core/ao_config.c | 4 ++++ 2 files changed, 6 insertions(+) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index b8bedd85..66c0881f 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -718,6 +718,8 @@ extern __xdata uint8_t ao_force_freq; #define AO_AES_LEN 16 +extern __xdata uint8_t ao_config_aes_seq; + struct ao_config { uint8_t major; uint8_t minor; diff --git a/src/core/ao_config.c b/src/core/ao_config.c index f19dd9cd..ce855ad1 100644 --- a/src/core/ao_config.c +++ b/src/core/ao_config.c @@ -463,6 +463,9 @@ ao_config_radio_enable_set(void) __reentrant #endif /* HAS_RADIO */ #if HAS_AES + +__xdata uint8_t ao_config_aes_seq = 1; + void ao_config_key_show(void) __reentrant { @@ -485,6 +488,7 @@ ao_config_key_set(void) __reentrant break; ao_config.aes_key[i] = ao_cmd_lex_i; } + ++ao_config_aes_seq; _ao_config_edit_finish(); } #endif -- cgit v1.2.3 From 442f1bfc89528103e2c28f768c954b956e39afc5 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 29 Aug 2012 11:21:09 -0700 Subject: altos: Use updated pad protocol for lco commands Stop using the older single-channel protocol and switch to the new multi-channel protocol Signed-off-by: Keith Packard --- src/drivers/ao_lco_cmd.c | 84 ++++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_lco_cmd.c b/src/drivers/ao_lco_cmd.c index cce7a259..b49c9dba 100644 --- a/src/drivers/ao_lco_cmd.c +++ b/src/drivers/ao_lco_cmd.c @@ -16,22 +16,23 @@ */ #include +#include #include #include -static __xdata struct ao_launch_command command; -static __xdata struct ao_launch_query query; -static __pdata uint16_t launch_serial; -static __pdata uint8_t launch_channel; +static __xdata struct ao_pad_command command; +static __xdata struct ao_pad_query query; +static __pdata uint16_t launch_box; +static __pdata uint8_t launch_channels; static __pdata uint16_t tick_offset; static void launch_args(void) __reentrant { ao_cmd_decimal(); - launch_serial = ao_cmd_lex_i; - ao_cmd_decimal(); - launch_channel = ao_cmd_lex_i; + launch_box = ao_cmd_lex_i; + ao_cmd_hex(); + launch_channels = ao_cmd_lex_i; } static int8_t @@ -44,9 +45,9 @@ launch_query(void) for (i = 0; i < 10; i++) { printf ("."); flush(); command.tick = ao_time(); - command.serial = launch_serial; + command.box = launch_box; command.cmd = AO_LAUNCH_QUERY; - command.channel = launch_channel; + command.channels = launch_channels; ao_radio_cmac_send(&command, sizeof (command)); r = ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500)); if (r == AO_RADIO_CMAC_OK) @@ -61,6 +62,7 @@ static void launch_report_cmd(void) __reentrant { int8_t r; + uint8_t c; launch_args(); if (ao_cmd_status != ao_cmd_success) @@ -68,28 +70,32 @@ launch_report_cmd(void) __reentrant r = launch_query(); switch (r) { case AO_RADIO_CMAC_OK: - if (query.valid) { - switch (query.arm_status) { - case ao_igniter_ready: - case ao_igniter_active: - printf ("Armed: "); - break; - default: - printf("Disarmed: "); - } - switch (query.igniter_status) { - default: - printf("unknown\n"); - break; - case ao_igniter_ready: - printf("igniter good\n"); - break; - case ao_igniter_open: - printf("igniter bad\n"); - break; + switch (query.arm_status) { + case ao_igniter_ready: + case ao_igniter_active: + printf ("Armed: "); + break; + default: + printf("Disarmed: "); + } + for (c = 0; c < AO_PAD_MAX_CHANNELS; c++) { + if (query.channels & (1 << c)) { + printf (" pad %d ", c); + switch (query.igniter_status[c]) { + default: + printf("unknown, "); + break; + case AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN: + printf("bad-open, "); + break; + case AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN: + printf("good-igniter, "); + break; + case AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED: + printf("bad-closed, "); + break; + } } - } else { - printf("Invalid channel %d\n", launch_channel); } printf("Rssi: %d\n", ao_radio_cmac_rssi); break; @@ -103,9 +109,9 @@ static void launch_arm(void) __reentrant { command.tick = ao_time() - tick_offset; - command.serial = launch_serial; + command.box = launch_box; command.cmd = AO_LAUNCH_ARM; - command.channel = launch_channel; + command.channels = launch_channels; ao_radio_cmac_send(&command, sizeof (command)); } @@ -113,16 +119,16 @@ static void launch_ignite(void) __reentrant { command.tick = ao_time() - tick_offset; - command.serial = launch_serial; + command.box = launch_box; command.cmd = AO_LAUNCH_FIRE; - command.channel = 0; + command.channels = 0; ao_radio_cmac_send(&command, sizeof (command)); } static void launch_fire_cmd(void) __reentrant { - static __xdata struct ao_launch_command command; + static __xdata struct ao_pad_command command; uint8_t secs; uint8_t i; int8_t r; @@ -178,10 +184,10 @@ launch_ignite_cmd(void) __reentrant } static __code struct ao_cmds ao_lco_cmds[] = { - { launch_report_cmd, "l \0Get remote launch status" }, - { launch_fire_cmd, "f \0Fire remote igniter" }, - { launch_arm_cmd, "a \0Arm remote igniter" }, - { launch_ignite_cmd, "i \0Pulse remote igniter" }, + { launch_report_cmd, "l \0Get remote launch status" }, + { launch_fire_cmd, "F \0Fire remote igniter" }, + { launch_arm_cmd, "a \0Arm remote igniter" }, + { launch_ignite_cmd, "i \0Pulse remote igniter" }, { 0, NULL }, }; -- cgit v1.2.3 From 1b6ed262460ee75fb5bb684d13d19c26c7ea750b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 29 Aug 2012 11:22:02 -0700 Subject: altos: fix ao_pad debug output for query command Igniter status is an array these days. Signed-off-by: Keith Packard --- src/drivers/ao_pad.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index 94dc5787..cd901aa3 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -207,9 +207,13 @@ ao_pad(void) query.box = ao_pad_box; query.channels = AO_PAD_ALL_PINS; query.armed = ao_pad_armed; - PRINTD ("query tick %d box %d channels %02x arm %d arm_status %d igniter %d\n", + PRINTD ("query tick %d box %d channels %02x arm %d arm_status %d igniter %d,%d,%d,%d\n", query.tick, query.box, query.channels, query.armed, - query.arm_status, query.igniter_status); + query.arm_status, + query.igniter_status[0], + query.igniter_status[1], + query.igniter_status[2], + query.igniter_status[3]); ao_radio_cmac_send(&query, sizeof (query)); break; case AO_LAUNCH_FIRE: -- cgit v1.2.3 From 3e7e8e21f2bb823cb6e74c73d0feddbc3a891107 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 29 Aug 2012 11:23:13 -0700 Subject: altos: SPI radio - use 1->0 for 'done' and 0->1 for 'ready' This changes how the SPI radio protocol uses the interrupt line. Instead of a pulse indicating operation done, this now uses a 0 value for done and a 1 value for ready. The key distinction is that the master can tell when the slave is waiting for the next command instead of hoping that it got done 'soon enough'. Signed-off-by: Keith Packard --- src/drivers/ao_radio_master.c | 112 ++++++++++++++++++++++-------------------- src/drivers/ao_radio_slave.c | 90 ++++++++++++++++----------------- 2 files changed, 101 insertions(+), 101 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_radio_master.c b/src/drivers/ao_radio_master.c index bfbcb1f8..73ac3c03 100644 --- a/src/drivers/ao_radio_master.c +++ b/src/drivers/ao_radio_master.c @@ -22,13 +22,16 @@ static __xdata struct ao_radio_spi_reply ao_radio_spi_reply; static __xdata struct ao_radio_spi_request ao_radio_spi_request; -static volatile __xdata uint8_t ao_radio_done = 1; +static volatile __xdata uint8_t ao_radio_wait_mode; +static volatile __xdata uint8_t ao_radio_done = 0; +static volatile __xdata uint8_t ao_radio_ready = 1; static __xdata uint8_t ao_radio_mutex; +static __xdata uint8_t ao_radio_aes_seq; __xdata int8_t ao_radio_cmac_rssi; #if 0 -#define PRINTD(...) do { printf ("\r%s: ", __func__); printf(__VA_ARGS__); flush(); } while(0) +#define PRINTD(...) do { printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0) #else #define PRINTD(...) #endif @@ -36,24 +39,18 @@ __xdata int8_t ao_radio_cmac_rssi; static void ao_radio_isr(void) { - ao_exti_disable(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN); - ao_radio_done = 1; - ao_wakeup((void *) &ao_radio_done); -} - -static void -ao_radio_master_delay(void) -{ -// uint16_t i; -// for (i = 0; i < 1000; i++) -// ao_arch_nop(); - ao_delay(1); + if (ao_gpio_get(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN, AO_RADIO_INT)) { + ao_radio_ready = 1; + ao_wakeup((void *) &ao_radio_ready); + } else { + ao_radio_done = 1; + ao_wakeup((void *) &ao_radio_done); + } } static void ao_radio_master_start(void) { - ao_radio_master_delay(); ao_spi_get_bit(AO_RADIO_CS_PORT, AO_RADIO_CS_PIN, AO_RADIO_CS, AO_RADIO_SPI_BUS, AO_SPI_SPEED_200kHz); @@ -64,32 +61,50 @@ ao_radio_master_stop(void) { ao_spi_put_bit(AO_RADIO_CS_PORT, AO_RADIO_CS_PIN, AO_RADIO_CS, AO_RADIO_SPI_BUS); -// ao_delay(1); } static uint8_t ao_radio_master_send(void) { - if (!ao_radio_done) - printf ("radio not done in ao_radio_master_send\n"); + uint8_t ret; + PRINTD("send %d\n", ao_radio_spi_request.len); ao_radio_done = 0; - ao_exti_enable(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN); + + /* Wait for radio chip to be ready for a command + */ + + PRINTD("Waiting radio ready\n"); + cli(); + ao_radio_ready = ao_gpio_get(AO_RADIO_INT_PORT, + AO_RADIO_INT_PIN, AO_RADIO_INT); + ret = 0; + while (!ao_radio_ready) { + ret = ao_sleep((void *) &ao_radio_ready); + if (ret) + break; + } + sei(); + if (ret) + return 0; + + PRINTD("radio_ready %d radio_done %d\n", ao_radio_ready, ao_radio_done); + + /* Send the command + */ + ao_radio_wait_mode = 0; ao_radio_master_start(); ao_spi_send(&ao_radio_spi_request, ao_radio_spi_request.len, AO_RADIO_SPI_BUS); ao_radio_master_stop(); + PRINTD("waiting for send done %d\n", ao_radio_done); cli(); while (!ao_radio_done) - if (ao_sleep((void *) &ao_radio_done)) { - printf ("ao_radio_master awoken\n"); + if (ao_sleep((void *) &ao_radio_done)) break; - } sei(); - PRINTD ("sent, radio done %d\n", ao_radio_done); - if (!ao_radio_done) - printf ("radio didn't finish after ao_radio_master_send\n"); + PRINTD ("sent, radio done %d isr_0 %d isr_1 %d\n", ao_radio_done, isr_0_count, isr_1_count); return ao_radio_done; } @@ -112,15 +127,6 @@ ao_radio_put(void) static void ao_radio_get_data(__xdata void *d, uint8_t size) { - uint8_t ret; - - PRINTD ("send fetch req\n"); - ao_radio_spi_request.len = AO_RADIO_SPI_REQUEST_HEADER_LEN; - ao_radio_spi_request.request = AO_RADIO_SPI_RECV_FETCH; - ao_radio_spi_request.recv_len = size; - ret = ao_radio_master_send(); - PRINTD ("fetch req sent %d\n", ret); - PRINTD ("fetch\n"); ao_radio_master_start(); ao_spi_recv(&ao_radio_spi_reply, @@ -167,21 +173,17 @@ ao_radio_recv(__xdata void *d, uint8_t size) return 0; } ao_radio_get_data(d, size); - recv = ao_radio_spi_reply.status; - ao_radio_put(); return recv; } -int8_t -ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant +static void +ao_radio_cmac_set_key(void) { - if (len > AO_CMAC_MAX_LEN) - return AO_RADIO_CMAC_LEN_ERROR; - - PRINTD ("cmac_send: send %d\n", len); + if (ao_radio_aes_seq == ao_config_aes_seq) + return; /* Set the key. */ PRINTD ("set key\n"); @@ -190,6 +192,18 @@ ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant ao_radio_master_send(); ao_radio_put(); PRINTD ("key set\n"); + ao_radio_aes_seq = ao_config_aes_seq; +} + +int8_t +ao_radio_cmac_send(__xdata void *packet, uint8_t len) __reentrant +{ + if (len > AO_CMAC_MAX_LEN) + return AO_RADIO_CMAC_LEN_ERROR; + + ao_radio_cmac_set_key(); + + PRINTD ("cmac_send: send %d\n", len); /* Send the data */ @@ -212,21 +226,14 @@ ao_radio_cmac_recv(__xdata void *packet, uint8_t len, uint16_t timeout) __reentr if (len > AO_CMAC_MAX_LEN) return AO_RADIO_CMAC_LEN_ERROR; - /* Set the key. - */ - PRINTD ("setting key\n"); - ao_radio_get(AO_RADIO_SPI_CMAC_KEY, AO_AES_LEN); - ao_radio_spi_request.timeout = timeout; - ao_xmemcpy(&ao_radio_spi_request.payload, &ao_config.aes_key, AO_AES_LEN); - recv = ao_radio_master_send(); - ao_radio_put(); - PRINTD ("key set: %d\n", recv); + ao_radio_cmac_set_key(); /* Recv the data */ PRINTD ("queuing recv\n"); ao_radio_get(AO_RADIO_SPI_CMAC_RECV, 0); ao_radio_spi_request.recv_len = len; + ao_radio_spi_request.timeout = timeout; recv = ao_radio_master_send(); PRINTD ("recv queued: %d\n", recv); if (!recv) { @@ -300,7 +307,8 @@ ao_radio_init(void) ao_enable_port(AO_RADIO_INT_PORT); ao_exti_setup(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN, - AO_EXTI_MODE_FALLING, + AO_EXTI_MODE_RISING|AO_EXTI_MODE_FALLING, ao_radio_isr); + ao_exti_enable(AO_RADIO_INT_PORT, AO_RADIO_INT_PIN); ao_cmd_register(&ao_radio_cmds[0]); } diff --git a/src/drivers/ao_radio_slave.c b/src/drivers/ao_radio_slave.c index ab23894f..9a01bbfa 100644 --- a/src/drivers/ao_radio_slave.c +++ b/src/drivers/ao_radio_slave.c @@ -23,54 +23,69 @@ static __xdata struct ao_radio_spi_reply ao_radio_spi_reply; static __xdata struct ao_radio_spi_request ao_radio_spi_request; -static __xdata uint8_t ao_radio_spi_recv_request; -static __xdata uint8_t ao_radio_spi_recv_len; -static __xdata uint16_t ao_radio_spi_recv_timeout; +static __xdata uint8_t slave_state; static void -ao_radio_slave_signal(void) +ao_radio_slave_low(void) { + uint16_t i; + + if (slave_state != 1) + ao_panic(1); + ao_led_toggle(AO_LED_GREEN); ao_gpio_set(AO_RADIO_SLAVE_INT_PORT, AO_RADIO_SLAVE_INT_BIT, AO_RADIO_SLAVE_INT_PIN, 0); - ao_arch_nop(); - ao_arch_nop(); - ao_arch_nop(); + for (i = 0; i < 1000; i++) + ao_arch_nop(); + slave_state = 0; +} + +static void +ao_radio_slave_high(void) +{ + if (slave_state != 0) + ao_panic(2); + ao_led_toggle(AO_LED_RED); ao_gpio_set(AO_RADIO_SLAVE_INT_PORT, AO_RADIO_SLAVE_INT_BIT, AO_RADIO_SLAVE_INT_PIN, 1); + slave_state = 1; } static void ao_radio_slave_spi(void) { - uint8_t need_signal = 0; - ao_spi_get_slave(AO_RADIO_SLAVE_BUS); for (;;) { ao_spi_recv(&ao_radio_spi_request, (2 << 13) | sizeof (ao_radio_spi_request), AO_RADIO_SLAVE_BUS); - if (need_signal) { - ao_radio_slave_signal(); - need_signal = 0; - } + ao_radio_slave_high(); ao_spi_recv_wait(); switch (ao_radio_spi_request.request) { case AO_RADIO_SPI_RECV: - case AO_RADIO_SPI_CMAC_RECV: + + /* XXX monitor CS to interrupt the receive */ + ao_config.radio_setting = ao_radio_spi_request.setting; - ao_radio_spi_recv_request = ao_radio_spi_request.request; - ao_radio_spi_recv_len = ao_radio_spi_request.recv_len; - ao_radio_spi_recv_timeout = ao_radio_spi_request.timeout; - ao_wakeup(&ao_radio_spi_recv_len); + ao_radio_spi_reply.status = ao_radio_recv(&ao_radio_spi_reply.payload, + ao_radio_spi_request.recv_len); + ao_radio_spi_reply.rssi = 0; + ao_spi_send(&ao_radio_spi_reply, + AO_RADIO_SPI_REPLY_HEADER_LEN + ao_radio_spi_request.recv_len, + AO_RADIO_SLAVE_BUS); + ao_radio_slave_low(); + ao_spi_send_wait(); continue; - case AO_RADIO_SPI_RECV_FETCH: + case AO_RADIO_SPI_CMAC_RECV: + ao_config.radio_setting = ao_radio_spi_request.setting; + ao_radio_spi_reply.status = ao_radio_cmac_recv(&ao_radio_spi_reply.payload, + ao_radio_spi_request.recv_len, + ao_radio_spi_request.timeout); + ao_radio_spi_reply.rssi = ao_radio_cmac_rssi; ao_spi_send(&ao_radio_spi_reply, - ao_radio_spi_request.recv_len, + AO_RADIO_SPI_REPLY_HEADER_LEN + ao_radio_spi_request.recv_len, AO_RADIO_SLAVE_BUS); - ao_radio_slave_signal(); + ao_radio_slave_low(); ao_spi_send_wait(); continue; - case AO_RADIO_SPI_RECV_ABORT: - ao_radio_recv_abort(); - break; case AO_RADIO_SPI_SEND: ao_config.radio_setting = ao_radio_spi_request.setting; ao_radio_send(&ao_radio_spi_request.payload, @@ -96,38 +111,15 @@ ao_radio_slave_spi(void) ao_radio_test(0); break; } - need_signal = 1; - } -} - -static void -ao_radio_slave_recv(void) -{ - uint8_t len; - for (;;) { - while (!ao_radio_spi_recv_len) - ao_sleep(&ao_radio_spi_recv_len); - len = ao_radio_spi_recv_len; - ao_radio_spi_recv_len = 0; - if (ao_radio_spi_recv_request == AO_RADIO_SPI_RECV) { - ao_radio_spi_reply.status = ao_radio_recv(&ao_radio_spi_reply.payload, len); - ao_radio_spi_reply.rssi = 0; - } else { - ao_radio_spi_reply.status = ao_radio_cmac_recv(&ao_radio_spi_reply.payload, len, - ao_radio_spi_recv_timeout); - ao_radio_spi_reply.rssi = ao_radio_cmac_rssi; - } - ao_radio_slave_signal(); + ao_radio_slave_low(); } } static __xdata struct ao_task ao_radio_slave_spi_task; -static __xdata struct ao_task ao_radio_slave_recv_task; void ao_radio_slave_init(void) { ao_add_task(&ao_radio_slave_spi_task, ao_radio_slave_spi, "radio_spi"); - ao_add_task(&ao_radio_slave_recv_task, ao_radio_slave_recv, "radio_recv"); - ao_enable_output(AO_RADIO_SLAVE_INT_PORT, AO_RADIO_SLAVE_INT_BIT, AO_RADIO_SLAVE_INT_PIN, 1); + ao_enable_output(AO_RADIO_SLAVE_INT_PORT, AO_RADIO_SLAVE_INT_BIT, AO_RADIO_SLAVE_INT_PIN, 0); } -- cgit v1.2.3 From aea10c107dff2643677a9c8d1fc41e14f4a66049 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 29 Aug 2012 11:25:36 -0700 Subject: altos: spiradio debug serial is port 1, not port 0 The SPI link uses port 0; it seems like the having the two try to share the same wires is a bad plan. Signed-off-by: Keith Packard --- src/spiradio-v0.1/ao_pins.h | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/spiradio-v0.1/ao_pins.h b/src/spiradio-v0.1/ao_pins.h index 363eafa4..f38aade6 100644 --- a/src/spiradio-v0.1/ao_pins.h +++ b/src/spiradio-v0.1/ao_pins.h @@ -24,12 +24,15 @@ #define HAS_USB 0 #define HAS_BEEP 0 #define HAS_GPS 0 -#define HAS_SERIAL_0 1 -#define HAS_SERIAL_0_ALT_1 1 +#define HAS_SERIAL_0 0 +#define HAS_SERIAL_0_ALT_1 0 #define HAS_SERIAL_0_HW_FLOW 0 -#define USE_SERIAL_0_STDIN 1 -#define DELAY_SERIAL_0_STDIN 0 -#define HAS_SERIAL_1 0 +#define USE_SERIAL_0_STDIN 0 +#define HAS_SERIAL_1 1 +#define HAS_SERIAL_1_ALT_1 1 +#define HAS_SERIAL_1_HW_FLOW 0 +#define USE_SERIAL_1_STDIN 1 +#define DELAY_SERIAL_1_STDIN 0 #define HAS_ADC 0 #define HAS_DBG 0 #define HAS_EEPROM 0 @@ -38,8 +41,8 @@ #define DBG_ON_P1 0 #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 0 -#define AO_LED_RED 2 -#define AO_LED_GREEN 1 +#define AO_LED_RED 1 +#define AO_LED_GREEN 2 #define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) #define HAS_EXTERNAL_TEMP 0 #define HAS_ACCEL_REF 0 -- cgit v1.2.3 From 72d44d14aefcb754b871835aec8d265771357212 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 30 Aug 2012 16:14:57 -0500 Subject: altos: Disable debug printfs and fix pad ignite time for telefire Signed-off-by: Keith Packard --- src/drivers/ao_pad.c | 2 +- src/drivers/ao_pad.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index cd901aa3..e47859a5 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -24,7 +24,7 @@ static __xdata uint8_t ao_pad_ignite; static __xdata struct ao_pad_command command; static __xdata struct ao_pad_query query; -#if 1 +#if 0 #define PRINTD(...) printf(__VA_ARGS__) #define FLUSHD() flush() #else diff --git a/src/drivers/ao_pad.h b/src/drivers/ao_pad.h index 3b0cf1fe..ae4f3db4 100644 --- a/src/drivers/ao_pad.h +++ b/src/drivers/ao_pad.h @@ -50,7 +50,7 @@ struct ao_pad_query { */ #define AO_PAD_FIRE 3 -#define AO_PAD_FIRE_TIME AO_MS_TO_TICKS(1000) +#define AO_PAD_FIRE_TIME AO_MS_TO_TICKS(250) #define AO_PAD_ARM_STATUS_DISARMED 0 #define AO_PAD_ARM_STATUS_ARMED 1 -- cgit v1.2.3 From 2c59954fdf204f443d9bb28c4a66a30f925ef348 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 30 Aug 2012 16:16:52 -0500 Subject: altos: Shuffle LCO functions around, add telelco first cut Pull LCO functions shared between LCO UI and command line into ao_lco_funcs.c. Import bits for telelco. Signed-off-by: Keith Packard --- src/drivers/ao_lco_cmd.c | 113 ++++++++++----------- src/drivers/ao_lco_func.c | 70 +++++++++++++ src/drivers/ao_lco_func.h | 32 ++++++ src/telelco-v0.1/Makefile | 97 ++++++++++++++++++ src/telelco-v0.1/ao_lco.c | 231 ++++++++++++++++++++++++++++++++++++++++++ src/telelco-v0.1/ao_lco.h | 24 +++++ src/telelco-v0.1/ao_pins.h | 224 ++++++++++++++++++++++++++++++++++++++++ src/telelco-v0.1/ao_telelco.c | 69 +++++++++++++ 8 files changed, 799 insertions(+), 61 deletions(-) create mode 100644 src/drivers/ao_lco_func.c create mode 100644 src/drivers/ao_lco_func.h create mode 100644 src/telelco-v0.1/Makefile create mode 100644 src/telelco-v0.1/ao_lco.c create mode 100644 src/telelco-v0.1/ao_lco.h create mode 100644 src/telelco-v0.1/ao_pins.h create mode 100644 src/telelco-v0.1/ao_telelco.c (limited to 'src') diff --git a/src/drivers/ao_lco_cmd.c b/src/drivers/ao_lco_cmd.c index b49c9dba..9c35b324 100644 --- a/src/drivers/ao_lco_cmd.c +++ b/src/drivers/ao_lco_cmd.c @@ -18,70 +18,81 @@ #include #include #include +#include #include -static __xdata struct ao_pad_command command; -static __xdata struct ao_pad_query query; -static __pdata uint16_t launch_box; -static __pdata uint8_t launch_channels; +static __pdata uint16_t lco_box; +static __pdata uint8_t lco_channels; static __pdata uint16_t tick_offset; static void -launch_args(void) __reentrant +lco_args(void) __reentrant { ao_cmd_decimal(); - launch_box = ao_cmd_lex_i; + lco_box = ao_cmd_lex_i; ao_cmd_hex(); - launch_channels = ao_cmd_lex_i; + lco_channels = ao_cmd_lex_i; } +static struct ao_pad_query ao_pad_query; +static uint16_t tick_offset; + static int8_t -launch_query(void) +lco_query(void) { uint8_t i; int8_t r = AO_RADIO_CMAC_OK; - tick_offset = ao_time(); for (i = 0; i < 10; i++) { printf ("."); flush(); - command.tick = ao_time(); - command.box = launch_box; - command.cmd = AO_LAUNCH_QUERY; - command.channels = launch_channels; - ao_radio_cmac_send(&command, sizeof (command)); - r = ao_radio_cmac_recv(&query, sizeof (query), AO_MS_TO_TICKS(500)); + r = ao_lco_query(lco_box, &ao_pad_query, &tick_offset); if (r == AO_RADIO_CMAC_OK) break; } - tick_offset -= query.tick; printf("\n"); flush(); return r; } static void -launch_report_cmd(void) __reentrant +lco_arm(void) +{ + ao_lco_arm(lco_box, lco_channels, tick_offset); +} + +static void +lco_ignite(void) +{ + ao_lco_ignite(lco_box, lco_channels, tick_offset); +} + +static void +lco_report_cmd(void) __reentrant { int8_t r; uint8_t c; - launch_args(); + lco_args(); if (ao_cmd_status != ao_cmd_success) return; - r = launch_query(); + r = lco_query(); switch (r) { case AO_RADIO_CMAC_OK: - switch (query.arm_status) { - case ao_igniter_ready: - case ao_igniter_active: + switch (ao_pad_query.arm_status) { + case AO_PAD_ARM_STATUS_ARMED: printf ("Armed: "); break; - default: + case AO_PAD_ARM_STATUS_DISARMED: printf("Disarmed: "); + break; + case AO_PAD_ARM_STATUS_UNKNOWN: + default: + printf("Unknown: "); + break; } for (c = 0; c < AO_PAD_MAX_CHANNELS; c++) { - if (query.channels & (1 << c)) { + if (ao_pad_query.channels & (1 << c)) { printf (" pad %d ", c); - switch (query.igniter_status[c]) { + switch (ao_pad_query.igniter_status[c]) { default: printf("unknown, "); break; @@ -106,39 +117,19 @@ launch_report_cmd(void) __reentrant } static void -launch_arm(void) __reentrant -{ - command.tick = ao_time() - tick_offset; - command.box = launch_box; - command.cmd = AO_LAUNCH_ARM; - command.channels = launch_channels; - ao_radio_cmac_send(&command, sizeof (command)); -} - -static void -launch_ignite(void) __reentrant -{ - command.tick = ao_time() - tick_offset; - command.box = launch_box; - command.cmd = AO_LAUNCH_FIRE; - command.channels = 0; - ao_radio_cmac_send(&command, sizeof (command)); -} - -static void -launch_fire_cmd(void) __reentrant +lco_fire_cmd(void) __reentrant { static __xdata struct ao_pad_command command; uint8_t secs; uint8_t i; int8_t r; - launch_args(); + lco_args(); ao_cmd_decimal(); secs = ao_cmd_lex_i; if (ao_cmd_status != ao_cmd_success) return; - r = launch_query(); + r = lco_query(); if (r != AO_RADIO_CMAC_OK) { printf("query failed %d\n", r); return; @@ -146,7 +137,7 @@ launch_fire_cmd(void) __reentrant for (i = 0; i < 4; i++) { printf("arm %d\n", i); flush(); - launch_arm(); + lco_arm(); } secs = secs * 10 - 5; @@ -154,40 +145,40 @@ launch_fire_cmd(void) __reentrant secs = 100; for (i = 0; i < secs; i++) { printf("fire %d\n", i); flush(); - launch_ignite(); + lco_ignite(); ao_delay(AO_MS_TO_TICKS(100)); } } static void -launch_arm_cmd(void) __reentrant +lco_arm_cmd(void) __reentrant { uint8_t i; int8_t r; - launch_args(); - r = launch_query(); + lco_args(); + r = lco_query(); if (r != AO_RADIO_CMAC_OK) { printf("query failed %d\n", r); return; } for (i = 0; i < 4; i++) - launch_arm(); + lco_arm(); } static void -launch_ignite_cmd(void) __reentrant +lco_ignite_cmd(void) __reentrant { uint8_t i; - launch_args(); + lco_args(); for (i = 0; i < 4; i++) - launch_ignite(); + lco_ignite(); } static __code struct ao_cmds ao_lco_cmds[] = { - { launch_report_cmd, "l \0Get remote launch status" }, - { launch_fire_cmd, "F \0Fire remote igniter" }, - { launch_arm_cmd, "a \0Arm remote igniter" }, - { launch_ignite_cmd, "i \0Pulse remote igniter" }, + { lco_report_cmd, "l \0Get remote status" }, + { lco_fire_cmd, "F \0Fire remote igniters" }, + { lco_arm_cmd, "a \0Arm remote igniter" }, + { lco_ignite_cmd, "i \0Pulse remote igniter" }, { 0, NULL }, }; diff --git a/src/drivers/ao_lco_func.c b/src/drivers/ao_lco_func.c new file mode 100644 index 00000000..152b5d1b --- /dev/null +++ b/src/drivers/ao_lco_func.c @@ -0,0 +1,70 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include + +static __xdata struct ao_pad_command command; +static __xdata uint8_t ao_lco_mutex; + +int8_t +ao_lco_query(uint16_t box, struct ao_pad_query *query, uint16_t *tick_offset) +{ + uint8_t i; + int8_t r; + uint16_t time; + + ao_mutex_get(&ao_lco_mutex); + time = ao_time(); + command.tick = time; + command.box = box; + command.cmd = AO_LAUNCH_QUERY; + command.channels = 0; + ao_radio_cmac_send(&command, sizeof (command)); + r = ao_radio_cmac_recv(query, sizeof (*query), AO_MS_TO_TICKS(500)); + if (r == AO_RADIO_CMAC_OK) + *tick_offset = time - query->tick; + ao_mutex_put(&ao_lco_mutex); + return r; +} + +void +ao_lco_arm(uint16_t box, uint8_t channels, uint16_t tick_offset) +{ + ao_mutex_get(&ao_lco_mutex); + command.tick = ao_time() - tick_offset; + command.box = box; + command.cmd = AO_LAUNCH_ARM; + command.channels = channels; + ao_radio_cmac_send(&command, sizeof (command)); + ao_mutex_put(&ao_lco_mutex); +} + +void +ao_lco_ignite(uint16_t box, uint8_t channels, uint16_t tick_offset) +{ + ao_mutex_get(&ao_lco_mutex); + command.tick = ao_time() - tick_offset; + command.box = box; + command.cmd = AO_LAUNCH_FIRE; + command.channels = channels; + ao_radio_cmac_send(&command, sizeof (command)); + ao_mutex_put(&ao_lco_mutex); +} + diff --git a/src/drivers/ao_lco_func.h b/src/drivers/ao_lco_func.h new file mode 100644 index 00000000..dccf602a --- /dev/null +++ b/src/drivers/ao_lco_func.h @@ -0,0 +1,32 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_LCO_FUNC_H_ +#define _AO_LCO_FUNC_H_ + +#include + +int8_t +ao_lco_query(uint16_t box, struct ao_pad_query *query, uint16_t *tick_offset); + +void +ao_lco_arm(uint16_t box, uint8_t channels, uint16_t tick_offset); + +void +ao_lco_ignite(uint16_t box, uint8_t channels, uint16_t tick_offset); + +#endif /* _AO_LCO_FUNC_H_ */ diff --git a/src/telelco-v0.1/Makefile b/src/telelco-v0.1/Makefile new file mode 100644 index 00000000..32115c42 --- /dev/null +++ b/src/telelco-v0.1/Makefile @@ -0,0 +1,97 @@ +# +# AltOS build for TeleLCO +# +# + +include ../stm/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_companion.h \ + ao_data.h \ + ao_sample.h \ + ao_pins.h \ + ao_product.h \ + ao_cc_spi.h \ + ao_seven_segment.h \ + ao_lco.h \ + ao_lco_cmd.h \ + ao_lco_func.h \ + ao_radio_spi.h \ + ao_radio_cmac.h \ + stm32l.h + +# +# Common AltOS sources +# + +#PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 + +ALTOS_SRC = \ + ao_interrupt.c \ + ao_product.c \ + ao_romconfig.c \ + ao_cmd.c \ + ao_config.c \ + ao_task.c \ + ao_led.c \ + ao_stdio.c \ + ao_panic.c \ + ao_timer.c \ + ao_mutex.c \ + ao_freq.c \ + ao_dma_stm.c \ + ao_spi_stm.c \ + ao_beep_stm.c \ + ao_storage.c \ + ao_eeprom_stm.c \ + ao_lcd_stm.c \ + ao_usb_stm.c \ + ao_exti_stm.c \ + ao_radio_master.c \ + ao_seven_segment.c \ + ao_quadrature.c \ + ao_button.c \ + ao_event.c \ + ao_lco.c \ + ao_lco_cmd.c \ + ao_lco_func.c \ + ao_radio_cmac_cmd.c + +PRODUCT=TeleLCO-v0.1 +PRODUCT_DEF=-DMEGAMETRUM +IDPRODUCT=0x0023 + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g + +PROGNAME=telelco-v0.1 +PROG=$(PROGNAME)-$(VERSION).elf + +SRC=$(ALTOS_SRC) ao_telelco.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) + +$(PROG): Makefile $(OBJ) altos.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc + +../altitude.h: make-altitude + nickle $< > $@ + +$(OBJ): $(INC) + +ao_product.h: ao-make-product.5c ../Version + $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ + +distclean: clean + +clean: + rm -f *.o $(PROGNAME)-*.elf + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/telelco-v0.1/ao_lco.c b/src/telelco-v0.1/ao_lco.c new file mode 100644 index 00000000..7ecee192 --- /dev/null +++ b/src/telelco-v0.1/ao_lco.c @@ -0,0 +1,231 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include +#include +#include +#include + +#if 1 +#define PRINTD(...) do { printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0) +#else +#define PRINTD(...) +#endif + +#define AO_LCO_PAD_DIGIT 0 +#define AO_LCO_BOX_DIGIT_1 1 +#define AO_LCO_BOX_DIGIT_10 2 + +#define AO_NUM_BOX 10 + +static uint8_t ao_lco_mutex; +static uint8_t ao_lco_pad; +static uint8_t ao_lco_box; +static uint8_t ao_lco_armed; +static uint8_t ao_lco_firing; +static uint8_t ao_lco_valid; + +static void +ao_lco_set_pad(void) +{ + ao_seven_segment_set(AO_LCO_PAD_DIGIT, ao_lco_pad); +} + +static void +ao_lco_set_box(void) +{ + ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, ao_lco_box % 10); + ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, ao_lco_box / 10); +} + +static void +ao_lco_input(void) +{ + static struct ao_event event; + + ao_lco_set_pad(); + ao_lco_set_box(); + for (;;) { + ao_event_get(&event); + PRINTD("event type %d unit %d value %d\n", + event.type, event.unit, event.value); + switch (event.type) { + case AO_EVENT_QUADRATURE: + switch (event.unit) { + case AO_QUADRATURE_PAD: + if (!ao_lco_armed) { + ao_lco_pad = event.value & 3; + ao_lco_valid = 0; + ao_quadrature_count[AO_QUADRATURE_PAD] = ao_lco_pad; + ao_lco_set_pad(); + } + break; + case AO_QUADRATURE_BOX: + if (!ao_lco_armed) { + ao_lco_box = event.value; + ao_lco_valid = 0; + while (ao_lco_box >= AO_NUM_BOX) + ao_lco_box -= AO_NUM_BOX; + while (ao_lco_box < 0) + ao_lco_box += AO_NUM_BOX; + ao_quadrature_count[AO_QUADRATURE_PAD] = ao_lco_box; + ao_lco_set_box(); + } + break; + } + break; + case AO_EVENT_BUTTON: + switch (event.unit) { + case AO_BUTTON_ARM: + ao_lco_armed = event.value; + PRINTD("Armed %d\n", ao_lco_armed); + ao_wakeup(&ao_lco_armed); + break; + case AO_BUTTON_FIRE: + if (ao_lco_armed) { + ao_lco_firing = event.value; + PRINTD("Firing %d\n", ao_lco_firing); + ao_wakeup(&ao_lco_armed); + } + break; + } + break; + } + } +} + +static AO_LED_TYPE continuity_led[AO_LED_CONTINUITY_NUM] = { +#ifdef AO_LED_CONTINUITY_0 + AO_LED_CONTINUITY_0, +#endif +#ifdef AO_LED_CONTINUITY_1 + AO_LED_CONTINUITY_1, +#endif +#ifdef AO_LED_CONTINUITY_2 + AO_LED_CONTINUITY_2, +#endif +#ifdef AO_LED_CONTINUITY_3 + AO_LED_CONTINUITY_3, +#endif +#ifdef AO_LED_CONTINUITY_4 + AO_LED_CONTINUITY_4, +#endif +#ifdef AO_LED_CONTINUITY_5 + AO_LED_CONTINUITY_5, +#endif +#ifdef AO_LED_CONTINUITY_6 + AO_LED_CONTINUITY_6, +#endif +#ifdef AO_LED_CONTINUITY_7 + AO_LED_CONTINUITY_7, +#endif +}; + +static uint16_t ao_lco_tick_offset; + +static void +ao_lco_update(void) +{ + int8_t r; + uint8_t c; + struct ao_pad_query query; + + r = ao_lco_query(ao_lco_box, &query, &ao_lco_tick_offset); + if (r != AO_RADIO_CMAC_OK) { + PRINTD("lco_query return %d\n", r); + return; + } + +#if 0 + PRINTD("lco_query success arm_status %d i0 %d i1 %d i2 %d i3 %d\n", + query.arm_status, + query.igniter_status[0], + query.igniter_status[1], + query.igniter_status[2], + query.igniter_status[3]); +#endif + + ao_lco_valid = 1; + if (query.arm_status) + ao_led_on(AO_LED_REMOTE_ARM); + else + ao_led_off(AO_LED_REMOTE_ARM); + for (c = 0; c < AO_LED_CONTINUITY_NUM; c++) { + uint8_t status; + + if (query.channels & (1 << c)) + status = query.igniter_status[c]; + else + status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN; + if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN) + ao_led_on(continuity_led[c]); + else + ao_led_off(continuity_led[c]); + } +} + +static void +ao_lco_monitor(void) +{ + uint16_t delay; + + for (;;) { + if (ao_lco_armed && ao_lco_firing) { + PRINTD("Firing box %d pad %d: valid %d\n", + ao_lco_box, ao_lco_pad, ao_lco_valid); + if (!ao_lco_valid) + ao_lco_update(); + if (ao_lco_valid) + ao_lco_ignite(ao_lco_box, ao_lco_pad, ao_lco_tick_offset); + } else { + ao_lco_update(); + } + if (ao_lco_armed && ao_lco_firing) + delay = AO_MS_TO_TICKS(100); + else + delay = AO_SEC_TO_TICKS(1); + ao_alarm(delay); + ao_sleep(&ao_lco_armed); + ao_clear_alarm(); + } +} + +static void +ao_lco_arm_warn(void) +{ + for (;;) { + while (!ao_lco_armed) + ao_sleep(&ao_lco_armed); + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + ao_delay(AO_MS_TO_TICKS(200)); + } +} + +static struct ao_task ao_lco_input_task; +static struct ao_task ao_lco_monitor_task; +static struct ao_task ao_lco_arm_warn_task; + +void +ao_lco_init(void) +{ + ao_add_task(&ao_lco_input_task, ao_lco_input, "lco input"); + ao_add_task(&ao_lco_monitor_task, ao_lco_monitor, "lco monitor"); + ao_add_task(&ao_lco_arm_warn_task, ao_lco_arm_warn, "lco arm warn"); +} diff --git a/src/telelco-v0.1/ao_lco.h b/src/telelco-v0.1/ao_lco.h new file mode 100644 index 00000000..253f9702 --- /dev/null +++ b/src/telelco-v0.1/ao_lco.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_LCO_H_ +#define _AO_LCO_H_ + +void +ao_lco_init(void); + +#endif /* _AO_LCO_H_ */ diff --git a/src/telelco-v0.1/ao_pins.h b/src/telelco-v0.1/ao_pins.h new file mode 100644 index 00000000..60cf018f --- /dev/null +++ b/src/telelco-v0.1/ao_pins.h @@ -0,0 +1,224 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#ifndef _AO_PINS_H_ +#define _AO_PINS_H_ + +/* 8MHz High speed external crystal */ +#define AO_HSE 8000000 + +/* PLLVCO = 96MHz (so that USB will work) */ +#define AO_PLLMUL 12 +#define AO_RCC_CFGR_PLLMUL (STM_RCC_CFGR_PLLMUL_12) + +/* SYSCLK = 32MHz (no need to go faster than CPU) */ +#define AO_PLLDIV 3 +#define AO_RCC_CFGR_PLLDIV (STM_RCC_CFGR_PLLDIV_3) + +/* HCLK = 32MHz (CPU clock) */ +#define AO_AHB_PRESCALER 1 +#define AO_RCC_CFGR_HPRE_DIV STM_RCC_CFGR_HPRE_DIV_1 + +/* Run APB1 at 16MHz (HCLK/2) */ +#define AO_APB1_PRESCALER 2 +#define AO_RCC_CFGR_PPRE1_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +/* Run APB2 at 16MHz (HCLK/2) */ +#define AO_APB2_PRESCALER 2 +#define AO_RCC_CFGR_PPRE2_DIV STM_RCC_CFGR_PPRE2_DIV_2 + +#define HAS_EEPROM 1 +#define USE_INTERNAL_FLASH 1 +#define HAS_USB 1 +#define HAS_BEEP 1 +#define HAS_RADIO 1 +#define HAS_TELEMETRY 0 +#define HAS_AES 1 + +#define HAS_SPI_1 1 +#define SPI_1_PA5_PA6_PA7 1 +#define SPI_1_PB3_PB4_PB5 0 +#define SPI_1_PE13_PE14_PE15 0 + +#define HAS_SPI_2 1 +#define SPI_2_PB13_PB14_PB15 1 +#define SPI_2_PD1_PD3_PD4 0 +#define SPI_2_GPIO (&stm_gpiob) +#define SPI_2_SCK 13 +#define SPI_2_MISO 14 +#define SPI_2_MOSI 15 + +#define HAS_I2C_1 0 + +#define HAS_I2C_2 0 + +#define PACKET_HAS_SLAVE 0 +#define PACKET_HAS_MASTER 0 + +/* + * Radio is a cc1111 connected via SPI + */ +#define AO_RADIO_CAL_DEFAULT 1186611 + +#define AO_RADIO_SPI_BUS AO_SPI_2_PB13_PB14_PB15 +#define AO_RADIO_CS_PORT (&stm_gpiob) +#define AO_RADIO_CS_PIN 12 + +#define AO_RADIO_INT_PORT (&stm_gpioc) +#define AO_RADIO_INT_PIN 14 + +#define LOW_LEVEL_DEBUG 0 + +#define LED_PORT_ENABLE STM_RCC_AHBENR_GPIOCEN +#define LED_PORT (&stm_gpioc) +#define LED_PIN_RED 7 +#define LED_PIN_GREEN 8 +#define LED_PIN_CONTINUITY_3 9 +#define LED_PIN_CONTINUITY_2 10 +#define LED_PIN_CONTINUITY_1 11 +#define LED_PIN_CONTINUITY_0 12 +#define LED_PIN_REMOTE_ARM 13 +#define AO_LED_RED (1 << LED_PIN_RED) +#define AO_LED_GREEN (1 << LED_PIN_GREEN) +#define AO_LED_CONTINUITY_3 (1 << LED_PIN_CONTINUITY_3) +#define AO_LED_CONTINUITY_2 (1 << LED_PIN_CONTINUITY_2) +#define AO_LED_CONTINUITY_1 (1 << LED_PIN_CONTINUITY_1) +#define AO_LED_CONTINUITY_0 (1 << LED_PIN_CONTINUITY_0) + +#define AO_LED_CONTINUITY_NUM 4 + +#define AO_LED_REMOTE_ARM (1 << LED_PIN_REMOTE_ARM) + +#define LEDS_AVAILABLE (AO_LED_RED | \ + AO_LED_GREEN | \ + AO_LED_CONTINUITY_3 | \ + AO_LED_CONTINUITY_2 | \ + AO_LED_CONTINUITY_1 | \ + AO_LED_CONTINUITY_0 | \ + AO_LED_REMOTE_ARM) + +/* LCD displays */ + +#define AO_LCD_STM_SEG_ENABLED_0 ( \ + (1 << 0) | /* PA1 */ \ + (1 << 1) | /* PA2 */ \ + (1 << 2) | /* PA3 */ \ + (1 << 3) | /* PA6 */ \ + (1 << 4) | /* PA7 */ \ + (1 << 5) | /* PB0 */ \ + (1 << 6) | /* PB1 */ \ + (1 << 7) | /* PB3 */ \ + (0 << 8) | /* PB4 */ \ + (0 << 9) | /* PB5 */ \ + (0 << 10) | /* PB10 */ \ + (0 << 11) | /* PB11 */ \ + (0 << 12) | /* PB12 */ \ + (0 << 13) | /* PB13 */ \ + (0 << 14) | /* PB14 */ \ + (0 << 15) | /* PB15 */ \ + (0 << 16) | /* PB8 */ \ + (0 << 17) | /* PA15 */ \ + (0 << 18) | /* PC0 */ \ + (0 << 19) | /* PC1 */ \ + (0 << 20) | /* PC2 */ \ + (0 << 21) | /* PC3 */ \ + (0 << 22) | /* PC4 */ \ + (0 << 23) | /* PC5 */ \ + (0 << 24) | /* PC6 */ \ + (0 << 25) | /* PC7 */ \ + (0 << 26) | /* PC8 */ \ + (0 << 27) | /* PC9 */ \ + (0 << 28) | /* PC10 or PD8 */ \ + (0 << 29) | /* PC11 or PD9 */ \ + (0 << 30) | /* PC12 or PD10 */ \ + (0 << 31)) /* PD2 or PD11 */ + +#define AO_LCD_STM_SEG_ENABLED_1 ( \ + (0 << 0) | /* PD12 */ \ + (0 << 1) | /* PD13 */ \ + (0 << 2) | /* PD14 */ \ + (0 << 3) | /* PD15 */ \ + (0 << 4) | /* PE0 */ \ + (0 << 5) | /* PE1 */ \ + (0 << 6) | /* PE2 */ \ + (0 << 7)) /* PE3 */ + +#define AO_LCD_STM_COM_ENABLED ( \ + (1 << 0) | /* PA8 */ \ + (1 << 1) | /* PA9 */ \ + (1 << 2) | /* PA10 */ \ + (0 << 3) | /* PB9 */ \ + (0 << 4) | /* PC10 */ \ + (0 << 5) | /* PC11 */ \ + (0 << 6)) /* PC12 */ + +#define AO_LCD_28_ON_C 0 + +#define AO_LCD_DUTY STM_LCD_CR_DUTY_1_4 + +#define AO_SEGMENT_0 0 +#define AO_SEGMENT_1 5 +#define AO_SEGMENT_2 1 +#define AO_SEGMENT_3 6 +#define AO_SEGMENT_4 4 +#define AO_SEGMENT_5 2 +#define AO_SEGMENT_6 3 +#define AO_SEGMENT_7 7 + +/* + * Use event queue for input devices + */ + +#define AO_EVENT 1 + +/* + * Knobs + */ + +#define AO_QUADRATURE_COUNT 2 +#define AO_QUADRATURE_MODE 0 + +#define AO_QUADRATURE_0_PORT &stm_gpioc +#define AO_QUADRATURE_0_A 3 +#define AO_QUADRATURE_0_B 2 + +#define AO_QUADRATURE_PAD 0 + +#define AO_QUADRATURE_1_PORT &stm_gpioc +#define AO_QUADRATURE_1_A 1 +#define AO_QUADRATURE_1_B 0 + +#define AO_QUADRATURE_BOX 1 + +/* + * Buttons + */ + +#define AO_BUTTON_COUNT 2 +#define AO_BUTTON_MODE AO_EXTI_MODE_PULL_UP + +#define AO_BUTTON_0_PORT &stm_gpioc +#define AO_BUTTON_0 4 + +#define AO_BUTTON_ARM 0 + +#define AO_BUTTON_1_PORT &stm_gpioc +#define AO_BUTTON_1 5 + +#define AO_BUTTON_FIRE 1 + +#endif /* _AO_PINS_H_ */ diff --git a/src/telelco-v0.1/ao_telelco.c b/src/telelco-v0.1/ao_telelco.c new file mode 100644 index 00000000..080a140b --- /dev/null +++ b/src/telelco-v0.1/ao_telelco.c @@ -0,0 +1,69 @@ +/* + * Copyright © 2011 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int +main(void) +{ + ao_clock_init(); + + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_GREEN); + ao_timer_init(); + + ao_spi_init(); + ao_dma_init(); + ao_exti_init(); + + ao_beep_init(); + ao_cmd_init(); + + ao_lcd_stm_init(); + ao_seven_segment_init(); + ao_quadrature_init(); + ao_button_init(); + + ao_storage_init(); + + ao_radio_init(); + + ao_usb_init(); + + ao_config_init(); + + ao_quadrature_init(); + ao_button_init(); + ao_lco_init(); + ao_lco_cmd_init(); +// ao_radio_cmac_cmd_init(); + + ao_start_scheduler(); + return 0; +} -- cgit v1.2.3 From 354c1fed7f06c2c45c661e7265c2ac4bc47e2750 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 30 Aug 2012 16:22:51 -0500 Subject: altos: Add a bunch of .gitignore entries Clean up the git status output Signed-off-by: Keith Packard --- ao-tools/ao-stmload/.gitignore | 1 + src/spiradio-v0.1/.gitignore | 2 ++ src/stm-bringup/bringup.ld | 69 ++++++++++++++++++++++++++++++++++++++++++ src/telefire-v0.1/.gitignore | 2 ++ src/test/.gitignore | 3 ++ 5 files changed, 77 insertions(+) create mode 100644 ao-tools/ao-stmload/.gitignore create mode 100644 src/spiradio-v0.1/.gitignore create mode 100644 src/stm-bringup/bringup.ld create mode 100644 src/telefire-v0.1/.gitignore (limited to 'src') diff --git a/ao-tools/ao-stmload/.gitignore b/ao-tools/ao-stmload/.gitignore new file mode 100644 index 00000000..dedb0094 --- /dev/null +++ b/ao-tools/ao-stmload/.gitignore @@ -0,0 +1 @@ +ao-stmload diff --git a/src/spiradio-v0.1/.gitignore b/src/spiradio-v0.1/.gitignore new file mode 100644 index 00000000..8e39138e --- /dev/null +++ b/src/spiradio-v0.1/.gitignore @@ -0,0 +1,2 @@ +spiradio-* +ao_product.h diff --git a/src/stm-bringup/bringup.ld b/src/stm-bringup/bringup.ld new file mode 100644 index 00000000..10d50cd6 --- /dev/null +++ b/src/stm-bringup/bringup.ld @@ -0,0 +1,69 @@ +/* + * Copyright © 2012 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +MEMORY { + rom (rx) : ORIGIN = 0x08000000, LENGTH = 128K + ram (!w) : ORIGIN = 0x20000000, LENGTH = 16K +} + +INCLUDE registers.ld + +EXTERN (stm_interrupt_vector) + +SECTIONS { + /* + * Rom contents + */ + + .text ORIGIN(rom) : { + __text_start__ = .; + *(.interrupt) /* Interrupt vectors */ + + *(.text*) /* Executable code */ + *(.rodata*) /* Constants */ + } > rom + + .ARM.exidx : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + __text_end__ = .; + } > rom + + . = ORIGIN(ram); + __data_start__ = .; + + /* Data -- relocated to RAM, but written to ROM + */ + .data : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) { + *(.data) /* initialized data */ + __data_end__ = .; + __bss_start__ = .; + } >ram + + .bss : { + *(.bss) + *(COMMON) + __bss_end__ = .; + } >ram + + PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram)); + PROVIDE(end = .); + +} + +ENTRY(start); + + diff --git a/src/telefire-v0.1/.gitignore b/src/telefire-v0.1/.gitignore new file mode 100644 index 00000000..4d4f4200 --- /dev/null +++ b/src/telefire-v0.1/.gitignore @@ -0,0 +1,2 @@ +telefire-* +ao_product.h diff --git a/src/test/.gitignore b/src/test/.gitignore index 33c7ef35..5d528ab9 100644 --- a/src/test/.gitignore +++ b/src/test/.gitignore @@ -4,3 +4,6 @@ ao_flight_test_accel ao_gps_test ao_gps_test_skytraq ao_convert_test +ao_convert_pa_test +ao_fec_test +ao_flight_test_noisy_accel -- cgit v1.2.3 From ab9d5bf13e6f1735a0463f4bcab13d65170b7015 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 30 Aug 2012 16:28:53 -0500 Subject: altos: ao_cc_spi.h isn't necessary for telelco The SPI radio defines are in ao_radio_spi.h Signed-off-by: Keith Packard --- src/telelco-v0.1/Makefile | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/telelco-v0.1/Makefile b/src/telelco-v0.1/Makefile index 32115c42..d2702dd6 100644 --- a/src/telelco-v0.1/Makefile +++ b/src/telelco-v0.1/Makefile @@ -14,7 +14,6 @@ INC = \ ao_sample.h \ ao_pins.h \ ao_product.h \ - ao_cc_spi.h \ ao_seven_segment.h \ ao_lco.h \ ao_lco_cmd.h \ -- cgit v1.2.3 From 6d8858ca1899c8b64f107ebb45711efbb7b8d62a Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 30 Aug 2012 16:30:04 -0500 Subject: altos: another .gitignore file Signed-off-by: Keith Packard --- src/telelco-v0.1/.gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/telelco-v0.1/.gitignore (limited to 'src') diff --git a/src/telelco-v0.1/.gitignore b/src/telelco-v0.1/.gitignore new file mode 100644 index 00000000..54267ec1 --- /dev/null +++ b/src/telelco-v0.1/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +telelco-* -- cgit v1.2.3 From f9af7819de086d9179c3a4d1df7c88ab67a7d7c7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 31 Aug 2012 21:01:21 -0500 Subject: altos: Add custom panic noise for self-test failures Make it easier to tell which component is failing self test Signed-off-by: Keith Packard --- src/core/ao.h | 5 ++++- src/core/ao_panic.c | 10 +++++++++- src/drivers/ao_cc1120.c | 4 ++-- src/drivers/ao_mpu6000.c | 2 +- src/drivers/ao_ms5607.c | 35 ++++++++++++++++++----------------- 5 files changed, 34 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 66c0881f..4f4779ec 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -115,7 +115,10 @@ ao_start_scheduler(void); #define AO_PANIC_BT 11 /* Communications with bluetooth device failed */ #define AO_PANIC_STACK 12 /* Stack overflow */ #define AO_PANIC_SPI 13 /* SPI communication failure */ -#define AO_PANIC_SELF_TEST 14 /* Self test failure */ +#define AO_PANIC_SELF_TEST_CC1120 0x40 | 1 /* Self test failure */ +#define AO_PANIC_SELF_TEST_HMC5883 0x40 | 2 /* Self test failure */ +#define AO_PANIC_SELF_TEST_MPU6000 0x40 | 3 /* Self test failure */ +#define AO_PANIC_SELF_TEST_MS5607 0x40 | 4 /* Self test failure */ /* Stop the operating system, beeping and blinking the reason */ void diff --git a/src/core/ao_panic.c b/src/core/ao_panic.c index 25dc145e..52433044 100644 --- a/src/core/ao_panic.c +++ b/src/core/ao_panic.c @@ -65,7 +65,15 @@ ao_panic(uint8_t reason) #ifdef SDCC #pragma disable_warning 126 #endif - for (n = 0; n < reason; n++) { + if (reason & 0x40) { + ao_led_on(AO_LED_RED); + ao_beep(AO_BEEP_HIGH); + ao_panic_delay(40); + ao_led_off(AO_LED_RED); + ao_beep(AO_BEEP_OFF); + ao_panic_delay(10); + } + for (n = 0; n < (reason & 0x3f); n++) { ao_led_on(AO_LED_RED); ao_beep(AO_BEEP_MID); ao_panic_delay(10); diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 4df931b5..2f9c296f 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -1028,12 +1028,12 @@ ao_radio_init(void) AO_CC1120_SPI_CS_PORT->bsrr = ((uint32_t) (1 << AO_CC1120_SPI_CS_PIN)); for (i = 0; i < 10000; i++) { - if ((SPI_2_GPIO->idr & (1 << SPI_2_MISO)) == 0) + if ((SPI_2_PORT->idr & (1 << SPI_2_MISO_PIN)) == 0) break; } AO_CC1120_SPI_CS_PORT->bsrr = (1 << AO_CC1120_SPI_CS_PIN); if (i == 10000) - ao_panic(AO_PANIC_SELF_TEST); + ao_panic(AO_PANIC_SELF_TEST_CC1120); /* Enable the EXTI interrupt for the appropriate pin */ ao_enable_port(AO_CC1120_INT_PORT); diff --git a/src/drivers/ao_mpu6000.c b/src/drivers/ao_mpu6000.c index e8c80f12..b3e284e0 100644 --- a/src/drivers/ao_mpu6000.c +++ b/src/drivers/ao_mpu6000.c @@ -225,7 +225,7 @@ ao_mpu6000_setup(void) errors += ao_mpu6000_gyro_check(normal_mode.gyro_z, test_mode.gyro_z, "z"); if (errors) - ao_panic(AO_PANIC_SELF_TEST); + ao_panic(AO_PANIC_SELF_TEST_MPU6000); /* Filter to about 100Hz, which also sets the gyro rate to 1000Hz */ ao_mpu6000_reg_write(MPU6000_CONFIG, diff --git a/src/drivers/ao_ms5607.c b/src/drivers/ao_ms5607.c index ec0d2202..704b4583 100644 --- a/src/drivers/ao_ms5607.c +++ b/src/drivers/ao_ms5607.c @@ -27,12 +27,12 @@ static uint8_t ms5607_configured; static void ao_ms5607_start(void) { ao_spi_get(AO_MS5607_SPI_INDEX,AO_SPI_SPEED_FAST); - stm_gpio_set(AO_MS5607_CS_GPIO, AO_MS5607_CS, 0); + stm_gpio_set(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, 0); } static void ao_ms5607_stop(void) { - stm_gpio_set(AO_MS5607_CS_GPIO, AO_MS5607_CS, 1); + stm_gpio_set(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, 1); ao_spi_put(AO_MS5607_SPI_INDEX); } @@ -92,7 +92,7 @@ ao_ms5607_prom_read(struct ao_ms5607_prom *prom) printf ("MS5607 PROM CRC error (computed %x actual %x)\n", crc, (((uint8_t *) prom)[15] & 0xf)); flush(); - ao_panic(AO_PANIC_SELF_TEST); +// ao_panic(AO_PANIC_SELF_TEST_MS5607); } #if __BYTE_ORDER == __LITTLE_ENDIAN @@ -120,7 +120,7 @@ static uint8_t ao_ms5607_done; static void ao_ms5607_isr(void) { - ao_exti_disable(AO_MS5607_MISO_GPIO, AO_MS5607_MISO); + ao_exti_disable(AO_MS5607_MISO_PORT, AO_MS5607_MISO_PIN); ao_ms5607_done = 1; ao_wakeup(&ao_ms5607_done); } @@ -135,7 +135,7 @@ ao_ms5607_get_sample(uint8_t cmd) { ao_ms5607_start(); ao_spi_send(&cmd, 1, AO_MS5607_SPI_INDEX); - ao_exti_enable(AO_MS5607_MISO_GPIO, AO_MS5607_MISO); + ao_exti_enable(AO_MS5607_MISO_PORT, AO_MS5607_MISO_PIN); #if AO_MS5607_PRIVATE_PINS ao_spi_put(AO_MS5607_SPI_INDEX); #endif @@ -144,7 +144,7 @@ ao_ms5607_get_sample(uint8_t cmd) { ao_sleep(&ao_ms5607_done); sei(); #if AO_MS5607_PRIVATE_PINS - stm_gpio_set(AO_MS5607_CS_GPIO, AO_MS5607_CS, 1); + stm_gpio_set(AO_MS5607_CS_PORT, AO_MS5607_CS_PIN, 1); #else ao_ms5607_stop(); #endif @@ -235,13 +235,14 @@ ao_ms5607_info(void) static void ao_ms5607_dump(void) { - struct ao_data sample; + struct ao_ms5607_sample sample; struct ao_ms5607_value value; - ao_data_get(&sample); - ao_ms5607_convert(&sample.ms5607_raw, &value); - printf ("Pressure: %8u %8d\n", sample.ms5607_raw.pres, value.pres); - printf ("Temperature: %8u %8d\n", sample.ms5607_raw.temp, value.temp); + ao_ms5607_setup(); + ao_ms5607_sample(&sample); + ao_ms5607_convert(&sample, &value); + printf ("Pressure: %8u %8d\n", sample.pres, value.pres); + printf ("Temperature: %8u %8d\n", sample.temp, value.temp); printf ("Altitude: %ld\n", ao_pa_to_altitude(value.pres)); } @@ -255,24 +256,24 @@ ao_ms5607_init(void) { ms5607_configured = 0; ao_cmd_register(&ao_ms5607_cmds[0]); - ao_spi_init_cs(AO_MS5607_CS_GPIO, (1 << AO_MS5607_CS)); + ao_spi_init_cs(AO_MS5607_CS_PORT, (1 << AO_MS5607_CS_PIN)); - ao_add_task(&ao_ms5607_task, ao_ms5607, "ms5607"); +// ao_add_task(&ao_ms5607_task, ao_ms5607, "ms5607"); /* Configure the MISO pin as an interrupt; when the * conversion is complete, the MS5607 will raise this * pin as a signal */ - ao_exti_setup(AO_MS5607_MISO_GPIO, - AO_MS5607_MISO, + ao_exti_setup(AO_MS5607_MISO_PORT, + AO_MS5607_MISO_PIN, AO_EXTI_MODE_RISING, ao_ms5607_isr); /* Reset the pin from INPUT to ALTERNATE so that SPI works * This needs an abstraction at some point... */ - stm_moder_set(AO_MS5607_MISO_GPIO, - AO_MS5607_MISO, + stm_moder_set(AO_MS5607_MISO_PORT, + AO_MS5607_MISO_PIN, STM_MODER_ALTERNATE); } -- cgit v1.2.3 From 48a3e6e073e927e456ef4e456e512f6fb8e3b9ee Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 31 Aug 2012 21:02:13 -0500 Subject: altos: Fix mma665x pin assigment for mma655x It's on PE13-PE15, not PA5-PA7 Signed-off-by: Keith Packard --- src/megametrum-v0.1/ao_pins.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/megametrum-v0.1/ao_pins.h b/src/megametrum-v0.1/ao_pins.h index 8b631ae9..af8eebae 100644 --- a/src/megametrum-v0.1/ao_pins.h +++ b/src/megametrum-v0.1/ao_pins.h @@ -77,10 +77,10 @@ #define SPI_2_PB13_PB14_PB15 1 /* Flash, Companion */ #define SPI_2_PD1_PD3_PD4 0 -#define SPI_2_GPIO (&stm_gpiob) -#define SPI_2_SCK 13 -#define SPI_2_MISO 14 -#define SPI_2_MOSI 15 +#define SPI_2_PORT (&stm_gpiob) +#define SPI_2_SCK_PIN 13 +#define SPI_2_MISO_PIN 14 +#define SPI_2_MOSI_PIN 15 #define HAS_I2C_1 1 #define I2C_1_PB8_PB9 1 @@ -249,11 +249,11 @@ struct ao_adc { */ #define HAS_MS5607 1 #define AO_MS5607_PRIVATE_PINS 1 -#define AO_MS5607_CS_GPIO (&stm_gpioc) -#define AO_MS5607_CS 4 +#define AO_MS5607_CS_PORT (&stm_gpioc) +#define AO_MS5607_CS_PIN 4 #define AO_MS5607_CS_MASK (1 << AO_MS5607_CS) -#define AO_MS5607_MISO_GPIO (&stm_gpioa) -#define AO_MS5607_MISO 6 +#define AO_MS5607_MISO_PORT (&stm_gpioa) +#define AO_MS5607_MISO_PIN 6 #define AO_MS5607_MISO_MASK (1 << AO_MS5607_MISO) #define AO_MS5607_SPI_INDEX AO_SPI_1_PA5_PA6_PA7 @@ -309,10 +309,10 @@ struct ao_adc { * mma655x */ -#define HAS_MMA655X 0 -#define AO_MMA655X_SPI_INDEX AO_SPI_1_PA5_PA6_PA7 -#define AO_MMA655X_CS_GPIO (&stm_gpiod) -#define AO_MMA655X_CS 4 +#define HAS_MMA655X 1 +#define AO_MMA655X_SPI_INDEX AO_SPI_1_PE13_PE14_PE15 +#define AO_MMA655X_CS_PORT (&stm_gpiod) +#define AO_MMA655X_CS_PIN 4 #define NUM_CMDS 16 -- cgit v1.2.3 From 503eabd0e351ecdffda1416b7d00f8ef1d6913c9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 31 Aug 2012 22:19:40 -0500 Subject: altos: Get mma655x driver limping along This appears to drive the chip correctly to see values from the accelerometer. Signed-off-by: Keith Packard --- src/drivers/ao_mma655x.c | 134 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 93 insertions(+), 41 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_mma655x.c b/src/drivers/ao_mma655x.c index cd304d80..06422206 100644 --- a/src/drivers/ao_mma655x.c +++ b/src/drivers/ao_mma655x.c @@ -20,67 +20,101 @@ #if HAS_MMA655X +#if 1 +#define PRINTD(...) do { printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); } while(0) +#else +#define PRINTD(...) +#endif + static uint8_t mma655x_configured; +uint8_t ao_mma655x_spi_index = AO_MMA655X_SPI_INDEX; + static void ao_mma655x_start(void) { - ao_spi_get_bit(AO_MMA655X_CS_GPIO, - AO_MMA655X_CS, + ao_spi_get_bit(AO_MMA655X_CS_PORT, AO_MMA655X_CS_PIN, + AO_MMA655X_CS, AO_MMA655X_SPI_INDEX, AO_SPI_SPEED_FAST); } static void ao_mma655x_stop(void) { - ao_spi_put_bit(AO_MMA655X_CS_GPIO, - AO_MMA655X_CS, + ao_spi_put_bit(AO_MMA655X_CS_PORT, AO_MMA655X_CS_PIN, + AO_MMA655X_CS, AO_MMA655X_SPI_INDEX); } +static void +ao_mma655x_restart(void) { + uint8_t i; + ao_gpio_set(AO_MMA655X_CS_PORT, AO_MMA655X_CS_PIN, AO_MMA655X_CS, 1); + + /* Emperical testing on STM32L151 at 32MHz for this delay amount */ + for (i = 0; i < 9; i++) + ao_arch_nop(); + ao_gpio_set(AO_MMA655X_CS_PORT, AO_MMA655X_CS_PIN, AO_MMA655X_CS, 0); +} + static uint8_t ao_parity(uint8_t v) { + uint8_t p; /* down to four bits */ - v = (v ^ (v >> 4)) & 0xf; + p = (v ^ (v >> 4)) & 0xf; /* Cute lookup hack -- 0x6996 encodes the sixteen * even parity values in order. */ - return (~0x6996 >> v) & 1; + p = (~0x6996 >> p) & 1; + return p; } static void ao_mma655x_cmd(uint8_t d[2]) { ao_mma655x_start(); - ao_spi_send(d, 2, AO_MMA655X_SPI_INDEX); - ao_spi_recv(d, 2, AO_MMA655X_SPI_INDEX); + PRINTD("\tSEND %02x %02x\n", d[0], d[1]); + ao_spi_duplex(d, d, 2, AO_MMA655X_SPI_INDEX); + PRINTD("\t\tRECV %02x %02x\n", d[0], d[1]); ao_mma655x_stop(); } static uint8_t -ao_mma655x_reg_write(uint8_t addr, uint8_t value) +ao_mma655x_reg_read(uint8_t addr) { uint8_t d[2]; + ao_mma655x_start(); + d[0] = addr | (ao_parity(addr) << 7); + d[1] = 0; + ao_spi_send(&d, 2, AO_MMA655X_SPI_INDEX); + ao_mma655x_restart(); - addr |= (1 << 6); /* write mode */ - d[0] = addr | (ao_parity(addr^value) << 7); - d[1] = value; - ao_mma655x_cmd(d); + /* Send a dummy read of 00 to clock out the SPI data */ + d[0] = 0x80; + d[1] = 0x00; + ao_spi_duplex(&d, &d, 2, AO_MMA655X_SPI_INDEX); + ao_mma655x_stop(); return d[1]; } -static uint8_t -ao_mma655x_reg_read(uint8_t addr) +static void +ao_mma655x_reg_write(uint8_t addr, uint8_t value) { uint8_t d[2]; - d[0] = addr | (ao_parity(addr) << 7); - d[1] = 0; - ao_mma655x_cmd(d); - return d[1]; + addr |= (1 << 6); /* write mode */ + d[0] = addr | (ao_parity(addr^value) << 7); + d[1] = value; + ao_mma655x_start(); + ao_spi_send(d, 2, AO_MMA655X_SPI_INDEX); + ao_mma655x_stop(); + + addr &= ~(1 << 6); + PRINTD("write %x %x = %x\n", + addr, value, ao_mma655x_reg_read(addr)); } static uint16_t @@ -89,14 +123,23 @@ ao_mma655x_value(void) uint8_t d[2]; uint16_t v; - d[0] = ((0 << 7) | /* Axis selection (X) */ - (1 << 6) | /* Acceleration operation */ - (1 << 5)); /* Raw data */ + d[0] = ((0 << 6) | /* Axis selection (X) */ + (1 << 5) | /* Acceleration operation */ + (1 << 4)); /* Raw data */ d[1] = ((1 << 3) | /* must be one */ (1 << 2) | /* Unsigned data */ (0 << 1) | /* Arm disabled */ (1 << 0)); /* Odd parity */ - ao_mma655x_cmd(d); + ao_mma655x_start(); + PRINTD("value SEND %02x %02x\n", d[0], d[1]); + ao_spi_send(d, 2, AO_MMA655X_SPI_INDEX); + ao_mma655x_restart(); + d[0] = 0x80; + d[1] = 0x00; + ao_spi_duplex(d, d, 2, AO_MMA655X_SPI_INDEX); + ao_mma655x_stop(); + PRINTD("value RECV %02x %02x\n", d[0], d[1]); + v = (uint16_t) d[1] << 2; v |= d[0] >> 6; v |= (uint16_t) (d[0] & 3) << 10; @@ -132,6 +175,12 @@ ao_mma655x_setup(void) uint8_t v; uint16_t a, a_st; uint8_t stdefl; + uint8_t i; + uint8_t s0, s1, s2, s3; + uint8_t pn; + uint32_t lot; + uint16_t serial; + if (mma655x_configured) return; @@ -157,7 +206,10 @@ ao_mma655x_setup(void) ao_mma655x_reg_write(AO_MMA655X_AXISCFG, AXISCFG_VALUE | (1 << AO_MMA655X_AXISCFG_ST)); - a_st = ao_mma655x_value(); + for (i = 0; i < 10; i++) { + a_st = ao_mma655x_value(); + printf ("SELF-TEST %2d = %6d\n", i, a_st); + } stdefl = ao_mma655x_reg_read(AO_MMA655X_STDEFL); @@ -165,22 +217,14 @@ ao_mma655x_setup(void) AXISCFG_VALUE | (0 << AO_MMA655X_AXISCFG_ST)); a = ao_mma655x_value(); - printf ("normal: %u self_test: %u stdefl: %u\n", - a, a_st, stdefl); + + for (i = 0; i < 10; i++) { + a = ao_mma655x_value(); + printf("NORMAL %2d = %6d\n", i, a); + } ao_mma655x_reg_write(AO_MMA655X_DEVCFG, DEVCFG_VALUE | (1 << AO_MMA655X_DEVCFG_ENDINIT)); -} - -static void -ao_mma655x_dump(void) -{ - uint8_t s0, s1, s2, s3; - uint32_t lot; - uint16_t serial; - - ao_mma655x_setup(); - s0 = ao_mma655x_reg_read(AO_MMA655X_SN0); s1 = ao_mma655x_reg_read(AO_MMA655X_SN1); s2 = ao_mma655x_reg_read(AO_MMA655X_SN2); @@ -189,8 +233,16 @@ ao_mma655x_dump(void) ((uint32_t) s1 << 8) | ((uint32_t) s0); serial = lot & 0x1fff; lot >>= 12; - printf ("MMA655X lot %d serial %d\n", lot, serial); - mma655x_configured = 0; + pn = ao_mma655x_reg_read(AO_MMA655X_PN); + printf ("MMA655X lot %d serial %d number %d\n", lot, serial, pn); + +} + +static void +ao_mma655x_dump(void) +{ + ao_mma655x_setup(); + printf ("MMA655X value %d\n", ao_mma655x_value()); } __code struct ao_cmds ao_mma655x_cmds[] = { @@ -219,9 +271,9 @@ ao_mma655x_init(void) mma655x_configured = 0; ao_cmd_register(&ao_mma655x_cmds[0]); - ao_spi_init_cs(AO_MMA655X_CS_GPIO, (1 << AO_MMA655X_CS)); + ao_spi_init_cs(AO_MMA655X_CS_PORT, (1 << AO_MMA655X_CS_PIN)); - ao_add_task(&ao_mma655x_task, ao_mma655x, "mma655x"); +// ao_add_task(&ao_mma655x_task, ao_mma655x, "mma655x"); } #endif -- cgit v1.2.3 From 294b1ec85a37e375a0ac70cbffc6398309d63a7f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 1 Sep 2012 00:14:27 -0500 Subject: Revert "telescience: correctly calculating rate values with higher resolution" PWM bits not suitable for master This reverts commit ada6f2dfc045e77cb9499f20cdec1b4a54ef0db1. --- src/avr/ao_pwmin.c | 28 ++++------------------------ 1 file changed, 4 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/avr/ao_pwmin.c b/src/avr/ao_pwmin.c index 84397357..73a153b2 100644 --- a/src/avr/ao_pwmin.c +++ b/src/avr/ao_pwmin.c @@ -25,40 +25,20 @@ * project payload developed at Challenger Middle School. */ -volatile __data uint16_t ao_icp3_count = 0; -volatile __data uint16_t ao_icp3_last = 0; - -uint16_t ao_icp3(void) -{ - uint16_t v; - ao_arch_critical( - v = ao_icp3_count; - ); - return v; -} +volatile __data uint16_t ao_icp3_count; static void ao_pwmin_display(void) __reentrant { /* display the most recent value */ - printf("icp 3: %5u\n", ao_icp3()); + printf("icp 3: %5u\n", ao_icp3_count); } - - ISR(TIMER3_CAPT_vect) { - uint8_t lo = ICR3L; uint8_t hi = ICR3H; - uint16_t ao_icp3_this = (hi <<8) | lo; - - /* handling counter rollovers */ - if (ao_icp3_this >= ao_icp3_last) - ao_icp3_count = ao_icp3_this - ao_icp3_last; - else - ao_icp3_count = ao_icp3_this + (65536 - ao_icp3_last); - ao_icp3_last = ao_icp3_this; + ao_icp3_count = (hi <<8) | lo; } __code struct ao_cmds ao_pwmin_cmds[] = { @@ -76,7 +56,7 @@ ao_pwmin_init(void) (0 << ICES3) | /* input capture on falling edge (don't care) */ (0 << WGM33) | /* normal mode, OCR3A */ (0 << WGM32) | /* normal mode, OCR3A */ - (3 << CS30)); /* clk/64 from prescaler */ + (4 << CS30)); /* clk/256 from prescaler */ -- cgit v1.2.3 From 8c743857525eff778d067068356dec486b9fefa2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 1 Sep 2012 00:14:49 -0500 Subject: Revert "ICP3 working" PWM bits not suitable for master This reverts commit 75d6aa6f798606f1a6c5a46542065dda81e63b2a. --- src/avr/ao_pwmin.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/avr/ao_pwmin.c b/src/avr/ao_pwmin.c index 73a153b2..edcb1636 100644 --- a/src/avr/ao_pwmin.c +++ b/src/avr/ao_pwmin.c @@ -25,20 +25,27 @@ * project payload developed at Challenger Middle School. */ -volatile __data uint16_t ao_icp3_count; +volatile __data uint16_t ao_tick3_count; static void ao_pwmin_display(void) __reentrant { - /* display the most recent value */ - printf("icp 3: %5u\n", ao_icp3_count); + uint8_t lo = TCNT1L; + uint8_t hi = TCNT1H; + uint16_t value = (hi <<8) | lo; + + uint8_t lo3 = TCNT3L; + uint8_t hi3 = TCNT3H; + uint16_t value3 = (hi3 <<8) | lo3; + + /* now display the value we read */ + printf("timer 1: %5u %2x %2x\n", value, hi, lo); + printf("timer 3: %5u %2x %2x\n", value3, hi3, lo3); } -ISR(TIMER3_CAPT_vect) +ISR(TIMER3_COMPA_vect) { - uint8_t lo = ICR3L; - uint8_t hi = ICR3H; - ao_icp3_count = (hi <<8) | lo; + ++ao_tick3_count; } __code struct ao_cmds ao_pwmin_cmds[] = { @@ -52,15 +59,15 @@ ao_pwmin_init(void) /* do hardware setup here */ TCCR3A = ((0 << WGM31) | /* normal mode, OCR3A */ (0 << WGM30)); /* normal mode, OCR3A */ - TCCR3B = ((1 << ICNC3) | /* input capture noise canceler on */ + TCCR3B = ((0 << ICNC3) | /* no input capture noise canceler */ (0 << ICES3) | /* input capture on falling edge (don't care) */ (0 << WGM33) | /* normal mode, OCR3A */ (0 << WGM32) | /* normal mode, OCR3A */ (4 << CS30)); /* clk/256 from prescaler */ - + OCR3A = 1250; /* 8MHz clock */ - TIMSK3 = (1 << ICIE3); /* Interrupt on input compare */ + TIMSK3 = (1 << OCIE3A); /* Interrupt on compare match */ /* set the spike filter bit in the TCCR3B register */ -- cgit v1.2.3 From 3ccc4a13e3f76bec864d61b0cdfd57c76c6baadb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 1 Sep 2012 00:15:02 -0500 Subject: Revert "Timer 3 working with slower clock and all 16 bits." PWM bits not suitable for master This reverts commit 49b1ff4c614d24977b33cd17b583acc87acff476. --- src/avr/ao_pwmin.c | 25 +------------------------ 1 file changed, 1 insertion(+), 24 deletions(-) (limited to 'src') diff --git a/src/avr/ao_pwmin.c b/src/avr/ao_pwmin.c index edcb1636..4d96404d 100644 --- a/src/avr/ao_pwmin.c +++ b/src/avr/ao_pwmin.c @@ -25,8 +25,6 @@ * project payload developed at Challenger Middle School. */ -volatile __data uint16_t ao_tick3_count; - static void ao_pwmin_display(void) __reentrant { @@ -34,19 +32,10 @@ ao_pwmin_display(void) __reentrant uint8_t hi = TCNT1H; uint16_t value = (hi <<8) | lo; - uint8_t lo3 = TCNT3L; - uint8_t hi3 = TCNT3H; - uint16_t value3 = (hi3 <<8) | lo3; - /* now display the value we read */ - printf("timer 1: %5u %2x %2x\n", value, hi, lo); - printf("timer 3: %5u %2x %2x\n", value3, hi3, lo3); + printf("timer 1: %5u", value); } -ISR(TIMER3_COMPA_vect) -{ - ++ao_tick3_count; -} __code struct ao_cmds ao_pwmin_cmds[] = { { ao_pwmin_display, "p\0PWM input" }, @@ -57,18 +46,6 @@ void ao_pwmin_init(void) { /* do hardware setup here */ - TCCR3A = ((0 << WGM31) | /* normal mode, OCR3A */ - (0 << WGM30)); /* normal mode, OCR3A */ - TCCR3B = ((0 << ICNC3) | /* no input capture noise canceler */ - (0 << ICES3) | /* input capture on falling edge (don't care) */ - (0 << WGM33) | /* normal mode, OCR3A */ - (0 << WGM32) | /* normal mode, OCR3A */ - (4 << CS30)); /* clk/256 from prescaler */ - - OCR3A = 1250; /* 8MHz clock */ - - TIMSK3 = (1 << OCIE3A); /* Interrupt on compare match */ - /* set the spike filter bit in the TCCR3B register */ ao_cmd_register(&ao_pwmin_cmds[0]); -- cgit v1.2.3 From 01820c3e95fe85d2bee648d41809f1a753f81020 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 1 Sep 2012 00:15:16 -0500 Subject: Revert "first work on PWM input to TeleScience, 'p' command displays timer 1" PWM bits not suitable for master This reverts commit e93c6bcc799d76d4ff425815e2601a25e6796229. --- src/avr/ao_pwmin.c | 54 ------------------------------------------- src/avr/ao_pwmin.h | 18 --------------- src/product/ao_telescience.c | 2 -- src/telescience-v0.1/Makefile | 1 - 4 files changed, 75 deletions(-) delete mode 100644 src/avr/ao_pwmin.c delete mode 100644 src/avr/ao_pwmin.h (limited to 'src') diff --git a/src/avr/ao_pwmin.c b/src/avr/ao_pwmin.c deleted file mode 100644 index 4d96404d..00000000 --- a/src/avr/ao_pwmin.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright © 2012 Robert D. Garbee - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - */ - -#include "ao.h" -#include "ao_pwmin.h" - -/* - * This code implements a PWM input using ICP3. - * - * The initial use is to measure wind speed in the ULA/Ball summer intern - * project payload developed at Challenger Middle School. - */ - -static void -ao_pwmin_display(void) __reentrant -{ - uint8_t lo = TCNT1L; - uint8_t hi = TCNT1H; - uint16_t value = (hi <<8) | lo; - - /* now display the value we read */ - printf("timer 1: %5u", value); - -} - -__code struct ao_cmds ao_pwmin_cmds[] = { - { ao_pwmin_display, "p\0PWM input" }, - { 0, NULL }, -}; - -void -ao_pwmin_init(void) -{ - /* do hardware setup here */ - /* set the spike filter bit in the TCCR3B register */ - - ao_cmd_register(&ao_pwmin_cmds[0]); -} - - diff --git a/src/avr/ao_pwmin.h b/src/avr/ao_pwmin.h deleted file mode 100644 index bbab4ddc..00000000 --- a/src/avr/ao_pwmin.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright © 2012 Robert D. Garbee - * - * 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. - */ - -void ao_pwmin_init(void); diff --git a/src/product/ao_telescience.c b/src/product/ao_telescience.c index 2d594d7f..45b6d40e 100644 --- a/src/product/ao_telescience.c +++ b/src/product/ao_telescience.c @@ -16,7 +16,6 @@ */ #include "ao.h" -#include "ao_pwmin.h" int main(void) @@ -35,7 +34,6 @@ main(void) ao_usb_init(); ao_adc_init(); ao_log_single_init(); - ao_pwmin_init(); ao_start_scheduler(); return 0; } diff --git a/src/telescience-v0.1/Makefile b/src/telescience-v0.1/Makefile index 5542913d..d24128ef 100644 --- a/src/telescience-v0.1/Makefile +++ b/src/telescience-v0.1/Makefile @@ -53,7 +53,6 @@ ALTOS_SRC = \ ao_adc_avr.c \ ao_science_slave.c \ ao_spi_slave.c \ - ao_pwmin.c \ $(TELESCIENCE_STORAGE)\ $(TELESCIENCE_LOG) -- cgit v1.2.3 From c5e98d2b226824f2012e5710ac4b1596b9f0bfb1 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 6 Sep 2012 18:07:33 -0700 Subject: altos: Fix radio slave to run lights in the normal way These were left in a debug mode, toggling instead of flashing. Signed-off-by: Keith Packard --- src/drivers/ao_radio_slave.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_radio_slave.c b/src/drivers/ao_radio_slave.c index 9a01bbfa..1d1f16fe 100644 --- a/src/drivers/ao_radio_slave.c +++ b/src/drivers/ao_radio_slave.c @@ -32,7 +32,6 @@ ao_radio_slave_low(void) if (slave_state != 1) ao_panic(1); - ao_led_toggle(AO_LED_GREEN); ao_gpio_set(AO_RADIO_SLAVE_INT_PORT, AO_RADIO_SLAVE_INT_BIT, AO_RADIO_SLAVE_INT_PIN, 0); for (i = 0; i < 1000; i++) ao_arch_nop(); @@ -44,7 +43,6 @@ ao_radio_slave_high(void) { if (slave_state != 0) ao_panic(2); - ao_led_toggle(AO_LED_RED); ao_gpio_set(AO_RADIO_SLAVE_INT_PORT, AO_RADIO_SLAVE_INT_BIT, AO_RADIO_SLAVE_INT_PIN, 1); slave_state = 1; } @@ -65,8 +63,10 @@ ao_radio_slave_spi(void) /* XXX monitor CS to interrupt the receive */ ao_config.radio_setting = ao_radio_spi_request.setting; + ao_led_on(AO_LED_RX); ao_radio_spi_reply.status = ao_radio_recv(&ao_radio_spi_reply.payload, ao_radio_spi_request.recv_len); + ao_led_off(AO_LED_RX); ao_radio_spi_reply.rssi = 0; ao_spi_send(&ao_radio_spi_reply, AO_RADIO_SPI_REPLY_HEADER_LEN + ao_radio_spi_request.recv_len, @@ -76,9 +76,11 @@ ao_radio_slave_spi(void) continue; case AO_RADIO_SPI_CMAC_RECV: ao_config.radio_setting = ao_radio_spi_request.setting; + ao_led_on(AO_LED_RX); ao_radio_spi_reply.status = ao_radio_cmac_recv(&ao_radio_spi_reply.payload, ao_radio_spi_request.recv_len, ao_radio_spi_request.timeout); + ao_led_off(AO_LED_RX); ao_radio_spi_reply.rssi = ao_radio_cmac_rssi; ao_spi_send(&ao_radio_spi_reply, AO_RADIO_SPI_REPLY_HEADER_LEN + ao_radio_spi_request.recv_len, @@ -88,14 +90,18 @@ ao_radio_slave_spi(void) continue; case AO_RADIO_SPI_SEND: ao_config.radio_setting = ao_radio_spi_request.setting; + ao_led_on(AO_LED_TX); ao_radio_send(&ao_radio_spi_request.payload, ao_radio_spi_request.len - AO_RADIO_SPI_REQUEST_HEADER_LEN); + ao_led_off(AO_LED_TX); break; case AO_RADIO_SPI_CMAC_SEND: ao_config.radio_setting = ao_radio_spi_request.setting; + ao_led_on(AO_LED_TX); ao_radio_cmac_send(&ao_radio_spi_request.payload, ao_radio_spi_request.len - AO_RADIO_SPI_REQUEST_HEADER_LEN); + ao_led_off(AO_LED_TX); break; case AO_RADIO_SPI_CMAC_KEY: -- cgit v1.2.3 From e053da3e7cb5a4c9ebbffd245cb5d83932183b22 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Sep 2012 13:11:57 -0700 Subject: altos: Allow products without MS5607 The define for a missing MS5607 was wrong, so anything using the fancy multi-sensor data code would break without an MS5607 in place. Signed-off-by: Keith Packard --- src/core/ao_data.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/core/ao_data.h b/src/core/ao_data.h index 3b66ef5d..5412febe 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -28,7 +28,7 @@ #include #define AO_DATA_MS5607 (1 << 1) #else -#define AO_DATA_MS5607 (1 << 1) +#define AO_DATA_MS5607 0 #endif #if HAS_MPU6000 -- cgit v1.2.3 From ced6a020d6d94b1c63837a7ab5b0091b7b8ea3c9 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Sep 2012 13:43:45 -0700 Subject: altos: include ao_arch_funcs.h at the very end of ao.h Move it below the definition of the ms5607 init function Signed-off-by: Keith Packard --- src/core/ao.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/core/ao.h b/src/core/ao.h index 4f4779ec..31ec4686 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -22,7 +22,7 @@ #include #include #include -#include "ao_pins.h" +#include #include #define TRUE 1 @@ -981,12 +981,12 @@ ao_sqrt(uint32_t op); int32_t ao_freq_to_set(int32_t freq, int32_t cal) __reentrant; -#include - /* * ao_ms5607.c */ void ao_ms5607_init(void); +#include + #endif /* _AO_H_ */ -- cgit v1.2.3 From 27ab744c6eec9243b7aa14161eec2fbf7003531e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Sep 2012 13:46:23 -0700 Subject: altos: Clean up flight data definitions These just shuffle the various definitions of data macros around to make the include files more sensible looking. Signed-off-by: Keith Packard --- src/core/ao_data.h | 64 +++++++++++++++++++++++++++++++++++------------ src/core/ao_sample.c | 2 ++ src/core/ao_sample.h | 17 +++++++------ src/test/ao_flight_test.c | 22 ++++++++-------- 4 files changed, 72 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/core/ao_data.h b/src/core/ao_data.h index 5412febe..2b9ef5ac 100644 --- a/src/core/ao_data.h +++ b/src/core/ao_data.h @@ -95,15 +95,19 @@ extern volatile __data uint8_t ao_data_count; } while (0); /* - * Wait for data to be completed by looking at the - * indicated bit + * Wait until it is time to write a sensor sample; this is + * signaled by the timer tick */ #define AO_DATA_WAIT() do { \ ao_sleep((void *) &ao_data_count); \ } while (0) +#if !HAS_BARO && HAS_MS5607 -#if HAS_MS5607 +/* Either an MS5607 or an MS5611 hooked to a SPI port + */ + +#define HAS_BARO 1 typedef int32_t pres_t; typedef int32_t alt_t; @@ -115,7 +119,11 @@ typedef int32_t alt_t; #define pres_to_altitude(p) ao_pa_to_altitude(p) -#else /* HAS_MS5607 */ +#endif + +#if !HAS_BARO && HAS_ADC + +#define HAS_BARO 1 typedef int16_t pres_t; typedef int16_t alt_t; @@ -125,7 +133,7 @@ typedef int16_t alt_t; #define pres_to_altitude(p) ao_pres_to_altitude(p) #define ao_data_pres_cook(p) -#endif /* else HAS_MS5607 */ +#endif /* * Need a few macros to pull data from the sensors: @@ -136,17 +144,12 @@ typedef int16_t alt_t; * ao_data_accel_invert - flip rocket ends for positive acceleration */ -#if HAS_MPU6000 && !HAS_HIGHG_ACCEL - -typedef int16_t accel_t; - -/* MPU6000 is hooked up so that positive y is positive acceleration */ -#define ao_data_accel(packet) ((packet)->mpu6000.accel_y) -#define ao_data_accel_cook(packet) (-(packet)->mpu6000.accel_y) -#define ao_data_set_accel(packet, accel) ((packet)->mpu6000.accel_y = (accel)) -#define ao_data_accel_invert(a) (-(a)) +#if HAS_ACCEL -#else /* HAS_MPU6000 && !HAS_HIGHG_ACCEL */ +/* This section is for an analog accelerometer hooked to one of the ADC pins. As + * those are 5V parts, this also requires that the 5V supply be hooked to to anothe ADC + * pin so that the both can be measured to correct for changes between the 3.3V and 5V rails + */ typedef int16_t accel_t; #define ao_data_accel(packet) ((packet)->adc.accel) @@ -245,6 +248,35 @@ typedef int16_t accel_t; #endif /* HAS_ACCEL_REF */ -#endif /* else some other accel sensor */ +#endif /* HAS_ACCEL */ + +#if !HAS_ACCEL && HAS_MMA655X + +#define HAS_ACCEL 1 + +typedef int16_t accel_t; + +/* MMA655X is hooked up so that positive values represent negative acceleration */ + +#define ao_data_accel(packet) ((packet)->mma655x) +#define ao_data_accel_cook(packet) ((packet)->mma655x) +#define ao_data_set_accel(packet, accel) ((packet)->mma655x = (accel)) +#define ao_data_accel_invert(accel) (4095 - (accel)) + +#endif + +#if !HAS_ACCEL && HAS_MPU6000 + +#define HAS_ACCEL 1 + +typedef int16_t accel_t; + +/* MPU6000 is hooked up so that positive y is positive acceleration */ +#define ao_data_accel(packet) ((packet)->mpu6000.accel_y) +#define ao_data_accel_cook(packet) (-(packet)->mpu6000.accel_y) +#define ao_data_set_accel(packet, accel) ((packet)->mpu6000.accel_y = (accel)) +#define ao_data_accel_invert(a) (-(a)) + +#endif #endif /* _AO_DATA_H_ */ diff --git a/src/core/ao_sample.c b/src/core/ao_sample.c index 6461def0..985c0940 100644 --- a/src/core/ao_sample.c +++ b/src/core/ao_sample.c @@ -134,10 +134,12 @@ ao_sample(void) ao_data = (struct ao_data *) &ao_data_ring[ao_sample_data]; ao_sample_tick = ao_data->tick; +#if HAS_BARO ao_data_pres_cook(ao_data); ao_sample_pres = ao_data_pres(ao_data); ao_sample_alt = pres_to_altitude(ao_sample_pres); ao_sample_height = ao_sample_alt - ao_ground_height; +#endif #if HAS_ACCEL ao_sample_accel = ao_data_accel_cook(ao_data); diff --git a/src/core/ao_sample.h b/src/core/ao_sample.h index 189b2019..9336bdf9 100644 --- a/src/core/ao_sample.h +++ b/src/core/ao_sample.h @@ -69,7 +69,11 @@ /* * Above this height, the baro sensor doesn't work */ +#if HAS_MS5607 +#define AO_MAX_BARO_HEIGHT 30000 +#else #define AO_MAX_BARO_HEIGHT 12000 +#endif /* * Above this speed, baro measurements are unreliable @@ -90,20 +94,19 @@ #define AO_MSS_TO_ACCEL(mss) ((int16_t) ((mss) * 16)) extern __pdata uint16_t ao_sample_tick; /* time of last data */ -extern __pdata pres_t ao_sample_pres; /* most recent pressure sensor reading */ -extern __pdata alt_t ao_sample_alt; /* MSL of ao_sample_pres */ -extern __pdata alt_t ao_sample_height; /* AGL of ao_sample_pres */ extern __data uint8_t ao_sample_adc; /* Ring position of last processed sample */ extern __data uint8_t ao_sample_data; /* Ring position of last processed sample */ -#if HAS_ACCEL -extern __pdata accel_t ao_sample_accel; /* most recent accel sensor reading */ -#endif - +#if HAS_BARO +extern __pdata pres_t ao_sample_pres; /* most recent pressure sensor reading */ +extern __pdata alt_t ao_sample_alt; /* MSL of ao_sample_pres */ +extern __pdata alt_t ao_sample_height; /* AGL of ao_sample_pres */ extern __pdata pres_t ao_ground_pres; /* startup pressure */ extern __pdata alt_t ao_ground_height; /* MSL of ao_ground_pres */ +#endif #if HAS_ACCEL +extern __pdata accel_t ao_sample_accel; /* most recent accel sensor reading */ extern __pdata accel_t ao_ground_accel; /* startup acceleration */ extern __pdata accel_t ao_accel_2g; /* factory accel calibration */ extern __pdata int32_t ao_accel_scale; /* sensor to m/s² conversion */ diff --git a/src/test/ao_flight_test.c b/src/test/ao_flight_test.c index a4ef8dc0..b9e291ce 100644 --- a/src/test/ao_flight_test.c +++ b/src/test/ao_flight_test.c @@ -54,6 +54,15 @@ struct ao_adc { #define __code #define __reentrant +#define HAS_FLIGHT 1 +#define HAS_IGNITE 1 +#define HAS_USB 1 +#define HAS_GPS 1 +#ifndef HAS_ACCEL +#define HAS_ACCEL 1 +#define HAS_ACCEL_REF 0 +#endif + #include #define to_fix16(x) ((int16_t) ((x) * 65536.0 + 0.5)) @@ -200,24 +209,17 @@ struct ao_config ao_config; #define DATA_TO_XDATA(x) (x) -#define HAS_FLIGHT 1 -#define HAS_IGNITE 1 -#define HAS_ADC 1 -#define HAS_USB 1 -#define HAS_GPS 1 -#ifndef HAS_ACCEL -#define HAS_ACCEL 1 -#define HAS_ACCEL_REF 0 -#endif #define GRAVITY 9.80665 extern int16_t ao_ground_accel, ao_flight_accel; extern int16_t ao_accel_2g; +typedef int16_t accel_t; + extern uint16_t ao_sample_tick; extern int16_t ao_sample_height; -extern int16_t ao_sample_accel; +extern accel_t ao_sample_accel; extern int32_t ao_accel_scale; extern int16_t ao_ground_height; extern int16_t ao_sample_alt; -- cgit v1.2.3 From 3fa71c497a5bf576974e70af06762f75734e6699 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Sep 2012 13:50:56 -0700 Subject: altos: Try to get remote cmac time closer to reality Record the time after the packet was sent, but before the return packet arrives to try and more closely approximate the time the packet arrived at the other end. Signed-off-by: Keith Packard --- src/drivers/ao_lco_func.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_lco_func.c b/src/drivers/ao_lco_func.c index 152b5d1b..99e58b76 100644 --- a/src/drivers/ao_lco_func.c +++ b/src/drivers/ao_lco_func.c @@ -28,18 +28,18 @@ ao_lco_query(uint16_t box, struct ao_pad_query *query, uint16_t *tick_offset) { uint8_t i; int8_t r; - uint16_t time; + uint16_t sent_time; ao_mutex_get(&ao_lco_mutex); - time = ao_time(); - command.tick = time; + command.tick = ao_time() - *tick_offset; command.box = box; command.cmd = AO_LAUNCH_QUERY; command.channels = 0; ao_radio_cmac_send(&command, sizeof (command)); - r = ao_radio_cmac_recv(query, sizeof (*query), AO_MS_TO_TICKS(500)); + sent_time = ao_time(); + r = ao_radio_cmac_recv(query, sizeof (*query), AO_MS_TO_TICKS(20)); if (r == AO_RADIO_CMAC_OK) - *tick_offset = time - query->tick; + *tick_offset = sent_time - query->tick; ao_mutex_put(&ao_lco_mutex); return r; } -- cgit v1.2.3 From 0339583996fc57a666f8d3007a0f4b1034039a73 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Sep 2012 13:56:35 -0700 Subject: altos/spiradio: Label LEDs so that the radio code can use them Mark which should be on for TX and which for RX Signed-off-by: Keith Packard --- src/spiradio-v0.1/ao_pins.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/spiradio-v0.1/ao_pins.h b/src/spiradio-v0.1/ao_pins.h index f38aade6..cf01c9c6 100644 --- a/src/spiradio-v0.1/ao_pins.h +++ b/src/spiradio-v0.1/ao_pins.h @@ -41,9 +41,10 @@ #define DBG_ON_P1 0 #define PACKET_HAS_MASTER 0 #define PACKET_HAS_SLAVE 0 -#define AO_LED_RED 1 -#define AO_LED_GREEN 2 -#define LEDS_AVAILABLE (AO_LED_RED|AO_LED_GREEN) +#define AO_LED_TX 1 +#define AO_LED_RX 2 +#define AO_LED_RED AO_LED_TX +#define LEDS_AVAILABLE (AO_LED_TX|AO_LED_RX) #define HAS_EXTERNAL_TEMP 0 #define HAS_ACCEL_REF 0 #define SPI_CS_ON_P1 1 -- cgit v1.2.3 From f2933103be122414a9b1795b37003b7a2aa9f3d7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Sep 2012 13:57:16 -0700 Subject: altos/stm: Fix basic time interval to 10ms -- was 10.1ms Counting from 0 to 100 takes 10.1ms, so count to 99 instead. Signed-off-by: Keith Packard --- src/stm/ao_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm/ao_timer.c b/src/stm/ao_timer.c index f561e6b5..1132f748 100644 --- a/src/stm/ao_timer.c +++ b/src/stm/ao_timer.c @@ -87,7 +87,7 @@ ao_timer_init(void) stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_TIM6EN); stm_tim6.psc = TIMER_10kHz; - stm_tim6.arr = 100; + stm_tim6.arr = 99; stm_tim6.cnt = 0; /* Enable update interrupt */ -- cgit v1.2.3 From 77775711d414227b3ed97859d1b21ab1c689a724 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Sep 2012 13:58:29 -0700 Subject: altos/telefire: Add steady warble when the LCO arm switch is on And make debugging a run-time option too. Signed-off-by: Keith Packard --- src/drivers/ao_pad.c | 119 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 80 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index e47859a5..55e6289d 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -23,10 +23,17 @@ static __xdata uint8_t ao_pad_ignite; static __xdata struct ao_pad_command command; static __xdata struct ao_pad_query query; +static __pdata uint8_t ao_pad_armed; +static __pdata uint16_t ao_pad_arm_time; +static __pdata uint8_t ao_pad_box; +static __xdata uint8_t ao_pad_disabled; + +#define DEBUG 1 -#if 0 -#define PRINTD(...) printf(__VA_ARGS__) -#define FLUSHD() flush() +#if DEBUG +static __pdata uint8_t ao_pad_debug; +#define PRINTD(...) (ao_pad_debug ? (printf(__VA_ARGS__), 0) : 0) +#define FLUSHD() (ao_pad_debug ? (flush(), 0) : 0) #else #define PRINTD(...) #define FLUSHD() @@ -50,6 +57,8 @@ ao_pad_run(void) } } +#define AO_PAD_ARM_BEEP_INTERVAL 200 + static void ao_pad_monitor(void) { @@ -58,6 +67,7 @@ ao_pad_monitor(void) __pdata uint8_t prev = 0, cur = 0; __pdata uint8_t beeping = 0; __xdata struct ao_data *packet; + __pdata uint16_t arm_beep_time = 0; sample = ao_data_head; for (;;) { @@ -75,54 +85,73 @@ ao_pad_monitor(void) #define VOLTS_TO_PYRO(x) ((int16_t) ((x) * 27.0 / 127.0 / 3.3 * 32767.0)) cur = 0; - if (pyro > VOLTS_TO_PYRO(4)) + if (pyro > VOLTS_TO_PYRO(10)) { query.arm_status = AO_PAD_ARM_STATUS_ARMED; - else if (pyro < VOLTS_TO_PYRO(1)) + cur |= AO_LED_ARMED; + } else if (pyro < VOLTS_TO_PYRO(5)) { query.arm_status = AO_PAD_ARM_STATUS_DISARMED; - else + arm_beep_time = 0; + } else { + if ((ao_time() % 100) < 50) + cur |= AO_LED_ARMED; query.arm_status = AO_PAD_ARM_STATUS_UNKNOWN; + arm_beep_time = 0; + } for (c = 0; c < AO_PAD_NUM; c++) { int16_t sense = packet->adc.sense[c]; uint8_t status = AO_PAD_IGNITER_STATUS_UNKNOWN; - if (query.arm_status == AO_PAD_ARM_STATUS_ARMED) { - /* - * pyro is run through a divider, so pyro = v_pyro * 27 / 127 ~= v_pyro / 20 - * v_pyro = pyro * 127 / 27 - * - * v_pyro \ - * 100k igniter - * output / - * 100k \ - * sense relay - * 27k / - * gnd --- - * - * If the relay is closed, then sense will be 0 - * If no igniter is present, then sense will be v_pyro * 27k/227k = pyro * 127 / 227 ~= pyro/2 - * If igniter is present, then sense will be v_pyro * 27k/127k ~= v_pyro / 20 = pyro - */ - - if (sense <= pyro / 8) - status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED; - else if (pyro / 8 * 3 <= sense && sense <= pyro / 8 * 5) - status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN; - else if (pyro / 8 * 7 <= sense) { - status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN; + /* + * pyro is run through a divider, so pyro = v_pyro * 27 / 127 ~= v_pyro / 20 + * v_pyro = pyro * 127 / 27 + * + * v_pyro \ + * 100k igniter + * output / + * 100k \ + * sense relay + * 27k / + * gnd --- + * + * If the relay is closed, then sense will be 0 + * If no igniter is present, then sense will be v_pyro * 27k/227k = pyro * 127 / 227 ~= pyro/2 + * If igniter is present, then sense will be v_pyro * 27k/127k ~= v_pyro / 20 = pyro + */ + + if (sense <= pyro / 8) { + status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED; + if ((ao_time() % 100) < 50) cur |= AO_LED_CONTINUITY(c); - } + } + else if (pyro / 8 * 3 <= sense && sense <= pyro / 8 * 5) + status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN; + else if (pyro / 8 * 7 <= sense) { + status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN; + cur |= AO_LED_CONTINUITY(c); } query.igniter_status[c] = status; } if (cur != prev) { - ao_led_set_mask(cur, AO_LED_CONTINUITY_MASK); + PRINTD("change leds from %02x to %02x mask %02x\n", + prev, cur, AO_LED_CONTINUITY_MASK|AO_LED_ARMED); + ao_led_set_mask(cur, AO_LED_CONTINUITY_MASK | AO_LED_ARMED); prev = cur; } - if (pyro > VOLTS_TO_PYRO(9) && sample == 0) { + if (ao_pad_armed) { + if (sample & 2) + ao_beep(AO_BEEP_HIGH); + else + ao_beep(AO_BEEP_LOW); beeping = 1; - ao_beep(AO_BEEP_HIGH); + } else if (query.arm_status == AO_PAD_ARM_STATUS_ARMED && !beeping) { + if (arm_beep_time == 0) { + arm_beep_time = AO_PAD_ARM_BEEP_INTERVAL; + beeping = 1; + ao_beep(AO_BEEP_HIGH); + } + --arm_beep_time; } else if (beeping) { beeping = 0; ao_beep(0); @@ -130,11 +159,6 @@ ao_pad_monitor(void) } } -static __pdata uint8_t ao_pad_armed; -static __pdata uint16_t ao_pad_arm_time; -static __pdata uint8_t ao_pad_box; -static __xdata uint8_t ao_pad_disabled; - void ao_pad_disable(void) { @@ -173,6 +197,9 @@ ao_pad(void) PRINTD ("tick %d box %d cmd %d channels %02x\n", command.tick, command.box, command.cmd, command.channels); + if (ao_pad_armed && (int16_t) (ao_time() - ao_pad_arm_time) > AO_PAD_ARM_TIME) + ao_pad_armed = 0; + switch (command.cmd) { case AO_LAUNCH_ARM: if (command.box != ao_pad_box) { @@ -235,6 +262,7 @@ ao_pad(void) } PRINTD ("ignite\n"); ao_pad_ignite = ao_pad_armed; + ao_pad_arm_time = ao_time(); ao_wakeup(&ao_pad_ignite); break; } @@ -287,9 +315,22 @@ static __xdata struct ao_task ao_pad_task; static __xdata struct ao_task ao_pad_ignite_task; static __xdata struct ao_task ao_pad_monitor_task; +#if DEBUG +void +ao_pad_set_debug(void) +{ + ao_cmd_decimal(); + if (ao_cmd_status == ao_cmd_success) + ao_pad_debug = ao_cmd_lex_i != 0; +} +#endif + __code struct ao_cmds ao_pad_cmds[] = { { ao_pad_test, "t\0Test pad continuity" }, { ao_pad_manual, "i \0Fire igniter. is doit with D&I" }, +#if DEBUG + { ao_pad_set_debug, "D <0 off, 1 on>\0Debug" }, +#endif { 0, NULL } }; -- cgit v1.2.3 From e45c47c52f9cc9c43b81148e0e58fdedb3af1eb8 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 9 Sep 2012 14:01:21 -0700 Subject: altos/telelco: Search for available firing nodes at boot time Query for available firing nodes, limiting device selections to those found. Signed-off-by: Keith Packard --- src/drivers/ao_pad.h | 8 +- src/telelco-v0.1/ao_lco.c | 198 +++++++++++++++++++++++++++++++++++----------- 2 files changed, 158 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/drivers/ao_pad.h b/src/drivers/ao_pad.h index ae4f3db4..23062899 100644 --- a/src/drivers/ao_pad.h +++ b/src/drivers/ao_pad.h @@ -19,6 +19,7 @@ #define _AO_PAD_H_ #define AO_PAD_MAX_CHANNELS 8 +#define AO_PAD_MAX_BOXES 100 struct ao_pad_command { uint16_t tick; @@ -41,16 +42,17 @@ struct ao_pad_query { uint8_t igniter_status[AO_PAD_MAX_CHANNELS]; /* status for each igniter */ }; -/* Set current armed pads, report back status +/* Arm pads for 3 seconds, no report */ - #define AO_PAD_ARM 2 +#define AO_PAD_ARM_TIME AO_SEC_TO_TICKS(3) + /* Fire current armed pads for 200ms, no report */ #define AO_PAD_FIRE 3 -#define AO_PAD_FIRE_TIME AO_MS_TO_TICKS(250) +#define AO_PAD_FIRE_TIME AO_MS_TO_TICKS(200) #define AO_PAD_ARM_STATUS_DISARMED 0 #define AO_PAD_ARM_STATUS_ARMED 1 diff --git a/src/telelco-v0.1/ao_lco.c b/src/telelco-v0.1/ao_lco.c index 7ecee192..41bba0ba 100644 --- a/src/telelco-v0.1/ao_lco.c +++ b/src/telelco-v0.1/ao_lco.c @@ -23,8 +23,11 @@ #include #include -#if 1 -#define PRINTD(...) do { printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0) +#define DEBUG 1 + +#if DEBUG +static uint8_t ao_lco_debug; +#define PRINTD(...) do { if (!ao_lco_debug) break; printf ("\r%5u %s: ", ao_tick_count, __func__); printf(__VA_ARGS__); flush(); } while(0) #else #define PRINTD(...) #endif @@ -33,8 +36,7 @@ #define AO_LCO_BOX_DIGIT_1 1 #define AO_LCO_BOX_DIGIT_10 2 -#define AO_NUM_BOX 10 - +static uint8_t ao_lco_min_box, ao_lco_max_box; static uint8_t ao_lco_mutex; static uint8_t ao_lco_pad; static uint8_t ao_lco_box; @@ -45,7 +47,7 @@ static uint8_t ao_lco_valid; static void ao_lco_set_pad(void) { - ao_seven_segment_set(AO_LCO_PAD_DIGIT, ao_lco_pad); + ao_seven_segment_set(AO_LCO_PAD_DIGIT, ao_lco_pad + 1); } static void @@ -55,11 +57,27 @@ ao_lco_set_box(void) ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, ao_lco_box / 10); } +#define MASK_SIZE(n) (((n) + 7) >> 3) +#define MASK_ID(n) ((n) >> 3) +#define MASK_SHIFT(n) ((n) & 7) + +static uint8_t ao_lco_box_mask[MASK_SIZE(AO_PAD_MAX_BOXES)]; + +static uint8_t +ao_lco_box_present(uint8_t box) +{ + if (box >= AO_PAD_MAX_BOXES) + return 0; + return (ao_lco_box_mask[MASK_ID(box)] >> MASK_SHIFT(box)) & 1; +} + static void ao_lco_input(void) { static struct ao_event event; + int8_t dir; + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); ao_lco_set_pad(); ao_lco_set_box(); for (;;) { @@ -72,19 +90,23 @@ ao_lco_input(void) case AO_QUADRATURE_PAD: if (!ao_lco_armed) { ao_lco_pad = event.value & 3; - ao_lco_valid = 0; ao_quadrature_count[AO_QUADRATURE_PAD] = ao_lco_pad; ao_lco_set_pad(); } break; case AO_QUADRATURE_BOX: if (!ao_lco_armed) { + if (event.value == ao_lco_box) + break; + dir = (event.value - ao_lco_box) > 0 ? 1 : -1; ao_lco_box = event.value; - ao_lco_valid = 0; - while (ao_lco_box >= AO_NUM_BOX) - ao_lco_box -= AO_NUM_BOX; - while (ao_lco_box < 0) - ao_lco_box += AO_NUM_BOX; + while (!ao_lco_box_present(ao_lco_box)) { + ao_lco_box += dir; + if (ao_lco_box > ao_lco_max_box) + ao_lco_box = ao_lco_min_box; + else if (ao_lco_box < ao_lco_min_box) + ao_lco_box = ao_lco_min_box; + } ao_quadrature_count[AO_QUADRATURE_PAD] = ao_lco_box; ao_lco_set_box(); } @@ -140,18 +162,17 @@ static AO_LED_TYPE continuity_led[AO_LED_CONTINUITY_NUM] = { static uint16_t ao_lco_tick_offset; +static struct ao_pad_query ao_pad_query; + static void ao_lco_update(void) { int8_t r; uint8_t c; - struct ao_pad_query query; - r = ao_lco_query(ao_lco_box, &query, &ao_lco_tick_offset); - if (r != AO_RADIO_CMAC_OK) { - PRINTD("lco_query return %d\n", r); - return; - } + r = ao_lco_query(ao_lco_box, &ao_pad_query, &ao_lco_tick_offset); + if (r == AO_RADIO_CMAC_OK) + ao_lco_valid = 1; #if 0 PRINTD("lco_query success arm_status %d i0 %d i1 %d i2 %d i3 %d\n", @@ -162,38 +183,124 @@ ao_lco_update(void) query.igniter_status[3]); #endif - ao_lco_valid = 1; - if (query.arm_status) - ao_led_on(AO_LED_REMOTE_ARM); - else - ao_led_off(AO_LED_REMOTE_ARM); - for (c = 0; c < AO_LED_CONTINUITY_NUM; c++) { - uint8_t status; + ao_wakeup(&ao_pad_query); +} - if (query.channels & (1 << c)) - status = query.igniter_status[c]; - else - status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN; - if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN) - ao_led_on(continuity_led[c]); +static void +ao_lco_box_set_present(uint8_t box) +{ + if (box >= AO_PAD_MAX_BOXES) + return; + ao_lco_box_mask[MASK_ID(box)] |= 1 << MASK_SHIFT(box); +} + +static void +ao_lco_search(void) +{ + uint16_t tick_offset; + int8_t r; + + ao_lco_min_box = 0xff; + ao_lco_max_box = 0x00; + for (ao_lco_box = 0; ao_lco_box < AO_PAD_MAX_BOXES; ao_lco_box++) { + ao_lco_set_box(); + r = ao_lco_query(ao_lco_box, &ao_pad_query, &ao_lco_tick_offset); + if (r == AO_RADIO_CMAC_OK) { + if (ao_lco_box < ao_lco_min_box) + ao_lco_min_box = ao_lco_box; + if (ao_lco_box > ao_lco_max_box) + ao_lco_max_box = ao_lco_box; + ao_lco_box_set_present(ao_lco_box); + } + } + ao_lco_box = ao_lco_min_box; + ao_lco_pad = 0; +} + +static void +ao_lco_igniter_status(void) +{ + uint8_t c; + uint16_t delay; + + for (;;) { +// ao_alarm(delay); + ao_sleep(&ao_pad_query); +// ao_clear_alarm(); + if (!ao_lco_valid) { + ao_led_on(AO_LED_RED); + ao_led_off(AO_LED_GREEN); + continue; + } + PRINTD("RSSI %d\n", ao_radio_cmac_rssi); + if (ao_radio_cmac_rssi < -70) + ao_led_on(AO_LED_RED|AO_LED_GREEN); + else { + ao_led_on(AO_LED_GREEN); + ao_led_off(AO_LED_RED); + } + if (ao_pad_query.arm_status) + ao_led_on(AO_LED_REMOTE_ARM); else - ao_led_off(continuity_led[c]); + ao_led_off(AO_LED_REMOTE_ARM); + for (c = 0; c < AO_LED_CONTINUITY_NUM; c++) { + uint8_t status; + + if (ao_pad_query.channels & (1 << c)) + status = ao_pad_query.igniter_status[c]; + else + status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN; + if (status == AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN) + ao_led_on(continuity_led[c]); + else + ao_led_off(continuity_led[c]); + } + } +} + +static void +ao_lco_arm_warn(void) +{ + for (;;) { + while (!ao_lco_armed) + ao_sleep(&ao_lco_armed); + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + ao_delay(AO_MS_TO_TICKS(200)); } } +static struct ao_task ao_lco_input_task; +static struct ao_task ao_lco_monitor_task; +static struct ao_task ao_lco_arm_warn_task; +static struct ao_task ao_lco_igniter_status_task; + static void ao_lco_monitor(void) { uint16_t delay; + ao_lco_search(); + ao_add_task(&ao_lco_input_task, ao_lco_input, "lco input"); + ao_add_task(&ao_lco_arm_warn_task, ao_lco_arm_warn, "lco arm warn"); + ao_add_task(&ao_lco_igniter_status_task, ao_lco_igniter_status, "lco igniter status"); for (;;) { + PRINTD("monitor armed %d firing %d offset %d\n", + ao_lco_armed, ao_lco_firing, ao_lco_tick_offset); + if (ao_lco_armed && ao_lco_firing) { PRINTD("Firing box %d pad %d: valid %d\n", ao_lco_box, ao_lco_pad, ao_lco_valid); if (!ao_lco_valid) ao_lco_update(); if (ao_lco_valid) - ao_lco_ignite(ao_lco_box, ao_lco_pad, ao_lco_tick_offset); + ao_lco_ignite(ao_lco_box, 1 << ao_lco_pad, ao_lco_tick_offset); + } else if (ao_lco_armed) { + PRINTD("Arming box %d pad %d\n", + ao_lco_box, ao_lco_pad); + if (!ao_lco_valid) + ao_lco_update(); + ao_lco_arm(ao_lco_box, 1 << ao_lco_pad, ao_lco_tick_offset); + ao_lco_update(); } else { ao_lco_update(); } @@ -207,25 +314,26 @@ ao_lco_monitor(void) } } -static void -ao_lco_arm_warn(void) +#if DEBUG +void +ao_lco_set_debug(void) { - for (;;) { - while (!ao_lco_armed) - ao_sleep(&ao_lco_armed); - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); - ao_delay(AO_MS_TO_TICKS(200)); - } + ao_cmd_decimal(); + if (ao_cmd_status == ao_cmd_success) + ao_lco_debug = ao_cmd_lex_i != 0; } -static struct ao_task ao_lco_input_task; -static struct ao_task ao_lco_monitor_task; -static struct ao_task ao_lco_arm_warn_task; +__code struct ao_cmds ao_lco_cmds[] = { + { ao_lco_set_debug, "D <0 off, 1 on>\0Debug" }, + { 0, NULL } +}; +#endif void ao_lco_init(void) { - ao_add_task(&ao_lco_input_task, ao_lco_input, "lco input"); ao_add_task(&ao_lco_monitor_task, ao_lco_monitor, "lco monitor"); - ao_add_task(&ao_lco_arm_warn_task, ao_lco_arm_warn, "lco arm warn"); +#if DEBUG + ao_cmd_register(&ao_lco_cmds[0]); +#endif } -- cgit v1.2.3