X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=blobdiff_plain;f=src%2Fao.h;h=5bbe5158e8452707518f88cccf477cc83e960a48;hp=6836e0103a7a155a9011387522a0a05e9c7b96d2;hb=02611efea0c485d78fad08c696c1f56e868d36b8;hpb=e59520e343c2573b1b92c0b3c4aaa93e51bc55d3 diff --git a/src/ao.h b/src/ao.h index 6836e010..5bbe5158 100644 --- a/src/ao.h +++ b/src/ao.h @@ -21,7 +21,9 @@ #include #include #include +#include #include "cc1111.h" +#include "ao_pins.h" #define TRUE 1 #define FALSE 0 @@ -39,8 +41,9 @@ /* 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 */ + uint8_t task_id; /* unique id */ __code char *name; /* task name */ uint8_t stack[AO_STACK_SIZE]; /* saved stack */ }; @@ -54,22 +57,34 @@ 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 */ 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; +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); @@ -88,6 +103,10 @@ 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 */ +#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 @@ -98,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 @@ -115,7 +135,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 @@ -126,15 +146,7 @@ void ao_clock_init(void); /* - * ao_adc.c - */ - -#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 + * One set of samples read from the A/D converter or telemetry */ struct ao_adc { uint16_t tick; /* tick when the sample was read */ @@ -146,12 +158,38 @@ 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 + */ + +#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 @@ -166,15 +204,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 +ao_adc_isr(void) __interrupt 1; /* Initialize the A/D converter */ void ao_adc_init(void); +#endif /* HAS_ADC */ + /* * ao_beep.c */ @@ -233,8 +272,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 @@ -260,6 +297,25 @@ 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 */ @@ -272,13 +328,21 @@ 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); +#if HAS_USB /* USB interrupt handler */ void -ao_usb_isr(void) interrupt 6; +ao_usb_isr(void) __interrupt 6; +#endif /* Enable the USB controller */ void @@ -303,6 +367,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; @@ -324,8 +389,10 @@ 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); const char *help; }; @@ -340,9 +407,10 @@ 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 and will be used to wakeup any waiters */ + uint8_t ao_dma_alloc(__xdata uint8_t * done); @@ -369,7 +437,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 @@ -382,54 +450,71 @@ 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; + +/* Block size - device is erased in these units. At least 256 bytes */ +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_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)) +/* 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_ee_flush(void) __reentrant; +ao_storage_setup(void); -/* Write to the eeprom */ +/* Write data. Returns 0 on failure, 1 on success */ 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; -/* Read from the eeprom */ +/* Read data. Returns 0 on failure, 1 on success */ 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; -/* Write the config block (at the end of the eeprom) */ +/* Erase a block of storage. This always clears ao_storage_block bytes */ uint8_t -ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant; +ao_storage_erase(uint32_t pos) __reentrant; -/* Read the config block (at the end of the eeprom) */ -uint8_t -ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant; +/* Flush any pending writes to stable storage */ +void +ao_storage_flush(void) __reentrant; -/* Initialize the EEPROM code */ +/* Initialize the storage code */ void -ao_ee_init(void); +ao_storage_init(void); /* - * ao_log.c + * Low-level functions wrapped by ao_storage.c */ -/* Structure containing GPS position, either lat or lon */ +/* 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; -struct ao_gps_pos { - uint8_t degrees; - uint8_t minutes; - uint16_t minutes_fraction; /* in units of 1/10000 minutes */ -}; +/* 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 + */ /* * The data log is recorded in the eeprom as a sequence @@ -465,6 +550,8 @@ struct ao_gps_pos { #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) @@ -499,12 +586,23 @@ struct ao_log_record { uint8_t second; uint8_t flags; } gps_time; - struct ao_gps_pos gps_latitude; - struct ao_gps_pos gps_longitude; + 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; @@ -513,26 +611,18 @@ struct ao_log_record { }; /* Write a record to the eeprom log */ -void -ao_log_data(struct ao_log_record *log); +uint8_t +ao_log_data(__xdata struct ao_log_record *log) __reentrant; /* Flush the 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; - -/* 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); +extern __xdata uint16_t ao_flight_number; /* Logging thread main routine */ void @@ -550,6 +640,18 @@ 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); + +/* 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 */ @@ -567,7 +669,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; @@ -577,6 +679,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 @@ -654,13 +757,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; +ao_serial_rx1_isr(void) __interrupt 3; void -ao_serial_tx1_isr(void) interrupt 14; -#endif +ao_serial_tx1_isr(void) __interrupt 14; char ao_serial_getchar(void) __critical; @@ -668,8 +774,29 @@ ao_serial_getchar(void) __critical; 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 + +void +ao_serial_set_speed(uint8_t speed); + 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 @@ -679,26 +806,45 @@ ao_serial_init(void); #define AO_GPS_NUM_SAT_SHIFT (0) #define AO_GPS_VALID (1 << 4) -#define AO_GPS_LONGITUDE_MASK (1 << 5) -#define AO_GPS_LONGITUDE_EAST (0 << 5) -#define AO_GPS_LONGITUDE_WEST (1 << 5) +#define AO_GPS_RUNNING (1 << 5) +#define AO_GPS_DATE_VALID (1 << 6) -#define AO_GPS_LATITUDE_MASK (1 << 6) -#define AO_GPS_LATITUDE_NORTH (0 << 6) -#define AO_GPS_LATITUDE_SOUTH (1 << 6) +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; - struct ao_gps_pos latitude; - struct ao_gps_pos longitude; - int16_t altitude; + 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); @@ -706,6 +852,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); @@ -724,18 +873,32 @@ ao_gps_report_init(void); */ #define AO_MAX_CALLSIGN 8 +#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; int16_t ground_accel; 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]; + 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) */ @@ -747,6 +910,9 @@ struct ao_telemetry { void ao_telemetry_set_interval(uint16_t interval); +void +ao_rdf_set(uint8_t rdf); + void ao_telemetry_init(void); @@ -754,17 +920,45 @@ 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_done; +extern __xdata uint8_t ao_radio_mutex; + void -ao_radio_send(__xdata struct ao_telemetry *telemetry) __reentrant; +ao_radio_general_isr(void) __interrupt 16; -struct ao_radio_recv { - struct ao_telemetry telemetry; - int8_t rssi; - uint8_t status; -}; +void +ao_radio_get(void); + +#define ao_radio_put() ao_mutex_put(&ao_radio_mutex) void -ao_radio_recv(__xdata struct ao_radio_recv *recv) __reentrant; +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)) + +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); @@ -788,9 +982,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 */ @@ -821,22 +1030,31 @@ ao_igniter_init(void); */ #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 0 +#define AO_CONFIG_MINOR 4 struct ao_config { uint8_t major; uint8_t minor; uint16_t main_deploy; - int16_t accel_zero_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; /* 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; +#define AO_CONFIG_MAX_SIZE 128 + void ao_config_get(void); +void +ao_config_put(void); + void ao_config_init(void); @@ -857,8 +1075,6 @@ ao_rssi_init(uint8_t rssi_led); * each instance of a product */ -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[]; @@ -894,37 +1110,60 @@ 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 64 +#define AO_PACKET_SYN (uint8_t) 0xff 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 callsign[AO_MAX_CALLSIGN]; }; -uint8_t -ao_packet_connect(uint8_t dest); +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_accept(void); +ao_packet_recv(void); + +void +ao_packet_flush(void); -int -ao_packet_send(uint8_t *data, int len); +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 */ -int -ao_packet_recv(uint8_t *data, int len); +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_ */