From da330c5975b9f565d059ef8084dfdacc20f34246 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 26 Oct 2011 22:49:11 -0700 Subject: [PATCH] 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 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 -- 2.30.2