From 9ab94a53e26b57d5411d557416c2aefc1b30995d Mon Sep 17 00:00:00 2001 From: Werner Almesberger Date: Tue, 19 Apr 2011 06:35:31 -0300 Subject: [PATCH] tools: new utility atrf-xmit for fast transmission tests - Makefile (DIRS): added atrf-xmit - atrf-xmit/Makefile, atrf-xmit/atrf-xmit.c: new utility atrf-xmit to rapidly send packets from one device to another and analyze the outcome --- tools/Makefile | 2 +- tools/atrf-xmit/Makefile | 16 +++ tools/atrf-xmit/atrf-xmit.c | 208 ++++++++++++++++++++++++++++++++++++ 3 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 tools/atrf-xmit/Makefile create mode 100644 tools/atrf-xmit/atrf-xmit.c diff --git a/tools/Makefile b/tools/Makefile index bfb6c1d..ae11e01 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -12,7 +12,7 @@ DIRS=atrf-id atrf-path atrf-proxy atrf-reset atrf-rssi atrf-trim atrf-txrx \ - atrf-xtal + atrf-xmit atrf-xtal TARGET_ONLY_DIRS=lib ifeq ($(TARGET),ben_jlime) diff --git a/tools/atrf-xmit/Makefile b/tools/atrf-xmit/Makefile new file mode 100644 index 0000000..9804d0b --- /dev/null +++ b/tools/atrf-xmit/Makefile @@ -0,0 +1,16 @@ +# +# atrf-xmit/Makefile - Fast transmission test +# +# Written 2011 by Werner Almesberger +# Copyright 2011 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 +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# + + +MAIN = atrf-xmit + +include ../Makefile.common diff --git a/tools/atrf-xmit/atrf-xmit.c b/tools/atrf-xmit/atrf-xmit.c new file mode 100644 index 0000000..51232d2 --- /dev/null +++ b/tools/atrf-xmit/atrf-xmit.c @@ -0,0 +1,208 @@ +/* + * atrf-ber/atrf-ber.c - Fast transmission test + * + * Written 2011 by Werner Almesberger + * Copyright 2011 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#include +#include +#include + +#include "at86rf230.h" + +#include "misctxrx.h" +#include "atrf.h" + + +#define DEFAULT_CHANNEL 15 +#define DEFAULT_TRIM 8 +#define DEFAULT_POWER 15 + +#define PSDU_SIZE 127 + + +static void init_common(struct atrf_dsc *dsc, int trim, int channel) +{ + atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_TRX_OFF); + atrf_reg_write(dsc, REG_XOSC_CTRL, + (XTAL_MODE_INT << XTAL_MODE_SHIFT) | trim); + atrf_set_clkm(dsc, 0); + atrf_reg_write(dsc, REG_PHY_CC_CCA, (1 << CCA_MODE_SHIFT) | channel); + atrf_reg_write(dsc, REG_IRQ_MASK, 0xff); + (void) atrf_reg_read(dsc, REG_IRQ_STATUS); +} + + +static void init_tx(struct atrf_dsc *dsc, int trim, int channel, int power) +{ + uint8_t buf[PSDU_SIZE]; + int i; + + init_common(dsc, trim, channel); + set_power_step(dsc, power, 1); + for (i = 0; i != sizeof(buf); i++) + buf[i] = i; + atrf_buf_write(dsc, buf, sizeof(buf)); + atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_PLL_ON); + wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 10, 20); +} + + +static void init_rx(struct atrf_dsc *dsc, int trim, int channel) +{ + init_common(dsc, trim, channel); + atrf_reg_write(dsc, REG_TRX_STATE, TRX_CMD_RX_ON); + wait_for_interrupt(dsc, IRQ_PLL_LOCK, IRQ_PLL_LOCK, 10, 20); +} + + +static int xfer_one(struct atrf_dsc *tx, struct atrf_dsc *rx) +{ + uint8_t irq; + uint8_t buf[PSDU_SIZE+1]; /* +1 for LQI */ + int n, i; + + atrf_reg_write(tx, REG_TRX_STATE, TRX_CMD_TX_START); +#if 0 + irq = wait_for_interrupt(rx, IRQ_TRX_END, IRQ_TRX_END | IRQ_RX_START, + 1000, 5); /* 5 ms */ +#else + /* + * Just waiting for the maximum time is much faster than polling the + * interrupt, at least for now. + */ + usleep(5000); + irq = atrf_reg_read(tx, REG_IRQ_STATUS); +#endif + if (!(irq & IRQ_TRX_END)) + return 0; + if (atrf_reg_read(rx, REG_PHY_RSSI) & RX_CRC_VALID) + return 1; + n = atrf_buf_read(rx, buf, sizeof(buf)); + if (n <= 0) + return 0; + n--; /* we don't care about the LQI */ + if (n != PSDU_SIZE) { + printf("0\n"); + return 0; + } + for (i = 0; i != n-2; i++) + if (buf[i] != i) + break; + /* + * @@@ We should analyze the CRC here to see if the first or the second + * byte got corrupted. + */ + printf("%d\n", i+1); + return 0; +} + + +static void xfer(struct atrf_dsc *tx, struct atrf_dsc *rx, int packets) +{ + int got = 0; + int i; + + for (i = 0; i != packets; i++) + got += xfer_one(tx, rx); + printf("%d/%d\n", got, packets); +} + + +static void usage(const char *name) +{ + fprintf(stderr, +"usage: %s [-c channel] [-p power] [-t trim_tx [-t trim_rx]]\n" +"%15s driver_tx[:arg] driver_rx[:arg] packets\n\n" +" -c channel transmit/receive channel, 11 to 26 (default %d)\n" +" -p power transmit power, 0 to 15 (default %d)\n" +" -t trim trim capacitor, 0 to 15 (default %d)\n" + , name, "", + DEFAULT_CHANNEL, DEFAULT_POWER, DEFAULT_TRIM); + exit(1); +} + + +int main(int argc, char **argv) +{ + const char *tx_drv, *rx_drv; + struct atrf_dsc *tx, *rx; + int trim_tx = -1, trim_rx = DEFAULT_TRIM; + int channel = DEFAULT_CHANNEL; + int power = DEFAULT_POWER; + int packets = 1; + unsigned long tmp; + char *end; + int c; + + while ((c = getopt(argc, argv, "c:p:t:")) != EOF) + switch (c) { + case 'c': + tmp = strtoul(optarg, &end, 0); + if (*end || tmp < 11 || tmp > 26) + usage(*argv); + channel = tmp; + break; + case 'p': + tmp = strtoul(optarg, &end, 0); + if (*end || tmp > 15) + usage(*argv); + power = tmp; + break; + case 't': + tmp = strtoul(optarg, &end, 0); + if (*end || tmp > 15) + usage(*argv); + if (trim_tx == -1) + trim_tx = tmp; + else + trim_rx = tmp; + break; + default: + usage(*argv); + } + + if (trim_tx == -1) + trim_tx = DEFAULT_TRIM; + + switch (argc-optind) { + case 3: + packets = strtoul(argv[optind+2], &end, 0); + if (*end) + usage(*argv); + /* fall through */ + case 2: + tx_drv = argv[optind]; + rx_drv = argv[optind+1]; + break; + default: + usage(*argv); + } + + tx = atrf_open(tx_drv); + if (!tx) + return 1; + rx = atrf_open(rx_drv); + if (!rx) + return 1; + + init_rx(rx, trim_rx, channel); + init_tx(tx, trim_tx, channel, 15-power); + + xfer(tx, rx, packets); + + atrf_reg_write(tx, REG_TRX_STATE, TRX_CMD_TRX_OFF); + atrf_reg_write(rx, REG_TRX_STATE, TRX_CMD_TRX_OFF); + + atrf_close(tx); + atrf_close(rx); + + return 0; +}