From f4c812bef76a2cd95f675cb27ea89059561ceec7 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 13 Feb 2015 23:51:10 -0800 Subject: altos: Replace ao_alarm/ao_clear_alarm with ao_sleep_for Having arbitrary alarms firing in the middle of complicated device logic makes no sense at all. Therefore only correct use of ao_alarm and ao_clear_alarm was around a specific ao_sleep call, with correct recovery in case the alarm fires. This patch replaces all uses of ao_alarm/ao_sleep/ao_clear_alarm with ao_sleep_for, a new function which takes the alarm timeout directly. A few cases which weren't simply calling ao_sleep have been reworked to pass the timeout value down to the place where sleep *is* being called, and having that code deal with the return correctly. Signed-off-by: Keith Packard --- src/drivers/ao_btm.c | 8 +++----- src/drivers/ao_cc1120.c | 16 +++------------- src/drivers/ao_cc1200.c | 8 +------- src/drivers/ao_companion.c | 3 +-- src/drivers/ao_hmc5883.c | 4 +--- src/drivers/ao_packet.c | 4 ++-- src/drivers/ao_packet_master.c | 8 ++------ src/drivers/ao_packet_slave.c | 2 +- 8 files changed, 14 insertions(+), 39 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_btm.c b/src/drivers/ao_btm.c index e6b28688..93d9dd9d 100644 --- a/src/drivers/ao_btm.c +++ b/src/drivers/ao_btm.c @@ -23,7 +23,7 @@ #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_sleep() ao_sleep((void *) &ao_serial1_rx_fifo) +#define _ao_serial_btm_sleep_for(timeout) ao_sleep_for((void *) &ao_serial1_rx_fifo, timeout) #define ao_serial_btm_set_speed ao_serial1_set_speed #define ao_serial_btm_drain ao_serial1_drain #endif @@ -111,7 +111,7 @@ ao_btm_do_echo(void) while (ao_btm_enable) { ao_arch_block_interrupts(); while ((c = _ao_serial_btm_pollchar()) == AO_READ_AGAIN && ao_btm_enable) - _ao_serial_btm_sleep(); + _ao_serial_btm_sleep_for(0); ao_arch_release_interrupts(); if (c != AO_READ_AGAIN) { putchar(c); @@ -166,9 +166,7 @@ ao_btm_getchar(void) ao_arch_block_interrupts(); while ((c = _ao_serial_btm_pollchar()) == AO_READ_AGAIN) { - ao_alarm(AO_MS_TO_TICKS(10)); - c = _ao_serial_btm_sleep(); - ao_clear_alarm(); + c = _ao_serial_btm_sleep_for(AO_MS_TO_TICKS(10)); if (c) { c = AO_READ_AGAIN; break; diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 90d6cc75..5b814667 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -837,15 +837,11 @@ ao_radio_test_cmd(void) static void ao_radio_wait_isr(uint16_t timeout) { - if (timeout) - ao_alarm(timeout); ao_arch_block_interrupts(); while (!ao_radio_wake && !ao_radio_mcu_wake && !ao_radio_abort) - if (ao_sleep(&ao_radio_wake)) + if (ao_sleep_for(&ao_radio_wake, timeout)) ao_radio_abort = 1; ao_arch_release_interrupts(); - if (timeout) - ao_clear_alarm(); if (ao_radio_mcu_wake) ao_radio_check_marc_status(); } @@ -1060,19 +1056,17 @@ ao_radio_rx_isr(void) static uint16_t ao_radio_rx_wait(void) { - ao_alarm(AO_MS_TO_TICKS(100)); ao_arch_block_interrupts(); rx_waiting = 1; while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK && !ao_radio_abort && !ao_radio_mcu_wake) { - if (ao_sleep(&ao_radio_wake)) + if (ao_sleep_for(&ao_radio_wake, AO_MS_TO_TICKS(100))) ao_radio_abort = 1; } rx_waiting = 0; ao_arch_release_interrupts(); - ao_clear_alarm(); if (ao_radio_abort || ao_radio_mcu_wake) return 0; rx_data_consumed += AO_FEC_DECODE_BLOCK; @@ -1133,19 +1127,15 @@ ao_radio_recv(__xdata void *d, uint8_t size, uint8_t timeout) ao_radio_strobe(CC1120_SRX); - if (timeout) - ao_alarm(timeout); ao_arch_block_interrupts(); while (rx_starting && !ao_radio_abort) { - if (ao_sleep(&ao_radio_wake)) + if (ao_sleep_for(&ao_radio_wake, timeout)) ao_radio_abort = 1; } uint8_t rx_task_id_save = rx_task_id; rx_task_id = 0; rx_starting = 0; ao_arch_release_interrupts(); - if (timeout) - ao_clear_alarm(); if (ao_radio_abort) { if (rx_task_id_save == 0) diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index 8546900e..df4bd335 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -715,17 +715,11 @@ ao_radio_show_state(char *where) static void ao_radio_wait_isr(uint16_t timeout) { - if (timeout) - ao_alarm(timeout); - ao_arch_block_interrupts(); while (!ao_radio_wake && !ao_radio_abort) - if (ao_sleep(&ao_radio_wake)) + if (ao_sleep_for(&ao_radio_wake, timeout)) ao_radio_abort = 1; ao_arch_release_interrupts(); - - if (timeout) - ao_clear_alarm(); } static void diff --git a/src/drivers/ao_companion.c b/src/drivers/ao_companion.c index 570b9e40..7e02939b 100644 --- a/src/drivers/ao_companion.c +++ b/src/drivers/ao_companion.c @@ -102,8 +102,7 @@ ao_companion(void) break; } while (ao_companion_running) { - ao_alarm(ao_companion_setup.update_period); - if (ao_sleep(DATA_TO_XDATA(&ao_flight_state))) + if (ao_sleep_for(DATA_TO_XDATA(&ao_flight_state), ao_companion_setup.update_period)) ao_companion_get_data(); else ao_companion_notify(); diff --git a/src/drivers/ao_hmc5883.c b/src/drivers/ao_hmc5883.c index 2d217bcf..f761671a 100644 --- a/src/drivers/ao_hmc5883.c +++ b/src/drivers/ao_hmc5883.c @@ -75,13 +75,11 @@ 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)); ao_arch_block_interrupts(); while (!ao_hmc5883_done) - if (ao_sleep(&ao_hmc5883_done)) + if (ao_sleep_for(&ao_hmc5883_done, AO_MS_TO_TICKS(10))) ++ao_hmc5883_missed_irq; ao_arch_release_interrupts(); - ao_clear_alarm(); ao_hmc5883_read(HMC5883_X_MSB, (uint8_t *) sample, sizeof (struct ao_hmc5883_sample)); #if __BYTE_ORDER == __LITTLE_ENDIAN diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c index 8cdf85a9..18330ead 100644 --- a/src/drivers/ao_packet.c +++ b/src/drivers/ao_packet.c @@ -54,14 +54,14 @@ ao_packet_send(void) } uint8_t -ao_packet_recv(void) +ao_packet_recv(uint16_t timeout) { 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), 0); + dma_done = ao_radio_recv(&ao_rx_packet, sizeof (struct ao_packet_recv), timeout); #ifdef AO_LED_GREEN ao_led_off(AO_LED_GREEN); #endif diff --git a/src/drivers/ao_packet_master.c b/src/drivers/ao_packet_master.c index 42a4f5bf..5e440db0 100644 --- a/src/drivers/ao_packet_master.c +++ b/src/drivers/ao_packet_master.c @@ -97,9 +97,7 @@ ao_packet_master(void) if (ao_tx_packet.len) ao_packet_master_busy(); ao_packet_master_check_busy(); - ao_alarm(AO_PACKET_MASTER_RECV_DELAY); - r = ao_packet_recv(); - ao_clear_alarm(); + r = ao_packet_recv(AO_PACKET_MASTER_RECV_DELAY); if (r) { /* if we can transmit data, do so */ if (ao_packet_tx_used && ao_tx_packet.len == 0) @@ -107,9 +105,7 @@ ao_packet_master(void) 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_sleep_for(&ao_packet_master_sleeping, ao_packet_master_delay); ao_packet_master_sleeping = 0; } } diff --git a/src/drivers/ao_packet_slave.c b/src/drivers/ao_packet_slave.c index e75df0d6..0872682f 100644 --- a/src/drivers/ao_packet_slave.c +++ b/src/drivers/ao_packet_slave.c @@ -24,7 +24,7 @@ ao_packet_slave(void) ao_tx_packet.len = AO_PACKET_SYN; ao_packet_restart = 1; while (ao_packet_enable) { - if (ao_packet_recv()) { + if (ao_packet_recv(0)) { ao_xmemcpy(&ao_tx_packet.callsign, &ao_rx_packet.packet.callsign, AO_MAX_CALLSIGN); #if HAS_FLIGHT ao_flight_force_idle = TRUE; -- cgit v1.2.3 From 135abf0e7c5ceb5738a0b5f68fe2be4b7abdae5e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 14 Feb 2015 23:18:38 -0800 Subject: altos/cc1200: Adjust bit-sync configuration The default bit timing adjustment mechanism allows for only a 0.2% deviation from the programmed bit timing. I found one TeleMini device which is beyond that tolerance as it was built with an older crystal with more error. Switch to the more expensive synchronization mechanism which allows up to 2% timing error, but requires a multi-byte preamble (which we have). This fixes packet mode nicely. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200.h | 32 ++++++++++++++++++++++++++++++++ src/drivers/ao_cc1200_CC1200.h | 9 +++++++++ src/drivers/ao_packet.c | 14 ++++++++++++-- 3 files changed, 53 insertions(+), 2 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_cc1200.h b/src/drivers/ao_cc1200.h index b04775fd..b2b63cde 100644 --- a/src/drivers/ao_cc1200.h +++ b/src/drivers/ao_cc1200.h @@ -438,6 +438,38 @@ #define CC1200_IF_MIX_CFG (CC1200_EXTENDED_BIT | 0x00) #define CC1200_FREQOFF_CFG (CC1200_EXTENDED_BIT | 0x01) #define CC1200_TOC_CFG (CC1200_EXTENDED_BIT | 0x02) + +#define CC1200_TOC_CFG_TOC_LIMIT 6 +#define CC1200_TOC_CFG_TOC_LIMIT_0_2 0 +#define CC1200_TOC_CFG_TOC_LIMIT_2 1 +#define CC1200_TOC_CFG_TOC_LIMIT_12 3 + +#define CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN 3 +#define CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_8 0 +#define CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_16 1 +#define CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_32 2 +#define CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_64 3 +#define CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_128 4 +#define CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_256 5 +#define CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_8_16 0 +#define CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_6_16 1 +#define CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_2_16 2 +#define CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_1_16 3 +#define CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_1_16_SYNC 4 + +#define CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN 0 +#define CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_8 0 +#define CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_16 1 +#define CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_32 2 +#define CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_64 3 +#define CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_128 4 +#define CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_256 5 +#define CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_FREEZE 0 +#define CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_6_32 1 +#define CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_2_32 2 +#define CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_1_32 3 +#define CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_1_32_SYNC 4 + #define CC1200_MARC_SPARE (CC1200_EXTENDED_BIT | 0x03) #define CC1200_ECG_CFG (CC1200_EXTENDED_BIT | 0x04) #define CC1200_MDMCFG2 (CC1200_EXTENDED_BIT | 0x05) diff --git a/src/drivers/ao_cc1200_CC1200.h b/src/drivers/ao_cc1200_CC1200.h index 35673123..f0214c2a 100644 --- a/src/drivers/ao_cc1200_CC1200.h +++ b/src/drivers/ao_cc1200_CC1200.h @@ -101,6 +101,15 @@ (CC1200_MDMCFG2_SYMBOL_MAP_CFG_MODE_0 << CC1200_MDMCFG2_SYMBOL_MAP_CFG) | (CC1200_MDMCFG2_UPSAMPLER_P_8 << CC1200_MDMCFG2_UPSAMPLER_P) | (0 << CC1200_MDMCFG2_CFM_DATA_EN)), + CC1200_MDMCFG0, /* General Modem Parameter Configuration Reg. 0 */ + ((0 << CC1200_MDMCFG0_TRANSPARENT_MODE_EN) | + (0 << CC1200_MDMCFG0_TRANSPARENT_INTFACT) | + (0 << CC1200_MDMCFG0_DATA_FILTER_EN) | + (1 << CC1200_MDMCFG0_VITERBI_EN)), + CC1200_TOC_CFG, /* Timing Offset Correction Configuration */ + ((CC1200_TOC_CFG_TOC_LIMIT_2 << CC1200_TOC_CFG_TOC_LIMIT) | + (CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN_6_16 << CC1200_TOC_CFG_TOC_PRE_SYNC_BLOCKLEN)| + (CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN_2_32 << CC1200_TOC_CFG_TOC_POST_SYNC_BLOCKLEN)), CC1200_FREQ2, 0x6c, /* Frequency Configuration [23:16] */ CC1200_FREQ1, 0xa3, /* Frequency Configuration [15:8] */ CC1200_FREQ0, 0x33, /* Frequency Configuration [7:0] */ diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c index 18330ead..8c2db275 100644 --- a/src/drivers/ao_packet.c +++ b/src/drivers/ao_packet.c @@ -81,8 +81,16 @@ ao_packet_recv(uint16_t timeout) /* Check to see if we got a valid packet */ if (!dma_done) return 0; - if (!(ao_rx_packet.status & AO_RADIO_STATUS_CRC_OK)) + if (!(ao_rx_packet.status & AO_RADIO_STATUS_CRC_OK)) { + printf("bad crc addr %d len %d seq %d ack %d callsign %8.8s\n", + ao_rx_packet.packet.addr, + ao_rx_packet.packet.len, + ao_rx_packet.packet.seq, + ao_rx_packet.packet.ack, + ao_rx_packet.packet.callsign); + flush(); return 0; + } /* Accept packets with matching call signs, or any packet if * our callsign hasn't been configured @@ -90,8 +98,10 @@ ao_packet_recv(uint16_t timeout) 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) + ao_xmemcmp(ao_config.callsign, CODE_TO_XDATA("N0CALL"), 7) != 0) { + printf ("bad call\n"); flush(); return 0; + } /* SYN packets carry no data */ if (ao_rx_packet.packet.len == AO_PACKET_SYN) { -- cgit v1.2.3 From 2ebb4dff758058ae9512cf36518416eb69b928f0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 15 Feb 2015 08:57:55 -0800 Subject: altos: Remove some accidental debug printfs from ao_packet.c While fixing the cc1200 configuration, I added some debug printfs to this code. They were accidentally committed with the fix... Signed-off-by: Keith Packard --- src/drivers/ao_packet.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c index 8c2db275..18330ead 100644 --- a/src/drivers/ao_packet.c +++ b/src/drivers/ao_packet.c @@ -81,16 +81,8 @@ ao_packet_recv(uint16_t timeout) /* Check to see if we got a valid packet */ if (!dma_done) return 0; - if (!(ao_rx_packet.status & AO_RADIO_STATUS_CRC_OK)) { - printf("bad crc addr %d len %d seq %d ack %d callsign %8.8s\n", - ao_rx_packet.packet.addr, - ao_rx_packet.packet.len, - ao_rx_packet.packet.seq, - ao_rx_packet.packet.ack, - ao_rx_packet.packet.callsign); - flush(); + if (!(ao_rx_packet.status & AO_RADIO_STATUS_CRC_OK)) return 0; - } /* Accept packets with matching call signs, or any packet if * our callsign hasn't been configured @@ -98,10 +90,8 @@ ao_packet_recv(uint16_t timeout) 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) { - printf ("bad call\n"); flush(); + 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) { -- cgit v1.2.3 From bd18bc5a42fcecfb710477371b9f62610a1ea640 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 28 Feb 2015 16:04:00 -0800 Subject: altos: Add chaoskey flash loader Signed-off-by: Keith Packard --- src/chaoskey-v0.1/flash-loader/.gitignore | 2 + src/chaoskey-v0.1/flash-loader/ao_pins.h | 36 ++++++++++++++++++ src/drivers/ao_trng_send.c | 62 +++++++++++++++++++++++++++++++ src/drivers/ao_trng_send.h | 24 ++++++++++++ 4 files changed, 124 insertions(+) create mode 100644 src/chaoskey-v0.1/flash-loader/.gitignore create mode 100644 src/chaoskey-v0.1/flash-loader/ao_pins.h create mode 100644 src/drivers/ao_trng_send.c create mode 100644 src/drivers/ao_trng_send.h (limited to 'src/drivers') diff --git a/src/chaoskey-v0.1/flash-loader/.gitignore b/src/chaoskey-v0.1/flash-loader/.gitignore new file mode 100644 index 00000000..32dbbbcf --- /dev/null +++ b/src/chaoskey-v0.1/flash-loader/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +usbtrng* diff --git a/src/chaoskey-v0.1/flash-loader/ao_pins.h b/src/chaoskey-v0.1/flash-loader/ao_pins.h new file mode 100644 index 00000000..295e0258 --- /dev/null +++ b/src/chaoskey-v0.1/flash-loader/ao_pins.h @@ -0,0 +1,36 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_ + +#include + +/* Pin 5 on debug connector */ + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO stm_gpioa +#define AO_BOOT_APPLICATION_PIN 15 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +/* USB */ +#define HAS_USB 1 +#define AO_USB_DIRECTIO 0 +#define AO_PA11_PA12_RMP 0 + +#endif /* _AO_PINS_H_ */ diff --git a/src/drivers/ao_trng_send.c b/src/drivers/ao_trng_send.c new file mode 100644 index 00000000..34a8a981 --- /dev/null +++ b/src/drivers/ao_trng_send.c @@ -0,0 +1,62 @@ +/* + * Copyright © 2015 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 void +ao_trng_send(void) +{ + static uint16_t *buffer[2]; + int usb_buf_id; + uint16_t i; + uint16_t *buf; + uint32_t *rnd; + + if (!buffer[0]) { + buffer[0] = ao_usb_alloc(); + buffer[1] = ao_usb_alloc(); + if (!buffer[0]) + return; + } + + usb_buf_id = 0; + + ao_crc_reset(); + + for (;;) { + ao_led_on(AO_LED_TRNG_ACTIVE); + rnd = (uint32_t *) ao_adc_get(AO_USB_IN_SIZE); /* one 16-bit value per output byte */ + buf = buffer[usb_buf_id]; + for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) + *buf++ = ao_crc_in_32_out_16(*rnd++); + ao_adc_ack(AO_USB_IN_SIZE); + ao_led_off(AO_LED_TRNG_ACTIVE); + ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE); + usb_buf_id = 1-usb_buf_id; + } +} + +static struct ao_task ao_trng_send_task; + +void +ao_trng_send_init(void) +{ + ao_add_task(&ao_trng_send_task, ao_trng_send, "trng_send"); +} diff --git a/src/drivers/ao_trng_send.h b/src/drivers/ao_trng_send.h new file mode 100644 index 00000000..83312d59 --- /dev/null +++ b/src/drivers/ao_trng_send.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2015 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_TRNG_SEND_H_ +#define _AO_TRNG_SEND_H_ + +void +ao_trng_send_init(void); + +#endif /* _AO_TRNG_SEND_H_ */ -- cgit v1.2.3 From 0724cc334a3bd8d81bbd4641d90a7e4040330efe Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sat, 28 Feb 2015 16:06:23 -0800 Subject: altos/usbtrng: Split out random number generating code to separate driver Signed-off-by: Keith Packard --- src/drivers/ao_trng.c | 76 +++++++++++++++++++++++++++++++++++++++++++ src/drivers/ao_trng.h | 24 ++++++++++++++ src/usbtrng-v2.0/Makefile | 2 ++ src/usbtrng-v2.0/ao_pins.h | 4 +++ src/usbtrng-v2.0/ao_usbtrng.c | 56 ++----------------------------- 5 files changed, 109 insertions(+), 53 deletions(-) create mode 100644 src/drivers/ao_trng.c create mode 100644 src/drivers/ao_trng.h (limited to 'src/drivers') diff --git a/src/drivers/ao_trng.c b/src/drivers/ao_trng.c new file mode 100644 index 00000000..db742928 --- /dev/null +++ b/src/drivers/ao_trng.c @@ -0,0 +1,76 @@ +/* + * Copyright © 2015 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public 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 void +ao_trng_fetch(void) +{ + static uint16_t *buffer[2]; + uint32_t kbytes = 1; + uint32_t count; + int usb_buf_id; + uint16_t i; + uint16_t *buf; + uint32_t *rnd; + + if (!buffer[0]) { + buffer[0] = ao_usb_alloc(); + buffer[1] = ao_usb_alloc(); + if (!buffer[0]) + return; + } + + ao_cmd_decimal(); + if (ao_cmd_status == ao_cmd_success) + kbytes = ao_cmd_lex_u32; + else + ao_cmd_status = ao_cmd_success; + usb_buf_id = 0; + count = kbytes * (1024/AO_USB_IN_SIZE); + + ao_crc_reset(); + + ao_led_on(AO_LED_TRNG_READ); + while (count--) { + rnd = (uint32_t *) ao_adc_get(AO_USB_IN_SIZE); /* one 16-bit value per output byte */ + buf = buffer[usb_buf_id]; + for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) + *buf++ = ao_crc_in_32_out_16(*rnd++); + ao_adc_ack(AO_USB_IN_SIZE); + ao_led_toggle(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE); + ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE); + ao_led_toggle(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE); + usb_buf_id = 1-usb_buf_id; + } + ao_led_off(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE); + flush(); +} + +static const struct ao_cmds ao_trng_cmds[] = { + { ao_trng_fetch, "f \0Fetch a block of numbers" }, + { 0, NULL }, +}; + +void +ao_trng_init(void) +{ + ao_cmd_register(ao_trng_cmds); +} diff --git a/src/drivers/ao_trng.h b/src/drivers/ao_trng.h new file mode 100644 index 00000000..78577428 --- /dev/null +++ b/src/drivers/ao_trng.h @@ -0,0 +1,24 @@ +/* + * Copyright © 2015 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_TRNG_H_ +#define _AO_TRNG_H_ + +void +ao_trng_init(void); + +#endif /* _AO_TRNG_H_ */ diff --git a/src/usbtrng-v2.0/Makefile b/src/usbtrng-v2.0/Makefile index abbdbbcc..49798f1c 100644 --- a/src/usbtrng-v2.0/Makefile +++ b/src/usbtrng-v2.0/Makefile @@ -12,6 +12,7 @@ INC = \ ao_pins.h \ ao_product.h \ ao_task.h \ + ao_adc_fast.h \ stm32f0.h # @@ -31,6 +32,7 @@ ALTOS_SRC = \ ao_boot_chain.c \ ao_cmd.c \ ao_usb_stm.c \ + ao_trng.c \ ao_task.c \ ao_product.c diff --git a/src/usbtrng-v2.0/ao_pins.h b/src/usbtrng-v2.0/ao_pins.h index 23759444..1997d205 100644 --- a/src/usbtrng-v2.0/ao_pins.h +++ b/src/usbtrng-v2.0/ao_pins.h @@ -60,4 +60,8 @@ #define AO_CRC_WIDTH 32 #define AO_CRC_INIT 0xffffffff +/* TRNG */ +#define AO_LED_TRNG_READ AO_LED_RED +#define AO_LED_TRNG_WRITE AO_LED_GREEN + #endif /* _AO_PINS_H_ */ diff --git a/src/usbtrng-v2.0/ao_usbtrng.c b/src/usbtrng-v2.0/ao_usbtrng.c index e1f43cdd..42713b6e 100644 --- a/src/usbtrng-v2.0/ao_usbtrng.c +++ b/src/usbtrng-v2.0/ao_usbtrng.c @@ -18,58 +18,7 @@ #include #include #include - -static void -ao_trng_fetch(void) -{ - static uint16_t *buffer[2]; - uint32_t kbytes = 1; - uint32_t count; - int usb_buf_id; - int i; - uint16_t *buf; - uint32_t *rnd; - - if (!buffer[0]) { - buffer[0] = ao_usb_alloc(); - buffer[1] = ao_usb_alloc(); - if (!buffer[0]) - return; - } - - ao_cmd_decimal(); - if (ao_cmd_status == ao_cmd_success) - kbytes = ao_cmd_lex_u32; - else - ao_cmd_status = ao_cmd_success; - usb_buf_id = 0; - count = kbytes * (1024/AO_USB_IN_SIZE); - - ao_crc_reset(); - - ao_led_on(AO_LED_GREEN); - while (count--) { - buf = buffer[usb_buf_id]; -// printf ("before get: head %3d tail %3d running %d\n", ao_adc_ring_head, ao_adc_ring_tail, ao_adc_running); flush(); - rnd = (uint32_t *) ao_adc_get(AO_USB_IN_SIZE); /* one 16-bit value per output byte */ -// printf ("after get: head %3d tail %3d running %d\n", ao_adc_ring_head, ao_adc_ring_tail, ao_adc_running); flush(); - for (i = 0; i < 32; i++) - *buf++ = ao_crc_in_32_out_16(*rnd++); - ao_adc_ack(AO_USB_IN_SIZE); -// printf ("after ack: head %3d tail %3d running %d\n", ao_adc_ring_head, ao_adc_ring_tail, ao_adc_running); flush(); - ao_led_toggle(AO_LED_GREEN|AO_LED_RED); - ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE); - ao_led_toggle(AO_LED_GREEN|AO_LED_RED); - usb_buf_id = 1-usb_buf_id; - } - ao_led_off(AO_LED_GREEN|AO_LED_RED); - flush(); -} - -static const struct ao_cmds usbtrng_cmds[] = { - { ao_trng_fetch, "f \0Fetch a block of numbers" }, - { 0, NULL }, -}; +#include void main(void) { @@ -86,7 +35,8 @@ void main(void) ao_usb_init(); - ao_cmd_register(usbtrng_cmds); + ao_trng_init(); + ao_led_off(AO_LED_RED); ao_start_scheduler(); -- cgit v1.2.3 From 2614d20b324ab215ef22f178e3635d48e757fa9b Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Mar 2015 21:02:31 -0800 Subject: altos: Make APRS format (compressed/uncompressed) configurable This provides a choice of compressed vs uncompressed when sending APRS packets to deal with receivers that still do not have support for the more useful compressed format. Signed-off-by: Keith Packard --- src/drivers/ao_aprs.c | 98 +++++++++++++++++++++++++++++++++++++++++--------- src/kernel/ao_config.c | 23 ++++++++++++ src/kernel/ao_config.h | 9 ++++- 3 files changed, 112 insertions(+), 18 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_aprs.c b/src/drivers/ao_aprs.c index 19beb78f..2e977612 100644 --- a/src/drivers/ao_aprs.c +++ b/src/drivers/ao_aprs.c @@ -707,8 +707,7 @@ static int tncPositionPacket(void) static int32_t latitude; static int32_t longitude; static int32_t altitude; - int32_t lat, lon, alt; - uint8_t *buf; + uint8_t *buf; if (ao_gps_data.flags & AO_GPS_VALID) { latitude = ao_gps_data.latitude; @@ -719,28 +718,93 @@ static int tncPositionPacket(void) } buf = tncBuffer; - *buf++ = '!'; - /* Symbol table ID */ - *buf++ = '/'; + switch (ao_config.aprs_format) { + case AO_APRS_FORMAT_COMPRESSED: + default: + { + int32_t lat, lon, alt; + + *buf++ = '!'; + + /* Symbol table ID */ + *buf++ = '/'; + + lat = ((uint64_t) 380926 * (900000000 - latitude)) / 10000000; + lon = ((uint64_t) 190463 * (1800000000 + longitude)) / 10000000; + + alt = ao_aprs_encode_altitude(altitude); + + tncCompressInt(buf, lat, 4); + buf += 4; + tncCompressInt(buf, lon, 4); + buf += 4; - lat = ((uint64_t) 380926 * (900000000 - latitude)) / 10000000; - lon = ((uint64_t) 190463 * (1800000000 + longitude)) / 10000000; + /* Symbol code */ + *buf++ = '\''; - alt = ao_aprs_encode_altitude(altitude); + tncCompressInt(buf, alt, 2); + buf += 2; - tncCompressInt(buf, lat, 4); - buf += 4; - tncCompressInt(buf, lon, 4); - buf += 4; + *buf++ = 33 + ((1 << 5) | (2 << 3)); - /* Symbol code */ - *buf++ = '\''; + break; + } + case AO_APRS_FORMAT_UNCOMPRESSED: + { + char lat_sign = 'N', lon_sign = 'E'; + int32_t lat = latitude; + int32_t lon = longitude; + int32_t alt = altitude; + uint16_t lat_deg; + uint16_t lon_deg; + uint16_t lat_min; + uint16_t lat_frac; + uint16_t lon_min; + uint16_t lon_frac; + + if (lat < 0) { + lat_sign = 'S'; + lat = -lat; + } - tncCompressInt(buf, alt, 2); - buf += 2; + if (lon < 0) { + lon_sign = 'W'; + lon = -lon; + } - *buf++ = 33 + ((1 << 5) | (2 << 3)); + /* Round latitude and longitude by 0.005 minutes */ + lat = lat + 833; + if (lat > 900000000) + lat = 900000000; + lon = lon + 833; + if (lon > 1800000000) + lon = 1800000000; + + lat_deg = lat / 10000000; + lat -= lat_deg * 10000000; + lat *= 60; + lat_min = lat / 10000000; + lat -= lat_min * 10000000; + lat_frac = lat / 100000; + + lon_deg = lon / 10000000; + lon -= lon_deg * 10000000; + lon *= 60; + lon_min = lon / 10000000; + lon -= lon_min * 10000000; + lon_frac = lon / 100000; + + /* Convert from meters to feet */ + alt = (alt * 328 + 50) / 100; + + buf += sprintf((char *) tncBuffer, "!%02u%02u.%02u%c/%03u%02u.%02u%c'/A=%06u ", + lat_deg, lat_min, lat_frac, lat_sign, + lon_deg, lon_min, lon_frac, lon_sign, + alt); + break; + } + } buf += tncComment(buf); diff --git a/src/kernel/ao_config.c b/src/kernel/ao_config.c index 8dab7c42..b0d3e541 100644 --- a/src/kernel/ao_config.c +++ b/src/kernel/ao_config.c @@ -219,6 +219,10 @@ _ao_config_get(void) #if HAS_RADIO_FORWARD if (minor < 21) ao_config.send_frequency = 434550; +#endif +#if HAS_APRS + if (minor < 22) + ao_config.aprs_format = AO_CONFIG_DEFAULT_APRS_FORMAT; #endif ao_config.minor = AO_CONFIG_MINOR; ao_config_dirty = 1; @@ -876,6 +880,23 @@ ao_config_aprs_ssid_set(void) ao_config.aprs_ssid = ao_cmd_lex_i; _ao_config_edit_finish(); } + +void +ao_config_aprs_format_set(void) +{ + ao_cmd_decimal(); + if (ao_cmd_status != ao_cmd_success) + return; + _ao_config_edit_start(); + ao_config.aprs_format = ao_cmd_lex_i != 0; + _ao_config_edit_finish(); +} + +void +ao_config_aprs_format_show(void) +{ + printf ("APRS format: %d\n", ao_config.aprs_format); +} #endif /* HAS_APRS */ struct ao_config_var { @@ -969,6 +990,8 @@ __code struct ao_config_var ao_config_vars[] = { #if HAS_APRS { "S \0Set APRS SSID (0-15)", ao_config_aprs_ssid_set, ao_config_aprs_ssid_show }, + { "C <0 compressed, 1 uncompressed>\0APRS format", + ao_config_aprs_format_set, ao_config_aprs_format_show }, #endif { "s\0Show", ao_config_show, 0 }, diff --git a/src/kernel/ao_config.h b/src/kernel/ao_config.h index 164584a5..cfe8555c 100644 --- a/src/kernel/ao_config.h +++ b/src/kernel/ao_config.h @@ -57,7 +57,7 @@ #endif #define AO_CONFIG_MAJOR 1 -#define AO_CONFIG_MINOR 21 +#define AO_CONFIG_MINOR 22 #define AO_AES_LEN 16 @@ -115,8 +115,15 @@ struct ao_config { #if HAS_RADIO_FORWARD uint32_t send_frequency; /* minor version 21 */ #endif +#if HAS_APRS + uint8_t aprs_format; /* minor version 22 */ +#endif }; +#define AO_APRS_FORMAT_COMPRESSED 0 +#define AO_APRS_FORMAT_UNCOMPRESSED 1 +#define AO_CONFIG_DEFAULT_APRS_FORMAT AO_APRS_FORMAT_COMPRESSED + #if HAS_RADIO_FORWARD extern __xdata uint32_t ao_send_radio_setting; #endif -- cgit v1.2.3 From 3b133656df4698ceb7af5902711edf9253a29227 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 2 Mar 2015 21:11:33 -0800 Subject: altos: Wait for BT disconnect before sending command If AltosDroid manages to connect to the BT module before we've configured it, we won't be able to talk to it as we can't force the module to ignore connection attempts. Wait for AltosDroid to give up and let us configure the device. Eventually, we'll manage, if AltosDroid's delay interval is longer than the time it takes to configure the unit. Signed-off-by: Keith Packard --- src/drivers/ao_btm.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_btm.c b/src/drivers/ao_btm.c index 93d9dd9d..8e7052cb 100644 --- a/src/drivers/ao_btm.c +++ b/src/drivers/ao_btm.c @@ -263,6 +263,15 @@ uint8_t ao_btm_cmd(__code char *cmd) { ao_btm_drain(); + +#ifdef AO_BTM_INT_PORT + /* Trust that AltosDroid will eventually disconnect and let us + * get things set up. The BTM module doesn't appear to listen + * for +++, so we have no way to force a disconnect. + */ + while (ao_btm_connected) + ao_sleep(&ao_btm_connected); +#endif ao_btm_string(cmd); return ao_btm_wait_reply(); } @@ -350,6 +359,10 @@ __xdata struct ao_task ao_btm_task; void ao_btm(void) { +#ifdef AO_BTM_INT_PORT + ao_exti_enable(AO_BTM_INT_PORT, AO_BTM_INT_PIN); +#endif + /* * Wait for the bluetooth device to boot */ @@ -380,6 +393,8 @@ ao_btm(void) /* Turn off status reporting */ ao_btm_cmd("ATQ1\r"); + ao_btm_drain(); + ao_btm_stdio = ao_add_stdio(_ao_serial_btm_pollchar, ao_serial_btm_putchar, NULL); @@ -388,10 +403,6 @@ ao_btm(void) /* Check current pin state */ ao_btm_check_link(); -#ifdef AO_BTM_INT_PORT - ao_exti_enable(AO_BTM_INT_PORT, AO_BTM_INT_PIN); -#endif - for (;;) { while (!ao_btm_connected) ao_sleep(&ao_btm_connected); -- cgit v1.2.3 From f92be7e22150b2de4c899e687d3bbfc1eb842f9e Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 10 Mar 2015 09:32:20 -0600 Subject: altos/test: Make aprs test code compile again Adding the compressed/uncompressed config option broke the APRS test harness. Signed-off-by: Keith Packard --- src/drivers/ao_aprs.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/drivers') diff --git a/src/drivers/ao_aprs.c b/src/drivers/ao_aprs.c index 2e977612..a8016673 100644 --- a/src/drivers/ao_aprs.c +++ b/src/drivers/ao_aprs.c @@ -719,7 +719,13 @@ static int tncPositionPacket(void) buf = tncBuffer; +#ifdef AO_APRS_TEST +#define AO_APRS_FORMAT_COMPRESSED 0 +#define AO_APRS_FORMAT_UNCOMPRESSED 1 + switch (AO_APRS_FORMAT_COMPRESSED) { +#else switch (ao_config.aprs_format) { +#endif case AO_APRS_FORMAT_COMPRESSED: default: { -- cgit v1.2.3 From b1b69c8b73cbffb56c688f6a968d144b642cdff2 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 20 Mar 2015 15:09:20 -0700 Subject: altos/stmf0: Have fast ADC ring buffer code use wrap-around Instead of requiring that the whole set of returned values fit precisely in the ring, allow for wrap-around so that we can fetch an odd number of ADC values. The previous version required that the fetch amount always be a factor of the ADC buffer size. Signed-off-by: Keith Packard --- src/drivers/ao_trng.c | 11 +++++++---- src/drivers/ao_trng_send.c | 11 +++++++---- src/stmf0/ao_adc_fast.c | 3 ++- src/stmf0/ao_adc_fast.h | 41 +++++++++++++++++++++-------------------- 4 files changed, 37 insertions(+), 29 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_trng.c b/src/drivers/ao_trng.c index db742928..e69cd30b 100644 --- a/src/drivers/ao_trng.c +++ b/src/drivers/ao_trng.c @@ -29,7 +29,8 @@ ao_trng_fetch(void) int usb_buf_id; uint16_t i; uint16_t *buf; - uint32_t *rnd; + uint16_t t; + uint32_t *rnd = (uint32_t *) ao_adc_ring; if (!buffer[0]) { buffer[0] = ao_usb_alloc(); @@ -50,10 +51,12 @@ ao_trng_fetch(void) ao_led_on(AO_LED_TRNG_READ); while (count--) { - rnd = (uint32_t *) ao_adc_get(AO_USB_IN_SIZE); /* one 16-bit value per output byte */ + t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* one 16-bit value per output byte */ buf = buffer[usb_buf_id]; - for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) - *buf++ = ao_crc_in_32_out_16(*rnd++); + for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) { + *buf++ = ao_crc_in_32_out_16(rnd[t]); + t = (t + 1) & ((AO_ADC_RING_SIZE>>1) - 1); + } ao_adc_ack(AO_USB_IN_SIZE); ao_led_toggle(AO_LED_TRNG_READ|AO_LED_TRNG_WRITE); ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE); diff --git a/src/drivers/ao_trng_send.c b/src/drivers/ao_trng_send.c index 34a8a981..bac6035c 100644 --- a/src/drivers/ao_trng_send.c +++ b/src/drivers/ao_trng_send.c @@ -27,7 +27,8 @@ ao_trng_send(void) int usb_buf_id; uint16_t i; uint16_t *buf; - uint32_t *rnd; + uint16_t t; + uint32_t *rnd = (uint32_t *) ao_adc_ring; if (!buffer[0]) { buffer[0] = ao_usb_alloc(); @@ -42,10 +43,12 @@ ao_trng_send(void) for (;;) { ao_led_on(AO_LED_TRNG_ACTIVE); - rnd = (uint32_t *) ao_adc_get(AO_USB_IN_SIZE); /* one 16-bit value per output byte */ + t = ao_adc_get(AO_USB_IN_SIZE) >> 1; /* one 16-bit value per output byte */ buf = buffer[usb_buf_id]; - for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) - *buf++ = ao_crc_in_32_out_16(*rnd++); + for (i = 0; i < AO_USB_IN_SIZE / sizeof (uint16_t); i++) { + *buf++ = ao_crc_in_32_out_16(rnd[t]); + t = (t + 1) & ((AO_ADC_RING_SIZE>>1) - 1); + } ao_adc_ack(AO_USB_IN_SIZE); ao_led_off(AO_LED_TRNG_ACTIVE); ao_usb_write(buffer[usb_buf_id], AO_USB_IN_SIZE); diff --git a/src/stmf0/ao_adc_fast.c b/src/stmf0/ao_adc_fast.c index 7d2a4fd7..26e6691c 100644 --- a/src/stmf0/ao_adc_fast.c +++ b/src/stmf0/ao_adc_fast.c @@ -23,7 +23,7 @@ uint16_t ao_adc_ring[AO_ADC_RING_SIZE] __attribute__((aligned(4))); /* Maximum number of samples fetched per _ao_adc_start call */ #define AO_ADC_RING_CHUNK (AO_ADC_RING_SIZE >> 1) -uint16_t ao_adc_ring_head, ao_adc_ring_tail; +uint16_t ao_adc_ring_head, ao_adc_ring_remain; uint16_t ao_adc_running; /* @@ -36,6 +36,7 @@ static void ao_adc_dma_done(int index) { (void) index; ao_adc_ring_head += ao_adc_running; + ao_adc_ring_remain += ao_adc_running; if (ao_adc_ring_head == AO_ADC_RING_SIZE) ao_adc_ring_head = 0; ao_adc_running = 0; diff --git a/src/stmf0/ao_adc_fast.h b/src/stmf0/ao_adc_fast.h index ca5f7fb9..c6903e9f 100644 --- a/src/stmf0/ao_adc_fast.h +++ b/src/stmf0/ao_adc_fast.h @@ -31,52 +31,53 @@ extern uint16_t ao_adc_ring[AO_ADC_RING_SIZE]; #define ao_adc_ring_step(pos,inc) (((pos) + (inc)) & (AO_ADC_RING_SIZE - 1)) -extern uint16_t ao_adc_ring_head, ao_adc_ring_tail; +extern uint16_t ao_adc_ring_head, ao_adc_ring_remain; extern uint16_t ao_adc_running; -void -_ao_adc_start(void); - +/* + * Place to start fetching values from + */ static inline uint16_t -_ao_adc_remain(void) +ao_adc_ring_tail(void) { - if (ao_adc_ring_tail > ao_adc_ring_head) - return AO_ADC_RING_SIZE - ao_adc_ring_tail; - return ao_adc_ring_head - ao_adc_ring_tail; + return (ao_adc_ring_head - ao_adc_ring_remain) & (AO_ADC_RING_SIZE - 1); } +void +_ao_adc_start(void); + +/* + * Space available to write ADC values into + */ static inline uint16_t _ao_adc_space(void) { - if (ao_adc_ring_head >= ao_adc_ring_tail) + /* Free to end of buffer? */ + if (ao_adc_ring_remain <= ao_adc_ring_head) return AO_ADC_RING_SIZE - ao_adc_ring_head; - return ao_adc_ring_tail - ao_adc_ring_head; + + /* no, return just the unused entries beyond head */ + return AO_ADC_RING_SIZE - ao_adc_ring_remain; } -static inline uint16_t * +static inline uint16_t ao_adc_get(uint16_t n) { - if (ao_adc_ring_tail + n > AO_ADC_RING_SIZE) - ao_panic(AO_PANIC_ADC); ao_arch_block_interrupts(); - while (_ao_adc_remain() < n) { + while (ao_adc_ring_remain < n) { if (!ao_adc_running) _ao_adc_start(); ao_sleep(&ao_adc_ring_head); } ao_arch_release_interrupts(); - return &ao_adc_ring[ao_adc_ring_tail]; + return ao_adc_ring_tail(); } static inline void ao_adc_ack(uint16_t n) { - if (ao_adc_ring_tail + n > AO_ADC_RING_SIZE) - ao_panic(AO_PANIC_ADC); ao_arch_block_interrupts(); - ao_adc_ring_tail += n; - if (ao_adc_ring_tail == AO_ADC_RING_SIZE) - ao_adc_ring_tail = 0; + ao_adc_ring_remain -= n; if (!ao_adc_running) _ao_adc_start(); ao_arch_release_interrupts(); -- cgit v1.2.3 From dba00b3d9102db99592f5822a703e64d98ace8bb Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 19 May 2015 10:17:01 -0700 Subject: altos: Support 32MHz xtal on cc1200 I ended up building some cc1200-based boards with 32MHz xtals, so just make this an option when building the driver. Signed-off-by: Keith Packard --- src/drivers/ao_cc1200.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_cc1200.c b/src/drivers/ao_cc1200.c index df4bd335..6547be39 100644 --- a/src/drivers/ao_cc1200.c +++ b/src/drivers/ao_cc1200.c @@ -41,7 +41,11 @@ int8_t ao_radio_rssi; /* Last received RSSI value */ extern const uint32_t ao_radio_cal; +#ifdef AO_CC1200_FOSC +#define FOSC AO_CC1200_FOSC +#else #define FOSC 40000000 +#endif #define ao_radio_select() ao_spi_get_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS,AO_SPI_SPEED_FAST) #define ao_radio_deselect() ao_spi_put_mask(AO_CC1200_SPI_CS_PORT,(1 << AO_CC1200_SPI_CS_PIN),AO_CC1200_SPI_BUS) @@ -301,20 +305,28 @@ ao_radio_idle(void) * CHANBW = 5.0 (round to 9.5) */ +#if FOSC == 40000000 #define PACKET_SYMBOL_RATE_M 1013008 - #define PACKET_SYMBOL_RATE_E_384 8 +#define PACKET_SYMBOL_RATE_E_96 6 +#define PACKET_SYMBOL_RATE_E_24 4 +#endif + +#if FOSC == 32000000 +#define PACKET_SYMBOL_RATE_M 239914 +#define PACKET_SYMBOL_RATE_E_384 9 +#define PACKET_SYMBOL_RATE_E_96 7 +#define PACKET_SYMBOL_RATE_E_24 5 +#endif /* 200 / 2 = 100 */ #define PACKET_CHAN_BW_384 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_12 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \ (16 << CC1200_CHAN_BW_BB_CIC_DECFACT)) -#define PACKET_SYMBOL_RATE_E_96 6 /* 200 / 10 = 20 */ #define PACKET_CHAN_BW_96 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \ (16 << CC1200_CHAN_BW_BB_CIC_DECFACT)) -#define PACKET_SYMBOL_RATE_E_24 4 /* 200 / 25 = 8 */ #define PACKET_CHAN_BW_24 ((CC1200_CHAN_BW_ADC_CIC_DECFACT_48 << CC1200_CHAN_BW_ADC_CIC_DECFACT) | \ (44 << CC1200_CHAN_BW_BB_CIC_DECFACT)) -- cgit v1.2.3 From e7c25e3ba04b1e9f8e6fa31e2d464fe96a074dad Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Sun, 24 May 2015 17:25:25 -0700 Subject: telefire: Make 'good' RSSI value configurable Different radios will have different 'good' RSSI values, so let each product configure it, leaving the default set to -90dBm, which is a solid signal value for the CC1111. Signed-off-by: Keith Packard --- src/drivers/ao_pad.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index dc2c83fe..3ad239cc 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -29,6 +29,10 @@ static __pdata uint8_t ao_pad_box; static __xdata uint8_t ao_pad_disabled; static __pdata uint16_t ao_pad_packet_time; +#ifndef AO_PAD_RSSI_MINIMUM +#define AO_PAD_RSSI_MINIMUM -90 +#endif + #define DEBUG 1 #if DEBUG @@ -36,8 +40,8 @@ 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() +#define PRINTD(...) +#define FLUSHD() #endif static void @@ -138,7 +142,7 @@ ao_pad_monitor(void) } if ((ao_time() - ao_pad_packet_time) > AO_SEC_TO_TICKS(2)) cur |= AO_LED_RED; - else if (ao_radio_cmac_rssi < -90) + else if (ao_radio_cmac_rssi < AO_PAD_RSSI_MINIMUM) cur |= AO_LED_AMBER; else cur |= AO_LED_GREEN; @@ -255,7 +259,7 @@ ao_pad(void) if (ret != AO_RADIO_CMAC_OK) continue; ao_pad_packet_time = ao_time(); - + ao_pad_box = ao_pad_read_box(); PRINTD ("tick %d box %d (me %d) cmd %d channels %02x\n", -- cgit v1.2.3 From 9b268351aee44de959dcc4c792189c10a00428fe Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 May 2015 13:23:54 -0700 Subject: telefire: Report telefire battery voltage over telemetry link Signed-off-by: Keith Packard --- src/drivers/ao_pad.c | 2 ++ src/drivers/ao_pad.h | 1 + 2 files changed, 3 insertions(+) (limited to 'src/drivers') diff --git a/src/drivers/ao_pad.c b/src/drivers/ao_pad.c index 3ad239cc..ffe46c68 100644 --- a/src/drivers/ao_pad.c +++ b/src/drivers/ao_pad.c @@ -127,6 +127,8 @@ ao_pad_monitor(void) #define VOLTS_TO_PYRO(x) ((int16_t) ((x) * 27.0 / 127.0 / 3.3 * 32767.0)) + /* convert ADC value to voltage in tenths, then add .2 for the diode drop */ + query.battery = (packet->adc.batt + 96) / 192 + 2; cur = 0; if (pyro > VOLTS_TO_PYRO(10)) { query.arm_status = AO_PAD_ARM_STATUS_ARMED; diff --git a/src/drivers/ao_pad.h b/src/drivers/ao_pad.h index 23062899..d77d105a 100644 --- a/src/drivers/ao_pad.h +++ b/src/drivers/ao_pad.h @@ -39,6 +39,7 @@ struct ao_pad_query { uint8_t channels; /* which chanels are present */ uint8_t armed; /* which channels are armed */ uint8_t arm_status; /* status of arming switch */ + uint8_t battery; /* battery voltage in decivolts */ uint8_t igniter_status[AO_PAD_MAX_CHANNELS]; /* status for each igniter */ }; -- cgit v1.2.3 From a54aac3361b7bd18f111e5ba06fb89015504b8a4 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 May 2015 15:47:46 -0700 Subject: altos: Add telelco v0.3 (v0.2 with cc1200 instead of cc1120) Signed-off-by: Keith Packard --- src/Makefile | 1 + src/drivers/ao_lco.c | 399 ++++++++++++++++++++++++++++++++ src/drivers/ao_lco.h | 24 ++ src/telelco-v0.2/ao_lco.c | 399 -------------------------------- src/telelco-v0.2/ao_lco.h | 24 -- src/telelco-v0.3/.gitignore | 2 + src/telelco-v0.3/Makefile | 108 +++++++++ src/telelco-v0.3/ao_pins.h | 269 +++++++++++++++++++++ src/telelco-v0.3/ao_telelco.c | 70 ++++++ src/telelco-v0.3/flash-loader/Makefile | 8 + src/telelco-v0.3/flash-loader/ao_pins.h | 34 +++ 11 files changed, 915 insertions(+), 423 deletions(-) create mode 100644 src/drivers/ao_lco.c create mode 100644 src/drivers/ao_lco.h delete mode 100644 src/telelco-v0.2/ao_lco.c delete mode 100644 src/telelco-v0.2/ao_lco.h create mode 100644 src/telelco-v0.3/.gitignore create mode 100644 src/telelco-v0.3/Makefile create mode 100644 src/telelco-v0.3/ao_pins.h create mode 100644 src/telelco-v0.3/ao_telelco.c create mode 100644 src/telelco-v0.3/flash-loader/Makefile create mode 100644 src/telelco-v0.3/flash-loader/ao_pins.h (limited to 'src/drivers') diff --git a/src/Makefile b/src/Makefile index d4c8a86f..dc74bf8c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -34,6 +34,7 @@ ARMM3DIRS=\ telegps-v0.3 telegps-v0.3/flash-loader \ telegps-v1.0 telegps-v1.0/flash-loader \ telelco-v0.2 telelco-v0.2/flash-loader \ + telelco-v0.3 telelco-v0.3/flash-loader \ telescience-v0.2 telescience-v0.2/flash-loader \ teledongle-v3.0 teledongle-v3.0/flash-loader \ teleballoon-v2.0 \ diff --git a/src/drivers/ao_lco.c b/src/drivers/ao_lco.c new file mode 100644 index 00000000..12a247bf --- /dev/null +++ b/src/drivers/ao_lco.c @@ -0,0 +1,399 @@ +/* + * 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 + +#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 + +#define AO_LCO_PAD_DIGIT 0 +#define AO_LCO_BOX_DIGIT_1 1 +#define AO_LCO_BOX_DIGIT_10 2 + +static uint8_t ao_lco_min_box, ao_lco_max_box; +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 uint8_t ao_lco_got_channels; +static uint16_t ao_lco_tick_offset; + +static struct ao_pad_query ao_pad_query; + +static void +ao_lco_set_pad(uint8_t pad) +{ + ao_seven_segment_set(AO_LCO_PAD_DIGIT, pad + 1); +} + +static void +ao_lco_set_box(uint8_t box) +{ + ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, box % 10); + ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, 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 uint8_t +ao_lco_pad_present(uint8_t pad) +{ + if (!ao_lco_got_channels || !ao_pad_query.channels) + return pad == 0; + if (pad >= AO_PAD_MAX_CHANNELS) + return 0; + return (ao_pad_query.channels >> pad) & 1; +} + +static uint8_t +ao_lco_pad_first(void) +{ + uint8_t pad; + + for (pad = 0; pad < AO_PAD_MAX_CHANNELS; pad++) + if (ao_lco_pad_present(pad)) + return pad; + return 0; +} + +static void +ao_lco_input(void) +{ + static struct ao_event event; + int8_t dir, new_box, new_pad; + + ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); + 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) { + dir = (int8_t) event.value; + new_pad = ao_lco_pad; + do { + new_pad += dir; + if (new_pad > AO_PAD_MAX_CHANNELS) + new_pad = 0; + else if (new_pad < 0) + new_pad = AO_PAD_MAX_CHANNELS - 1; + if (new_pad == ao_lco_pad) + break; + } while (!ao_lco_pad_present(new_pad)); + if (new_pad != ao_lco_pad) { + ao_lco_pad = new_pad; + ao_lco_set_pad(ao_lco_pad); + } + } + break; + case AO_QUADRATURE_BOX: + if (!ao_lco_armed) { + dir = (int8_t) event.value; + new_box = ao_lco_box; + do { + new_box += dir; + if (new_box > ao_lco_max_box) + new_box = ao_lco_min_box; + else if (new_box < ao_lco_min_box) + new_box = ao_lco_max_box; + if (new_box == ao_lco_box) + break; + } while (!ao_lco_box_present(new_box)); + if (ao_lco_box != new_box) { + ao_lco_box = new_box; + ao_lco_got_channels = 0; + ao_lco_set_box(ao_lco_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 void +ao_lco_update(void) +{ + int8_t r; + uint8_t c; + + r = ao_lco_query(ao_lco_box, &ao_pad_query, &ao_lco_tick_offset); + if (r == AO_RADIO_CMAC_OK) { + c = ao_lco_got_channels; + ao_lco_got_channels = 1; + ao_lco_valid = 1; + if (!c) { + ao_lco_pad = ao_lco_pad_first(); + ao_lco_set_pad(ao_lco_pad); + } + } else + ao_lco_valid = 0; + +#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_wakeup(&ao_pad_query); +} + +static void +ao_lco_box_reset_present(void) +{ + ao_lco_min_box = 0xff; + ao_lco_max_box = 0x00; + memset(ao_lco_box_mask, 0, sizeof (ao_lco_box_mask)); +} + +static void +ao_lco_box_set_present(uint8_t box) +{ + if (box < ao_lco_min_box) + ao_lco_min_box = box; + if (box > ao_lco_max_box) + ao_lco_max_box = 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; + int8_t try; + uint8_t box; + + ao_lco_box_reset_present(); + for (box = 0; box < AO_PAD_MAX_BOXES; box++) { + if ((box % 10) == 0) + ao_lco_set_box(box); + for (try = 0; try < 3; try++) { + tick_offset = 0; + r = ao_lco_query(box, &ao_pad_query, &tick_offset); + PRINTD("box %d result %d\n", box, r); + if (r == AO_RADIO_CMAC_OK) { + ao_lco_box_set_present(box); + ao_delay(AO_MS_TO_TICKS(30)); + break; + } + } + } + if (ao_lco_min_box <= ao_lco_max_box) + ao_lco_box = ao_lco_min_box; + else + ao_lco_min_box = ao_lco_max_box = ao_lco_box = 0; + ao_lco_valid = 0; + ao_lco_got_channels = 0; + ao_lco_pad = 0; + ao_lco_set_pad(ao_lco_pad); + ao_lco_set_box(ao_lco_box); +} + +static void +ao_lco_igniter_status(void) +{ + uint8_t c; + + for (;;) { + ao_sleep(&ao_pad_query); + if (!ao_lco_valid) { + ao_led_on(AO_LED_RED); + ao_led_off(AO_LED_GREEN|AO_LED_AMBER); + continue; + } + PRINTD("RSSI %d\n", ao_radio_cmac_rssi); + if (ao_radio_cmac_rssi < -90) { + ao_led_on(AO_LED_AMBER); + ao_led_off(AO_LED_RED|AO_LED_GREEN); + } else { + ao_led_on(AO_LED_GREEN); + ao_led_off(AO_LED_RED|AO_LED_AMBER); + } + if (ao_pad_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 (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, 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(); + } + if (ao_lco_armed && ao_lco_firing) + delay = AO_MS_TO_TICKS(100); + else + delay = AO_SEC_TO_TICKS(1); + ao_sleep_for(&ao_lco_armed, delay); + } +} + +#if DEBUG +void +ao_lco_set_debug(void) +{ + ao_cmd_decimal(); + if (ao_cmd_status == ao_cmd_success) + ao_lco_debug = ao_cmd_lex_i != 0; +} + +__code struct ao_cmds ao_lco_cmds[] = { + { ao_lco_set_debug, "D <0 off, 1 on>\0Debug" }, + { ao_lco_search, "s\0Search for pad boxes" }, + { 0, NULL } +}; +#endif + +void +ao_lco_init(void) +{ + ao_add_task(&ao_lco_monitor_task, ao_lco_monitor, "lco monitor"); +#if DEBUG + ao_cmd_register(&ao_lco_cmds[0]); +#endif +} 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_ */ diff --git a/src/telelco-v0.2/ao_lco.c b/src/telelco-v0.2/ao_lco.c deleted file mode 100644 index 12a247bf..00000000 --- a/src/telelco-v0.2/ao_lco.c +++ /dev/null @@ -1,399 +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 -#include -#include - -#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 - -#define AO_LCO_PAD_DIGIT 0 -#define AO_LCO_BOX_DIGIT_1 1 -#define AO_LCO_BOX_DIGIT_10 2 - -static uint8_t ao_lco_min_box, ao_lco_max_box; -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 uint8_t ao_lco_got_channels; -static uint16_t ao_lco_tick_offset; - -static struct ao_pad_query ao_pad_query; - -static void -ao_lco_set_pad(uint8_t pad) -{ - ao_seven_segment_set(AO_LCO_PAD_DIGIT, pad + 1); -} - -static void -ao_lco_set_box(uint8_t box) -{ - ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, box % 10); - ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, 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 uint8_t -ao_lco_pad_present(uint8_t pad) -{ - if (!ao_lco_got_channels || !ao_pad_query.channels) - return pad == 0; - if (pad >= AO_PAD_MAX_CHANNELS) - return 0; - return (ao_pad_query.channels >> pad) & 1; -} - -static uint8_t -ao_lco_pad_first(void) -{ - uint8_t pad; - - for (pad = 0; pad < AO_PAD_MAX_CHANNELS; pad++) - if (ao_lco_pad_present(pad)) - return pad; - return 0; -} - -static void -ao_lco_input(void) -{ - static struct ao_event event; - int8_t dir, new_box, new_pad; - - ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(200)); - 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) { - dir = (int8_t) event.value; - new_pad = ao_lco_pad; - do { - new_pad += dir; - if (new_pad > AO_PAD_MAX_CHANNELS) - new_pad = 0; - else if (new_pad < 0) - new_pad = AO_PAD_MAX_CHANNELS - 1; - if (new_pad == ao_lco_pad) - break; - } while (!ao_lco_pad_present(new_pad)); - if (new_pad != ao_lco_pad) { - ao_lco_pad = new_pad; - ao_lco_set_pad(ao_lco_pad); - } - } - break; - case AO_QUADRATURE_BOX: - if (!ao_lco_armed) { - dir = (int8_t) event.value; - new_box = ao_lco_box; - do { - new_box += dir; - if (new_box > ao_lco_max_box) - new_box = ao_lco_min_box; - else if (new_box < ao_lco_min_box) - new_box = ao_lco_max_box; - if (new_box == ao_lco_box) - break; - } while (!ao_lco_box_present(new_box)); - if (ao_lco_box != new_box) { - ao_lco_box = new_box; - ao_lco_got_channels = 0; - ao_lco_set_box(ao_lco_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 void -ao_lco_update(void) -{ - int8_t r; - uint8_t c; - - r = ao_lco_query(ao_lco_box, &ao_pad_query, &ao_lco_tick_offset); - if (r == AO_RADIO_CMAC_OK) { - c = ao_lco_got_channels; - ao_lco_got_channels = 1; - ao_lco_valid = 1; - if (!c) { - ao_lco_pad = ao_lco_pad_first(); - ao_lco_set_pad(ao_lco_pad); - } - } else - ao_lco_valid = 0; - -#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_wakeup(&ao_pad_query); -} - -static void -ao_lco_box_reset_present(void) -{ - ao_lco_min_box = 0xff; - ao_lco_max_box = 0x00; - memset(ao_lco_box_mask, 0, sizeof (ao_lco_box_mask)); -} - -static void -ao_lco_box_set_present(uint8_t box) -{ - if (box < ao_lco_min_box) - ao_lco_min_box = box; - if (box > ao_lco_max_box) - ao_lco_max_box = 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; - int8_t try; - uint8_t box; - - ao_lco_box_reset_present(); - for (box = 0; box < AO_PAD_MAX_BOXES; box++) { - if ((box % 10) == 0) - ao_lco_set_box(box); - for (try = 0; try < 3; try++) { - tick_offset = 0; - r = ao_lco_query(box, &ao_pad_query, &tick_offset); - PRINTD("box %d result %d\n", box, r); - if (r == AO_RADIO_CMAC_OK) { - ao_lco_box_set_present(box); - ao_delay(AO_MS_TO_TICKS(30)); - break; - } - } - } - if (ao_lco_min_box <= ao_lco_max_box) - ao_lco_box = ao_lco_min_box; - else - ao_lco_min_box = ao_lco_max_box = ao_lco_box = 0; - ao_lco_valid = 0; - ao_lco_got_channels = 0; - ao_lco_pad = 0; - ao_lco_set_pad(ao_lco_pad); - ao_lco_set_box(ao_lco_box); -} - -static void -ao_lco_igniter_status(void) -{ - uint8_t c; - - for (;;) { - ao_sleep(&ao_pad_query); - if (!ao_lco_valid) { - ao_led_on(AO_LED_RED); - ao_led_off(AO_LED_GREEN|AO_LED_AMBER); - continue; - } - PRINTD("RSSI %d\n", ao_radio_cmac_rssi); - if (ao_radio_cmac_rssi < -90) { - ao_led_on(AO_LED_AMBER); - ao_led_off(AO_LED_RED|AO_LED_GREEN); - } else { - ao_led_on(AO_LED_GREEN); - ao_led_off(AO_LED_RED|AO_LED_AMBER); - } - if (ao_pad_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 (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, 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(); - } - if (ao_lco_armed && ao_lco_firing) - delay = AO_MS_TO_TICKS(100); - else - delay = AO_SEC_TO_TICKS(1); - ao_sleep_for(&ao_lco_armed, delay); - } -} - -#if DEBUG -void -ao_lco_set_debug(void) -{ - ao_cmd_decimal(); - if (ao_cmd_status == ao_cmd_success) - ao_lco_debug = ao_cmd_lex_i != 0; -} - -__code struct ao_cmds ao_lco_cmds[] = { - { ao_lco_set_debug, "D <0 off, 1 on>\0Debug" }, - { ao_lco_search, "s\0Search for pad boxes" }, - { 0, NULL } -}; -#endif - -void -ao_lco_init(void) -{ - ao_add_task(&ao_lco_monitor_task, ao_lco_monitor, "lco monitor"); -#if DEBUG - ao_cmd_register(&ao_lco_cmds[0]); -#endif -} diff --git a/src/telelco-v0.2/ao_lco.h b/src/telelco-v0.2/ao_lco.h deleted file mode 100644 index 253f9702..00000000 --- a/src/telelco-v0.2/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/telelco-v0.3/.gitignore b/src/telelco-v0.3/.gitignore new file mode 100644 index 00000000..a32ec26e --- /dev/null +++ b/src/telelco-v0.3/.gitignore @@ -0,0 +1,2 @@ +ao_product.h +telelco*.elf diff --git a/src/telelco-v0.3/Makefile b/src/telelco-v0.3/Makefile new file mode 100644 index 00000000..83d3fc43 --- /dev/null +++ b/src/telelco-v0.3/Makefile @@ -0,0 +1,108 @@ +# +# AltOS build for TeleLCO +# +# + +include ../stm/Makefile.defs + +INC = \ + ao.h \ + ao_arch.h \ + ao_arch_funcs.h \ + ao_boot.h \ + ao_companion.h \ + ao_data.h \ + ao_sample.h \ + ao_pins.h \ + ao_product.h \ + ao_seven_segment.h \ + ao_lco.h \ + ao_lco_cmd.h \ + ao_lco_func.h \ + ao_radio_spi.h \ + ao_radio_cmac.h \ + ao_cc1200_CC1200.h \ + ao_cc1200.h \ + ao_debounce.h \ + stm32l.h + +# +# Common AltOS sources +# + +#PROFILE=ao_profile.c +#PROFILE_DEF=-DAO_PROFILE=1 + +ALTOS_SRC = \ + ao_boot_chain.c \ + 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_eeprom_stm.c \ + ao_fast_timer.c \ + ao_lcd_stm.c \ + ao_usb_stm.c \ + ao_exti_stm.c \ + ao_cc1200.c \ + ao_radio_cmac.c \ + ao_aes.c \ + ao_aes_tables.c \ + ao_fec_tx.c \ + ao_fec_rx.c \ + ao_seven_segment.c \ + ao_debounce.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.3 +PRODUCT_DEF=-DTELELCO +IDPRODUCT=0x0023 + +CFLAGS = $(PRODUCT_DEF) $(STM_CFLAGS) $(PROFILE_DEF) -Os -g + +PROGNAME=telelco-v0.3 +PROG=$(PROGNAME)-$(VERSION).elf +HEX=$(PROGNAME)-$(VERSION).ihx + +SRC=$(ALTOS_SRC) ao_telelco.c +OBJ=$(SRC:.c=.o) + +all: $(PROG) $(HEX) + +$(PROG): Makefile $(OBJ) altos.ld + $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS) + +../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 $(PROGNAME)-*.ihx + rm -f ao_product.h + +install: + +uninstall: diff --git a/src/telelco-v0.3/ao_pins.h b/src/telelco-v0.3/ao_pins.h new file mode 100644 index 00000000..92095a7c --- /dev/null +++ b/src/telelco-v0.3/ao_pins.h @@ -0,0 +1,269 @@ +/* + * 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) + +#define AO_CC1200_FOSC 40000000 + +/* 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 USE_EEPROM_CONFIG 1 +#define USE_STORAGE_CONFIG 0 +#define HAS_USB 1 +#define HAS_BEEP 1 +#define HAS_RADIO 1 +#define HAS_RADIO_RATE 1 +#define HAS_TELEMETRY 0 +#define HAS_AES 1 + +#define HAS_SPI_1 0 +#define SPI_1_PA5_PA6_PA7 0 +#define SPI_1_PB3_PB4_PB5 0 +#define SPI_1_PE13_PE14_PE15 0 + +#define HAS_SPI_2 1 /* CC1120 */ +#define SPI_2_PB13_PB14_PB15 0 +#define SPI_2_PD1_PD3_PD4 1 +#define SPI_2_GPIO (&stm_gpiod) +#define SPI_2_SCK 1 +#define SPI_2_MISO 3 +#define SPI_2_MOSI 4 +#define SPI_2_OSPEEDR STM_OSPEEDR_10MHz + +#define HAS_I2C_1 0 + +#define HAS_I2C_2 0 + +#define PACKET_HAS_SLAVE 0 +#define PACKET_HAS_MASTER 0 + +#define FAST_TIMER_FREQ 10000 /* .1ms for debouncing */ + +/* + * Radio is a cc1200 connected via SPI + */ + +#define AO_RADIO_CAL_DEFAULT 5695733 + +#define AO_FEC_DEBUG 0 +#define AO_CC1200_SPI_CS_PORT (&stm_gpiod) +#define AO_CC1200_SPI_CS_PIN 0 +#define AO_CC1200_SPI_BUS AO_SPI_2_PD1_PD3_PD4 +#define AO_CC1200_SPI stm_spi2 + +#define AO_CC1200_INT_PORT (&stm_gpioc) +#define AO_CC1200_INT_PIN (15) + +#define AO_CC1200_INT_GPIO 2 +#define AO_CC1200_INT_GPIO_IOCFG CC1200_IOCFG2 + +#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_AMBER 8 +#define LED_PIN_GREEN 9 +#define LED_PIN_CONTINUITY_3 10 +#define LED_PIN_CONTINUITY_2 11 +#define LED_PIN_CONTINUITY_1 12 +#define LED_PIN_CONTINUITY_0 13 +#define LED_PIN_REMOTE_ARM 14 +#define AO_LED_RED (1 << LED_PIN_RED) +#define AO_LED_AMBER (1 << LED_PIN_AMBER) +#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_AMBER | \ + 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 LCD_DEBUG 0 +#define SEVEN_SEGMENT_DEBUG 0 + +#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 */ \ + (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 */ \ + (1 << 22) | /* PC4 */ \ + (1 << 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 */ \ + (0 << 1) | /* PA9 */ \ + (0 << 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_STATIC + +#define AO_LCD_PER_DIGIT 1 + +#define AO_LCD_DIGITS 3 +#define AO_LCD_SEGMENTS 8 + +#define AO_SEGMENT_MAP { \ + /* pad segments */ \ + { 0, 14 }, \ + { 0, 13 }, \ + { 0, 15 }, \ + { 0, 17 }, \ + { 0, 16 }, \ + { 0, 8 }, \ + { 0, 9 }, \ + { 0, 7 }, \ + /* box1 segments */ \ + { 0, 10 }, \ + { 0, 6 }, \ + { 0, 11 }, \ + { 0, 12 }, \ + { 0, 21 }, \ + { 0, 19 }, \ + { 0, 20 }, \ + { 0, 18 }, \ + /* box0 segments */ \ + { 0, 22 }, \ + { 0, 4 }, \ + { 0, 23 }, \ + { 0, 5 }, \ + { 0, 3 }, \ + { 0, 1 }, \ + { 0, 2 }, \ + { 0, 0 }, \ +} + +/* + * Use event queue for input devices + */ + +#define AO_EVENT 1 + +/* + * Knobs + */ + +#define AO_QUADRATURE_COUNT 2 + +#define AO_QUADRATURE_0_PORT &stm_gpioe +#define AO_QUADRATURE_0_A 3 +#define AO_QUADRATURE_0_B 2 + +#define AO_QUADRATURE_PAD 0 + +#define AO_QUADRATURE_1_PORT &stm_gpioe +#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_gpioe +#define AO_BUTTON_0 4 + +#define AO_BUTTON_ARM 0 + +#define AO_BUTTON_1_PORT &stm_gpioe +#define AO_BUTTON_1 5 + +#define AO_BUTTON_FIRE 1 + +#endif /* _AO_PINS_H_ */ diff --git a/src/telelco-v0.3/ao_telelco.c b/src/telelco-v0.3/ao_telelco.c new file mode 100644 index 00000000..d9f7c693 --- /dev/null +++ b/src/telelco-v0.3/ao_telelco.c @@ -0,0 +1,70 @@ +/* + * 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 +#include + +int +main(void) +{ + ao_clock_init(); + + ao_led_init(LEDS_AVAILABLE); + ao_led_on(AO_LED_GREEN); + ao_task_init(); + + 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_eeprom_init(); + + ao_radio_init(); + + ao_usb_init(); + + ao_config_init(); + + ao_lco_init(); + ao_lco_cmd_init(); +// ao_radio_cmac_cmd_init(); + + ao_start_scheduler(); + return 0; +} diff --git a/src/telelco-v0.3/flash-loader/Makefile b/src/telelco-v0.3/flash-loader/Makefile new file mode 100644 index 00000000..679e61ba --- /dev/null +++ b/src/telelco-v0.3/flash-loader/Makefile @@ -0,0 +1,8 @@ +# +# AltOS flash loader build +# +# + +TOPDIR=../.. +HARDWARE=telelco-v0.2 +include $(TOPDIR)/stm/Makefile-flash.defs diff --git a/src/telelco-v0.3/flash-loader/ao_pins.h b/src/telelco-v0.3/flash-loader/ao_pins.h new file mode 100644 index 00000000..6c8ff7e2 --- /dev/null +++ b/src/telelco-v0.3/flash-loader/ao_pins.h @@ -0,0 +1,34 @@ +/* + * Copyright © 2013 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public 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_ + +/* External crystal at 8MHz */ +#define AO_HSE 8000000 + +#include + +/* Arm switch. Press at power on to get boot loader */ + +#define AO_BOOT_PIN 1 +#define AO_BOOT_APPLICATION_GPIO stm_gpioe +#define AO_BOOT_APPLICATION_PIN 4 +#define AO_BOOT_APPLICATION_VALUE 1 +#define AO_BOOT_APPLICATION_MODE AO_EXTI_MODE_PULL_UP + +#endif /* _AO_PINS_H_ */ -- cgit v1.2.3 From 91f617d450c187500593d1ae785958187f68ca14 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 May 2015 15:49:21 -0700 Subject: altos/telelco: Display telefire battery voltage When the firing button is pressed while unarmed, show the telefire battery voltage in the display. Signed-off-by: Keith Packard --- src/drivers/ao_lco.c | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_lco.c b/src/drivers/ao_lco.c index 12a247bf..9250d444 100644 --- a/src/drivers/ao_lco.c +++ b/src/drivers/ao_lco.c @@ -44,6 +44,7 @@ static uint8_t ao_lco_firing; static uint8_t ao_lco_valid; static uint8_t ao_lco_got_channels; static uint16_t ao_lco_tick_offset; +static uint8_t ao_lco_show_voltage; static struct ao_pad_query ao_pad_query; @@ -60,6 +61,19 @@ ao_lco_set_box(uint8_t box) ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, box / 10); } +static void +ao_lco_set_voltage(uint16_t decivolts) +{ + uint8_t tens, ones, tenths; + + tenths = decivolts % 10; + ones = (decivolts / 10) % 10; + tens = (decivolts / 100) % 10; + ao_seven_segment_set(AO_LCO_PAD_DIGIT, tenths); + ao_seven_segment_set(AO_LCO_BOX_DIGIT_1, ones | 0x10); + ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, tens); +} + #define MASK_SIZE(n) (((n) + 7) >> 3) #define MASK_ID(n) ((n) >> 3) #define MASK_SHIFT(n) ((n) & 7) @@ -124,6 +138,7 @@ ao_lco_input(void) } while (!ao_lco_pad_present(new_pad)); if (new_pad != ao_lco_pad) { ao_lco_pad = new_pad; + ao_lco_set_box(ao_lco_box); ao_lco_set_pad(ao_lco_pad); } } @@ -145,6 +160,7 @@ ao_lco_input(void) ao_lco_box = new_box; ao_lco_got_channels = 0; ao_lco_set_box(ao_lco_box); + ao_lco_set_pad(ao_lco_pad); } } break; @@ -160,8 +176,18 @@ ao_lco_input(void) case AO_BUTTON_FIRE: if (ao_lco_armed) { ao_lco_firing = event.value; + ao_lco_show_voltage = 0; PRINTD("Firing %d\n", ao_lco_firing); ao_wakeup(&ao_lco_armed); + } else { + if (event.value) { + if (ao_lco_got_channels) + ao_lco_set_voltage(ao_pad_query.battery); + } else { + ao_lco_set_box(ao_lco_box); + ao_lco_set_pad(ao_lco_pad); + } + ao_lco_show_voltage = event.value; } break; } @@ -210,8 +236,11 @@ ao_lco_update(void) ao_lco_valid = 1; if (!c) { ao_lco_pad = ao_lco_pad_first(); - ao_lco_set_pad(ao_lco_pad); + if (!ao_lco_show_voltage) + ao_lco_set_pad(ao_lco_pad); } + if (ao_lco_show_voltage) + ao_lco_set_voltage(ao_pad_query.battery); } else ao_lco_valid = 0; @@ -223,6 +252,7 @@ ao_lco_update(void) query.igniter_status[2], query.igniter_status[3]); #endif + PRINTD("ao_lco_update valid %d\n", ao_lco_valid); ao_wakeup(&ao_pad_query); } @@ -253,8 +283,10 @@ ao_lco_search(void) int8_t r; int8_t try; uint8_t box; + uint8_t boxes = 0; ao_lco_box_reset_present(); + ao_lco_set_pad(-1); for (box = 0; box < AO_PAD_MAX_BOXES; box++) { if ((box % 10) == 0) ao_lco_set_box(box); @@ -263,7 +295,9 @@ ao_lco_search(void) r = ao_lco_query(box, &ao_pad_query, &tick_offset); PRINTD("box %d result %d\n", box, r); if (r == AO_RADIO_CMAC_OK) { + ++boxes; ao_lco_box_set_present(box); + ao_lco_set_pad((boxes % 10) - 1); ao_delay(AO_MS_TO_TICKS(30)); break; } @@ -287,12 +321,12 @@ ao_lco_igniter_status(void) for (;;) { ao_sleep(&ao_pad_query); + PRINTD("RSSI %d VALID %d\n", ao_radio_cmac_rssi, ao_lco_valid); if (!ao_lco_valid) { ao_led_on(AO_LED_RED); ao_led_off(AO_LED_GREEN|AO_LED_AMBER); continue; } - PRINTD("RSSI %d\n", ao_radio_cmac_rssi); if (ao_radio_cmac_rssi < -90) { ao_led_on(AO_LED_AMBER); ao_led_off(AO_LED_RED|AO_LED_GREEN); @@ -361,6 +395,7 @@ ao_lco_monitor(void) if (!ao_lco_valid) ao_lco_update(); ao_lco_arm(ao_lco_box, 1 << ao_lco_pad, ao_lco_tick_offset); + ao_delay(AO_MS_TO_TICKS(30)); ao_lco_update(); } else { ao_lco_update(); -- cgit v1.2.3 From dcbd87bc685924a6587a5f4dae47d34f417601b0 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Mon, 25 May 2015 16:26:01 -0700 Subject: altos/telelco: Show box voltage with pad knob instead of firing button Turn left past '1' and see the firing box battery voltage instead of pushing the firing button with the box disarmed. This seems like a safer UI. Signed-off-by: Keith Packard --- src/drivers/ao_lco.c | 75 +++++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 36 deletions(-) (limited to 'src/drivers') diff --git a/src/drivers/ao_lco.c b/src/drivers/ao_lco.c index 9250d444..b8698a80 100644 --- a/src/drivers/ao_lco.c +++ b/src/drivers/ao_lco.c @@ -44,14 +44,13 @@ static uint8_t ao_lco_firing; static uint8_t ao_lco_valid; static uint8_t ao_lco_got_channels; static uint16_t ao_lco_tick_offset; -static uint8_t ao_lco_show_voltage; static struct ao_pad_query ao_pad_query; static void ao_lco_set_pad(uint8_t pad) { - ao_seven_segment_set(AO_LCO_PAD_DIGIT, pad + 1); + ao_seven_segment_set(AO_LCO_PAD_DIGIT, pad); } static void @@ -74,6 +73,17 @@ ao_lco_set_voltage(uint16_t decivolts) ao_seven_segment_set(AO_LCO_BOX_DIGIT_10, tens); } +static void +ao_lco_set_display(void) +{ + if (ao_lco_pad == 0) { + ao_lco_set_voltage(ao_pad_query.battery); + } else { + ao_lco_set_pad(ao_lco_pad); + ao_lco_set_box(ao_lco_box); + } +} + #define MASK_SIZE(n) (((n) + 7) >> 3) #define MASK_ID(n) ((n) >> 3) #define MASK_SHIFT(n) ((n) & 7) @@ -93,9 +103,12 @@ ao_lco_pad_present(uint8_t pad) { if (!ao_lco_got_channels || !ao_pad_query.channels) return pad == 0; - if (pad >= AO_PAD_MAX_CHANNELS) + /* voltage measurement is always valid */ + if (pad == 0) + return 1; + if (pad > AO_PAD_MAX_CHANNELS) return 0; - return (ao_pad_query.channels >> pad) & 1; + return (ao_pad_query.channels >> (pad - 1)) & 1; } static uint8_t @@ -103,7 +116,7 @@ ao_lco_pad_first(void) { uint8_t pad; - for (pad = 0; pad < AO_PAD_MAX_CHANNELS; pad++) + for (pad = 1; pad <= AO_PAD_MAX_CHANNELS; pad++) if (ao_lco_pad_present(pad)) return pad; return 0; @@ -131,15 +144,14 @@ ao_lco_input(void) new_pad += dir; if (new_pad > AO_PAD_MAX_CHANNELS) new_pad = 0; - else if (new_pad < 0) - new_pad = AO_PAD_MAX_CHANNELS - 1; + if (new_pad < 0) + new_pad = AO_PAD_MAX_CHANNELS; if (new_pad == ao_lco_pad) break; } while (!ao_lco_pad_present(new_pad)); if (new_pad != ao_lco_pad) { ao_lco_pad = new_pad; - ao_lco_set_box(ao_lco_box); - ao_lco_set_pad(ao_lco_pad); + ao_lco_set_display(); } } break; @@ -158,9 +170,9 @@ ao_lco_input(void) } while (!ao_lco_box_present(new_box)); if (ao_lco_box != new_box) { ao_lco_box = new_box; + ao_lco_pad = 1; ao_lco_got_channels = 0; - ao_lco_set_box(ao_lco_box); - ao_lco_set_pad(ao_lco_pad); + ao_lco_set_display(); } } break; @@ -176,18 +188,8 @@ ao_lco_input(void) case AO_BUTTON_FIRE: if (ao_lco_armed) { ao_lco_firing = event.value; - ao_lco_show_voltage = 0; PRINTD("Firing %d\n", ao_lco_firing); ao_wakeup(&ao_lco_armed); - } else { - if (event.value) { - if (ao_lco_got_channels) - ao_lco_set_voltage(ao_pad_query.battery); - } else { - ao_lco_set_box(ao_lco_box); - ao_lco_set_pad(ao_lco_pad); - } - ao_lco_show_voltage = event.value; } break; } @@ -235,12 +237,12 @@ ao_lco_update(void) ao_lco_got_channels = 1; ao_lco_valid = 1; if (!c) { - ao_lco_pad = ao_lco_pad_first(); - if (!ao_lco_show_voltage) - ao_lco_set_pad(ao_lco_pad); + if (ao_lco_pad != 0) + ao_lco_pad = ao_lco_pad_first(); + ao_lco_set_display(); } - if (ao_lco_show_voltage) - ao_lco_set_voltage(ao_pad_query.battery); + if (ao_lco_pad == 0) + ao_lco_set_display(); } else ao_lco_valid = 0; @@ -286,7 +288,7 @@ ao_lco_search(void) uint8_t boxes = 0; ao_lco_box_reset_present(); - ao_lco_set_pad(-1); + ao_lco_set_pad(0); for (box = 0; box < AO_PAD_MAX_BOXES; box++) { if ((box % 10) == 0) ao_lco_set_box(box); @@ -297,7 +299,7 @@ ao_lco_search(void) if (r == AO_RADIO_CMAC_OK) { ++boxes; ao_lco_box_set_present(box); - ao_lco_set_pad((boxes % 10) - 1); + ao_lco_set_pad(boxes % 10); ao_delay(AO_MS_TO_TICKS(30)); break; } @@ -309,9 +311,8 @@ ao_lco_search(void) ao_lco_min_box = ao_lco_max_box = ao_lco_box = 0; ao_lco_valid = 0; ao_lco_got_channels = 0; - ao_lco_pad = 0; - ao_lco_set_pad(ao_lco_pad); - ao_lco_set_box(ao_lco_box); + ao_lco_pad = 1; + ao_lco_set_display(); } static void @@ -387,16 +388,18 @@ ao_lco_monitor(void) 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, 1 << ao_lco_pad, ao_lco_tick_offset); + if (ao_lco_valid && ao_lco_pad) + ao_lco_ignite(ao_lco_box, 1 << (ao_lco_pad - 1), 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_delay(AO_MS_TO_TICKS(30)); - ao_lco_update(); + if (ao_lco_pad) { + ao_lco_arm(ao_lco_box, 1 << (ao_lco_pad - 1), ao_lco_tick_offset); + ao_delay(AO_MS_TO_TICKS(30)); + ao_lco_update(); + } } else { ao_lco_update(); } -- cgit v1.2.3