From 1489263b895a2a825e29d0560c9b1dbba8a3f431 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Tue, 17 Apr 2012 11:01:18 -0700 Subject: altos: Starting to write cc1120 driver This does "something" in radio test mode, appearing to generate a 730MHz signal. Signed-off-by: Keith Packard --- src/drivers/ao_packet.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 src/drivers/ao_packet.c (limited to 'src/drivers/ao_packet.c') diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c new file mode 100644 index 00000000..19fe0558 --- /dev/null +++ b/src/drivers/ao_packet.c @@ -0,0 +1,163 @@ +/* + * Copyright © 2009 Keith Packard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ + +#include "ao.h" + +__xdata struct ao_packet_recv ao_rx_packet; +__xdata struct ao_packet ao_tx_packet; +__pdata uint8_t ao_packet_rx_len, ao_packet_rx_used, ao_packet_tx_used; + +static __xdata char tx_data[AO_PACKET_MAX]; +static __xdata char rx_data[AO_PACKET_MAX]; +static __pdata uint8_t rx_seq; + +__xdata struct ao_task ao_packet_task; +__xdata uint8_t ao_packet_enable; +__xdata uint8_t ao_packet_master_sleeping; + +void +ao_packet_send(void) +{ +#ifdef AO_LED_RED + ao_led_on(AO_LED_RED); +#endif + /* If any tx data is pending then copy it into the tx packet */ + if (ao_packet_tx_used && ao_tx_packet.len == 0) { + ao_xmemcpy(&ao_tx_packet.d, tx_data, ao_packet_tx_used); + ao_tx_packet.len = ao_packet_tx_used; + ao_tx_packet.seq++; + ao_packet_tx_used = 0; + ao_wakeup(&tx_data); + } + ao_radio_send(&ao_tx_packet, sizeof (ao_tx_packet)); +#ifdef AO_LED_RED + ao_led_off(AO_LED_RED); +#endif +} + +uint8_t +ao_packet_recv(void) +{ + uint8_t dma_done; + +#ifdef AO_LED_GREEN + ao_led_on(AO_LED_GREEN); +#endif + dma_done = ao_radio_recv(&ao_rx_packet, sizeof (struct ao_packet_recv)); +#ifdef AO_LED_GREEN + ao_led_off(AO_LED_GREEN); +#endif + + /* Check to see if we got a valid packet */ + if (!dma_done) + return 0; +#ifdef PKT_APPEND_STATUS_1_CRC_OK + if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) + return 0; +#endif + + /* Accept packets with matching call signs, or any packet if + * our callsign hasn't been configured + */ + if (ao_xmemcmp(ao_rx_packet.packet.callsign, + ao_config.callsign, + AO_MAX_CALLSIGN) != 0 && + ao_xmemcmp(ao_config.callsign, CODE_TO_XDATA("N0CALL"), 7) != 0) + return 0; + + /* SYN packets carry no data */ + if (ao_rx_packet.packet.len == AO_PACKET_SYN) { + rx_seq = ao_rx_packet.packet.seq; + ao_tx_packet.seq = ao_rx_packet.packet.ack; + ao_tx_packet.ack = rx_seq; + } else if (ao_rx_packet.packet.len) { + + /* Check for incoming data at the next sequence and + * for an empty data buffer + */ + if (ao_rx_packet.packet.seq == (uint8_t) (rx_seq + (uint8_t) 1) && + ao_packet_rx_used == ao_packet_rx_len) { + + /* Copy data to the receive data buffer and set up the + * offsets + */ + ao_xmemcpy(rx_data, ao_rx_packet.packet.d, ao_rx_packet.packet.len); + ao_packet_rx_used = 0; + ao_packet_rx_len = ao_rx_packet.packet.len; + + /* Mark the sequence that we've received to + * let the sender know when we return a packet + */ + rx_seq = ao_rx_packet.packet.seq; + ao_tx_packet.ack = rx_seq; + + /* Poke anyone looking for received data */ + ao_wakeup(&ao_stdin_ready); + } + } + + /* If the other side has seen the latest data we queued, + * wake up any task waiting to send data and let them go again + */ + if (ao_rx_packet.packet.ack == ao_tx_packet.seq) { + ao_tx_packet.len = 0; + ao_wakeup(&ao_tx_packet); + } + return 1; +} + +#ifndef PACKET_HAS_MASTER +#define PACKET_HAS_MASTER 1 +#endif + +#if PACKET_HAS_MASTER +void +ao_packet_flush(void) +{ + /* If there is data to send, and this is the master, + * then poke the master to send all queued data + */ + if (ao_packet_tx_used && ao_packet_master_sleeping) + ao_wakeup(&ao_packet_master_sleeping); +} +#endif /* PACKET_HAS_MASTER */ + +void +ao_packet_putchar(char c) __reentrant +{ + while (ao_packet_tx_used == AO_PACKET_MAX && ao_packet_enable) { +#if PACKET_HAS_MASTER + ao_packet_flush(); +#endif + ao_sleep(&tx_data); + } + + if (ao_packet_enable) + tx_data[ao_packet_tx_used++] = c; +} + +char +ao_packet_pollchar(void) __critical +{ + if (!ao_packet_enable) + return AO_READ_AGAIN; + + if (ao_packet_rx_used == ao_packet_rx_len) + return AO_READ_AGAIN; + + return rx_data[ao_packet_rx_used++]; +} -- cgit v1.2.3 From 84f9a525c64491afa9b7a565e3c10a4cee106e14 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 17:17:44 -0700 Subject: altos: Clean up radio CRC handling Make the FEC code just set the CRC_OK bit like the cc1111 radio does; eliminates a bunch of weird conventions across the FEC API. Signed-off-by: Keith Packard --- src/core/ao.h | 7 +++++++ src/core/ao_fec.h | 2 ++ src/core/ao_fec_rx.c | 26 +++++++++++++++----------- src/drivers/ao_cc1120.c | 7 +------ src/drivers/ao_packet.c | 4 +--- src/test/ao_fec_test.c | 21 ++++++++++----------- 6 files changed, 36 insertions(+), 31 deletions(-) (limited to 'src/drivers/ao_packet.c') diff --git a/src/core/ao.h b/src/core/ao.h index 62eb488e..861a0fd4 100644 --- a/src/core/ao.h +++ b/src/core/ao.h @@ -511,6 +511,13 @@ extern __xdata uint8_t ao_radio_dma_done; extern __xdata uint8_t ao_radio_done; extern __xdata uint8_t ao_radio_mutex; +#ifdef PKT_APPEND_STATUS_1_CRC_OK +#define AO_RADIO_STATUS_CRC_OK PKT_APPEND_STATUS_1_CRC_OK +#else +#include +#define AO_RADIO_STATUS_CRC_OK AO_FEC_DECODE_CRC_OK +#endif + void ao_radio_general_isr(void) ao_arch_interrupt(16); diff --git a/src/core/ao_fec.h b/src/core/ao_fec.h index f1192b62..771732bd 100644 --- a/src/core/ao_fec.h +++ b/src/core/ao_fec.h @@ -70,6 +70,8 @@ ao_fec_encode(const uint8_t *in, uint8_t len, uint8_t *out); #define AO_FEC_DECODE_BLOCK (32) /* callback must return multiples of this many bits */ +#define AO_FEC_DECODE_CRC_OK 0x80 /* stored in out[out_len-1] */ + uint8_t ao_fec_decode(const uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len, uint16_t (*callback)()); diff --git a/src/core/ao_fec_rx.c b/src/core/ao_fec_rx.c index 0d400bb0..d4c98475 100644 --- a/src/core/ao_fec_rx.c +++ b/src/core/ao_fec_rx.c @@ -211,6 +211,7 @@ ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, ui int8_t dist = b - (o + 8); /* distance to last ready-for-writing bit */ uint32_t min_cost; /* lowest cost */ uint8_t min_state; /* lowest cost state */ + uint8_t byte; /* Find the best fit at the current point * of the decode. @@ -238,24 +239,27 @@ ao_fec_decode(const uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, ui printf ("\tbit %3d min_cost %5d old bit %3d old_state %x bits %02x whiten %0x\n", i/2, min_cost, o + 8, min_state, (bits[p][min_state] >> dist) & 0xff, *whiten); #endif - if (out_len) { - uint8_t byte = (bits[p][min_state] >> dist) ^ *whiten++; + byte = (bits[p][min_state] >> dist) ^ *whiten++; + *out++ = byte; + if (out_len > 2) + crc = ao_fec_crc_byte(byte, crc); - if (out_len > 2) { - crc = ao_fec_crc_byte(byte, crc); - *out++ = byte; - } else { - *out++ = byte ^ (crc >> 8); - crc <<= 8; - } - --out_len; + if (!--out_len) { + if ((out[-2] == (uint8_t) (crc >> 8)) && + out[-1] == (uint8_t) crc) + out[-1] = AO_FEC_DECODE_CRC_OK; + else + out[-1] = 0; + out[-2] = 0; + goto done; } o += 8; } } +done: #if AO_PROFILE ao_fec_decode_start = start_tick; ao_fec_decode_end = ao_profile_tick(); #endif - return len/16; + return 1; } diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index c974613e..30663042 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -690,12 +690,7 @@ ao_radio_recv(__xdata void *d, uint8_t size) ao_radio_put(); - /* Construct final packet */ - - if (ret && ((uint8_t *) d)[size] == 0 && ((uint8_t *)d)[size+1] == 0) - ((uint8_t *) d)[size + 1] = 0x80; - else - ((uint8_t *) d)[size + 1] = 0x00; + /* Store the received RSSI value; the crc-OK byte is already done */ ((uint8_t *) d)[size] = (uint8_t) rssi; diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c index 19fe0558..28a0c415 100644 --- a/src/drivers/ao_packet.c +++ b/src/drivers/ao_packet.c @@ -65,10 +65,8 @@ ao_packet_recv(void) /* Check to see if we got a valid packet */ if (!dma_done) return 0; -#ifdef PKT_APPEND_STATUS_1_CRC_OK - if (!(ao_rx_packet.status & PKT_APPEND_STATUS_1_CRC_OK)) + if (!(ao_rx_packet.status & AO_RADIO_STATUS_CRC_OK)) return 0; -#endif /* Accept packets with matching call signs, or any packet if * our callsign hasn't been configured diff --git a/src/test/ao_fec_test.c b/src/test/ao_fec_test.c index 8ce532c8..671fcafc 100644 --- a/src/test/ao_fec_test.c +++ b/src/test/ao_fec_test.c @@ -268,18 +268,17 @@ int ao_real_packet(void) { uint8_t decode[64]; - uint8_t decode_len; - int ok = 0; + int ok; - decode_len = ao_fec_decode(real_packet, 576, decode, 34, NULL); + ok = ao_fec_decode(real_packet, 576, decode, 34, NULL); - if (decode[32] == 0 && decode[33] == 0) { + if (ok && decode[33] == AO_FEC_DECODE_CRC_OK) { printf ("match\n"); - ao_fec_dump_bytes(decode, decode_len, "Decode"); - ok = 1; + ao_fec_dump_bytes(decode, 34, "Decode"); } else { printf ("actual packet crc error\n"); + ok = 0; } return ok; } @@ -302,7 +301,7 @@ main(int argc, char **argv) int receive_len, receive_errors; uint8_t decode[DECODE_LEN(sizeof(original))]; - int decode_len; + int decode_ok; int errors = 0; int error; @@ -327,17 +326,17 @@ main(int argc, char **argv) receive_len = transmit_len; /* Decode it */ - decode_len = ao_fec_decode(receive, receive_len, decode, original_len + 2, NULL); + decode_ok = ao_fec_decode(receive, receive_len, decode, original_len + 2, NULL); /* Check to see if we received the right data */ error = 0; - if (decode_len < original_len + 2) { - printf ("len mis-match\n"); + if (!decode_ok) { + printf ("decode failed\n"); error++; } - if (decode[original_len] != 0 || decode[original_len+1] != 0) { + if (decode[original_len +1] != AO_FEC_DECODE_CRC_OK) { printf ("crc mis-match\n"); error++; } -- cgit v1.2.3 From bd21c050fd8b96b33ab6859c942bf55cf2b91868 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 27 Jun 2012 19:47:52 -0700 Subject: altos: Make profiling Viterbi decoder more useful This blocks starting the decoder until all of the data have arrived so that the time spent in the decoder is easily computed. Signed-off-by: Keith Packard --- src/drivers/ao_cc1120.c | 8 +++++++- src/drivers/ao_packet.c | 12 ++++++++++++ src/megametrum-v0.1/Makefile | 7 +++---- src/megametrum-v0.1/ao_megametrum.c | 3 +++ 4 files changed, 25 insertions(+), 5 deletions(-) (limited to 'src/drivers/ao_packet.c') diff --git a/src/drivers/ao_cc1120.c b/src/drivers/ao_cc1120.c index 30663042..1d28148b 100644 --- a/src/drivers/ao_cc1120.c +++ b/src/drivers/ao_cc1120.c @@ -605,8 +605,10 @@ ao_radio_rx_isr(void) rx_data[rx_data_cur++] = d; if (rx_waiting && rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) { #if AO_PROFILE - if (rx_data_consumed == 0) + if (!rx_packet_tick) rx_packet_tick = ao_profile_tick(); + if (rx_data_cur < rx_data_count) + return; #endif rx_waiting = 0; ao_wakeup(&ao_radio_wake); @@ -630,6 +632,9 @@ ao_radio_rx_wait(void) if (ao_radio_abort) return 0; rx_data_consumed += AO_FEC_DECODE_BLOCK; +#if AO_PROFILE + return rx_data_cur - rx_data_consumed; +#endif return AO_FEC_DECODE_BLOCK; } @@ -649,6 +654,7 @@ ao_radio_recv(__xdata void *d, uint8_t size) } #if AO_PROFILE rx_start_tick = ao_profile_tick(); + rx_packet_tick = 0; #endif len = size + 2; /* CRC bytes */ len += 1 + ~(len & 1); /* 1 or two pad bytes */ diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c index 28a0c415..e020c003 100644 --- a/src/drivers/ao_packet.c +++ b/src/drivers/ao_packet.c @@ -61,6 +61,18 @@ ao_packet_recv(void) #ifdef AO_LED_GREEN ao_led_off(AO_LED_GREEN); #endif +#if AO_PROFILE + { + extern uint32_t ao_rx_start_tick, ao_rx_packet_tick, ao_rx_done_tick, ao_rx_last_done_tick; + extern uint32_t ao_fec_decode_start, ao_fec_decode_end; + + printf ("between packet: %d\n", ao_rx_start_tick - ao_rx_last_done_tick); + printf ("receive start delay: %d\n", ao_rx_packet_tick - ao_rx_start_tick); + printf ("decode time: %d\n", ao_fec_decode_end - ao_fec_decode_start); + printf ("rx cleanup: %d\n\n", ao_rx_done_tick - ao_fec_decode_end); + flush(); + } +#endif /* Check to see if we got a valid packet */ if (!dma_done) diff --git a/src/megametrum-v0.1/Makefile b/src/megametrum-v0.1/Makefile index 07a339b9..06b5e2ae 100644 --- a/src/megametrum-v0.1/Makefile +++ b/src/megametrum-v0.1/Makefile @@ -27,8 +27,7 @@ INC = \ # Common AltOS sources # -# ao_packet.c \ -# ao_packet_slave.c \ +#PROFILE=ao_profile.c ALTOS_SRC = \ ao_interrupt.c \ @@ -72,8 +71,8 @@ ALTOS_SRC = \ ao_telemetry.c \ ao_packet_slave.c \ ao_packet.c \ - ao_companion.c - + ao_companion.c \ + $(PROFILE) PRODUCT=MegaMetrum-v0.1 PRODUCT_DEF=-DMEGAMETRUM diff --git a/src/megametrum-v0.1/ao_megametrum.c b/src/megametrum-v0.1/ao_megametrum.c index ed35efa4..749f251d 100644 --- a/src/megametrum-v0.1/ao_megametrum.c +++ b/src/megametrum-v0.1/ao_megametrum.c @@ -63,6 +63,9 @@ main(void) ao_companion_init(); ao_config_init(); +#if AO_PROFILE + ao_profile_init(); +#endif ao_start_scheduler(); return 0; -- cgit v1.2.3 From 846a6298e4a8bfbe87bb24d7b0802c0bf6f233be Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Wed, 11 Jul 2012 13:53:30 -0700 Subject: Report RSSI values in monitor idle UI (trac #44) This adds a new 's' command to TeleDongle to report RSSI value from last received packet, and then has AltosUI request that value when closing the remote link. Signed-off-by: Keith Packard --- altosui/AltosIdleMonitorUI.java | 46 ++++++++++++++++++++++++++++------------- src/core/ao_packet.h | 2 ++ src/drivers/ao_packet.c | 11 ++++++---- src/drivers/ao_packet_master.c | 7 ++++++- 4 files changed, 47 insertions(+), 19 deletions(-) (limited to 'src/drivers/ao_packet.c') diff --git a/altosui/AltosIdleMonitorUI.java b/altosui/AltosIdleMonitorUI.java index 949e3926..eb6ec5e7 100644 --- a/altosui/AltosIdleMonitorUI.java +++ b/altosui/AltosIdleMonitorUI.java @@ -178,8 +178,23 @@ class AltosIdleMonitor extends Thread { AltosADC adc; AltosGPS gps; + int AltosRSSI() throws TimeoutException, InterruptedException { + serial.printf("s\n"); + String line = serial.get_reply_no_dialog(5000); + if (line == null) + throw new TimeoutException(); + String[] items = line.split("\\s+"); + if (items.length < 2) + return 0; + if (!items[0].equals("RSSI:")) + return 0; + int rssi = Integer.parseInt(items[1]); + return rssi; + } + void update_state() throws InterruptedException, TimeoutException { - AltosRecord record = new AltosRecord(); + AltosRecordTM record = new AltosRecordTM(); + int rssi; try { if (remote) { @@ -191,31 +206,34 @@ class AltosIdleMonitor extends Thread { adc = new AltosADC(serial); gps = new AltosGPSQuery(serial, config_data); } finally { - if (remote) + if (remote) { serial.stop_remote(); + rssi = AltosRSSI(); + } else + rssi = 0; } record.version = 0; record.callsign = config_data.callsign; record.serial = config_data.serial; record.flight = config_data.log_available() > 0 ? 255 : 0; - record.rssi = 0; + record.rssi = rssi; record.status = 0; record.state = Altos.ao_flight_idle; record.tick = adc.tick; -// record.accel = adc.accel; -// record.pres = adc.pres; -// record.batt = adc.batt; -// record.temp = adc.temp; -// record.drogue = adc.drogue; -// record.main = adc.main; - -// record.ground_accel = record.accel; -// record.ground_pres = record.pres; -// record.accel_plus_g = config_data.accel_cal_plus; -// record.accel_minus_g = config_data.accel_cal_minus; + record.accel = adc.accel; + record.pres = adc.pres; + record.batt = adc.batt; + record.temp = adc.temp; + record.drogue = adc.drogue; + record.main = adc.main; + + record.ground_accel = record.accel; + record.ground_pres = record.pres; + record.accel_plus_g = config_data.accel_cal_plus; + record.accel_minus_g = config_data.accel_cal_minus; record.acceleration = 0; record.speed = 0; record.height = 0; diff --git a/src/core/ao_packet.h b/src/core/ao_packet.h index 618ccda4..f232a878 100644 --- a/src/core/ao_packet.h +++ b/src/core/ao_packet.h @@ -67,6 +67,8 @@ ao_packet_pollchar(void) __critical; #if PACKET_HAS_MASTER /* ao_packet_master.c */ +extern __xdata uint8_t ao_packet_last_rssi; + void ao_packet_master_init(void); #endif diff --git a/src/drivers/ao_packet.c b/src/drivers/ao_packet.c index e020c003..d813b25f 100644 --- a/src/drivers/ao_packet.c +++ b/src/drivers/ao_packet.c @@ -27,7 +27,11 @@ static __pdata uint8_t rx_seq; __xdata struct ao_task ao_packet_task; __xdata uint8_t ao_packet_enable; + +#if PACKET_HAS_MASTER __xdata uint8_t ao_packet_master_sleeping; +__xdata uint8_t ao_packet_last_rssi; +#endif void ao_packet_send(void) @@ -80,6 +84,9 @@ ao_packet_recv(void) if (!(ao_rx_packet.status & AO_RADIO_STATUS_CRC_OK)) return 0; +#if PACKET_HAS_MASTER + ao_packet_last_rssi = ao_rx_packet.rssi; +#endif /* Accept packets with matching call signs, or any packet if * our callsign hasn't been configured */ @@ -130,10 +137,6 @@ ao_packet_recv(void) return 1; } -#ifndef PACKET_HAS_MASTER -#define PACKET_HAS_MASTER 1 -#endif - #if PACKET_HAS_MASTER void ao_packet_flush(void) diff --git a/src/drivers/ao_packet_master.c b/src/drivers/ao_packet_master.c index 66f94288..e97a6648 100644 --- a/src/drivers/ao_packet_master.c +++ b/src/drivers/ao_packet_master.c @@ -137,10 +137,15 @@ ao_packet_forward(void) __reentrant #endif } - +static void +ao_packet_signal(void) +{ + printf ("RSSI: %d\n", AO_RSSI_FROM_RADIO(ao_packet_last_rssi)); +} __code struct ao_cmds ao_packet_master_cmds[] = { { ao_packet_forward, "p\0Remote packet link." }, + { ao_packet_signal, "s\0Report signal strength." }, { 0, NULL }, }; -- cgit v1.2.3