atrf/fw/atspi/atspi.c |
| 1 | /* |
| 2 | * atspi/atspi.c - ATSPI initialization and main loop |
| 3 | * |
| 4 | * Written 2008-2010 by Werner Almesberger |
| 5 | * Copyright 2008-2010 Werner Almesberger |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by |
| 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | * (at your option) any later version. |
| 11 | */ |
| 12 | |
| 13 | |
| 14 | #include "regs.h" |
| 15 | #include "io.h" |
| 16 | #include "usb.h" |
| 17 | #include "atspi/ep0.h" |
| 18 | #include "version.h" |
| 19 | |
| 20 | |
| 21 | void reset_rf(void) |
| 22 | { |
| 23 | int i; |
| 24 | |
| 25 | nRST_RF = 0; |
| 26 | /* |
| 27 | * 11.4.12: min 625 ns. |
| 28 | * The pulse we generate is slightly longer than 4 us. |
| 29 | */ |
| 30 | for (i = 0; i != 10; i++); |
| 31 | nRST_RF = 1; |
| 32 | } |
| 33 | |
| 34 | |
| 35 | static void init_io(void) |
| 36 | { |
| 37 | /* |
| 38 | * Signal Mode Value |
| 39 | * |
| 40 | * MOSI push-pull 0 |
| 41 | * MISO open drain 1 (input) |
| 42 | * SCLK push-pull 0 |
| 43 | * nSS push-pull 1 |
| 44 | * nRST_RF push-pull 1 |
| 45 | * IRQ_RF open drain 1 (input) |
| 46 | * SLP_TR push-pull 0 |
| 47 | * |
| 48 | * LED push-pull 0 (set up by boot loader) |
| 49 | * |
| 50 | * all unused open drain 0 |
| 51 | */ |
| 52 | |
| 53 | MOSI = 0; |
| 54 | MOSI_MODE |= 1 << MOSI_BIT; |
| 55 | |
| 56 | SCLK = 0; |
| 57 | SCLK_MODE |= 1 << SCLK_BIT; |
| 58 | |
| 59 | nSS_MODE |= 1 << nSS_BIT; |
| 60 | |
| 61 | nRST_RF_MODE |= 1 << nRST_RF_BIT; |
| 62 | |
| 63 | SLP_TR = 0; |
| 64 | SLP_TR_MODE |= 1 << SLP_TR_BIT; |
| 65 | |
| 66 | P0 &= |
| 67 | ~((1 << 0) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7)); |
| 68 | /* change 1 << 0 to 1 << 2 once 100813 boards are reworked */ |
| 69 | P3 = 0; |
| 70 | |
| 71 | #if 0 |
| 72 | /* |
| 73 | * We can *almost* disable the pull-ups. The only obstacle is that |
| 74 | * MISO is not driven when not in use. So we either need an external |
| 75 | * pull-up/down or keep all the pull-ups on. |
| 76 | */ |
| 77 | |
| 78 | /* |
| 79 | * Disable pull-ups |
| 80 | */ |
| 81 | GPIOCN |= WEAKPUD; |
| 82 | #endif |
| 83 | |
| 84 | /* |
| 85 | * The manual says the reset is optional, but reality disagrees with |
| 86 | * this optimistic assessment quite violently. |
| 87 | */ |
| 88 | |
| 89 | reset_rf(); |
| 90 | } |
| 91 | |
| 92 | |
| 93 | void main(void) |
| 94 | { |
| 95 | init_io(); |
| 96 | |
| 97 | usb_init(); |
| 98 | ep0_init(); |
| 99 | |
| 100 | while (1) { |
| 101 | usb_poll(); |
| 102 | } |
| 103 | } |
atrf/fw/atspi/descr.c |
| 1 | /* |
| 2 | * atspi/descr.c - USB descriptors |
| 3 | * |
| 4 | * Written 2008-2010 by Werner Almesberger |
| 5 | * Copyright 2008-2010 Werner Almesberger |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by |
| 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | * (at your option) any later version. |
| 11 | */ |
| 12 | |
| 13 | |
| 14 | #include "usb.h" |
| 15 | |
| 16 | #include "config.h" |
| 17 | |
| 18 | |
| 19 | /* |
| 20 | * Device descriptor |
| 21 | */ |
| 22 | |
| 23 | const uint8_t device_descriptor[18] = { |
| 24 | 18, /* bLength */ |
| 25 | USB_DT_DEVICE, /* bDescriptorType */ |
| 26 | LE(0x200), /* bcdUSB */ |
| 27 | USB_CLASS_VENDOR_SPEC, /* bDeviceClass */ |
| 28 | 0x00, /* bDeviceSubClass */ |
| 29 | 0x00, /* bDeviceProtocol */ |
| 30 | EP0_SIZE, /* bMaxPacketSize */ |
| 31 | LE(USB_VENDOR), /* idVendor */ |
| 32 | LE(USB_PRODUCT), /* idProduct */ |
| 33 | LE(0x0001), /* bcdDevice */ |
| 34 | 0, /* iManufacturer */ |
| 35 | 0, /* iProduct */ |
| 36 | 0, /* iSerialNumber */ |
| 37 | 1 /* bNumConfigurations */ |
| 38 | }; |
| 39 | |
| 40 | |
| 41 | /* |
| 42 | * Our configuration |
| 43 | * |
| 44 | * While in DFU mode, we're always bus-powered. |
| 45 | */ |
| 46 | |
| 47 | const uint8_t config_descriptor[] = { |
| 48 | 9, /* bLength */ |
| 49 | USB_DT_CONFIG, /* bDescriptorType */ |
| 50 | LE(9+9+7+7), /* wTotalLength */ |
| 51 | 1, /* bNumInterfaces */ |
| 52 | 1, /* bConfigurationValue (> 0 !) */ |
| 53 | 0, /* iConfiguration */ |
| 54 | // USB_ATTR_SELF_POWERED | USB_ATTR_BUS_POWERED, |
| 55 | USB_ATTR_BUS_POWERED, /* bmAttributes */ |
| 56 | 15, /* bMaxPower */ |
| 57 | |
| 58 | /* Interface #0 */ |
| 59 | |
| 60 | 9, /* bLength */ |
| 61 | USB_DT_INTERFACE, /* bDescriptorType */ |
| 62 | 0, /* bInterfaceNumber */ |
| 63 | 0, /* bAlternateSetting */ |
| 64 | 2, /* bNumEndpoints */ |
| 65 | USB_CLASS_VENDOR_SPEC, /* bInterfaceClass */ |
| 66 | 0, /* bInterfaceSubClass */ |
| 67 | 0, /* bInterfaceProtocol */ |
| 68 | 0, /* iInterface */ |
| 69 | |
| 70 | /* EP OUT */ |
| 71 | |
| 72 | 7, /* bLength */ |
| 73 | USB_DT_ENDPOINT, /* bDescriptorType */ |
| 74 | 0x01, /* bEndPointAddress */ |
| 75 | 0x02, /* bmAttributes (bulk) */ |
| 76 | LE(EP1_SIZE), /* wMaxPacketSize */ |
| 77 | 0, /* bInterval */ |
| 78 | |
| 79 | /* EP IN */ |
| 80 | |
| 81 | 7, /* bLength */ |
| 82 | USB_DT_ENDPOINT, /* bDescriptorType */ |
| 83 | 0x81, /* bEndPointAddress */ |
| 84 | 0x02, /* bmAttributes (bulk) */ |
| 85 | LE(EP1_SIZE), /* wMaxPacketSize */ |
| 86 | 0, /* bInterval */ |
| 87 | |
| 88 | }; |
atrf/fw/atspi/ep0.c |
| 1 | /* |
| 2 | * atspi/ep0.c - EP0 extension protocol |
| 3 | * |
| 4 | * Written 2008-2010 by Werner Almesberger |
| 5 | * Copyright 2008-2010 Werner Almesberger |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by |
| 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | * (at your option) any later version. |
| 11 | */ |
| 12 | |
| 13 | |
| 14 | #include <stdint.h> |
| 15 | |
| 16 | #ifndef NULL |
| 17 | #define NULL 0 |
| 18 | #endif |
| 19 | |
| 20 | #include "regs.h" |
| 21 | //#include "uart.h" |
| 22 | #include "usb.h" |
| 23 | #include "atspi/ep0.h" |
| 24 | #include "at86rf230.h" |
| 25 | #include "version.h" |
| 26 | |
| 27 | |
| 28 | extern void reset_rf(void); |
| 29 | |
| 30 | |
| 31 | #define debug(...) |
| 32 | #define error(...) |
| 33 | |
| 34 | |
| 35 | /* |
| 36 | * SDCC 2.8.0 had a number of code generation bugs that appeared in the big |
| 37 | * switch statement of my_setup. SDCC_FORCE_UPDATE forced the value of the |
| 38 | * "size" variable to be written to memory. This work-around doesn't seem |
| 39 | * to be necessary with 2.9.0, but we keep it around, just in case. |
| 40 | * |
| 41 | * Unfortunately, the setup->bRequest garbling bug is still with us. Without |
| 42 | * the evaluation forced with SDCC_FORCE_EVAL, sdcc gets confused about the |
| 43 | * value of setup->bRequest and then rejects all SETUP requests. |
| 44 | */ |
| 45 | |
| 46 | #define SDCC_FORCE_EVAL(type, value) \ |
| 47 | do { \ |
| 48 | static volatile type foo; \ |
| 49 | foo = value; \ |
| 50 | } while (0) |
| 51 | |
| 52 | #define SDCC_FORCE_UPDATE(type, var) \ |
| 53 | do { \ |
| 54 | volatile type foo; \ |
| 55 | foo = var; \ |
| 56 | var = foo; \ |
| 57 | } while (0) |
| 58 | |
| 59 | |
| 60 | static const uint8_t id[] = { EP0ATSPI_MAJOR, EP0ATSPI_MINOR, HW_TYPE }; |
| 61 | static __xdata uint8_t buf[MAX_PSDU+3]; /* command, PHDR, and LQ */ |
| 62 | static uint8_t size; |
| 63 | |
| 64 | |
| 65 | static void spi_send(uint8_t v) |
| 66 | { |
| 67 | uint8_t mask; |
| 68 | |
| 69 | for (mask = 0x80; mask; mask >>= 1) { |
| 70 | MOSI = !!(v & mask); |
| 71 | SCLK = 1; |
| 72 | SCLK = 0; |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | |
| 77 | static uint8_t spi_recv(void) |
| 78 | { |
| 79 | uint8_t res = 0; |
| 80 | uint8_t i; |
| 81 | |
| 82 | for (i = 0; i != 8; i++) { |
| 83 | res = (res << 1) | MISO; |
| 84 | SCLK = 1; |
| 85 | SCLK = 0; |
| 86 | } |
| 87 | return res; |
| 88 | } |
| 89 | |
| 90 | |
| 91 | static void do_buf_write(void *user) |
| 92 | { |
| 93 | uint8_t i; |
| 94 | |
| 95 | user; /* suppress warning */ |
| 96 | nSS = 0; |
| 97 | spi_send(AT86RF230_BUF_WRITE); |
| 98 | for (i = 0; i != size; i++) |
| 99 | spi_send(buf[i]); |
| 100 | nSS = 1; |
| 101 | } |
| 102 | |
| 103 | |
| 104 | #define BUILD_OFFSET 7 /* '#' plus "65535" plus ' ' */ |
| 105 | |
| 106 | |
| 107 | static __bit my_setup(struct setup_request *setup) __reentrant |
| 108 | { |
| 109 | unsigned tmp; |
| 110 | uint8_t i; |
| 111 | |
| 112 | switch (setup->bmRequestType | setup->bRequest << 8) { |
| 113 | case ATSPI_FROM_DEV(ATSPI_ID): |
| 114 | debug("ATSPI_ID\n"); |
| 115 | if (setup->wLength > 3) |
| 116 | return 0; |
| 117 | usb_send(&ep0, id, setup->wLength, NULL, NULL); |
| 118 | return 1; |
| 119 | case ATSPI_FROM_DEV(ATSPI_BUILD): |
| 120 | debug("ATSPI_BUILD\n"); |
| 121 | tmp = build_number; |
| 122 | for (i = BUILD_OFFSET-2; tmp; i--) { |
| 123 | buf[i] = (tmp % 10)+'0'; |
| 124 | tmp /= 10; |
| 125 | } |
| 126 | buf[i] = '#'; |
| 127 | buf[BUILD_OFFSET-1] = ' '; |
| 128 | for (size = 0; build_date[size]; size++) |
| 129 | buf[BUILD_OFFSET+size] = build_date[size]; |
| 130 | size += BUILD_OFFSET-i+1; |
| 131 | SDCC_FORCE_EVAL(uint8_t, setup->bRequest); |
| 132 | if (size > setup->wLength) |
| 133 | return 0; |
| 134 | usb_send(&ep0, buf+i, size, NULL, NULL); |
| 135 | return 1; |
| 136 | |
| 137 | case ATSPI_TO_DEV(ATSPI_RESET): |
| 138 | debug("ATSPI_RESET\n"); |
| 139 | RSTSRC = SWRSF; |
| 140 | while (1); |
| 141 | |
| 142 | case ATSPI_TO_DEV(ATSPI_RF_RESET): |
| 143 | debug("ATSPI_RF_RESET\n"); |
| 144 | reset_rf(); |
| 145 | return 1; |
| 146 | |
| 147 | case ATSPI_TO_DEV(ATSPI_REG_WRITE): |
| 148 | debug("ATSPI_REG_WRITE\n"); |
| 149 | nSS = 0; |
| 150 | spi_send(AT86RF230_REG_WRITE | setup->wIndex); |
| 151 | spi_send(setup->wValue); |
| 152 | nSS = 1; |
| 153 | return 1; |
| 154 | case ATSPI_FROM_DEV(ATSPI_REG_READ): |
| 155 | debug("ATSPI_REG_READ\n"); |
| 156 | nSS = 0; |
| 157 | spi_send(AT86RF230_REG_READ | setup->wIndex); |
| 158 | *buf = spi_recv(); |
| 159 | nSS = 1; |
| 160 | usb_send(&ep0, buf, 1, NULL, NULL); |
| 161 | return 1; |
| 162 | |
| 163 | case ATSPI_TO_DEV(ATSPI_BUF_WRITE): |
| 164 | debug("ATSPI_BUF_WRITE\n"); |
| 165 | if (setup->wLength < 1) |
| 166 | return 0; |
| 167 | if (setup->wLength > MAX_PSDU+1) /* PHR+PSDU */ |
| 168 | return 0; |
| 169 | buf[0] = AT86RF230_BUF_WRITE; |
| 170 | size = setup->wLength+1; |
| 171 | usb_recv(&ep0, buf+1, setup->wLength, do_buf_write, NULL); |
| 172 | return 1; |
| 173 | case ATSPI_TO_DEV(ATSPI_BUF_READ): |
| 174 | debug("ATSPI_BUF_READ\n"); |
| 175 | if (setup->wLength < 2) /* PHR+LQ */ |
| 176 | return 0; |
| 177 | if (setup->wLength > MAX_PSDU+2) /* PHR+PSDU+LQ */ |
| 178 | return 0; |
| 179 | nSS = 0; |
| 180 | spi_send(AT86RF230_BUF_READ); |
| 181 | size = *buf = spi_recv(); |
| 182 | if (size+2 > setup->wLength) |
| 183 | size = setup->wLength-2; |
| 184 | for (i = 0; i != size+1; i++) |
| 185 | buf[i+1] = spi_recv(); |
| 186 | nSS = 1; |
| 187 | usb_send(&ep0, buf, size+1, NULL, NULL); |
| 188 | return 1; |
| 189 | |
| 190 | case ATSPI_TO_DEV(ATSPI_SRAM_WRITE): |
| 191 | debug("ATSPI_SRAM_WRITE\n"); |
| 192 | if (setup->wIndex > SRAM_SIZE) |
| 193 | return 0; |
| 194 | if (setup->wIndex+setup->wLength > SRAM_SIZE) |
| 195 | return 0; |
| 196 | buf[0] = AT86RF230_SRAM_WRITE; |
| 197 | buf[1] = setup->wIndex; |
| 198 | size = setup->wLength+2; |
| 199 | usb_recv(&ep0, buf+2, setup->wLength, do_buf_write, NULL); |
| 200 | return 1; |
| 201 | case ATSPI_TO_DEV(ATSPI_SRAM_READ): |
| 202 | debug("ATSPI_SRAM_READ\n"); |
| 203 | if (setup->wIndex > SRAM_SIZE) |
| 204 | return 0; |
| 205 | if (setup->wIndex+setup->wLength > SRAM_SIZE) |
| 206 | return 0; |
| 207 | nSS = 0; |
| 208 | spi_send(AT86RF230_SRAM_READ); |
| 209 | spi_send(setup->wIndex); |
| 210 | for (i = 0; i != size; i++) |
| 211 | buf[i] = spi_recv(); |
| 212 | nSS = 1; |
| 213 | usb_send(&ep0, buf, size, NULL, NULL); |
| 214 | return 1; |
| 215 | |
| 216 | default: |
| 217 | error("Unrecognized SETUP: 0x%02x 0x%02x ...\n", |
| 218 | setup->bmRequestType, setup->bRequest); |
| 219 | return 0; |
| 220 | } |
| 221 | } |
| 222 | |
| 223 | |
| 224 | void ep0_init(void) |
| 225 | { |
| 226 | user_setup = my_setup; |
| 227 | } |
atrf/fw/common/Makefile |
| 1 | # |
| 2 | # common/Makefile - Makefile for shared items |
| 3 | # |
| 4 | # Written 2008, 2010 by Werner Almesberger |
| 5 | # Copyright 2008, 2010 Werner Almesberger |
| 6 | # |
| 7 | # This program is free software; you can redistribute it and/or modify |
| 8 | # it under the terms of the GNU General Public License as published by |
| 9 | # the Free Software Foundation; either version 2 of the License, or |
| 10 | # (at your option) any later version. |
| 11 | # |
| 12 | |
| 13 | |
| 14 | GEN_quiet = @echo " GENERATE " $@ && |
| 15 | |
| 16 | ifeq ($(V),1) |
| 17 | GEN = |
| 18 | else |
| 19 | GEN = $(GEN_quiet) |
| 20 | endif |
| 21 | |
| 22 | |
| 23 | .PHONY: all depend clean spotless |
| 24 | |
| 25 | all: io-parts.h |
| 26 | |
| 27 | io-parts.h: io.h Makefile |
| 28 | $(GEN) $(CPP) -dD $< | \ |
| 29 | sed '1,/IO_H/d' | \ |
| 30 | awk \ |
| 31 | 'BEGIN { print "/* MACHINE-GENERATED. DO NOT EDIT ! */"; \ |
| 32 | print "#ifndef IO_PARTS_H"; \ |
| 33 | print "#define IO_PARTS_H"; } \ |
| 34 | /#define/ && $$3 != "" { \ |
| 35 | split($$3, a, "_"); \ |
| 36 | print $$1, $$2 "_PORT", a[1]; \ |
| 37 | print $$1, $$2 "_MODE", a[1] "MDOUT"; \ |
| 38 | print $$1, $$2 "_BIT", a[2]; } \ |
| 39 | END { print "#endif" }' >$@ || \ |
| 40 | { rm -f $@; exit 1; } |
| 41 | |
| 42 | |
| 43 | # |
| 44 | # When we do a global "make depend", we'll come here first. So we create |
| 45 | # io-parts.h so that "make depend" in the other directories can pick it up. |
| 46 | # |
| 47 | |
| 48 | depend: io-parts.h |
| 49 | |
| 50 | clean: |
| 51 | rm -f io-parts.h |
| 52 | |
| 53 | spotless: clean |
atrf/fw/include/at86rf230.h |
| 1 | /* |
| 2 | * include/at86rf230.h - AT86RF230 protocol and register definitions |
| 3 | * |
| 4 | * Written 2008-2010 by Werner Almesberger |
| 5 | * Copyright 2008-2010 Werner Almesberger |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by |
| 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | * (at your option) any later version. |
| 11 | */ |
| 12 | |
| 13 | |
| 14 | #ifndef AT86RF230_H |
| 15 | #define AT86RF230_H |
| 16 | |
| 17 | enum { |
| 18 | AT86RF230_REG_WRITE = 0xc0, /* 11... */ |
| 19 | AT86RF230_REG_READ = 0x80, /* 10... */ |
| 20 | AT86RF230_BUF_WRITE = 0x60, /* 011... */ |
| 21 | AT86RF230_BUF_READ = 0x20, /* 001... */ |
| 22 | AT86RF230_SRAM_WRITE = 0x40, /* 010... */ |
| 23 | AT86RF230_SRAM_READ = 0x00 /* 000... */ |
| 24 | }; |
| 25 | |
| 26 | #define MAX_PSDU 127 /* octets, see AT86RF230 manual section 8.1 */ |
| 27 | #define SRAM_SIZE 128 |
| 28 | |
| 29 | |
| 30 | /* --- Registers ----------------------------------------------------------- */ |
| 31 | |
| 32 | enum { |
| 33 | REG_TRX_STATUS = 0x01, |
| 34 | REG_TRX_STATE = 0x02, |
| 35 | REG_TRX_CTRL_0 = 0x03, |
| 36 | |
| 37 | REG_TR_PWR = 0x05, |
| 38 | REG_PHY_RSSI = 0x06, |
| 39 | REG_PHY_ED_LEVEL = 0x07, |
| 40 | REG_PHY_CC_CCA = 0x08, |
| 41 | REG_CCA_THRES = 0x09, |
| 42 | |
| 43 | REG_IRQ_MASK = 0x0e, |
| 44 | REG_IRQ_STATUS = 0x0f, |
| 45 | REG_VREG_CTRL = 0x10, |
| 46 | REG_BATMON = 0x10, |
| 47 | REG_XOSC_CTRL = 0x12, |
| 48 | |
| 49 | REG_PLL_CF = 0x1a, |
| 50 | REL_PLL_DCU = 0x1b, |
| 51 | REG_PART_NUM = 0x1c, |
| 52 | REG_VERSION_NUM = 0x1d, |
| 53 | REG_MAN_ID_0 = 0x1e, |
| 54 | REG_MAN_ID_1 = 0x1f, |
| 55 | REG_SHORT_ADDR_0 = 0x20, |
| 56 | REG_SHORT_ADDR_1 = 0x21, |
| 57 | REG_PAN_ID_0 = 0x22, |
| 58 | REG_PAN_ID_1 = 0x23, |
| 59 | REG_IEEE_ADDR_0 = 0x24, |
| 60 | REG_IEEE_ADDR_1 = 0x25, |
| 61 | REG_IEEE_ADDR_2 = 0x26, |
| 62 | REG_IEEE_ADDR_3 = 0x27, |
| 63 | REG_IEEE_ADDR_4 = 0x28, |
| 64 | REG_IEEE_ADDR_5 = 0x29, |
| 65 | REG_IEEE_ADDR_6 = 0x2a, |
| 66 | REG_IEEE_ADDR_7 = 0x2b, |
| 67 | REG_XAH_CTRL = 0x2c, |
| 68 | REG_CSMA_SEED_0 = 0x2d, |
| 69 | REG_CSMA_SEED_1 = 0x2e, |
| 70 | }; |
| 71 | |
| 72 | /* --- TRX_STATUS [7] ------------------------------------------------------ */ |
| 73 | |
| 74 | #define CCA_DONE (1 << 7) |
| 75 | |
| 76 | /* --- TRX_STATUS [6] ------------------------------------------------------ */ |
| 77 | |
| 78 | #define CCA_STATUS (1 << 6) |
| 79 | |
| 80 | /* --- TRX_STATUS [4:0] ---------------------------------------------------- */ |
| 81 | |
| 82 | #define TRX_STATUS_SHIFT 0 |
| 83 | #define TRX_STATUS_MASK 0x0f |
| 84 | |
| 85 | enum { |
| 86 | TRX_STATUS_P_ON = 0x00, /* reset default */ |
| 87 | TRX_STATUS_BUSY_RX = 0x01, |
| 88 | TRX_STATUS_BUSY_TX = 0x02, |
| 89 | TRX_STATUS_RX_ON = 0x06, |
| 90 | TRX_STATUS_TRX_OFF = 0x08, |
| 91 | TRX_STATUS_PLL_ON = 0x09, |
| 92 | TRX_STATUS_SLEEP = 0x0f, |
| 93 | TRX_STATUS_BUSY_RX_AACK = 0x11, |
| 94 | TRX_STATUS_BUSY_TX_ARET = 0x12, |
| 95 | TRX_STATUS_RX_AACK_ON = 0x16, |
| 96 | TRX_STATUS_TX_ARET_ON = 0x19, |
| 97 | TRX_STATUS_RX_ON_NOCLK = 0x1c, |
| 98 | TRX_STATUS_RX_AACK_ON_NOCLK = 0x1d, |
| 99 | TRX_STATUS_BUSY_RX_AACK_NOCLK = 0x1e, |
| 100 | TRX_STATUS_TRANSITION = 0x1f |
| 101 | }; |
| 102 | |
| 103 | /* --- TRX_STATE [7:5] ----------------------------------------------------- */ |
| 104 | |
| 105 | #define TRAC_STATUS_SHIFT 5 |
| 106 | #define TRAC_STATUS_MASK 7 |
| 107 | |
| 108 | enum { |
| 109 | TRAC_STATUS_SUCCESS = 0, /* reset default */ |
| 110 | TRAC_STATUS_SUCCESS_DATA_PENDING = 1, |
| 111 | TRAC_STATUS_CHANNEL_ACCESS_FAILURE = 3, |
| 112 | TRAC_STATUS_NO_ACK = 5, |
| 113 | TRAC_STATUS_INVALID = 7 |
| 114 | }; |
| 115 | |
| 116 | /* --- TRX_CMD [4:0] ----------------------------------------------------- */ |
| 117 | |
| 118 | #define TRX_CMD_SHIFT 0 |
| 119 | #define TRX_CMD_MASK 7 |
| 120 | |
| 121 | enum { |
| 122 | TRX_CMD_NOP = 0x00, /* reset default */ |
| 123 | TRX_CMD_TX_START = 0x02, |
| 124 | TRX_CMD_FORCE_TRX_OFF = 0x03, |
| 125 | TRX_CMD_RX_ON = 0x06, |
| 126 | TRX_CMD_TRX_OFF = 0x08, |
| 127 | TRX_CMD_PLL_ON = 0x09, |
| 128 | TRX_CMD_RX_AACK_ON = 0x16, |
| 129 | TRX_CMD_TX_ARET_ON = 0x19, |
| 130 | }; |
| 131 | |
| 132 | /* --- TRX_CTRL_0 [7:6] ---------------------------------------------------- */ |
| 133 | |
| 134 | #define PAD_IO_SHIFT 6 |
| 135 | #define PAD_IO_MASK 3 |
| 136 | |
| 137 | enum { |
| 138 | PAD_IO_2mA, /* reset default */ |
| 139 | PAD_IO_4mA, |
| 140 | PAD_IO_6mA, |
| 141 | PAD_IO_8mA |
| 142 | }; |
| 143 | |
| 144 | /* --- TRX_CTRL_0 [5:4] ---------------------------------------------------- */ |
| 145 | |
| 146 | #define PAD_IO_CLKM_SHIFT 4 |
| 147 | #define PAD_IO_CLKM_MASK 3 |
| 148 | |
| 149 | enum { |
| 150 | PAD_IO_CLKM_2mA, |
| 151 | PAD_IO_CLKM_4mA, /* reset default */ |
| 152 | PAD_IO_CLKM_5mA, |
| 153 | PAD_IO_CLKM_8mA, |
| 154 | }; |
| 155 | |
| 156 | /* --- TRX_CTRL_0 [3] ------------------------------------------------------ */ |
| 157 | |
| 158 | #define CLKM_SHA_SEL (1 << 3) |
| 159 | |
| 160 | /* --- TRX_CTRL_0 [2:0] ---------------------------------------------------- */ |
| 161 | |
| 162 | #define CLKM_CTRL_SHIFT 0 |
| 163 | #define CLKM_CTRL_MASK 3 |
| 164 | |
| 165 | enum { |
| 166 | CLKM_CTRL_OFF = 0, |
| 167 | CLKM_CTRL_1MHz = 1, /* reset default */ |
| 168 | CLKM_CTRL_2MHz = 2, |
| 169 | CLKM_CTRL_4MHz = 3, |
| 170 | CLKM_CTRL_8MHz = 4, |
| 171 | CLKM_CTRL_16MHz = 5 |
| 172 | }; |
| 173 | |
| 174 | /* --- PHY_TX_PWR [7] ------------------------------------------------------ */ |
| 175 | |
| 176 | #define TX_AUTO_CRC_ON (1 << 7) |
| 177 | |
| 178 | /* --- PHY_TX_PWR [3:0] ---------------------------------------------------- */ |
| 179 | |
| 180 | #define TX_PWR_SHIFT 0 |
| 181 | #define TX_PWR_MASK 0x0f |
| 182 | |
| 183 | /* --- PHY_RSSI [7] -------------------------------------------------------- */ |
| 184 | |
| 185 | #define RX_CRC_VALID (1 << 7) |
| 186 | |
| 187 | /* --- PHY_RSSI [4:0] ------------------------------------------------------ */ |
| 188 | |
| 189 | #define RSSI_SHIFT 0 |
| 190 | #define RSSI_MASK 0x1f |
| 191 | |
| 192 | /* --- PHY_CC_CCA [7] ------------------------------------------------------ */ |
| 193 | |
| 194 | #define CCA_REQUEST (1 << 7) |
| 195 | |
| 196 | /* --- PHY_CC_CCA [6:5] ---------------------------------------------------- */ |
| 197 | |
| 198 | #define CCA_MODE_SHIFT 5 |
| 199 | #define CCA_MODE_MASK 3 |
| 200 | |
| 201 | /* --- PHY_CC_CCA [4:0] ---------------------------------------------------- */ |
| 202 | |
| 203 | #define CHANNEL_SHIFT 0 |
| 204 | #define CHANNEL_MASK 0x1f |
| 205 | |
| 206 | /* --- CCA_THRES [3:0] ----------------------------------------------------- */ |
| 207 | |
| 208 | #define CCA_ED_THRES_SHIFT 0 |
| 209 | #define CCA_ED_THRES_MASK 0x0f |
| 210 | |
| 211 | /* --- IRQ_MASK/IRQ_STATUS ------------------------------------------------- */ |
| 212 | |
| 213 | enum { |
| 214 | IRQ_PLL_LOCK = 1 << 0, |
| 215 | IRQ_PLL_UNLOCK = 1 << 1, |
| 216 | IRQ_RX_START = 1 << 2, |
| 217 | IRQ_TRX_END = 1 << 3, |
| 218 | IRQ_TRX_UR = 1 << 6, |
| 219 | IRQ_BAT_LOW = 1 << 7 |
| 220 | }; |
| 221 | |
| 222 | /* --- VREG_CTRL [7, 6, 3, 2] ---------------------------------------------- */ |
| 223 | |
| 224 | #define AVREG_EXT (1 << 7) |
| 225 | #define AVDD_OK (1 << 6) |
| 226 | #define DVREG_EXT (1 << 3) |
| 227 | #define DVDD_OK (1 << 2) |
| 228 | |
| 229 | /* --- BATMON [5, 4] ------------------------------------------------------- */ |
| 230 | |
| 231 | #define BATMON_OK (1 << 5) |
| 232 | #define BATMON_HR (1 << 4) |
| 233 | |
| 234 | /* --- BATMON [3:0] -------------------------------------------------------- */ |
| 235 | |
| 236 | #define NATMON_VTH_SHIFT 0 |
| 237 | #define NATMON_VTH_MASK 0x0f |
| 238 | |
| 239 | /* --- XOSC_CTRL [7:4] ----------------------------------------------------- */ |
| 240 | |
| 241 | #define XTAL_MODE_SHIFT 4 |
| 242 | #define XTAL_MODE_MASK 0x0f |
| 243 | |
| 244 | enum { |
| 245 | XTAL_MODE_OFF = 0x0, |
| 246 | XTAL_MODE_EXT = 0x4, |
| 247 | XTAL_MODE_INT = 0xf /* reset default */ |
| 248 | }; |
| 249 | |
| 250 | /* --- XOSC_CTRL [3:1] ----------------------------------------------------- */ |
| 251 | |
| 252 | #define XTAL_TRIM_SHIFT 4 |
| 253 | #define XTAL_TRIM_MASK 0x0f |
| 254 | |
| 255 | /* --- XAH_CTRL [7:4] ------------------------------------------------------ */ |
| 256 | |
| 257 | #define MAX_FRAME_RETRIES_SHIFT 4 |
| 258 | #define MAX_FRAME_RETRIES_MASK 0x0f |
| 259 | #define MAX_CSMA_RETRIES_SHIFT 1 |
| 260 | #define MAX_CSMA_RETRIES_MASK 0x07 |
| 261 | |
| 262 | /* --- PLL_CF [7] ---------------------------------------------------------- */ |
| 263 | |
| 264 | #define PLL_CF_START (1 << 7) |
| 265 | |
| 266 | /* --- PLL_DCU [8] --------------------------------------------------------- */ |
| 267 | |
| 268 | #define PLL_DCU_START (1 << 7) |
| 269 | |
| 270 | /* --- CSMA_SEED_1 [7:6] --------------------------------------------------- */ |
| 271 | |
| 272 | #define MIN_BE_SHIFT 6 |
| 273 | #define MIN_BE_MASK 3 |
| 274 | |
| 275 | /* --- CSMA_SEED_1 [5] ----------------------------------------------------- */ |
| 276 | |
| 277 | #define AACK_SET_PD (1 << 5) |
| 278 | |
| 279 | /* --- CSMA_SEED_1 [3] ----------------------------------------------------- */ |
| 280 | |
| 281 | #define I_AM_COORD (1 << 3) |
| 282 | |
| 283 | /* --- CSMA_SEED_1 [2:0] --------------------------------------------------- */ |
| 284 | |
| 285 | #define CSMA_SEED_1_SHIFT 0 |
| 286 | #define CSMA_SEED_1_MASK 7 |
| 287 | |
| 288 | #endif /* !AT86RF230_H */ |
atrf/tools/atspi-id/atspi-id.c |
| 1 | /* |
| 2 | * atspi-id/atspi-id.c - Identify a ben-wpan AF86RF230 board |
| 3 | * |
| 4 | * Written 2010 by Werner Almesberger |
| 5 | * Copyright 2010 Werner Almesberger |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by |
| 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | * (at your option) any later version. |
| 11 | */ |
| 12 | |
| 13 | |
| 14 | #include <stdlib.h> |
| 15 | #include <stdio.h> |
| 16 | #include <usb.h> |
| 17 | |
| 18 | #include "at86rf230.h" |
| 19 | #include "atspi/ep0.h" |
| 20 | #include "atspi.h" |
| 21 | |
| 22 | |
| 23 | #define FROM_DEV ATSPI_FROM_DEV(0) |
| 24 | |
| 25 | #define BUF_SIZE 256 |
| 26 | |
| 27 | |
| 28 | |
| 29 | static int get_id(usb_dev_handle *dev, void *data, int size) |
| 30 | { |
| 31 | int res; |
| 32 | |
| 33 | res = usb_control_msg(dev, FROM_DEV, ATSPI_ID, 0, 0, data, size, 1000); |
| 34 | if (res < 0) |
| 35 | fprintf(stderr, "ATSPI_ID: %s\n", usb_strerror()); |
| 36 | return res; |
| 37 | } |
| 38 | |
| 39 | |
| 40 | static int atspi_get_protocol(usb_dev_handle *dev, |
| 41 | uint8_t *major, uint8_t *minor, uint8_t *target) |
| 42 | { |
| 43 | uint8_t ids[3]; |
| 44 | |
| 45 | if (get_id(dev, ids, 3) < 0) |
| 46 | return -1; |
| 47 | if (major) |
| 48 | *major = ids[0]; |
| 49 | if (minor) |
| 50 | *minor = ids[1]; |
| 51 | if (target) |
| 52 | *target = ids[2]; |
| 53 | |
| 54 | return 0; |
| 55 | } |
| 56 | |
| 57 | |
| 58 | static int atspi_get_build(usb_dev_handle *dev, char *buf, size_t size) |
| 59 | { |
| 60 | int res; |
| 61 | |
| 62 | res = usb_control_msg(dev, FROM_DEV, ATSPI_BUILD, 0, 0, buf, size, |
| 63 | 1000); |
| 64 | if (res < 0) |
| 65 | fprintf(stderr, "ATSPI_BUILD: %s\n", usb_strerror()); |
| 66 | return res; |
| 67 | } |
| 68 | |
| 69 | |
| 70 | static void show_info(usb_dev_handle *dev) |
| 71 | { |
| 72 | const struct usb_device *device = usb_device(dev); |
| 73 | uint8_t major, minor, target; |
| 74 | char buf[BUF_SIZE+1]; /* +1 for terminating \0 */ |
| 75 | int len; |
| 76 | uint8_t part, version, man_id_0, man_id_1; |
| 77 | |
| 78 | printf("%04x:%04x ", |
| 79 | device->descriptor.idVendor, device->descriptor.idProduct); |
| 80 | |
| 81 | if (atspi_get_protocol(dev, &major, &minor, &target) < 0) |
| 82 | exit(1); |
| 83 | printf("protocol %u.%u hw %u\n", major, minor, target); |
| 84 | |
| 85 | len = atspi_get_build(dev, buf, sizeof(buf)-1); |
| 86 | if (len < 0) |
| 87 | exit(1); |
| 88 | buf[len] = 0; |
| 89 | printf("%10s%s\n", "", buf); |
| 90 | |
| 91 | part = atspi_reg_read(dev, REG_PART_NUM); |
| 92 | version = atspi_reg_read(dev, REG_VERSION_NUM); |
| 93 | man_id_0 = atspi_reg_read(dev, REG_MAN_ID_0); |
| 94 | man_id_1 = atspi_reg_read(dev, REG_MAN_ID_1); |
| 95 | printf("%10spart 0x%02x version %u manufacturer xxxx%02x%02x\n", "", |
| 96 | part, version, man_id_1, man_id_0); |
| 97 | } |
| 98 | |
| 99 | |
| 100 | static void usage(const char *name) |
| 101 | { |
| 102 | fprintf(stderr, "%s\n", name); |
| 103 | exit(1); |
| 104 | } |
| 105 | |
| 106 | |
| 107 | int main(int argc, const char **argv) |
| 108 | { |
| 109 | usb_dev_handle *dev; |
| 110 | |
| 111 | if (argc != 1) |
| 112 | usage(*argv); |
| 113 | dev = atspi_open(); |
| 114 | if (!dev) |
| 115 | return 1; |
| 116 | |
| 117 | show_info(dev); |
| 118 | |
| 119 | return 0; |
| 120 | } |
atrf/tools/atspi-rssi/atspi-rssi.c |
| 1 | /* |
| 2 | * atspi-rssi/atspi-rssi.c - ben-wpan AF86RF230 spectrum scan |
| 3 | * |
| 4 | * Written 2010 by Werner Almesberger |
| 5 | * Copyright 2010 Werner Almesberger |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by |
| 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | * (at your option) any later version. |
| 11 | */ |
| 12 | |
| 13 | |
| 14 | #include <stdlib.h> |
| 15 | #include <stdio.h> |
| 16 | #include <usb.h> |
| 17 | #include <sys/time.h> |
| 18 | |
| 19 | #include "at86rf230.h" |
| 20 | #include "atspi/ep0.h" |
| 21 | #include "atspi.h" |
| 22 | |
| 23 | |
| 24 | #define FROM_DEV ATSPI_FROM_DEV(0) |
| 25 | #define TO_DEV ATSPI_TO_DEV(0) |
| 26 | |
| 27 | |
| 28 | static struct timeval t0; |
| 29 | |
| 30 | |
| 31 | static void sweep(usb_dev_handle *dev) |
| 32 | { |
| 33 | int chan, rssi; |
| 34 | struct timeval t; |
| 35 | |
| 36 | for (chan = 11; chan <= 26; chan++) { |
| 37 | atspi_reg_write(dev, REG_PHY_CC_CCA, chan); |
| 38 | /* |
| 39 | * No need to explicitly wait for the PPL lock - going USB-SPI |
| 40 | * is pretty slow, leaving the transceiver plenty of time. |
| 41 | */ |
| 42 | gettimeofday(&t, NULL); |
| 43 | rssi = atspi_reg_read(dev, REG_PHY_RSSI) & RSSI_MASK; |
| 44 | t.tv_sec -= t0.tv_sec; |
| 45 | t.tv_usec -= t0.tv_usec; |
| 46 | printf("%d %f %d\n", |
| 47 | 2405+(chan-11)*5, |
| 48 | (double) t.tv_sec+t.tv_usec/1000000.0, |
| 49 | -91+3*(rssi-1)); |
| 50 | } |
| 51 | printf("\n"); |
| 52 | } |
| 53 | |
| 54 | |
| 55 | static void usage(const char *name) |
| 56 | { |
| 57 | fprintf(stderr, "%s sweeps \n", name); |
| 58 | exit(1); |
| 59 | } |
| 60 | |
| 61 | |
| 62 | int main(int argc, const char **argv) |
| 63 | { |
| 64 | usb_dev_handle *dev; |
| 65 | unsigned long sweeps, i; |
| 66 | char *end; |
| 67 | |
| 68 | if (argc != 2) |
| 69 | usage(*argv); |
| 70 | sweeps = strtoul(argv[1], &end, 0); |
| 71 | if (*end) |
| 72 | usage(*argv); |
| 73 | |
| 74 | dev = atspi_open(); |
| 75 | if (!dev) |
| 76 | return 1; |
| 77 | |
| 78 | atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_TRX_OFF); |
| 79 | /* |
| 80 | * No need to explicitly wait for things to stabilize - going USB-SPI |
| 81 | * is pretty slow, leaving the transceiver more than enough time. |
| 82 | */ |
| 83 | atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_RX_ON); |
| 84 | |
| 85 | gettimeofday(&t0, NULL); |
| 86 | for (i = 0; i != sweeps; i++) |
| 87 | sweep(dev); |
| 88 | |
| 89 | atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_TRX_OFF); |
| 90 | |
| 91 | return 0; |
| 92 | } |
atrf/tools/lib/atspi.c |
| 1 | /* |
| 2 | * lib/atspi.c - ATSPI access functions library |
| 3 | * |
| 4 | * Written 2010 by Werner Almesberger |
| 5 | * Copyright 2010 Werner Almesberger |
| 6 | * |
| 7 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License as published by |
| 9 | * the Free Software Foundation; either version 2 of the License, or |
| 10 | * (at your option) any later version. |
| 11 | */ |
| 12 | |
| 13 | |
| 14 | #include <stdio.h> |
| 15 | #include <usb.h> |
| 16 | |
| 17 | #include "f32xbase/usb.h" |
| 18 | #include "atspi/ep0.h" |
| 19 | #include "atspi/usb-ids.h" |
| 20 | |
| 21 | #include "atspi.h" |
| 22 | |
| 23 | |
| 24 | #define FROM_DEV ATSPI_FROM_DEV(0) |
| 25 | #define TO_DEV ATSPI_TO_DEV(0) |
| 26 | |
| 27 | |
| 28 | /* ----- error handling ---------------------------------------------------- */ |
| 29 | |
| 30 | |
| 31 | static int error; |
| 32 | |
| 33 | |
| 34 | int atspi_error(void) |
| 35 | { |
| 36 | return error; |
| 37 | } |
| 38 | |
| 39 | |
| 40 | int atspi_clear_error(void) |
| 41 | { |
| 42 | int ret; |
| 43 | |
| 44 | ret = error; |
| 45 | error = 0; |
| 46 | return ret; |
| 47 | } |
| 48 | |
| 49 | |
| 50 | /* ----- open/close -------------------------------------------------------- */ |
| 51 | |
| 52 | |
| 53 | usb_dev_handle *atspi_open(void) |
| 54 | { |
| 55 | usb_dev_handle *dev; |
| 56 | |
| 57 | dev = open_usb(USB_VENDOR, USB_PRODUCT); |
| 58 | if (dev) { |
| 59 | error = 0; |
| 60 | } else { |
| 61 | fprintf(stderr, ":-(\n"); |
| 62 | error = 1; |
| 63 | } |
| 64 | return dev; |
| 65 | } |
| 66 | |
| 67 | |
| 68 | void atspi_close(usb_dev_handle *dev) |
| 69 | { |
| 70 | /* to do */ |
| 71 | } |
| 72 | |
| 73 | |
| 74 | /* ----- device mode ------------------------------------------------------- */ |
| 75 | |
| 76 | |
| 77 | void atspi_reset(usb_dev_handle *dev) |
| 78 | { |
| 79 | int res; |
| 80 | |
| 81 | if (error) |
| 82 | return; |
| 83 | |
| 84 | res = |
| 85 | usb_control_msg(dev, TO_DEV, ATSPI_RESET, 0, 0, NULL, 0, 1000); |
| 86 | if (res < 0) { |
| 87 | fprintf(stderr, "ATSPI_RESET: %d\n", res); |
| 88 | error = 1; |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | |
| 93 | void atspi_reset_rf(usb_dev_handle *dev) |
| 94 | { |
| 95 | int res; |
| 96 | |
| 97 | if (error) |
| 98 | return; |
| 99 | |
| 100 | res = |
| 101 | usb_control_msg(dev, TO_DEV, ATSPI_RF_RESET, 0, 0, NULL, 0, 1000); |
| 102 | if (res < 0) { |
| 103 | fprintf(stderr, "ATSPI_RF_RESET: %d\n", res); |
| 104 | error = 1; |
| 105 | } |
| 106 | } |
| 107 | |
| 108 | |
| 109 | /* ----- register access --------------------------------------------------- */ |
| 110 | |
| 111 | |
| 112 | void atspi_reg_write(usb_dev_handle *dev, uint8_t reg, uint8_t value) |
| 113 | { |
| 114 | int res; |
| 115 | |
| 116 | if (error) |
| 117 | return; |
| 118 | |
| 119 | res = usb_control_msg(dev, TO_DEV, ATSPI_REG_WRITE, value, reg, |
| 120 | NULL, 0, 1000); |
| 121 | if (res < 0) { |
| 122 | fprintf(stderr, "ATSPI_REG_WRITE: %d\n", res); |
| 123 | error = 1; |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | |
| 128 | uint8_t atspi_reg_read(usb_dev_handle *dev, uint8_t reg) |
| 129 | { |
| 130 | uint8_t value = 0; |
| 131 | int res; |
| 132 | |
| 133 | if (error) |
| 134 | return 0; |
| 135 | |
| 136 | res = usb_control_msg(dev, FROM_DEV, ATSPI_REG_READ, 0, reg, |
| 137 | (void *) &value, 1, 1000); |
| 138 | if (res < 0) { |
| 139 | fprintf(stderr, "ATSPI_REG_READ: %d\n", res); |
| 140 | error = 1; |
| 141 | } |
| 142 | return value; |
| 143 | } |
fw/atspi/atspi.c |
1 | | /* |
2 | | * atspi/atspi.c - ATSPI initialization and main loop |
3 | | * |
4 | | * Written 2008-2010 by Werner Almesberger |
5 | | * Copyright 2008-2010 Werner Almesberger |
6 | | * |
7 | | * This program is free software; you can redistribute it and/or modify |
8 | | * it under the terms of the GNU General Public License as published by |
9 | | * the Free Software Foundation; either version 2 of the License, or |
10 | | * (at your option) any later version. |
11 | | */ |
12 | | |
13 | | |
14 | | #include "regs.h" |
15 | | #include "io.h" |
16 | | #include "usb.h" |
17 | | #include "atspi/ep0.h" |
18 | | #include "version.h" |
19 | | |
20 | | |
21 | | void reset_rf(void) |
22 | | { |
23 | | int i; |
24 | | |
25 | | nRST_RF = 0; |
26 | | /* |
27 | | * 11.4.12: min 625 ns. |
28 | | * The pulse we generate is slightly longer than 4 us. |
29 | | */ |
30 | | for (i = 0; i != 10; i++); |
31 | | nRST_RF = 1; |
32 | | } |
33 | | |
34 | | |
35 | | static void init_io(void) |
36 | | { |
37 | | /* |
38 | | * Signal Mode Value |
39 | | * |
40 | | * MOSI push-pull 0 |
41 | | * MISO open drain 1 (input) |
42 | | * SCLK push-pull 0 |
43 | | * nSS push-pull 1 |
44 | | * nRST_RF push-pull 1 |
45 | | * IRQ_RF open drain 1 (input) |
46 | | * SLP_TR push-pull 0 |
47 | | * |
48 | | * LED push-pull 0 (set up by boot loader) |
49 | | * |
50 | | * all unused open drain 0 |
51 | | */ |
52 | | |
53 | | MOSI = 0; |
54 | | MOSI_MODE |= 1 << MOSI_BIT; |
55 | | |
56 | | SCLK = 0; |
57 | | SCLK_MODE |= 1 << SCLK_BIT; |
58 | | |
59 | | nSS_MODE |= 1 << nSS_BIT; |
60 | | |
61 | | nRST_RF_MODE |= 1 << nRST_RF_BIT; |
62 | | |
63 | | SLP_TR = 0; |
64 | | SLP_TR_MODE |= 1 << SLP_TR_BIT; |
65 | | |
66 | | P0 &= |
67 | | ~((1 << 0) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6) | (1 << 7)); |
68 | | /* change 1 << 0 to 1 << 2 once 100813 boards are reworked */ |
69 | | P3 = 0; |
70 | | |
71 | | #if 0 |
72 | | /* |
73 | | * We can *almost* disable the pull-ups. The only obstacle is that |
74 | | * MISO is not driven when not in use. So we either need an external |
75 | | * pull-up/down or keep all the pull-ups on. |
76 | | */ |
77 | | |
78 | | /* |
79 | | * Disable pull-ups |
80 | | */ |
81 | | GPIOCN |= WEAKPUD; |
82 | | #endif |
83 | | |
84 | | /* |
85 | | * The manual says the reset is optional, but reality disagrees with |
86 | | * this optimistic assessment quite violently. |
87 | | */ |
88 | | |
89 | | reset_rf(); |
90 | | } |
91 | | |
92 | | |
93 | | void main(void) |
94 | | { |
95 | | init_io(); |
96 | | |
97 | | usb_init(); |
98 | | ep0_init(); |
99 | | |
100 | | while (1) { |
101 | | usb_poll(); |
102 | | } |
103 | | } |
fw/atspi/descr.c |
1 | | /* |
2 | | * atspi/descr.c - USB descriptors |
3 | | * |
4 | | * Written 2008-2010 by Werner Almesberger |
5 | | * Copyright 2008-2010 Werner Almesberger |
6 | | * |
7 | | * This program is free software; you can redistribute it and/or modify |
8 | | * it under the terms of the GNU General Public License as published by |
9 | | * the Free Software Foundation; either version 2 of the License, or |
10 | | * (at your option) any later version. |
11 | | */ |
12 | | |
13 | | |
14 | | #include "usb.h" |
15 | | |
16 | | #include "config.h" |
17 | | |
18 | | |
19 | | /* |
20 | | * Device descriptor |
21 | | */ |
22 | | |
23 | | const uint8_t device_descriptor[18] = { |
24 | | 18, /* bLength */ |
25 | | USB_DT_DEVICE, /* bDescriptorType */ |
26 | | LE(0x200), /* bcdUSB */ |
27 | | USB_CLASS_VENDOR_SPEC, /* bDeviceClass */ |
28 | | 0x00, /* bDeviceSubClass */ |
29 | | 0x00, /* bDeviceProtocol */ |
30 | | EP0_SIZE, /* bMaxPacketSize */ |
31 | | LE(USB_VENDOR), /* idVendor */ |
32 | | LE(USB_PRODUCT), /* idProduct */ |
33 | | LE(0x0001), /* bcdDevice */ |
34 | | 0, /* iManufacturer */ |
35 | | 0, /* iProduct */ |
36 | | 0, /* iSerialNumber */ |
37 | | 1 /* bNumConfigurations */ |
38 | | }; |
39 | | |
40 | | |
41 | | /* |
42 | | * Our configuration |
43 | | * |
44 | | * While in DFU mode, we're always bus-powered. |
45 | | */ |
46 | | |
47 | | const uint8_t config_descriptor[] = { |
48 | | 9, /* bLength */ |
49 | | USB_DT_CONFIG, /* bDescriptorType */ |
50 | | LE(9+9+7+7), /* wTotalLength */ |
51 | | 1, /* bNumInterfaces */ |
52 | | 1, /* bConfigurationValue (> 0 !) */ |
53 | | 0, /* iConfiguration */ |
54 | | // USB_ATTR_SELF_POWERED | USB_ATTR_BUS_POWERED, |
55 | | USB_ATTR_BUS_POWERED, /* bmAttributes */ |
56 | | 15, /* bMaxPower */ |
57 | | |
58 | | /* Interface #0 */ |
59 | | |
60 | | 9, /* bLength */ |
61 | | USB_DT_INTERFACE, /* bDescriptorType */ |
62 | | 0, /* bInterfaceNumber */ |
63 | | 0, /* bAlternateSetting */ |
64 | | 2, /* bNumEndpoints */ |
65 | | USB_CLASS_VENDOR_SPEC, /* bInterfaceClass */ |
66 | | 0, /* bInterfaceSubClass */ |
67 | | 0, /* bInterfaceProtocol */ |
68 | | 0, /* iInterface */ |
69 | | |
70 | | /* EP OUT */ |
71 | | |
72 | | 7, /* bLength */ |
73 | | USB_DT_ENDPOINT, /* bDescriptorType */ |
74 | | 0x01, /* bEndPointAddress */ |
75 | | 0x02, /* bmAttributes (bulk) */ |
76 | | LE(EP1_SIZE), /* wMaxPacketSize */ |
77 | | 0, /* bInterval */ |
78 | | |
79 | | /* EP IN */ |
80 | | |
81 | | 7, /* bLength */ |
82 | | USB_DT_ENDPOINT, /* bDescriptorType */ |
83 | | 0x81, /* bEndPointAddress */ |
84 | | 0x02, /* bmAttributes (bulk) */ |
85 | | LE(EP1_SIZE), /* wMaxPacketSize */ |
86 | | 0, /* bInterval */ |
87 | | |
88 | | }; |
fw/atspi/ep0.c |
1 | | /* |
2 | | * atspi/ep0.c - EP0 extension protocol |
3 | | * |
4 | | * Written 2008-2010 by Werner Almesberger |
5 | | * Copyright 2008-2010 Werner Almesberger |
6 | | * |
7 | | * This program is free software; you can redistribute it and/or modify |
8 | | * it under the terms of the GNU General Public License as published by |
9 | | * the Free Software Foundation; either version 2 of the License, or |
10 | | * (at your option) any later version. |
11 | | */ |
12 | | |
13 | | |
14 | | #include <stdint.h> |
15 | | |
16 | | #ifndef NULL |
17 | | #define NULL 0 |
18 | | #endif |
19 | | |
20 | | #include "regs.h" |
21 | | //#include "uart.h" |
22 | | #include "usb.h" |
23 | | #include "atspi/ep0.h" |
24 | | #include "at86rf230.h" |
25 | | #include "version.h" |
26 | | |
27 | | |
28 | | extern void reset_rf(void); |
29 | | |
30 | | |
31 | | #define debug(...) |
32 | | #define error(...) |
33 | | |
34 | | |
35 | | /* |
36 | | * SDCC 2.8.0 had a number of code generation bugs that appeared in the big |
37 | | * switch statement of my_setup. SDCC_FORCE_UPDATE forced the value of the |
38 | | * "size" variable to be written to memory. This work-around doesn't seem |
39 | | * to be necessary with 2.9.0, but we keep it around, just in case. |
40 | | * |
41 | | * Unfortunately, the setup->bRequest garbling bug is still with us. Without |
42 | | * the evaluation forced with SDCC_FORCE_EVAL, sdcc gets confused about the |
43 | | * value of setup->bRequest and then rejects all SETUP requests. |
44 | | */ |
45 | | |
46 | | #define SDCC_FORCE_EVAL(type, value) \ |
47 | | do { \ |
48 | | static volatile type foo; \ |
49 | | foo = value; \ |
50 | | } while (0) |
51 | | |
52 | | #define SDCC_FORCE_UPDATE(type, var) \ |
53 | | do { \ |
54 | | volatile type foo; \ |
55 | | foo = var; \ |
56 | | var = foo; \ |
57 | | } while (0) |
58 | | |
59 | | |
60 | | static const uint8_t id[] = { EP0ATSPI_MAJOR, EP0ATSPI_MINOR, HW_TYPE }; |
61 | | static __xdata uint8_t buf[MAX_PSDU+3]; /* command, PHDR, and LQ */ |
62 | | static uint8_t size; |
63 | | |
64 | | |
65 | | static void spi_send(uint8_t v) |
66 | | { |
67 | | uint8_t mask; |
68 | | |
69 | | for (mask = 0x80; mask; mask >>= 1) { |
70 | | MOSI = !!(v & mask); |
71 | | SCLK = 1; |
72 | | SCLK = 0; |
73 | | } |
74 | | } |
75 | | |
76 | | |
77 | | static uint8_t spi_recv(void) |
78 | | { |
79 | | uint8_t res = 0; |
80 | | uint8_t i; |
81 | | |
82 | | for (i = 0; i != 8; i++) { |
83 | | res = (res << 1) | MISO; |
84 | | SCLK = 1; |
85 | | SCLK = 0; |
86 | | } |
87 | | return res; |
88 | | } |
89 | | |
90 | | |
91 | | static void do_buf_write(void *user) |
92 | | { |
93 | | uint8_t i; |
94 | | |
95 | | user; /* suppress warning */ |
96 | | nSS = 0; |
97 | | spi_send(AT86RF230_BUF_WRITE); |
98 | | for (i = 0; i != size; i++) |
99 | | spi_send(buf[i]); |
100 | | nSS = 1; |
101 | | } |
102 | | |
103 | | |
104 | | #define BUILD_OFFSET 7 /* '#' plus "65535" plus ' ' */ |
105 | | |
106 | | |
107 | | static __bit my_setup(struct setup_request *setup) __reentrant |
108 | | { |
109 | | unsigned tmp; |
110 | | uint8_t i; |
111 | | |
112 | | switch (setup->bmRequestType | setup->bRequest << 8) { |
113 | | case ATSPI_FROM_DEV(ATSPI_ID): |
114 | | debug("ATSPI_ID\n"); |
115 | | if (setup->wLength > 3) |
116 | | return 0; |
117 | | usb_send(&ep0, id, setup->wLength, NULL, NULL); |
118 | | return 1; |
119 | | case ATSPI_FROM_DEV(ATSPI_BUILD): |
120 | | debug("ATSPI_BUILD\n"); |
121 | | tmp = build_number; |
122 | | for (i = BUILD_OFFSET-2; tmp; i--) { |
123 | | buf[i] = (tmp % 10)+'0'; |
124 | | tmp /= 10; |
125 | | } |
126 | | buf[i] = '#'; |
127 | | buf[BUILD_OFFSET-1] = ' '; |
128 | | for (size = 0; build_date[size]; size++) |
129 | | buf[BUILD_OFFSET+size] = build_date[size]; |
130 | | size += BUILD_OFFSET-i+1; |
131 | | SDCC_FORCE_EVAL(uint8_t, setup->bRequest); |
132 | | if (size > setup->wLength) |
133 | | return 0; |
134 | | usb_send(&ep0, buf+i, size, NULL, NULL); |
135 | | return 1; |
136 | | |
137 | | case ATSPI_TO_DEV(ATSPI_RESET): |
138 | | debug("ATSPI_RESET\n"); |
139 | | RSTSRC = SWRSF; |
140 | | while (1); |
141 | | |
142 | | case ATSPI_TO_DEV(ATSPI_RF_RESET): |
143 | | debug("ATSPI_RF_RESET\n"); |
144 | | reset_rf(); |
145 | | return 1; |
146 | | |
147 | | case ATSPI_TO_DEV(ATSPI_REG_WRITE): |
148 | | debug("ATSPI_REG_WRITE\n"); |
149 | | nSS = 0; |
150 | | spi_send(AT86RF230_REG_WRITE | setup->wIndex); |
151 | | spi_send(setup->wValue); |
152 | | nSS = 1; |
153 | | return 1; |
154 | | case ATSPI_FROM_DEV(ATSPI_REG_READ): |
155 | | debug("ATSPI_REG_READ\n"); |
156 | | nSS = 0; |
157 | | spi_send(AT86RF230_REG_READ | setup->wIndex); |
158 | | *buf = spi_recv(); |
159 | | nSS = 1; |
160 | | usb_send(&ep0, buf, 1, NULL, NULL); |
161 | | return 1; |
162 | | |
163 | | case ATSPI_TO_DEV(ATSPI_BUF_WRITE): |
164 | | debug("ATSPI_BUF_WRITE\n"); |
165 | | if (setup->wLength < 1) |
166 | | return 0; |
167 | | if (setup->wLength > MAX_PSDU+1) /* PHR+PSDU */ |
168 | | return 0; |
169 | | buf[0] = AT86RF230_BUF_WRITE; |
170 | | size = setup->wLength+1; |
171 | | usb_recv(&ep0, buf+1, setup->wLength, do_buf_write, NULL); |
172 | | return 1; |
173 | | case ATSPI_TO_DEV(ATSPI_BUF_READ): |
174 | | debug("ATSPI_BUF_READ\n"); |
175 | | if (setup->wLength < 2) /* PHR+LQ */ |
176 | | return 0; |
177 | | if (setup->wLength > MAX_PSDU+2) /* PHR+PSDU+LQ */ |
178 | | return 0; |
179 | | nSS = 0; |
180 | | spi_send(AT86RF230_BUF_READ); |
181 | | size = *buf = spi_recv(); |
182 | | if (size+2 > setup->wLength) |
183 | | size = setup->wLength-2; |
184 | | for (i = 0; i != size+1; i++) |
185 | | buf[i+1] = spi_recv(); |
186 | | nSS = 1; |
187 | | usb_send(&ep0, buf, size+1, NULL, NULL); |
188 | | return 1; |
189 | | |
190 | | case ATSPI_TO_DEV(ATSPI_SRAM_WRITE): |
191 | | debug("ATSPI_SRAM_WRITE\n"); |
192 | | if (setup->wIndex > SRAM_SIZE) |
193 | | return 0; |
194 | | if (setup->wIndex+setup->wLength > SRAM_SIZE) |
195 | | return 0; |
196 | | buf[0] = AT86RF230_SRAM_WRITE; |
197 | | buf[1] = setup->wIndex; |
198 | | size = setup->wLength+2; |
199 | | usb_recv(&ep0, buf+2, setup->wLength, do_buf_write, NULL); |
200 | | return 1; |
201 | | case ATSPI_TO_DEV(ATSPI_SRAM_READ): |
202 | | debug("ATSPI_SRAM_READ\n"); |
203 | | if (setup->wIndex > SRAM_SIZE) |
204 | | return 0; |
205 | | if (setup->wIndex+setup->wLength > SRAM_SIZE) |
206 | | return 0; |
207 | | nSS = 0; |
208 | | spi_send(AT86RF230_SRAM_READ); |
209 | | spi_send(setup->wIndex); |
210 | | for (i = 0; i != size; i++) |
211 | | buf[i] = spi_recv(); |
212 | | nSS = 1; |
213 | | usb_send(&ep0, buf, size, NULL, NULL); |
214 | | return 1; |
215 | | |
216 | | default: |
217 | | error("Unrecognized SETUP: 0x%02x 0x%02x ...\n", |
218 | | setup->bmRequestType, setup->bRequest); |
219 | | return 0; |
220 | | } |
221 | | } |
222 | | |
223 | | |
224 | | void ep0_init(void) |
225 | | { |
226 | | user_setup = my_setup; |
227 | | } |
fw/common/Makefile |
1 | | # |
2 | | # common/Makefile - Makefile for shared items |
3 | | # |
4 | | # Written 2008, 2010 by Werner Almesberger |
5 | | # Copyright 2008, 2010 Werner Almesberger |
6 | | # |
7 | | # This program is free software; you can redistribute it and/or modify |
8 | | # it under the terms of the GNU General Public License as published by |
9 | | # the Free Software Foundation; either version 2 of the License, or |
10 | | # (at your option) any later version. |
11 | | # |
12 | | |
13 | | |
14 | | GEN_quiet = @echo " GENERATE " $@ && |
15 | | |
16 | | ifeq ($(V),1) |
17 | | GEN = |
18 | | else |
19 | | GEN = $(GEN_quiet) |
20 | | endif |
21 | | |
22 | | |
23 | | .PHONY: all depend clean spotless |
24 | | |
25 | | all: io-parts.h |
26 | | |
27 | | io-parts.h: io.h Makefile |
28 | | $(GEN) $(CPP) -dD $< | \ |
29 | | sed '1,/IO_H/d' | \ |
30 | | awk \ |
31 | | 'BEGIN { print "/* MACHINE-GENERATED. DO NOT EDIT ! */"; \ |
32 | | print "#ifndef IO_PARTS_H"; \ |
33 | | print "#define IO_PARTS_H"; } \ |
34 | | /#define/ && $$3 != "" { \ |
35 | | split($$3, a, "_"); \ |
36 | | print $$1, $$2 "_PORT", a[1]; \ |
37 | | print $$1, $$2 "_MODE", a[1] "MDOUT"; \ |
38 | | print $$1, $$2 "_BIT", a[2]; } \ |
39 | | END { print "#endif" }' >$@ || \ |
40 | | { rm -f $@; exit 1; } |
41 | | |
42 | | |
43 | | # |
44 | | # When we do a global "make depend", we'll come here first. So we create |
45 | | # io-parts.h so that "make depend" in the other directories can pick it up. |
46 | | # |
47 | | |
48 | | depend: io-parts.h |
49 | | |
50 | | clean: |
51 | | rm -f io-parts.h |
52 | | |
53 | | spotless: clean |
fw/include/at86rf230.h |
1 | | /* |
2 | | * atspi/at86rf230.h - AT86RF230 protocol and register definitions |
3 | | * |
4 | | * Written 2008-2010 by Werner Almesberger |
5 | | * Copyright 2008-2010 Werner Almesberger |
6 | | * |
7 | | * This program is free software; you can redistribute it and/or modify |
8 | | * it under the terms of the GNU General Public License as published by |
9 | | * the Free Software Foundation; either version 2 of the License, or |
10 | | * (at your option) any later version. |
11 | | */ |
12 | | |
13 | | |
14 | | #ifndef AT86RF230_H |
15 | | #define AT86RF230_H |
16 | | |
17 | | enum { |
18 | | AT86RF230_REG_WRITE = 0xc0, /* 11... */ |
19 | | AT86RF230_REG_READ = 0x80, /* 10... */ |
20 | | AT86RF230_BUF_WRITE = 0x60, /* 011... */ |
21 | | AT86RF230_BUF_READ = 0x20, /* 001... */ |
22 | | AT86RF230_SRAM_WRITE = 0x40, /* 010... */ |
23 | | AT86RF230_SRAM_READ = 0x00 /* 000... */ |
24 | | }; |
25 | | |
26 | | #define MAX_PSDU 127 /* octets, see AT86RF230 manual section 8.1 */ |
27 | | #define SRAM_SIZE 128 |
28 | | |
29 | | |
30 | | /* --- Registers ----------------------------------------------------------- */ |
31 | | |
32 | | enum { |
33 | | REG_TRX_STATUS = 0x01, |
34 | | REG_TRX_STATE = 0x02, |
35 | | REG_TRX_CTRL_0 = 0x03, |
36 | | |
37 | | REG_TR_PWR = 0x05, |
38 | | REG_PHY_RSSI = 0x06, |
39 | | REG_PHY_ED_LEVEL = 0x07, |
40 | | REG_PHY_CC_CCA = 0x08, |
41 | | REG_CCA_THRES = 0x09, |
42 | | |
43 | | REG_IRQ_MASK = 0x0e, |
44 | | REG_IRQ_STATUS = 0x0f, |
45 | | REG_VREG_CTRL = 0x10, |
46 | | REG_BATMON = 0x10, |
47 | | REG_XOSC_CTRL = 0x12, |
48 | | |
49 | | REG_PLL_CF = 0x1a, |
50 | | REL_PLL_DCU = 0x1b, |
51 | | REG_PART_NUM = 0x1c, |
52 | | REG_VERSION_NUM = 0x1d, |
53 | | REG_MAN_ID_0 = 0x1e, |
54 | | REG_MAN_ID_1 = 0x1f, |
55 | | REG_SHORT_ADDR_0 = 0x20, |
56 | | REG_SHORT_ADDR_1 = 0x21, |
57 | | REG_PAN_ID_0 = 0x22, |
58 | | REG_PAN_ID_1 = 0x23, |
59 | | REG_IEEE_ADDR_0 = 0x24, |
60 | | REG_IEEE_ADDR_1 = 0x25, |
61 | | REG_IEEE_ADDR_2 = 0x26, |
62 | | REG_IEEE_ADDR_3 = 0x27, |
63 | | REG_IEEE_ADDR_4 = 0x28, |
64 | | REG_IEEE_ADDR_5 = 0x29, |
65 | | REG_IEEE_ADDR_6 = 0x2a, |
66 | | REG_IEEE_ADDR_7 = 0x2b, |
67 | | REG_XAH_CTRL = 0x2c, |
68 | | REG_CSMA_SEED_0 = 0x2d, |
69 | | REG_CSMA_SEED_1 = 0x2e, |
70 | | }; |
71 | | |
72 | | /* --- TRX_STATUS [7] ------------------------------------------------------ */ |
73 | | |
74 | | #define CCA_DONE (1 << 7) |
75 | | |
76 | | /* --- TRX_STATUS [6] ------------------------------------------------------ */ |
77 | | |
78 | | #define CCA_STATUS (1 << 6) |
79 | | |
80 | | /* --- TRX_STATUS [4:0] ---------------------------------------------------- */ |
81 | | |
82 | | #define TRX_STATUS_SHIFT 0 |
83 | | #define TRX_STATUS_MASK 0x0f |
84 | | |
85 | | enum { |
86 | | TRX_STATUS_P_ON = 0x00, /* reset default */ |
87 | | TRX_STATUS_BUSY_RX = 0x01, |
88 | | TRX_STATUS_BUSY_TX = 0x02, |
89 | | TRX_STATUS_RX_ON = 0x06, |
90 | | TRX_STATUS_TRX_OFF = 0x08, |
91 | | TRX_STATUS_PLL_ON = 0x09, |
92 | | TRX_STATUS_SLEEP = 0x0f, |
93 | | TRX_STATUS_BUSY_RX_AACK = 0x11, |
94 | | TRX_STATUS_BUSY_TX_ARET = 0x12, |
95 | | TRX_STATUS_RX_AACK_ON = 0x16, |
96 | | TRX_STATUS_TX_ARET_ON = 0x19, |
97 | | TRX_STATUS_RX_ON_NOCLK = 0x1c, |
98 | | TRX_STATUS_RX_AACK_ON_NOCLK = 0x1d, |
99 | | TRX_STATUS_BUSY_RX_AACK_NOCLK = 0x1e, |
100 | | TRX_STATUS_TRANSITION = 0x1f |
101 | | }; |
102 | | |
103 | | /* --- TRX_STATE [7:5] ----------------------------------------------------- */ |
104 | | |
105 | | #define TRAC_STATUS_SHIFT 5 |
106 | | #define TRAC_STATUS_MASK 7 |
107 | | |
108 | | enum { |
109 | | TRAC_STATUS_SUCCESS = 0, /* reset default */ |
110 | | TRAC_STATUS_SUCCESS_DATA_PENDING = 1, |
111 | | TRAC_STATUS_CHANNEL_ACCESS_FAILURE = 3, |
112 | | TRAC_STATUS_NO_ACK = 5, |
113 | | TRAC_STATUS_INVALID = 7 |
114 | | }; |
115 | | |
116 | | /* --- TRX_CMD [4:0] ----------------------------------------------------- */ |
117 | | |
118 | | #define TRX_CMD_SHIFT 0 |
119 | | #define TRX_CMD_MASK 7 |
120 | | |
121 | | enum { |
122 | | TRX_CMD_NOP = 0x00, /* reset default */ |
123 | | TRX_CMD_TX_START = 0x02, |
124 | | TRX_CMD_FORCE_TRX_OFF = 0x03, |
125 | | TRX_CMD_RX_ON = 0x06, |
126 | | TRX_CMD_TRX_OFF = 0x08, |
127 | | TRX_CMD_PLL_ON = 0x09, |
128 | | TRX_CMD_RX_AACK_ON = 0x16, |
129 | | TRX_CMD_TX_ARET_ON = 0x19, |
130 | | }; |
131 | | |
132 | | /* --- TRX_CTRL_0 [7:6] ---------------------------------------------------- */ |
133 | | |
134 | | #define PAD_IO_SHIFT 6 |
135 | | #define PAD_IO_MASK 3 |
136 | | |
137 | | enum { |
138 | | PAD_IO_2mA, /* reset default */ |
139 | | PAD_IO_4mA, |
140 | | PAD_IO_6mA, |
141 | | PAD_IO_8mA |
142 | | }; |
143 | | |
144 | | /* --- TRX_CTRL_0 [5:4] ---------------------------------------------------- */ |
145 | | |
146 | | #define PAD_IO_CLKM_SHIFT 4 |
147 | | #define PAD_IO_CLKM_MASK 3 |
148 | | |
149 | | enum { |
150 | | PAD_IO_CLKM_2mA, |
151 | | PAD_IO_CLKM_4mA, /* reset default */ |
152 | | PAD_IO_CLKM_5mA, |
153 | | PAD_IO_CLKM_8mA, |
154 | | }; |
155 | | |
156 | | /* --- TRX_CTRL_0 [3] ------------------------------------------------------ */ |
157 | | |
158 | | #define CLKM_SHA_SEL (1 << 3) |
159 | | |
160 | | /* --- TRX_CTRL_0 [2:0] ---------------------------------------------------- */ |
161 | | |
162 | | #define CLKM_CTRL_SHIFT 0 |
163 | | #define CLKM_CTRL_MASK 3 |
164 | | |
165 | | enum { |
166 | | CLKM_CTRL_OFF = 0, |
167 | | CLKM_CTRL_1MHz = 1, /* reset default */ |
168 | | CLKM_CTRL_2MHz = 2, |
169 | | CLKM_CTRL_4MHz = 3, |
170 | | CLKM_CTRL_8MHz = 4, |
171 | | CLKM_CTRL_16MHz = 5 |
172 | | }; |
173 | | |
174 | | /* --- PHY_TX_PWR [7] ------------------------------------------------------ */ |
175 | | |
176 | | #define TX_AUTO_CRC_ON (1 << 7) |
177 | | |
178 | | /* --- PHY_TX_PWR [3:0] ---------------------------------------------------- */ |
179 | | |
180 | | #define TX_PWR_SHIFT 0 |
181 | | #define TX_PWR_MASK 0x0f |
182 | | |
183 | | /* --- PHY_RSSI [7] -------------------------------------------------------- */ |
184 | | |
185 | | #define RX_CRC_VALID (1 << 7) |
186 | | |
187 | | /* --- PHY_RSSI [4:0] ------------------------------------------------------ */ |
188 | | |
189 | | #define RSSI_SHIFT 0 |
190 | | #define RSSI_MASK 0x1f |
191 | | |
192 | | /* --- PHY_CC_CCA [7] ------------------------------------------------------ */ |
193 | | |
194 | | #define CCA_REQUEST (1 << 7) |
195 | | |
196 | | /* --- PHY_CC_CCA [6:5] ---------------------------------------------------- */ |
197 | | |
198 | | #define CCA_MODE_SHIFT 5 |
199 | | #define CCA_MODE_MASK 3 |
200 | | |
201 | | /* --- PHY_CC_CCA [4:0] ---------------------------------------------------- */ |
202 | | |
203 | | #define CHANNEL_SHIFT 0 |
204 | | #define CHANNEL_MASK 0x1f |
205 | | |
206 | | /* --- CCA_THRES [3:0] ----------------------------------------------------- */ |
207 | | |
208 | | #define CCA_ED_THRES_SHIFT 0 |
209 | | #define CCA_ED_THRES_MASK 0x0f |
210 | | |
211 | | /* --- IRQ_MASK/IRQ_STATUS ------------------------------------------------- */ |
212 | | |
213 | | enum { |
214 | | IRQ_PLL_LOCK = 1 << 0, |
215 | | IRQ_PLL_UNLOCK = 1 << 1, |
216 | | IRQ_RX_START = 1 << 2, |
217 | | IRQ_TRX_END = 1 << 3, |
218 | | IRQ_TRX_UR = 1 << 6, |
219 | | IRQ_BAT_LOW = 1 << 7 |
220 | | }; |
221 | | |
222 | | /* --- VREG_CTRL [7, 6, 3, 2] ---------------------------------------------- */ |
223 | | |
224 | | #define AVREG_EXT (1 << 7) |
225 | | #define AVDD_OK (1 << 6) |
226 | | #define DVREG_EXT (1 << 3) |
227 | | #define DVDD_OK (1 << 2) |
228 | | |
229 | | /* --- BATMON [5, 4] ------------------------------------------------------- */ |
230 | | |
231 | | #define BATMON_OK (1 << 5) |
232 | | #define BATMON_HR (1 << 4) |
233 | | |
234 | | /* --- BATMON [3:0] -------------------------------------------------------- */ |
235 | | |
236 | | #define NATMON_VTH_SHIFT 0 |
237 | | #define NATMON_VTH_MASK 0x0f |
238 | | |
239 | | /* --- XOSC_CTRL [7:4] ----------------------------------------------------- */ |
240 | | |
241 | | #define XTAL_MODE_SHIFT 4 |
242 | | #define XTAL_MODE_MASK 0x0f |
243 | | |
244 | | enum { |
245 | | XTAL_MODE_OFF = 0x0, |
246 | | XTAL_MODE_EXT = 0x4, |
247 | | XTAL_MODE_INT = 0xf /* reset default */ |
248 | | }; |
249 | | |
250 | | /* --- XOSC_CTRL [3:1] ----------------------------------------------------- */ |
251 | | |
252 | | #define XTAL_TRIM_SHIFT 4 |
253 | | #define XTAL_TRIM_MASK 0x0f |
254 | | |
255 | | /* --- XAH_CTRL [7:4] ------------------------------------------------------ */ |
256 | | |
257 | | #define MAX_FRAME_RETRIES_SHIFT 4 |
258 | | #define MAX_FRAME_RETRIES_MASK 0x0f |
259 | | #define MAX_CSMA_RETRIES_SHIFT 1 |
260 | | #define MAX_CSMA_RETRIES_MASK 0x07 |
261 | | |
262 | | /* --- PLL_CF [7] ---------------------------------------------------------- */ |
263 | | |
264 | | #define PLL_CF_START (1 << 7) |
265 | | |
266 | | /* --- PLL_DCU [8] --------------------------------------------------------- */ |
267 | | |
268 | | #define PLL_DCU_START (1 << 7) |
269 | | |
270 | | /* --- CSMA_SEED_1 [7:6] --------------------------------------------------- */ |
271 | | |
272 | | #define MIN_BE_SHIFT 6 |
273 | | #define MIN_BE_MASK 3 |
274 | | |
275 | | /* --- CSMA_SEED_1 [5] ----------------------------------------------------- */ |
276 | | |
277 | | #define AACK_SET_PD (1 << 5) |
278 | | |
279 | | /* --- CSMA_SEED_1 [3] ----------------------------------------------------- */ |
280 | | |
281 | | #define I_AM_COORD (1 << 3) |
282 | | |
283 | | /* --- CSMA_SEED_1 [2:0] --------------------------------------------------- */ |
284 | | |
285 | | #define CSMA_SEED_1_SHIFT 0 |
286 | | #define CSMA_SEED_1_MASK 7 |
287 | | |
288 | | #endif /* !AT86RF230_H */ |
tools/atspi-id/atspi-id.c |
1 | | /* |
2 | | * atspi-id/atspi-id.c - Identify a ben-wpan AF86RF230 board |
3 | | * |
4 | | * Written 2010 by Werner Almesberger |
5 | | * Copyright 2010 Werner Almesberger |
6 | | * |
7 | | * This program is free software; you can redistribute it and/or modify |
8 | | * it under the terms of the GNU General Public License as published by |
9 | | * the Free Software Foundation; either version 2 of the License, or |
10 | | * (at your option) any later version. |
11 | | */ |
12 | | |
13 | | |
14 | | #include <stdlib.h> |
15 | | #include <stdio.h> |
16 | | #include <usb.h> |
17 | | |
18 | | #include "at86rf230.h" |
19 | | #include "atspi/ep0.h" |
20 | | #include "atspi.h" |
21 | | |
22 | | |
23 | | #define FROM_DEV ATSPI_FROM_DEV(0) |
24 | | |
25 | | #define BUF_SIZE 256 |
26 | | |
27 | | |
28 | | |
29 | | static int get_id(usb_dev_handle *dev, void *data, int size) |
30 | | { |
31 | | int res; |
32 | | |
33 | | res = usb_control_msg(dev, FROM_DEV, ATSPI_ID, 0, 0, data, size, 1000); |
34 | | if (res < 0) |
35 | | fprintf(stderr, "ATSPI_ID: %s\n", usb_strerror()); |
36 | | return res; |
37 | | } |
38 | | |
39 | | |
40 | | static int atspi_get_protocol(usb_dev_handle *dev, |
41 | | uint8_t *major, uint8_t *minor, uint8_t *target) |
42 | | { |
43 | | uint8_t ids[3]; |
44 | | |
45 | | if (get_id(dev, ids, 3) < 0) |
46 | | return -1; |
47 | | if (major) |
48 | | *major = ids[0]; |
49 | | if (minor) |
50 | | *minor = ids[1]; |
51 | | if (target) |
52 | | *target = ids[2]; |
53 | | |
54 | | return 0; |
55 | | } |
56 | | |
57 | | |
58 | | static int atspi_get_build(usb_dev_handle *dev, char *buf, size_t size) |
59 | | { |
60 | | int res; |
61 | | |
62 | | res = usb_control_msg(dev, FROM_DEV, ATSPI_BUILD, 0, 0, buf, size, |
63 | | 1000); |
64 | | if (res < 0) |
65 | | fprintf(stderr, "ATSPI_BUILD: %s\n", usb_strerror()); |
66 | | return res; |
67 | | } |
68 | | |
69 | | |
70 | | static void show_info(usb_dev_handle *dev) |
71 | | { |
72 | | const struct usb_device *device = usb_device(dev); |
73 | | uint8_t major, minor, target; |
74 | | char buf[BUF_SIZE+1]; /* +1 for terminating \0 */ |
75 | | int len; |
76 | | uint8_t part, version, man_id_0, man_id_1; |
77 | | |
78 | | printf("%04x:%04x ", |
79 | | device->descriptor.idVendor, device->descriptor.idProduct); |
80 | | |
81 | | if (atspi_get_protocol(dev, &major, &minor, &target) < 0) |
82 | | exit(1); |
83 | | printf("protocol %u.%u hw %u\n", major, minor, target); |
84 | | |
85 | | len = atspi_get_build(dev, buf, sizeof(buf)-1); |
86 | | if (len < 0) |
87 | | exit(1); |
88 | | buf[len] = 0; |
89 | | printf("%10s%s\n", "", buf); |
90 | | |
91 | | part = atspi_reg_read(dev, REG_PART_NUM); |
92 | | version = atspi_reg_read(dev, REG_VERSION_NUM); |
93 | | man_id_0 = atspi_reg_read(dev, REG_MAN_ID_0); |
94 | | man_id_1 = atspi_reg_read(dev, REG_MAN_ID_1); |
95 | | printf("%10spart 0x%02x version %u manufacturer xxxx%02x%02x\n", "", |
96 | | part, version, man_id_1, man_id_0); |
97 | | } |
98 | | |
99 | | |
100 | | static void usage(const char *name) |
101 | | { |
102 | | fprintf(stderr, "%s\n", name); |
103 | | exit(1); |
104 | | } |
105 | | |
106 | | |
107 | | int main(int argc, const char **argv) |
108 | | { |
109 | | usb_dev_handle *dev; |
110 | | |
111 | | if (argc != 1) |
112 | | usage(*argv); |
113 | | dev = atspi_open(); |
114 | | if (!dev) |
115 | | return 1; |
116 | | |
117 | | show_info(dev); |
118 | | |
119 | | return 0; |
120 | | } |
tools/atspi-rssi/atspi-rssi.c |
1 | | /* |
2 | | * atspi-rssi/atspi-rssi.c - ben-wpan AF86RF230 spectrum scan |
3 | | * |
4 | | * Written 2010 by Werner Almesberger |
5 | | * Copyright 2010 Werner Almesberger |
6 | | * |
7 | | * This program is free software; you can redistribute it and/or modify |
8 | | * it under the terms of the GNU General Public License as published by |
9 | | * the Free Software Foundation; either version 2 of the License, or |
10 | | * (at your option) any later version. |
11 | | */ |
12 | | |
13 | | |
14 | | #include <stdlib.h> |
15 | | #include <stdio.h> |
16 | | #include <usb.h> |
17 | | #include <sys/time.h> |
18 | | |
19 | | #include "at86rf230.h" |
20 | | #include "atspi/ep0.h" |
21 | | #include "atspi.h" |
22 | | |
23 | | |
24 | | #define FROM_DEV ATSPI_FROM_DEV(0) |
25 | | #define TO_DEV ATSPI_TO_DEV(0) |
26 | | |
27 | | |
28 | | static struct timeval t0; |
29 | | |
30 | | |
31 | | static void sweep(usb_dev_handle *dev) |
32 | | { |
33 | | int chan, rssi; |
34 | | struct timeval t; |
35 | | |
36 | | for (chan = 11; chan <= 26; chan++) { |
37 | | atspi_reg_write(dev, REG_PHY_CC_CCA, chan); |
38 | | /* |
39 | | * No need to explicitly wait for the PPL lock - going USB-SPI |
40 | | * is pretty slow, leaving the transceiver plenty of time. |
41 | | */ |
42 | | gettimeofday(&t, NULL); |
43 | | rssi = atspi_reg_read(dev, REG_PHY_RSSI) & RSSI_MASK; |
44 | | t.tv_sec -= t0.tv_sec; |
45 | | t.tv_usec -= t0.tv_usec; |
46 | | printf("%d %f %d\n", |
47 | | 2405+(chan-11)*5, |
48 | | (double) t.tv_sec+t.tv_usec/1000000.0, |
49 | | -91+3*(rssi-1)); |
50 | | } |
51 | | printf("\n"); |
52 | | } |
53 | | |
54 | | |
55 | | static void usage(const char *name) |
56 | | { |
57 | | fprintf(stderr, "%s sweeps \n", name); |
58 | | exit(1); |
59 | | } |
60 | | |
61 | | |
62 | | int main(int argc, const char **argv) |
63 | | { |
64 | | usb_dev_handle *dev; |
65 | | unsigned long sweeps, i; |
66 | | char *end; |
67 | | |
68 | | if (argc != 2) |
69 | | usage(*argv); |
70 | | sweeps = strtoul(argv[1], &end, 0); |
71 | | if (*end) |
72 | | usage(*argv); |
73 | | |
74 | | dev = atspi_open(); |
75 | | if (!dev) |
76 | | return 1; |
77 | | |
78 | | atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_TRX_OFF); |
79 | | /* |
80 | | * No need to explicitly wait for things to stabilize - going USB-SPI |
81 | | * is pretty slow, leaving the transceiver more than enough time. |
82 | | */ |
83 | | atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_RX_ON); |
84 | | |
85 | | gettimeofday(&t0, NULL); |
86 | | for (i = 0; i != sweeps; i++) |
87 | | sweep(dev); |
88 | | |
89 | | atspi_reg_write(dev, REG_TRX_STATE, TRX_CMD_TRX_OFF); |
90 | | |
91 | | return 0; |
92 | | } |
tools/lib/atspi.c |
1 | | /* |
2 | | * lib/atspi.c - ATSPI access functions library |
3 | | * |
4 | | * Written 2010 by Werner Almesberger |
5 | | * Copyright 2010 Werner Almesberger |
6 | | * |
7 | | * This program is free software; you can redistribute it and/or modify |
8 | | * it under the terms of the GNU General Public License as published by |
9 | | * the Free Software Foundation; either version 2 of the License, or |
10 | | * (at your option) any later version. |
11 | | */ |
12 | | |
13 | | |
14 | | #include <stdio.h> |
15 | | #include <usb.h> |
16 | | |
17 | | #include "f32xbase/usb.h" |
18 | | #include "atspi/ep0.h" |
19 | | #include "atspi/usb-ids.h" |
20 | | |
21 | | #include "atspi.h" |
22 | | |
23 | | |
24 | | #define FROM_DEV ATSPI_FROM_DEV(0) |
25 | | #define TO_DEV ATSPI_TO_DEV(0) |
26 | | |
27 | | |
28 | | /* ----- error handling ---------------------------------------------------- */ |
29 | | |
30 | | |
31 | | static int error; |
32 | | |
33 | | |
34 | | int atspi_error(void) |
35 | | { |
36 | | return error; |
37 | | } |
38 | | |
39 | | |
40 | | int atspi_clear_error(void) |
41 | | { |
42 | | int ret; |
43 | | |
44 | | ret = error; |
45 | | error = 0; |
46 | | return ret; |
47 | | } |
48 | | |
49 | | |
50 | | /* ----- open/close -------------------------------------------------------- */ |
51 | | |
52 | | |
53 | | usb_dev_handle *atspi_open(void) |
54 | | { |
55 | | usb_dev_handle *dev; |
56 | | |
57 | | dev = open_usb(USB_VENDOR, USB_PRODUCT); |
58 | | if (dev) { |
59 | | error = 0; |
60 | | } else { |
61 | | fprintf(stderr, ":-(\n"); |
62 | | error = 1; |
63 | | } |
64 | | return dev; |
65 | | } |
66 | | |
67 | | |
68 | | void atspi_close(usb_dev_handle *dev) |
69 | | { |
70 | | /* to do */ |
71 | | } |
72 | | |
73 | | |
74 | | /* ----- device mode ------------------------------------------------------- */ |
75 | | |
76 | | |
77 | | void atspi_reset(usb_dev_handle *dev) |
78 | | { |
79 | | int res; |
80 | | |
81 | | if (error) |
82 | | return; |
83 | | |
84 | | res = |
85 | | usb_control_msg(dev, TO_DEV, ATSPI_RESET, 0, 0, NULL, 0, 1000); |
86 | | if (res < 0) { |
87 | | fprintf(stderr, "ATSPI_RESET: %d\n", res); |
88 | | error = 1; |
89 | | } |
90 | | } |
91 | | |
92 | | |
93 | | void atspi_reset_rf(usb_dev_handle *dev) |
94 | | { |
95 | | int res; |
96 | | |
97 | | if (error) |
98 | | return; |
99 | | |
100 | | res = |
101 | | usb_control_msg(dev, TO_DEV, ATSPI_RF_RESET, 0, 0, NULL, 0, 1000); |
102 | | if (res < 0) { |
103 | | fprintf(stderr, "ATSPI_RF_RESET: %d\n", res); |
104 | | error = 1; |
105 | | } |
106 | | } |
107 | | |
108 | | |
109 | | /* ----- register access --------------------------------------------------- */ |
110 | | |
111 | | |
112 | | void atspi_reg_write(usb_dev_handle *dev, uint8_t reg, uint8_t value) |
113 | | { |
114 | | int res; |
115 | | |
116 | | if (error) |
117 | | return; |
118 | | |
119 | | res = usb_control_msg(dev, TO_DEV, ATSPI_REG_WRITE, value, reg, |
120 | | NULL, 0, 1000); |
121 | | if (res < 0) { |
122 | | fprintf(stderr, "ATSPI_REG_WRITE: %d\n", res); |
123 | | error = 1; |
124 | | } |
125 | | } |
126 | | |
127 | | |
128 | | uint8_t atspi_reg_read(usb_dev_handle *dev, uint8_t reg) |
129 | | { |
130 | | uint8_t value = 0; |
131 | | int res; |
132 | | |
133 | | if (error) |
134 | | return 0; |
135 | | |
136 | | res = usb_control_msg(dev, FROM_DEV, ATSPI_REG_READ, 0, reg, |
137 | | (void *) &value, 1, 1000); |
138 | | if (res < 0) { |
139 | | fprintf(stderr, "ATSPI_REG_READ: %d\n", res); |
140 | | error = 1; |
141 | | } |
142 | | return value; |
143 | | } |