Decode radio input one interleave block at a time. This overlaps the
decode computation with the packet reception, leading to lower latency
in an attempt to keep up with the transmitter.
Signed-off-by: Keith Packard <keithp@keithp.com>
* 'out' must be len/8 bytes long
*/
* 'out' must be len/8 bytes long
*/
+#define AO_FEC_DECODE_BLOCK (8 * 32) /* callback must return multiples of this many bits */
+
-ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len);
+ao_fec_decode(uint8_t *in, uint16_t in_len, uint8_t *out, uint8_t out_len, uint16_t (*callback)());
/*
* Interleave data packed in bytes. 'out' must be 'len' bytes long.
/*
* Interleave data packed in bytes. 'out' must be 'len' bytes long.
-ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len)
+ao_fec_decode(uint8_t *in, uint16_t len, uint8_t *out, uint8_t out_len, uint16_t (*callback)())
{
static uint16_t cost[2][NUM_STATE]; /* path cost */
static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */
{
static uint16_t cost[2][NUM_STATE]; /* path cost */
static uint16_t bits[2][NUM_STATE]; /* save bits to quickly output them */
const uint8_t *whiten = ao_fec_whiten_table;
uint16_t interleave; /* input byte array index */
struct ao_soft_sym s; /* input symbol pair */
const uint8_t *whiten = ao_fec_whiten_table;
uint16_t interleave; /* input byte array index */
struct ao_soft_sym s; /* input symbol pair */
p = 0;
for (state = 0; state < NUM_STATE; state++) {
p = 0;
for (state = 0; state < NUM_STATE; state++) {
+ if (callback)
+ avail = 0;
+ else
+ avail = len;
+
o = 0;
for (i = 0; i < len; i += 2) {
b = i/2;
n = p ^ 1;
o = 0;
for (i = 0; i < len; i += 2) {
b = i/2;
n = p ^ 1;
+ if (!avail) {
+ avail = callback();
+ if (!avail)
+ break;
+ }
+
/* Fetch one pair of input bytes, de-interleaving
* the input.
*/
/* Fetch one pair of input bytes, de-interleaving
* the input.
*/
static uint8_t rx_data[2048];
static uint16_t rx_data_count;
static uint8_t rx_data[2048];
static uint16_t rx_data_count;
+static uint16_t rx_data_consumed;
static uint16_t rx_data_cur;
static uint8_t rx_ignore;
static uint16_t rx_data_cur;
static uint8_t rx_ignore;
{
if (rx_ignore == 0) {
rx_data[rx_data_cur++] = stm_spi2.dr;
{
if (rx_ignore == 0) {
rx_data[rx_data_cur++] = stm_spi2.dr;
- if (rx_data_cur >= rx_data_count) {
+ if (rx_data_cur >= rx_data_count)
ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
ao_exti_disable(&AO_CC1120_INT_PORT, AO_CC1120_INT_PIN);
+ if (rx_data_cur - rx_data_consumed >= AO_FEC_DECODE_BLOCK) {
ao_wakeup(&ao_radio_wake);
}
} else {
ao_wakeup(&ao_radio_wake);
}
} else {
+static uint16_t
+ao_radio_rx_wait(void)
+{
+ cli();
+ while (rx_data_cur - rx_data_consumed < AO_FEC_DECODE_BLOCK &&
+ !ao_radio_abort)
+ ao_sleep(&ao_radio_wake);
+ sei();
+ if (ao_radio_abort)
+ return 0;
+ return AO_FEC_DECODE_BLOCK;
+}
+
uint8_t
ao_radio_recv(__xdata void *d, uint8_t size)
{
uint8_t
ao_radio_recv(__xdata void *d, uint8_t size)
{
len *= 2; /* 1/2 rate convolution */
rx_data_count = len * 8; /* bytes to bits */
rx_data_cur = 0;
len *= 2; /* 1/2 rate convolution */
rx_data_count = len * 8; /* bytes to bits */
rx_data_cur = 0;
rx_ignore = 2;
printf ("len %d rx_data_count %d\n", len, rx_data_count);
rx_ignore = 2;
printf ("len %d rx_data_count %d\n", len, rx_data_count);
ao_radio_strobe(CC1120_SRX);
ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
ao_radio_strobe(CC1120_SRX);
ao_radio_burst_read_start(CC1120_SOFT_RX_DATA_OUT);
- cli();
- while (!ao_radio_wake && !ao_radio_abort)
- ao_sleep(&ao_radio_wake);
- sei();
+
+ ao_fec_decode(rx_data, rx_data_count, d, size + 2, ao_radio_rx_wait);
+
ao_radio_burst_read_stop();
/* Convert from 'real' rssi to cc1111-style values */
ao_radio_burst_read_stop();
/* Convert from 'real' rssi to cc1111-style values */
/* Construct final packet */
/* Construct final packet */
- ao_fec_decode(rx_data, rx_data_cur, d, size + 2);
+ ao_fec_decode(rx_data, rx_data_cur, d, size + 2, 0);
if (ao_fec_check_crc(d, size))
((uint8_t *) d)[size + 1] = 0x80;
if (ao_fec_check_crc(d, size))
((uint8_t *) d)[size + 1] = 0x80;
int off;
for (off = 0; off < sizeof (real_packet) - 576; off++) {
int off;
for (off = 0; off < sizeof (real_packet) - 576; off++) {
- decode_len = ao_fec_decode(real_packet+off, 576, decode);
+ decode_len = ao_fec_decode(real_packet+off, 576, decode, 34, NULL);
if (ao_fec_check_crc(decode, 32)) {
printf ("match at %d\n", off);
if (ao_fec_check_crc(decode, 32)) {
printf ("match at %d\n", off);
receive_len = transmit_len;
/* Decode it */
receive_len = transmit_len;
/* Decode it */
- decode_len = ao_fec_decode(receive, receive_len, decode);
+ decode_len = ao_fec_decode(receive, receive_len, decode, original_len + 2, NULL);
/* Check to see if we received the right data */
error = 0;
/* Check to see if we received the right data */
error = 0;