1
0
mirror of git://projects.qi-hardware.com/ben-wpan.git synced 2024-12-22 19:48:39 +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"
#define RX_BUFS 2
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_size = 0;
static bool txing = 0;
static bool queued_tx_ack = 0;
static bool queued_rx = 0;
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 --------------------------------------------------- */
@ -62,27 +76,45 @@ static void reg_write(uint8_t reg, uint8_t value)
/* ----- 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);
if (queued_rx) {
receive_frame();
queued_rx = 0;
return;
const uint8_t *buf;
if (rx_in != rx_out) {
buf = rx_buf[rx_out];
led(1);
usb_send(&eps[1], buf, buf[0]+2, rx_done, NULL);
}
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;
}
}
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)
{
uint8_t size, i;
uint8_t size;
uint8_t *buf;
spi_begin();
if (!(spi_io(AT86RF230_BUF_READ) & RX_CRC_VALID)) {
@ -95,20 +127,15 @@ static void receive_frame(void)
return;
}
rx_buf[0] = size;
for (i = 0; i != size+1; i++)
rx_buf[i+1] = spi_recv();
buf = rx_buf[rx_in];
spi_recv_block(buf+1, size+1);
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 (queued_rx)
receive_frame();
queued_rx = 0;
if (eps[1].state == EP_IDLE)
usb_next();
}
@ -122,7 +149,7 @@ static bool handle_irq(void)
if (txing) {
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 {
queued_tx_ack = 1;
queued_seq = this_seq;
@ -131,13 +158,9 @@ static bool handle_irq(void)
return 1;
}
/* unlikely */
if (eps[1].state != EP_IDLE) {
queued_rx = 1;
return 1;
}
receive_frame();
/* likely */
if (eps[1].state == EP_IDLE || rx_in != rx_out)
receive_frame();
return 1;
}
@ -193,9 +216,7 @@ static void do_tx(void *user)
*/
reg_write(REG_TRX_STATE, TRX_CMD_FORCE_PLL_ON);
flush_queued_rx();
handle_irq();
queued_rx = 0;
spi_begin();
spi_send(AT86RF230_BUF_WRITE);
@ -233,7 +254,7 @@ void mac_reset(void)
mac_irq = NULL;
txing = 0;
queued_tx_ack = 0;
queued_rx = 0;
rx_in = rx_out = 0;
next_seq = this_seq = queued_seq = 0;
/* 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)
{
spi_initialized = 0;

View File

@ -1,8 +1,8 @@
/*
* fw/spi.h - ATmega8 family SPI I/O
*
* Written 2011 by Werner Almesberger
* Copyright 2011 Werner Almesberger
* Written 2011, 2013 by Werner Almesberger
* Copyright 2011, 2013 Werner Almesberger
*
* 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
@ -25,4 +25,6 @@ void spi_init(void);
#define spi_send(v) (void) spi_io(v)
#define spi_recv(v) spi_io(0)
void spi_recv_block(uint8_t *buf, uint8_t n);
#endif /* !SPI_H */

View File

@ -11,6 +11,7 @@
*/
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
@ -74,6 +75,7 @@ enum mode {
static volatile int run = 1;
static bool quick = 0;
/* ----- Helper functions -------------------------------------------------- */
@ -237,7 +239,9 @@ static void receive_pcap(struct atrf_dsc *dsc, const char *name)
write_pcap_hdr(file);
while (run) {
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)
break;
gettimeofday(&now, NULL);
@ -249,7 +253,8 @@ static void receive_pcap(struct atrf_dsc *dsc, const char *name)
continue;
}
write_pcap_rec(file, &now, buf, n-1);
(void) write(2, ".", 1);
if (!quick)
(void) write(2, ".", 1);
count++;
}
if (fclose(file) == EOF) {
@ -666,7 +671,7 @@ static void usage(const char *name)
" command shell command to run while transmitting (default: wait for\n"
" SIGINT instead)\n\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 mhz output clock at 1, 2, 4, 8, or 16 MHz (default: off)\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"
" -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"
" -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"
" -t trim trim capacitor, 0 to 15 (default %d)\n"
, name, name, name, name, name, name,
@ -718,7 +725,7 @@ int main(int argc, char *const *argv)
const char *pcap_file = NULL;
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) {
case 'c':
channel = strtoul(optarg, &end, 0);
@ -767,6 +774,9 @@ int main(int argc, char *const *argv)
case 'P':
set_mode(&mode, mode_ping);
break;
case 'q':
quick = 1;
break;
case 'r':
if (!strcmp(optarg, "250k"))
rate = OQPSK_DATA_RATE_250;

View File

@ -19,6 +19,14 @@
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 ignore, int timeout_ms);

View File

@ -1,8 +1,8 @@
/*
* lib/atben.c - ATRF access functions library (Ben 8:10 card version)
*
* Written 2010-2011 by Werner Almesberger
* Copyright 2010-2011 Werner Almesberger
* Written 2010-2011, 2013 by Werner Almesberger
* Copyright 2010-2011, 2013 Werner Almesberger
*
* 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
@ -439,10 +439,10 @@ int atben_interrupt_wait(void *handle, int timeout_ms)
int timedout = 0;
uint8_t irq;
if (timeout_ms)
if (timeout_ms > 0)
timeout_start(&to, timeout_ms);
while (1) {
if (timeout_ms)
if (timeout_ms > 0)
timedout = timeout_reached(&to);
if (atben_interrupt(handle)) {
irq = atben_reg_read(handle, REG_IRQ_STATUS);
@ -452,7 +452,8 @@ int atben_interrupt_wait(void *handle, int timeout_ms)
}
if (timedout)
return 0;
usleep(1000);
if (timeout_ms >= 0)
usleep(1000);
}
return 0;

View File

@ -221,7 +221,7 @@ int atusb_interrupt_wait(void *handle, int timeout_ms)
return 0;
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)
return 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;
old_sig = signal(SIGINT, die);
if (timeout_ms) {
if (timeout_ms > 0) {
if (timeout_ms < MIN_TIMEOUT_MS)
timeout_ms = MIN_TIMEOUT_MS;
timeout_start(&to, timeout_ms);
}
while (!sigint && !timedout) {
while (!sigint && !timedout) {
if (timeout_ms) {
if (timeout_ms > 0) {
ms = timeout_left_ms(&to);
if (ms <= 0) {
timedout = 1;
@ -78,7 +78,8 @@ uint8_t wait_for_interrupt(struct atrf_dsc *dsc, uint8_t wait_for,
} else {
ms = 0;
}
irq = atrf_interrupt_wait(dsc, ms);
irq = atrf_interrupt_wait(dsc,
timeout_ms < 0 ? -1 : ms);
if (irq)
break;
}