diff --git a/Makefile.recurse b/Makefile.recurse index 493816c..7fcfd9f 100644 --- a/Makefile.recurse +++ b/Makefile.recurse @@ -1,8 +1,8 @@ # # Makefile.recurse - Recursively build a few standard targets # -# Written 2008, 2009 by Werner Almesberger -# Copyright 2008, 2009 Werner Almesberger +# Written 2008-2010 by Werner Almesberger +# Copyright 2008-2010 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 @@ -14,7 +14,7 @@ .PHONY: all install uninstall clean spotless all: - for d in $(DIRS) $(TARGET_ONLY_DIRS); \ + for d in $(TARGET_ONLY_DIRS) $(DIRS); \ do make -C $$d all || exit 1; done install: diff --git a/atrf/fw/atspi/ep0.c b/atrf/fw/atspi/ep0.c index ae4ad2b..010acd0 100644 --- a/atrf/fw/atspi/ep0.c +++ b/atrf/fw/atspi/ep0.c @@ -94,7 +94,6 @@ static void do_buf_write(void *user) user; /* suppress warning */ nSS = 0; - spi_send(AT86RF230_BUF_WRITE); for (i = 0; i != size; i++) spi_send(buf[i]); nSS = 1; @@ -164,13 +163,14 @@ static __bit my_setup(struct setup_request *setup) __reentrant debug("ATSPI_BUF_WRITE\n"); if (setup->wLength < 1) return 0; - if (setup->wLength > MAX_PSDU+1) /* PHR+PSDU */ + if (setup->wLength > MAX_PSDU) return 0; buf[0] = AT86RF230_BUF_WRITE; - size = setup->wLength+1; - usb_recv(&ep0, buf+1, setup->wLength, do_buf_write, NULL); + buf[1] = setup->wLength; + size = setup->wLength+2; + usb_recv(&ep0, buf+2, setup->wLength, do_buf_write, NULL); return 1; - case ATSPI_TO_DEV(ATSPI_BUF_READ): + case ATSPI_FROM_DEV(ATSPI_BUF_READ): debug("ATSPI_BUF_READ\n"); if (setup->wLength < 2) /* PHR+LQ */ return 0; @@ -178,11 +178,11 @@ static __bit my_setup(struct setup_request *setup) __reentrant return 0; nSS = 0; spi_send(AT86RF230_BUF_READ); - size = *buf = spi_recv(); - if (size+2 > setup->wLength) - size = setup->wLength-2; + size = spi_recv(); + if (size >= setup->wLength) + size = setup->wLength-1; for (i = 0; i != size+1; i++) - buf[i+1] = spi_recv(); + buf[i] = spi_recv(); nSS = 1; usb_send(&ep0, buf, size+1, NULL, NULL); return 1; diff --git a/atrf/fw/include/at86rf230.h b/atrf/fw/include/at86rf230.h index d49050f..20a3aa3 100644 --- a/atrf/fw/include/at86rf230.h +++ b/atrf/fw/include/at86rf230.h @@ -34,7 +34,7 @@ enum { REG_TRX_STATE = 0x02, REG_TRX_CTRL_0 = 0x03, - REG_TR_PWR = 0x05, + REG_PHY_TX_PWR = 0x05, REG_PHY_RSSI = 0x06, REG_PHY_ED_LEVEL = 0x07, REG_PHY_CC_CCA = 0x08, diff --git a/atrf/tools/Makefile b/atrf/tools/Makefile index 3c52c03..f177a59 100644 --- a/atrf/tools/Makefile +++ b/atrf/tools/Makefile @@ -11,6 +11,7 @@ # -DIRS=atspi-id atspi-reset atspi-rssi atspi-trim +DIRS=atspi-id atspi-reset atspi-rssi atspi-trim atspi-txrx +TARGET_ONLY_DIRS=lib include ../../Makefile.recurse diff --git a/atrf/tools/atspi-txrx/Makefile b/atrf/tools/atspi-txrx/Makefile index 5b92a5a..a23f155 100644 --- a/atrf/tools/atspi-txrx/Makefile +++ b/atrf/tools/atspi-txrx/Makefile @@ -11,7 +11,7 @@ # -F32XBASE = ../../../f32xbase +F32XBASE = ../../../../f32xbase MAIN = atspi-txrx diff --git a/atrf/tools/atspi-txrx/atspi-txrx.c b/atrf/tools/atspi-txrx/atspi-txrx.c index a0779d2..1a67045 100644 --- a/atrf/tools/atspi-txrx/atspi-txrx.c +++ b/atrf/tools/atspi-txrx/atspi-txrx.c @@ -13,6 +13,7 @@ #include #include +#include #include #include "at86rf230.h" @@ -20,31 +21,196 @@ #include "atspi.h" -#define FROM_DEV ATSPI_FROM_DEV(0) -#define TO_DEV ATSPI_TO_DEV(0) +/* + * According to IEEE 802.15.4-2003 section E.2.6, channel 15 is the only + * channel that falls into the 802.11 guard bands in North America an Europe. + */ -#define BUF_SIZE 256 +#define DEFAULT_CHANNEL 15 /* channel 15, 2425 MHz */ + +/* + * Transmit power, dBm. IEEE 802.15.4-2003 section E.3.1.3 specifies a transmit + * power of 0 dBm for IEEE 802.15.4. We assume an antenna gain of 3 dB or + * better. + */ + +#define DEFAULT_POWER -3.2 /* transmit power, dBm */ + + +static double tx_pwr[] = { + 3.0, 2.6, 2.1, 1.6, + 1.1, 0.5, -0.2, -1.2, + -2.2, -3.2, -4.2, -5.2, + -7.2, -9.2, -12.2, -17.2 +}; + + +static usb_dev_handle *init_txrx(int trim) +{ + usb_dev_handle *dev; + + dev = atspi_open(); + if (!dev) + exit(1); + + atspi_reset_rf(dev); + atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_TRX_OFF); + atspi_reg_write(dev, REG_XOSC_CTRL, + (XTAL_MODE_INT << XTAL_MODE_SHIFT) | trim); + + return dev; +} + + +static void set_channel(usb_dev_handle *dev, int channel) +{ + atspi_reg_write(dev, REG_PHY_CC_CCA, (1 << CCA_MODE_SHIFT) | channel); +} + + +static void set_power(usb_dev_handle *dev, double power) +{ + int n; + + for (n = 0; n != sizeof(tx_pwr)/sizeof(*tx_pwr); n++) + if (tx_pwr[n] <= power) + break; + atspi_reg_write(dev, REG_PHY_TX_PWR, TX_AUTO_CRC_ON | n); +} + + +static void receive(usb_dev_handle *dev) +{ + uint8_t irq; + uint8_t buf[MAX_PSDU+1]; /* PSDU+LQ */ + int n, ok, i; + uint8_t lq; + + atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_RX_ON); + + (void) atspi_reg_read(dev, REG_IRQ_STATUS); + + fprintf(stderr, "Ready.\n"); + while (1) { + irq = atspi_reg_read(dev, REG_IRQ_STATUS); + if (atspi_error()) + exit(1); + if (!irq) + continue; + if (irq == IRQ_TRX_END) + break; + fprintf(stderr, "IRQ (0x%02x):", irq); + if (irq & IRQ_PLL_LOCK) + fprintf(stderr, " PLL_LOCK"); + if (irq & IRQ_PLL_UNLOCK) + fprintf(stderr, " PLL_UNLOCK"); + if (irq & IRQ_RX_START) + fprintf(stderr, " RX_START"); + if (irq & IRQ_TRX_UR) + fprintf(stderr, " TRX_UR"); + if (irq & IRQ_BAT_LOW) + fprintf(stderr, " BAT_LOW"); + fprintf(stderr, "\n"); + if (irq & IRQ_TRX_END) + break; + } + + n = atspi_buf_read(dev, buf, sizeof(buf)); + if (n < 0) + exit(1); + if (n < 3) { + fprintf(stderr, "%d bytes received\n", n); + exit(1); + } + ok = !!(atspi_reg_read(dev, REG_PHY_RSSI) & RX_CRC_VALID); + lq = buf[n-1]; + fprintf(stderr, "%d bytes payload, CRC %s, LQ %u\n", + n-3, ok ? "OK" : "BAD", lq); + for (i = 0; i != n-3; i++) + putchar(buf[i] < ' ' || buf[i] > '~' ? '?' : buf[i]); + putchar('\n'); +} + + +static void transmit(usb_dev_handle *dev, const char *msg) +{ + uint8_t buf[MAX_PSDU]; + + atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_PLL_ON); + + /* + * We need to copy the message to append the CRC placeholders. + */ + strcpy((void *) buf, msg); + atspi_buf_write(dev, buf, strlen(msg)+2); + + /* @@@ should wait for clear channel */ + atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_TX_START); + /* @@@ should wait for TX done */ +} static void usage(const char *name) { - fprintf(stderr, "%s\n", name); + fprintf(stderr, +"usage: %s [-c channel] [-p power] [-t trim] [message]\n" +" -c channel channel number, 11 to 26 (default %d)\n" +" -p power transmit power, -17.2 to 3.0 dBm (default %.1f)\n" +" -t trim trim capacitor, 0 to 15 (default 0)\n" + , name , DEFAULT_CHANNEL, DEFAULT_POWER); exit(1); } -int main(int argc, const char **argv) +int main(int argc, char *const *argv) { + int channel = DEFAULT_CHANNEL; + double power = DEFAULT_POWER; + int trim = 0; + char *end; + int c; usb_dev_handle *dev; - if (argc != 1) - usage(*argv); - dev = atspi_open(); - if (!dev) - return 1; + while ((c = getopt(argc, argv, "c:p:t:")) != EOF) + switch (c) { + case 'c': + channel = strtoul(optarg, &end, 0); + if (*end) + usage(*argv); + if (channel < 11 || channel > 26) + usage(*argv); + break; + case 'p': + power = strtod(optarg, &end); + if (*end) + usage(*argv); + break; + case 't': + trim = strtoul(optarg, &end, 0); + if (*end) + usage(*argv); + if (trim > 15) + usage(*argv); + break; + default: + usage(*argv); + } - atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_TRX_OFF); - sleep(1000); + switch (argc-optind) { + case 0: + dev = init_txrx(trim); + set_channel(dev, channel); + receive(dev); + break; + case 1: + dev = init_txrx(trim); + set_channel(dev, channel); + set_power(dev, power); + transmit(dev, argv[optind]); + break; + default: + usage(*argv); + } return 0; } diff --git a/atrf/tools/include/atspi.h b/atrf/tools/include/atspi.h index f7a6477..a1fdadd 100644 --- a/atrf/tools/include/atspi.h +++ b/atrf/tools/include/atspi.h @@ -29,4 +29,7 @@ void atspi_reset_rf(usb_dev_handle *dev); void atspi_reg_write(usb_dev_handle *dev, uint8_t reg, uint8_t value); uint8_t atspi_reg_read(usb_dev_handle *dev, uint8_t reg); +void atspi_buf_write(usb_dev_handle *dev, const void *buf, int size); +int atspi_buf_read(usb_dev_handle *dev, void *buf, int size); + #endif /* !ATSPI_H */ diff --git a/atrf/tools/lib/atspi.c b/atrf/tools/lib/atspi.c index 42b27d5..1b3a0de 100644 --- a/atrf/tools/lib/atspi.c +++ b/atrf/tools/lib/atspi.c @@ -141,3 +141,41 @@ uint8_t atspi_reg_read(usb_dev_handle *dev, uint8_t reg) } return value; } + + +/* ----- frame buffer access ----------------------------------------------- */ + + +void atspi_buf_write(usb_dev_handle *dev, const void *buf, int size) +{ + int res; + + if (error) + return; + + res = usb_control_msg(dev, TO_DEV, ATSPI_BUF_WRITE, 0, 0, + (void *) buf, size, 1000); + if (res < 0) { + fprintf(stderr, "ATSPI_BUF_WRITE: %d\n", res); + error = 1; + } + +} + + +int atspi_buf_read(usb_dev_handle *dev, void *buf, int size) +{ + int res; + + if (error) + return -1; + + res = usb_control_msg(dev, FROM_DEV, ATSPI_BUF_READ, 0, 0, + buf, size, 1000); + if (res < 0) { + fprintf(stderr, "ATSPI_BUF_READ: %d\n", res); + error = 1; + } + + return res; +}