From acc4fc635edb70ec1ba2dff9f7ac0c8542c72c47 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 14 Apr 2009 19:08:01 -0700 Subject: [PATCH] Add in existing flight pieces: flight/report/log These pieces come from the old telemetrum firmware. Signed-off-by: Keith Packard --- Makefile | 3 + ao.h | 165 ++++++++++++++++++++++++++++++++++++++++++--- ao_adc.c | 6 +- ao_cmd.c | 12 ++-- ao_ee.c | 24 ++++--- ao_flight.c | 160 ++++++++++++++++++++++++++++++++++++++++++++ ao_log.c | 189 ++++++++++++++++++++++++++++++++++++++++++++++++++++ ao_report.c | 81 ++++++++++++++++++++++ ao_timer.c | 8 ++- 9 files changed, 621 insertions(+), 27 deletions(-) create mode 100644 ao_flight.c create mode 100644 ao_log.c create mode 100644 ao_report.c diff --git a/Makefile b/Makefile index 909bb462..f8c9c73a 100644 --- a/Makefile +++ b/Makefile @@ -20,9 +20,12 @@ SRC = \ ao_cmd.c \ ao_dma.c \ ao_ee.c \ + ao_flight.c \ ao_led.c \ + ao_log.c \ ao_mutex.c \ ao_panic.c \ + ao_report.c \ ao_task.c \ ao_timer.c \ ao_usb.c \ diff --git a/ao.h b/ao.h index 82678595..5574f30f 100644 --- a/ao.h +++ b/ao.h @@ -29,7 +29,7 @@ /* Stack runs from above the allocated __data space to 0xfe, which avoids * writing to 0xff as that triggers the stack overflow indicator */ -#define AO_STACK_START 0x75 +#define AO_STACK_START 0x7f #define AO_STACK_END 0xfe #define AO_STACK_SIZE (AO_STACK_END - AO_STACK_START + 1) @@ -78,6 +78,7 @@ ao_start_scheduler(void); #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 */ /* Stop the operating system, beeping and blinking the reason */ void @@ -111,7 +112,7 @@ ao_timer_init(void); * ao_adc.c */ -#define ADC_RING 128 +#define AO_ADC_RING 128 /* * One set of samples read from the A/D converter @@ -130,7 +131,7 @@ struct ao_adc { * 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[ADC_RING]; +extern volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; extern volatile __data uint8_t ao_adc_head; /* Trigger a conversion sequence (called from the timer interrupt) */ @@ -325,26 +326,174 @@ ao_mutex_put(__xdata uint8_t *ao_mutex); #define AO_EE_CONFIG_BLOCK ((uint16_t) (AO_EE_DATA_SIZE / AO_EE_BLOCK_SIZE)) void -ao_ee_flush(void); +ao_ee_flush(void) __reentrant; /* Write to the eeprom */ uint8_t -ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len); +ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant; /* Read from the eeprom */ uint8_t -ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len); +ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant; /* Write the config block (at the end of the eeprom) */ uint8_t -ao_ee_write_config(uint8_t *buf, uint16_t len); +ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant; /* Read the config block (at the end of the eeprom) */ uint8_t -ao_ee_read_config(uint8_t *buf, uint16_t len); +ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant; /* Initialize the EEPROM code */ void ao_ee_init(void); +/* + * ao_log.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_POS_NONE (~0UL) + +struct ao_log_record { + uint8_t type; + uint8_t csum; + uint16_t tick; + union { + struct { + uint16_t serial; + 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 { + uint16_t d0; + uint16_t d1; + } anon; + } u; +}; + +/* Write a record to the eeprom log */ +void +ao_log_data(struct ao_log_record *log); + +/* 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 + */ +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); + +/* Logging thread main routine */ +void +ao_log(void); + +/* Start logging to eeprom */ +void +ao_log_start(void); + +/* Initialize the logging system */ +void +ao_log_init(void); + +/* + * ao_flight.c + */ + +enum ao_flight_state { + ao_flight_startup, + ao_flight_idle, + ao_flight_launchpad, + ao_flight_boost, + ao_flight_coast, + ao_flight_apogee, + ao_flight_drogue, + ao_flight_main, + ao_flight_landed, + ao_flight_invalid +}; + +extern __xdata struct ao_adc ao_flight_data; +extern __data enum flight_state ao_flight_state; +extern __data uint16_t ao_flight_state_tick; +extern __data int16_t ao_flight_accel; +extern __data int16_t ao_flight_pres; +extern __data int16_t ao_ground_pres; +extern __data int16_t ao_ground_accel; +extern __data int16_t ao_min_pres; +extern __data uint16_t ao_launch_time; + +/* Flight thread */ +void +ao_flight(void); + +/* Initialize flight thread */ +void +ao_flight_init(void); + +/* + * ao_report.c + */ + +void +ao_report_notify(void); + +void +ao_report_init(void); + #endif /* _AO_H_ */ diff --git a/ao_adc.c b/ao_adc.c index 549cc944..8834f26e 100644 --- a/ao_adc.c +++ b/ao_adc.c @@ -18,7 +18,7 @@ #include "ao.h" -volatile __xdata struct ao_adc ao_adc_ring[ADC_RING]; +volatile __xdata struct ao_adc ao_adc_ring[AO_ADC_RING]; volatile __data uint8_t ao_adc_head; void @@ -38,7 +38,7 @@ ao_adc_get(__xdata struct ao_adc *packet) { uint8_t i = ao_adc_head; if (i == 0) - i = ADC_RING; + i = AO_ADC_RING; i--; memcpy(packet, &ao_adc_ring[i], sizeof (struct ao_adc)); } @@ -60,7 +60,7 @@ ao_adc_isr(void) interrupt 1 /* record this conversion series */ ao_adc_ring[ao_adc_head].tick = ao_time(); ao_adc_head++; - if (ao_adc_head == ADC_RING) + if (ao_adc_head == AO_ADC_RING) ao_adc_head = 0; ao_wakeup(ao_adc_ring); } diff --git a/ao_cmd.c b/ao_cmd.c index fd87f87e..303f9bc5 100644 --- a/ao_cmd.c +++ b/ao_cmd.c @@ -463,20 +463,18 @@ debug_output(void) static void dump_log(void) { -#if 0 uint8_t more; - for (more = log_first(); more; more = log_next()) { - putchar(log_dump.type); + for (more = ao_log_dump_first(); more; more = ao_log_dump_next()) { + putchar(ao_log_dump.type); putchar(' '); - put16(log_dump.tick); + put16(ao_log_dump.tick); putchar(' '); - put16(log_dump.u.anon.d0); + put16(ao_log_dump.u.anon.d0); putchar(' '); - put16(log_dump.u.anon.d1); + put16(ao_log_dump.u.anon.d1); putchar('\n'); } -#endif } static const uint8_t help_txt[] = diff --git a/ao_ee.c b/ao_ee.c index 8e2e94d5..e731ba2a 100644 --- a/ao_ee.c +++ b/ao_ee.c @@ -216,15 +216,15 @@ ao_ee_read_block(void) ao_ee_cs_high(); } -void -ao_ee_flush(void) +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) { @@ -236,7 +236,7 @@ ao_ee_fill(uint16_t block) } uint8_t -ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) +ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant { uint16_t block; uint16_t this_len; @@ -262,7 +262,7 @@ ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) if (this_len != 256) ao_ee_fill(block); else { - ao_ee_flush(); + ao_ee_flush_internal(); ao_ee_block = block; } memcpy(ao_ee_data + this_off, buf, this_len); @@ -277,7 +277,7 @@ ao_ee_write(uint32_t pos, uint8_t *buf, uint16_t len) } uint8_t -ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) +ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) __reentrant { uint16_t block; uint16_t this_len; @@ -311,12 +311,20 @@ ao_ee_read(uint32_t pos, uint8_t *buf, uint16_t len) return 1; } +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) +ao_ee_write_config(uint8_t *buf, uint16_t len) __reentrant { if (len > AO_EE_BLOCK_SIZE) return 0; @@ -329,7 +337,7 @@ ao_ee_write_config(uint8_t *buf, uint16_t len) } uint8_t -ao_ee_read_config(uint8_t *buf, uint16_t len) +ao_ee_read_config(uint8_t *buf, uint16_t len) __reentrant { if (len > AO_EE_BLOCK_SIZE) return 0; diff --git a/ao_flight.c b/ao_flight.c new file mode 100644 index 00000000..f31b4cd4 --- /dev/null +++ b/ao_flight.c @@ -0,0 +1,160 @@ +/* + * 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. + */ + +#include "ao.h" + +/* Main flight thread. */ + +__xdata struct ao_adc ao_flight_data; +__data enum flight_state ao_flight_state; +__data uint16_t ao_flight_state_tick; +__data int16_t ao_flight_accel; +__data int16_t ao_flight_pres; +__data int16_t ao_ground_pres; +__data int16_t ao_ground_accel; +__data int16_t ao_min_pres; +__data uint16_t ao_launch_time; + +/* 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) + */ + +#define ACCEL_G 265 +#define ACCEL_ZERO_G 16000 +#define ACCEL_NOSE_UP (ACCEL_ZERO_G - ACCEL_G * 2 /3) +#define ACCEL_BOOST (ACCEL_NOSE_UP - ACCEL_G * 2) + +/* + * 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 + */ + +#define BARO_kPa 268 +#define BARO_LAUNCH (BARO_kPa / 5) /* .2kPa */ +#define BARO_APOGEE (BARO_kPa / 10) /* .1kPa */ + +/* 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(10) + +void +ao_flight(void) +{ + __data static uint8_t nsamples = 0; + + for (;;) { + ao_sleep(&ao_adc_ring); + ao_adc_get(&ao_flight_data); + ao_flight_accel -= ao_flight_accel >> 4; + ao_flight_accel += ao_flight_data.accel >> 4; + ao_flight_pres -= ao_flight_pres >> 4; + ao_flight_pres += ao_flight_data.pres >> 4; + + switch (ao_flight_state) { + case ao_flight_startup: + if (nsamples < 100) { + ++nsamples; + continue; + } + ao_ground_accel = ao_flight_accel; + ao_ground_pres = ao_flight_pres; + ao_min_pres = ao_flight_pres; + if (ao_flight_accel < ACCEL_NOSE_UP) { + ao_flight_state = ao_flight_launchpad; + ao_flight_state_tick = ao_time(); + ao_report_notify(); + } else { + ao_flight_state = ao_flight_idle; + ao_flight_state_tick = ao_time(); + ao_report_notify(); + } + break; + case ao_flight_launchpad: + if (ao_flight_accel < ACCEL_BOOST || + ao_flight_pres + BARO_LAUNCH < ao_ground_pres) + { + ao_flight_state = ao_flight_boost; + ao_flight_state_tick = ao_time(); + ao_log_start(); + ao_report_notify(); + break; + } + break; + case ao_flight_boost: + if (ao_flight_accel > ACCEL_ZERO_G || + (int16_t) (ao_flight_data.tick - ao_launch_time) > BOOST_TICKS_MAX) + { + ao_flight_state = ao_flight_coast; + ao_flight_state_tick = ao_time(); + ao_report_notify(); + break; + } + break; + case ao_flight_coast: + if (ao_flight_pres < ao_min_pres) + ao_min_pres = ao_flight_pres; + if (ao_flight_pres - BARO_APOGEE > ao_min_pres) { + ao_flight_state = ao_flight_apogee; + ao_flight_state_tick = ao_time(); + ao_report_notify(); + } + break; + case ao_flight_apogee: + 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); +} + diff --git a/ao_log.c b/ao_log.c new file mode 100644 index 00000000..112ea510 --- /dev/null +++ b/ao_log.c @@ -0,0 +1,189 @@ +/* + * 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. + */ + +#include "ao.h" + +__data uint32_t ao_log_current_pos; +__data uint32_t ao_log_start_pos; +__xdata uint8_t ao_log_running; +__xdata uint8_t ao_log_mutex; + +static uint8_t +ao_log_csum(uint8_t *b) +{ + uint8_t sum = 0x5a; + uint8_t i; + + for (i = 0; i < sizeof (struct ao_log_record); i++) + sum += *b++; + return -sum; +} + +void +ao_log_data(struct ao_log_record *log) +{ + /* set checksum */ + log->csum = 0; + log->csum = ao_log_csum((uint8_t *) log); + ao_mutex_get(&ao_log_mutex); { + if (ao_log_running) { + ao_ee_write(ao_log_current_pos, + (uint8_t *) 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); +} + +void +ao_log_flush(void) +{ + ao_ee_flush(); +} + +__xdata struct ao_log_record ao_log_dump; +static __data uint16_t ao_log_dump_flight; +static __data uint32_t ao_log_dump_pos; + +static uint8_t +ao_log_dump_check_data(void) +{ + if (ao_log_csum((uint8_t *) &ao_log_dump) != 0) + return 0; + return 1; +} + +static uint8_t +ao_log_dump_scan(void) +{ + if (!ao_ee_read(0, (uint8_t *) &ao_log_dump, 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; + } else { + ao_log_dump_flight = 0; + return 0; + } +} + +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(); +} + +uint8_t ao_log_adc_pos; +enum flight_state ao_log_state; + +void +ao_log(void) +{ + static __xdata struct ao_log_record log; + + ao_log_dump_scan(); + + while (!ao_log_running) + ao_sleep(&ao_log_running); + + log.type = AO_LOG_FLIGHT; + log.tick = ao_flight_state_tick; + log.u.flight.serial = 0; + log.u.flight.flight = ao_log_dump_flight + 1; + ao_log_data(&log); + for (;;) { + /* 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_state_tick; + log.u.state.state = ao_log_state; + log.u.state.reason = 0; + ao_log_data(&log); + } + /* Write samples to EEPROM */ + while (ao_log_adc_pos != ao_adc_head) { + 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 == 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++; + if (ao_log_adc_pos == AO_ADC_RING) + ao_log_adc_pos = 0; + } + + /* Wait for a while */ + ao_delay(AO_MS_TO_TICKS(100)); + } +} + +void +ao_log_start(void) +{ + /* start logging */ + ao_log_running = 1; + ao_wakeup(&ao_log_running); +} + +static __xdata struct ao_task ao_log_task; + +void +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 */ + ao_add_task(&ao_log_task, ao_log); +} diff --git a/ao_report.c b/ao_report.c new file mode 100644 index 00000000..1cc883be --- /dev/null +++ b/ao_report.c @@ -0,0 +1,81 @@ +/* + * 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. + */ + +#include "ao.h" + +static const char * __xdata flight_reports[] = { + "...", /* startup, 'S' */ + "..", /* idle 'I' */ + ".--.", /* launchpad 'P' */ + "-...", /* boost 'B' */ + "-.-.", /* coast 'C' */ + ".-", /* apogee 'A' */ + "-..", /* drogue 'D' */ + "--", /* main 'M' */ + ".-..", /* landed 'L' */ + ".-.-.-", /* invalid */ +}; + +#if 1 +#define signal(time) ao_beep_for(AO_BEEP_MID, time) +#else +#define signal(time) ao_led_for(AO_LED_RED, time) +#endif +#define pause(time) ao_delay(time) + +static void +ao_report_state(void) +{ + char *r = flight_reports[ao_flight_state]; + char c; + + if (!r) + return; + while (c = *r++) { + if (c == '.') + signal(AO_MS_TO_TICKS(200)); + else + signal(AO_MS_TO_TICKS(600)); + pause(AO_MS_TO_TICKS(200)); + } +} + +static __xdata ao_report_wait; + +void +ao_report_notify(void) +{ + ao_wakeup(&ao_report_wait); +} + +void +ao_report(void) +{ + for(;;) { + ao_report_state(); + ao_sleep(&ao_report_wait); + } +} + +static __xdata struct ao_task ao_report_task; + +void +ao_report_init(void) +{ + ao_add_task(&ao_report_task, ao_report); +} diff --git a/ao_timer.c b/ao_timer.c index 9583a388..702159b7 100644 --- a/ao_timer.c +++ b/ao_timer.c @@ -42,10 +42,16 @@ ao_delay(uint16_t ticks) #define T1_CLOCK_DIVISOR 8 /* 24e6/8 = 3e6 */ #define T1_SAMPLE_TIME 30000 /* 3e6/30000 = 100 */ +__data uint8_t ao_adc_interval = 1; +__data uint8_t ao_adc_count; + void ao_timer_isr(void) interrupt 9 { ++ao_tick_count; - ao_adc_poll(); + if (++ao_adc_count >= ao_adc_interval) { + ao_adc_count = 0; + ao_adc_poll(); + } ao_wakeup(DATA_TO_XDATA(&ao_tick_count)); } -- 2.30.2