diff --git a/fw/atspi/at86rf230.h b/fw/atspi/at86rf230.h new file mode 100644 index 0000000..e0f2701 --- /dev/null +++ b/fw/atspi/at86rf230.h @@ -0,0 +1,29 @@ +/* + * atspi/at86rf230.h - AT86RF230 protocol and register definitions + * + * 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 + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + */ + + +#ifndef AT86RF230_H +#define AT86RF230_H + +enum at86rf230_spi_cmd { + AT86RF230_REG_WRITE = 0xc0, /* 11... */ + AT86RF230_REG_READ = 0x80, /* 10... */ + AT86RF230_BUF_WRITE = 0x60, /* 011... */ + AT86RF230_BUF_READ = 0x20, /* 001... */ + AT86RF230_SRAM_WRITE = 0x40, /* 010... */ + AT86RF230_SRAM_READ = 0x00 /* 000... */ +}; + +#define MAX_PSDU 127 /* octets, see AT86RF230 manual section 8.1 */ +#define SRAM_SIZE 128 + +#endif /* !AT86RF230_H */ diff --git a/fw/atspi/atspi.c b/fw/atspi/atspi.c index 69ae16d..7c57e9d 100644 --- a/fw/atspi/atspi.c +++ b/fw/atspi/atspi.c @@ -18,8 +18,48 @@ #include "version.h" +static void init_io(void) +{ + /* + * Signal Mode Value + * + * MOSI push-pull 0 + * MISO open drain 1 (input) + * SCLK push-pull 1 + * nSS push-pull 1 + * nRST_RF push-pull 1 + * IRQ_RF open drain 1 (input) + * SLP_TR push-pull 0 + * + * LED push-pull 0 (set up by boot loader) + * + * all unused open drain 0 + */ + + MOSI = 0; + MOSI_MODE = 1; + + SCLK = 0; + SCLK_MODE = 1; + + nSS_MODE = 1; + + nRST_RF_MODE = 1; + + SLP_TR = 0; + SLP_TR_MODE = 1; + + P0 &= + ~((1 << 0) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7)); + P3 = 0; + +} + + void main(void) { + init_io(); + usb_init(); ep0_init(); diff --git a/fw/atspi/ep0.c b/fw/atspi/ep0.c index 911509a..f9f311e 100644 --- a/fw/atspi/ep0.c +++ b/fw/atspi/ep0.c @@ -21,6 +21,7 @@ //#include "uart.h" #include "usb.h" #include "atspi/ep0.h" +#include "at86rf230.h" #include "version.h" @@ -29,11 +30,52 @@ static const uint8_t id[] = { EP0ATSPI_MAJOR, EP0ATSPI_MINOR, HW_TYPE }; +static __xdata uint8_t buf[MAX_PSDU+3]; /* command, PHDR, and LQ */ +static uint8_t size; + + +static void spi_send(uint8_t v) +{ + uint8_t mask; + + for (mask = 0x80; mask; mask >>= 1) { + MOSI = !!(v & mask); + SCLK = 1; + SCLK = 0; + } +} + + +static uint8_t spi_recv(void) +{ + uint8_t res = 0; + uint8_t i; + + for (i = 0; i != 8; i++) { + res = (res << 1) | MISO; + SCLK = 1; + SCLK = 0; + } + return res; +} + + +static void do_buf_write(void *user) +{ + uint8_t i; + + user; /* suppress warning */ + nSS = 0; + spi_send(AT86RF230_BUF_WRITE); + for (i = 0; i != size; i++) + spi_send(buf[i]); + nSS = 1; +} static __bit my_setup(struct setup_request *setup) __reentrant { - uint8_t size; + uint8_t i; switch (setup->bmRequestType | setup->bRequest << 8) { case ATSPI_FROM_DEV(ATSPI_ID): @@ -63,6 +105,82 @@ static __bit my_setup(struct setup_request *setup) __reentrant RSTSRC = SWRSF; while (1); + case ATSPI_TO_DEV(ATSPI_RF_RESET): + debug("ATSPI_RF_RESET\n"); + nRST_RF = 0; + /* 11.4.12 min 625 ns */ + nRST_RF = 1; + return 1; + + case ATSPI_TO_DEV(ATSPI_REG_WRITE): + debug("ATSPI_REG_WRITE\n"); + nSS = 0; + spi_send(AT86RF230_REG_WRITE | setup->wIndex); + spi_send(setup->wValue); + nSS = 1; + return 1; + case ATSPI_FROM_DEV(ATSPI_REG_READ): + debug("ATSPI_REG_READ\n"); + nSS = 0; + spi_send(AT86RF230_REG_READ | setup->wIndex); + *buf = spi_recv(); + nSS = 1; + usb_send(&ep0, buf, 1, NULL, NULL); + return 1; + + case ATSPI_TO_DEV(ATSPI_BUF_WRITE): + debug("ATSPI_BUF_WRITE\n"); + if (setup->wLength < 1) + return 0; + if (setup->wLength > MAX_PSDU+1) /* PHR+PSDU */ + return 0; + buf[0] = AT86RF230_BUF_WRITE; + size = setup->wLength+1; + usb_recv(&ep0, buf+1, setup->wLength, do_buf_write, NULL); + return 1; + case ATSPI_TO_DEV(ATSPI_BUF_READ): + debug("ATSPI_BUF_READ\n"); + if (setup->wLength < 2) /* PHR+LQ */ + return 0; + if (setup->wLength > MAX_PSDU+2) /* PHR+PSDU+LQ */ + return 0; + nSS = 0; + spi_send(AT86RF230_BUF_READ); + size = *buf = spi_recv(); + if (size+2 > setup->wLength) + size = setup->wLength-2; + for (i = 0; i != size+1; i++) + buf[i+1] = spi_recv(); + nSS = 1; + usb_send(&ep0, buf, size+1, NULL, NULL); + return 1; + + case ATSPI_TO_DEV(ATSPI_SRAM_WRITE): + debug("ATSPI_SRAM_WRITE\n"); + if (setup->wIndex > SRAM_SIZE) + return 0; + if (setup->wIndex+setup->wLength > SRAM_SIZE) + return 0; + buf[0] = AT86RF230_SRAM_WRITE; + buf[1] = setup->wIndex; + size = setup->wLength+2; + usb_recv(&ep0, buf+2, setup->wLength, do_buf_write, NULL); + return 1; + case ATSPI_TO_DEV(ATSPI_SRAM_READ): + debug("ATSPI_SRAM_READ\n"); + if (setup->wIndex > SRAM_SIZE) + return 0; + if (setup->wIndex+setup->wLength > SRAM_SIZE) + return 0; + nSS = 0; + spi_send(AT86RF230_SRAM_READ); + spi_send(setup->wIndex); + for (i = 0; i != size; i++) + buf[i] = spi_recv(); + nSS = 1; + usb_send(&ep0, buf, size, NULL, NULL); + return 1; + default: error("Unrecognized SETUP: 0x%02x 0x%02x ...\n", setup->bmRequestType, setup->bRequest); diff --git a/fw/include/atspi/ep0.h b/fw/include/atspi/ep0.h index 1320cf9..a23d619 100644 --- a/fw/include/atspi/ep0.h +++ b/fw/include/atspi/ep0.h @@ -17,10 +17,19 @@ /* * Direction bRequest wValue wIndex wLength * - * ->host ATSPI_ID 0 0 3 - * host-> ATSPI_RESET 0 0 0 + * ->host ATSPI_ID - - 3 + * host-> ATSPI_RESET - - 0 * ->host ATSPI_BUILD_NUMBER - - 2 * ->host ATSPI_BUILD_DATE - - #bytes + * + * host-> ATSPI_RF_RESET - - + * + * host-> ATSPI_REG_WRITE value addr 0 + * ->host ATSPI_REG_READ - addr 1 + * host-> ATSPI_BUF_WRITE - - #bytes + * ->host ATSPI_BUF_READ - - #bytes + * host-> ATSPI_SRAM_WRITE - addr #bytes + * ->host ATSPI_SRAM_READ - addr #bytes */ /* @@ -55,6 +64,13 @@ enum atspi_requests { ATSPI_RESET, ATSPI_BUILD_NUMBER, ATSPI_BUILD_DATE, + ATSPI_RF_RESET = 0x10, + ATSPI_REG_WRITE = 0x20, + ATSPI_REG_READ, + ATSPI_BUF_WRITE, + ATSPI_BUF_READ, + ATSPI_SRAM_WRITE, + ATSPI_SRAM_READ, };