1
0
mirror of git://projects.qi-hardware.com/ben-wpan.git synced 2024-11-25 20:56:00 +02:00

Merge branch 'buffer-frames'

This commit is contained in:
Werner Almesberger 2013-07-30 20:37:12 -03:00
commit 08f4ac98fa
8 changed files with 106 additions and 48 deletions

View File

@ -22,18 +22,32 @@
#include "mac.h" #include "mac.h"
#define RX_BUFS 2
bool (*mac_irq)(void) = NULL; bool (*mac_irq)(void) = NULL;
static uint8_t rx_buf[MAX_PSDU+2]; /* PHDR+payload+LQ */ static uint8_t rx_buf[RX_BUFS][MAX_PSDU+2]; /* PHDR+payload+LQ */
static uint8_t tx_buf[MAX_PSDU]; static uint8_t tx_buf[MAX_PSDU];
static uint8_t tx_size = 0; static uint8_t tx_size = 0;
static bool txing = 0; static bool txing = 0;
static bool queued_tx_ack = 0; static bool queued_tx_ack = 0;
static bool queued_rx = 0;
static uint8_t next_seq, this_seq, queued_seq; static uint8_t next_seq, this_seq, queued_seq;
/* ----- Receive buffer management ----------------------------------------- */
static uint8_t rx_in = 0, rx_out = 0;
static inline void next_buf(uint8_t *index)
{
*index = (*index+1) % RX_BUFS;
}
/* ----- Register access --------------------------------------------------- */ /* ----- Register access --------------------------------------------------- */
@ -62,27 +76,45 @@ static void reg_write(uint8_t reg, uint8_t value)
/* ----- Interrupt handling ------------------------------------------------ */ /* ----- Interrupt handling ------------------------------------------------ */
static void receive_frame(void); static void rx_done(void *user);
static void tx_ack_done(void *user);
static void rx_done(void *user) static void usb_next(void)
{ {
led(0); const uint8_t *buf;
if (queued_rx) {
receive_frame(); if (rx_in != rx_out) {
queued_rx = 0; buf = rx_buf[rx_out];
return; led(1);
usb_send(&eps[1], buf, buf[0]+2, rx_done, NULL);
} }
if (queued_tx_ack) { if (queued_tx_ack) {
usb_send(&eps[1], &queued_seq, 1, rx_done, NULL); usb_send(&eps[1], &queued_seq, 1, tx_ack_done, NULL);
queued_tx_ack = 0; queued_tx_ack = 0;
} }
} }
static void tx_ack_done(void *user)
{
usb_next();
}
static void rx_done(void *user)
{
led(0);
next_buf(&rx_out);
usb_next();
}
static void receive_frame(void) static void receive_frame(void)
{ {
uint8_t size, i; uint8_t size;
uint8_t *buf;
spi_begin(); spi_begin();
if (!(spi_io(AT86RF230_BUF_READ) & RX_CRC_VALID)) { if (!(spi_io(AT86RF230_BUF_READ) & RX_CRC_VALID)) {
@ -95,20 +127,15 @@ static void receive_frame(void)
return; return;
} }
rx_buf[0] = size; buf = rx_buf[rx_in];
for (i = 0; i != size+1; i++) spi_recv_block(buf+1, size+1);
rx_buf[i+1] = spi_recv();
spi_end(); spi_end();
led(1);
usb_send(&eps[1], rx_buf, size+2, rx_done, NULL);
}
buf[0] = size;
next_buf(&rx_in);
static void flush_queued_rx(void) if (eps[1].state == EP_IDLE)
{ usb_next();
if (queued_rx)
receive_frame();
queued_rx = 0;
} }
@ -122,7 +149,7 @@ static bool handle_irq(void)
if (txing) { if (txing) {
if (eps[1].state == EP_IDLE) { if (eps[1].state == EP_IDLE) {
usb_send(&eps[1], &this_seq, 1, rx_done, NULL); usb_send(&eps[1], &this_seq, 1, tx_ack_done, NULL);
} else { } else {
queued_tx_ack = 1; queued_tx_ack = 1;
queued_seq = this_seq; queued_seq = this_seq;
@ -131,12 +158,8 @@ static bool handle_irq(void)
return 1; return 1;
} }
/* unlikely */ /* likely */
if (eps[1].state != EP_IDLE) { if (eps[1].state == EP_IDLE || rx_in != rx_out)
queued_rx = 1;
return 1;
}
receive_frame(); receive_frame();
return 1; return 1;
@ -193,9 +216,7 @@ static void do_tx(void *user)
*/ */
reg_write(REG_TRX_STATE, TRX_CMD_FORCE_PLL_ON); reg_write(REG_TRX_STATE, TRX_CMD_FORCE_PLL_ON);
flush_queued_rx();
handle_irq(); handle_irq();
queued_rx = 0;
spi_begin(); spi_begin();
spi_send(AT86RF230_BUF_WRITE); spi_send(AT86RF230_BUF_WRITE);
@ -233,7 +254,7 @@ void mac_reset(void)
mac_irq = NULL; mac_irq = NULL;
txing = 0; txing = 0;
queued_tx_ack = 0; queued_tx_ack = 0;
queued_rx = 0; rx_in = rx_out = 0;
next_seq = this_seq = queued_seq = 0; next_seq = this_seq = queued_seq = 0;
/* enable CRC and PHY_RSSI (with RX_CRC_VALID) in SPI status return */ /* enable CRC and PHY_RSSI (with RX_CRC_VALID) in SPI status return */

View File

@ -47,6 +47,21 @@ void spi_end(void)
} }
void spi_recv_block(uint8_t *buf, uint8_t n)
{
if (!n)
return;
UDR1 = 0;
while (--n) {
while (!(UCSR1A & 1 << RXC1));
*buf++ = UDR1;
UDR1 = 0;
}
while (!(UCSR1A & 1 << RXC1));
*buf++ = UDR1;
}
void spi_off(void) void spi_off(void)
{ {
spi_initialized = 0; spi_initialized = 0;

View File

@ -1,8 +1,8 @@
/* /*
* fw/spi.h - ATmega8 family SPI I/O * fw/spi.h - ATmega8 family SPI I/O
* *
* Written 2011 by Werner Almesberger * Written 2011, 2013 by Werner Almesberger
* Copyright 2011 Werner Almesberger * Copyright 2011, 2013 Werner Almesberger
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -25,4 +25,6 @@ void spi_init(void);
#define spi_send(v) (void) spi_io(v) #define spi_send(v) (void) spi_io(v)
#define spi_recv(v) spi_io(0) #define spi_recv(v) spi_io(0)
void spi_recv_block(uint8_t *buf, uint8_t n);
#endif /* !SPI_H */ #endif /* !SPI_H */

View File

@ -11,6 +11,7 @@
*/ */
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
@ -74,6 +75,7 @@ enum mode {
static volatile int run = 1; static volatile int run = 1;
static bool quick = 0;
/* ----- Helper functions -------------------------------------------------- */ /* ----- Helper functions -------------------------------------------------- */
@ -237,7 +239,9 @@ static void receive_pcap(struct atrf_dsc *dsc, const char *name)
write_pcap_hdr(file); write_pcap_hdr(file);
while (run) { while (run) {
wait_for_interrupt(dsc, wait_for_interrupt(dsc,
IRQ_TRX_END, IRQ_TRX_END | IRQ_RX_START | IRQ_AMI, 0); IRQ_TRX_END,
quick ? 0xff : IRQ_TRX_END | IRQ_RX_START | IRQ_AMI,
quick ? -1 : 0);
if (!run) if (!run)
break; break;
gettimeofday(&now, NULL); gettimeofday(&now, NULL);
@ -249,6 +253,7 @@ static void receive_pcap(struct atrf_dsc *dsc, const char *name)
continue; continue;
} }
write_pcap_rec(file, &now, buf, n-1); write_pcap_rec(file, &now, buf, n-1);
if (!quick)
(void) write(2, ".", 1); (void) write(2, ".", 1);
count++; count++;
} }
@ -666,7 +671,7 @@ static void usage(const char *name)
" command shell command to run while transmitting (default: wait for\n" " command shell command to run while transmitting (default: wait for\n"
" SIGINT instead)\n\n" " SIGINT instead)\n\n"
" common options: [-c channel|-f freq] [-C mhz] [-d driver[:arg]] [-o file]\n" " common options: [-c channel|-f freq] [-C mhz] [-d driver[:arg]] [-o file]\n"
" [-p power] [-r rate] [-t trim]\n" " [-p power] [-q] [-r rate] [-t trim]\n"
" -c channel channel number, 11 to 26 (default %d)\n" " -c channel channel number, 11 to 26 (default %d)\n"
" -C mhz output clock at 1, 2, 4, 8, or 16 MHz (default: off)\n" " -C mhz output clock at 1, 2, 4, 8, or 16 MHz (default: off)\n"
" -d driver[:arg]\n" " -d driver[:arg]\n"
@ -674,6 +679,8 @@ static void usage(const char *name)
" -f freq frequency in MHz, 2405 to 2480 (default %d)\n" " -f freq frequency in MHz, 2405 to 2480 (default %d)\n"
" -o file write received data to a file in pcap format\n" " -o file write received data to a file in pcap format\n"
" -p power transmit power, -17.2 to 3.0 dBm (default %.1f)\n" " -p power transmit power, -17.2 to 3.0 dBm (default %.1f)\n"
" -q quick and quiet - suppress progress reports and warnings,\n"
" poll aggressively (currently only used when capturing)\n"
" -r rate data rate, 250k, 500k, 1M, or 2M (default: 250k)\n" " -r rate data rate, 250k, 500k, 1M, or 2M (default: 250k)\n"
" -t trim trim capacitor, 0 to 15 (default %d)\n" " -t trim trim capacitor, 0 to 15 (default %d)\n"
, name, name, name, name, name, name, , name, name, name, name, name, name,
@ -718,7 +725,7 @@ int main(int argc, char *const *argv)
const char *pcap_file = NULL; const char *pcap_file = NULL;
struct atrf_dsc *dsc; struct atrf_dsc *dsc;
while ((c = getopt(argc, argv, "c:C:d:E:f:Ho:p:Pr:Rt:T:x")) != EOF) while ((c = getopt(argc, argv, "c:C:d:E:f:Ho:p:Pqr:Rt:T:x")) != EOF)
switch (c) { switch (c) {
case 'c': case 'c':
channel = strtoul(optarg, &end, 0); channel = strtoul(optarg, &end, 0);
@ -767,6 +774,9 @@ int main(int argc, char *const *argv)
case 'P': case 'P':
set_mode(&mode, mode_ping); set_mode(&mode, mode_ping);
break; break;
case 'q':
quick = 1;
break;
case 'r': case 'r':
if (!strcmp(optarg, "250k")) if (!strcmp(optarg, "250k"))
rate = OQPSK_DATA_RATE_250; rate = OQPSK_DATA_RATE_250;

View File

@ -19,6 +19,14 @@
void flush_interrupts(struct atrf_dsc *dsc); void flush_interrupts(struct atrf_dsc *dsc);
/*
* timeout_ms:
* > 0: time out after that many milliseconds
* == 0: wait forever
* < 0: wait forever and eliminate poll delays (for high-speed capture)
*/
uint8_t wait_for_interrupt(struct atrf_dsc *dsc, uint8_t wait_for, uint8_t wait_for_interrupt(struct atrf_dsc *dsc, uint8_t wait_for,
uint8_t ignore, int timeout_ms); uint8_t ignore, int timeout_ms);

View File

@ -1,8 +1,8 @@
/* /*
* lib/atben.c - ATRF access functions library (Ben 8:10 card version) * lib/atben.c - ATRF access functions library (Ben 8:10 card version)
* *
* Written 2010-2011 by Werner Almesberger * Written 2010-2011, 2013 by Werner Almesberger
* Copyright 2010-2011 Werner Almesberger * Copyright 2010-2011, 2013 Werner Almesberger
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -439,10 +439,10 @@ int atben_interrupt_wait(void *handle, int timeout_ms)
int timedout = 0; int timedout = 0;
uint8_t irq; uint8_t irq;
if (timeout_ms) if (timeout_ms > 0)
timeout_start(&to, timeout_ms); timeout_start(&to, timeout_ms);
while (1) { while (1) {
if (timeout_ms) if (timeout_ms > 0)
timedout = timeout_reached(&to); timedout = timeout_reached(&to);
if (atben_interrupt(handle)) { if (atben_interrupt(handle)) {
irq = atben_reg_read(handle, REG_IRQ_STATUS); irq = atben_reg_read(handle, REG_IRQ_STATUS);
@ -452,6 +452,7 @@ int atben_interrupt_wait(void *handle, int timeout_ms)
} }
if (timedout) if (timedout)
return 0; return 0;
if (timeout_ms >= 0)
usleep(1000); usleep(1000);
} }

View File

@ -221,7 +221,7 @@ int atusb_interrupt_wait(void *handle, int timeout_ms)
return 0; return 0;
res = usb_bulk_read(dsc->dev, 1, res = usb_bulk_read(dsc->dev, 1,
(char *) &buf, sizeof(buf), timeout_ms); (char *) &buf, sizeof(buf), timeout_ms < 0 : 0 : timeout_ms);
if (res == -ETIMEDOUT) if (res == -ETIMEDOUT)
return 0; return 0;
if (res < 0) { if (res < 0) {

View File

@ -62,14 +62,14 @@ uint8_t wait_for_interrupt(struct atrf_dsc *dsc, uint8_t wait_for,
sigint = 0; sigint = 0;
old_sig = signal(SIGINT, die); old_sig = signal(SIGINT, die);
if (timeout_ms) { if (timeout_ms > 0) {
if (timeout_ms < MIN_TIMEOUT_MS) if (timeout_ms < MIN_TIMEOUT_MS)
timeout_ms = MIN_TIMEOUT_MS; timeout_ms = MIN_TIMEOUT_MS;
timeout_start(&to, timeout_ms); timeout_start(&to, timeout_ms);
} }
while (!sigint && !timedout) { while (!sigint && !timedout) {
while (!sigint && !timedout) { while (!sigint && !timedout) {
if (timeout_ms) { if (timeout_ms > 0) {
ms = timeout_left_ms(&to); ms = timeout_left_ms(&to);
if (ms <= 0) { if (ms <= 0) {
timedout = 1; timedout = 1;
@ -78,7 +78,8 @@ uint8_t wait_for_interrupt(struct atrf_dsc *dsc, uint8_t wait_for,
} else { } else {
ms = 0; ms = 0;
} }
irq = atrf_interrupt_wait(dsc, ms); irq = atrf_interrupt_wait(dsc,
timeout_ms < 0 ? -1 : ms);
if (irq) if (irq)
break; break;
} }