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:
commit
08f4ac98fa
@ -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 */
|
||||||
|
@ -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;
|
||||||
|
@ -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 */
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user