diff options
author | Mike Ossmann <mike@ossmann.com> | 2011-08-04 04:21:34 +0000 |
---|---|---|
committer | Mike Ossmann <mike@ossmann.com> | 2011-08-04 04:21:34 +0000 |
commit | 7e8bf630c71dddede1486421cf4e2479ab0e9b95 (patch) | |
tree | 0724b35cd8aef4b3364badf672aa7d64313df62c | |
parent | f1ce18792283db94bcf22c9e8879a2522c861593 (diff) |
added assembly_test firmware and procedure
-rw-r--r-- | firmware/Makefile | 2 | ||||
-rw-r--r-- | firmware/README | 15 | ||||
-rw-r--r-- | firmware/assembly_test/Makefile | 23 | ||||
-rw-r--r-- | firmware/assembly_test/README | 165 | ||||
-rw-r--r-- | firmware/assembly_test/assembly_test.c | 1273 | ||||
-rw-r--r-- | firmware/bluetooth_rxtx/bluetooth_rxtx.c | 21 | ||||
-rw-r--r-- | firmware/common.mk | 2 | ||||
-rw-r--r-- | web/content/hardware/build.html | 4 |
8 files changed, 1467 insertions, 38 deletions
diff --git a/firmware/Makefile b/firmware/Makefile index 7eed09c..80dc0ed 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -19,7 +19,7 @@ # the Free Software Foundation, Inc., 51 Franklin Street, # Boston, MA 02110-1301, USA. -DIRS = blinky bluetooth_rxtx cc2400_test clock_test usb_test bootloader +DIRS = blinky bluetooth_rxtx cc2400_test clock_test usb_test bootloader assembly_test all: -for d in $(DIRS); do (cd $$d; $(MAKE) all ); done diff --git a/firmware/README b/firmware/README index 7e913db..eafea36 100644 --- a/firmware/README +++ b/firmware/README @@ -1,17 +1,6 @@ -For testing a new board, the recommended sequence is: +For testing a new board, see: assembly_test/README - 1. install bootloader using ISP (e.g. Pogoprog) or JTAG - - 2. use bootloader to install and test the following applications in - sequence (see ../host/usb_dfu/README): - - a. blinky - b. cc2400_test - c. clock_test - d. usb_test - e. bluetooth_rxtx - -The preferred firmware for Bluetooth functions is bluetooth_rxtx. +The general purpose firmware including Bluetooth functions is bluetooth_rxtx. The default hardware target is Ubertooth One. If you are compiling for Ubertooth Zero, you must set the environment variable BOARD=UBERTOOTH_ZERO. diff --git a/firmware/assembly_test/Makefile b/firmware/assembly_test/Makefile new file mode 100644 index 0000000..09860bf --- /dev/null +++ b/firmware/assembly_test/Makefile @@ -0,0 +1,23 @@ +# Hey Emacs, this is a -*- makefile -*- + +# Target file name (without extension). +TARGET = assembly_test + +# List C source files here. (C dependencies are automatically generated.) +SRC = $(TARGET).c \ + $(LIBS_PATH)/usb_serial.c \ + $(LIBS_PATH)/serial_fifo.c \ + $(LIBS_PATH)/LPC17xx_Startup.c \ + $(LIBS_PATH)/LPC17xx_Interrupts.c \ + $(LIBS_PATH)/ubertooth.c \ + $(LPCUSB_PATH)/usbcontrol.c \ + $(LPCUSB_PATH)/usbinit.c \ + $(LPCUSB_PATH)/usbhw_lpc.c \ + $(LPCUSB_PATH)/usbstdreq.c + +# The assembly_test firmware should be installed via ISP or JTAG without a +# bootloader present. After the test succeeds, install the bootloader with ISP +# or JTAG. +LINKER_SCRIPT = LPC17xx_Linker_Script_without_bootloader.ld + +include ../common.mk diff --git a/firmware/assembly_test/README b/firmware/assembly_test/README new file mode 100644 index 0000000..b9dfb8a --- /dev/null +++ b/firmware/assembly_test/README @@ -0,0 +1,165 @@ +Follow this procedure to test, rework, and program a new Ubertooth One. For +reference, see ubertooth-one-hardware/ubertooth-one-assembly.pdf and +ubertooth-one-hardware/ubertooth-one-schematic.pdf in the release package or +use KiCad to view the design files located in hardware/ubertooth-one. + + +Required Equipment + + - Equipment Under Test (EUT): Ubertooth One with 2 dBi antenna + + - Personal Computer (PC) with two open USB ports + + - Pogoprog, a serial programmer for Ubertooth One + + - USB Mini-B cable to connect Pogoprog to PC + + - USB A extension cable or USB hub to allow access to underside of Ubertooth + One while it is plugged into the PC + + - A Bluetooth device such as a mobile phone + + - Multi-meter (voltmeter and continuity tester) + + +Required Software + + - lpc21isp + + +Visual Inspection + + 1. Check EUT for missing components. + + 2. Check that components are installed with the correct orientation and + placement. + + 3. Check in particular that R1 and C12 are not soldered together (one side, + GND, may be together, but the side closest to U1 should not be). + + +Electrical Inspection + + 1. Verify no conductivity across C18. + + 2. Verify no conductivity across C22. + + 3. Verify no conductivity across C32. + + If shorts are detected, carefully inspect (in order) the three capacitors + listed above, the voltage regulator (U7), bypass capacitors, and all IC pins. + + +Power On EUT + + 1. Connect to EUT the 2 dBi antenna. Check that the antenna fully screws + onto the RP-SMA connector. + + 2. Plug EUT in to PC with USB A extension cable or USB hub. + + 3. The "RST" LED (D5) should be illuminated. No other LED should be fully + illuminated, though they may be dimly lit. D5 indicates that U4 has been + powered on and passed reset. If D5 does not illuminate, check D5, R8, R9, + and pins 11 and 14 on U4. + + +Program EUT with assembly_test Firmware + + 1. Ensure EUT is plugged into PC. + + 2. Plug Pogoprog into PC with USB Mini-B cable. + + 3. Hold Pogoprog against the "PROGRAM" pads on the underside of EUT as shown + in the photograph: + + http://ubertooth.sourceforge.net/hardware/program/ + + 4. on the PC, execute: + + $ make program + + If you have not yet compiled the assembly_test firmware, you will need to + have a gcc/arm environment set up. See: + + http://ubertooth.sourceforge.net/firmware/develop/ + + 5. The 'make program' command will indicate "Download Finished . . . Now + launching the brand new code" if successful. If it was not successful, check + the orientation and contact between the Pogoprog and sample Ubertooth One, + make sure both are plugged in, and try again. + + +Automated Test + + 1. Unplug EUT from PC and plug back in. + + 2. "RST" LED (D5) should illuminate immediately and remain on throughout this + test. + + 3. "TX" LED (D2), "RX" LED (D3), and "USR" LED (D4) should flash twice + together. Flashing indicates that the test program is executing on U4. If + any of the three LEDs do not flash, check that LED, the adjacent resistor, + and pins 73, 74, and 75 of U4. + + 4. Next, "1V8" LED (D1) should illuminate and remain on. This indicates that + U3 is powered on. If D1 does not illuminate, check D1, R3, R4, U7, and pin + 72 of U4. + + 5. Next, "TX" LED (D2) should flash twice and then illuminate and remain on. + This indicates that U4 is able to communicate with U3. If D2 does not flash + and illuminate, check pins 25-35 on U3 and pins 53, 54, 58, 59, 60, and 70 on + U4. Check that there is a 1.8 Volt potential across C18. Check that there + is a 3.3 Volt potential across C25. + + 6. Next, "RX" LED (D3) should flash four times quickly and then illuminate + and remain on. This indicates that the 16 MHz crystal oscillator is active + and supplying clock to both U3 and U4. If D3 does not flash and illuminate, + check X1, C19, C21, C29, C31, pins 21, 42, and 43 on U3, and pins 19 and 20 + on U4. + + 7. At this point, four LEDs (D1, D2, D3, and D5) should all be on. + + 8. Use a mobile phone or other Bluetooth device approximately 1 meter away + from EUT to initiate an inquiry. This function is typically called “search + for new Bluetooth devices” or similar. + + 9. During the inquiry, "USR" LED (D4) may flash and should then illuminate + and remain on. If D4 flashes but does not remain on after the inquiry, this + indicates that RF performance is poor. If D4 does not flash at all, this + indicates a total RF failure. Check that a 2 dBi antenna is securely + connected to P1. Check L1, L2, C1, C3, and C5. Check all pins on U1 and U3. + Check R1, R2, and R17. Check all bypass capacitors around U1 and U3. Check + pins 50, 51, 61, 62, 63, 64, 65, 68, and 69 on U4. + + 10. After D4 illuminates, the "USB" LED (D6) may flash and should then + illuminate and remain on. This indicates that the PC has established USB + communication with EUT. With some non-Linux operating systems, D6 may not + illuminate. Depending on the OS running on the PC, you might see a "found + new hardware" or "install device driver software" dialog instead of + illumination of D6. You should be able to use operating system logging or + reporting (e.g. dmesg on Linux) to see that a USB device with the product + name "ubertooth assembly_test" has been detected. This indicates success. + Cancel any dialog and visually inspect D6 and R15. + + 11. If all six LEDs are on (with the possible exception of D6 as mentioned + above), the Automated Test is successful. To repeat the Automated Test, + unplug EUT from PC and plug in again. + + +Test Complete + + If your Ubertooth One has passed the assembly test procedure, the recommended + next steps are: + + 1. Install the USB bootloader on your Ubertooth One. See: + + firmware/bootloader/README + + 2. Use the bootloader to install the bluetooth_rxtx application firmware. + See: + + host/usb_dfu/README + + 3. Follow the Getting Started guide: + + http://ubertooth.sourceforge.net/usage/start/ diff --git a/firmware/assembly_test/assembly_test.c b/firmware/assembly_test/assembly_test.c new file mode 100644 index 0000000..68ed10d --- /dev/null +++ b/firmware/assembly_test/assembly_test.c @@ -0,0 +1,1273 @@ +/* + * Copyright 2010 Michael Ossmann + * + * This file is part of Project Ubertooth. + * + * 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, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, + * Boston, MA 02110-1301, USA. + */ + +/* + LPCUSB, an USB device driver for LPC microcontrollers + Copyright (C) 2006 Bertrik Sikken (bertrik@sikken.nl) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "ubertooth.h" +#include "usbapi.h" +#include "usbhw_lpc.h" + +#define IAP_LOCATION 0x1FFF1FF1 +typedef void (*IAP)(u32[], u32[]); +IAP iap_entry = (IAP)IAP_LOCATION; + +/* + * CLK100NS is a free-running clock with a period of 100ns. It resets every + * 2^15 * 10^5 cycles (about 5.5 minutes) and is used to compute CLKN. + * + * CLKN is the native (local) clock as defined in the Bluetooth specification. + * It advances 3200 times per second. Two CLKN periods make a Bluetooth time + * slot. + */ + +#define CLK100NS T0TC +volatile u8 clkn_high; +#define CLKN ((clkn_high << 20) | (CLK100NS / 3125)) + +#define BULK_IN_EP 0x82 +#define BULK_OUT_EP 0x05 + +#define MAX_PACKET_SIZE 64 + +#define LE_WORD(x) ((x)&0xFF),((x)>>8) + +/* DMA buffers */ +#define DMA_SIZE 50 +u8 rxbuf1[DMA_SIZE]; +u8 rxbuf2[DMA_SIZE]; + +/* + * The active buffer is the one with an active DMA transfer. + * The idle buffer is the one we can read/write between transfers. + */ +u8 *active_rxbuf = &rxbuf1[0]; +u8 *idle_rxbuf = &rxbuf2[0]; + +enum ubertooth_usb_commands { + UBERTOOTH_PING = 0, + UBERTOOTH_RX_SYMBOLS = 1, + UBERTOOTH_TX_SYMBOLS = 2, /* not implemented */ + UBERTOOTH_GET_USRLED = 3, + UBERTOOTH_SET_USRLED = 4, + UBERTOOTH_GET_RXLED = 5, + UBERTOOTH_SET_RXLED = 6, + UBERTOOTH_GET_TXLED = 7, + UBERTOOTH_SET_TXLED = 8, + UBERTOOTH_GET_1V8 = 9, + UBERTOOTH_SET_1V8 = 10, + UBERTOOTH_GET_CHANNEL = 11, + UBERTOOTH_SET_CHANNEL = 12, + UBERTOOTH_RESET = 13, + UBERTOOTH_GET_SERIAL = 14, + UBERTOOTH_GET_PARTNUM = 15, + UBERTOOTH_GET_PAEN = 16, + UBERTOOTH_SET_PAEN = 17, + UBERTOOTH_GET_HGM = 18, + UBERTOOTH_SET_HGM = 19, + UBERTOOTH_TX_TEST = 20, + UBERTOOTH_STOP = 21, + UBERTOOTH_GET_MOD = 22, + UBERTOOTH_SET_MOD = 23, + UBERTOOTH_SET_ISP = 24, + UBERTOOTH_FLASH = 25, + BOOTLOADER_FLASH = 26, /* do not implement */ + UBERTOOTH_SPECAN = 27, + UBERTOOTH_GET_PALEVEL = 28, + UBERTOOTH_SET_PALEVEL = 29, + UBERTOOTH_REPEATER = 30, + UBERTOOTH_RANGE_TEST = 31, + UBERTOOTH_RANGE_CHECK = 32, + UBERTOOTH_GET_REV_NUM = 33 +}; + +enum operating_modes { + MODE_IDLE = 0, + MODE_RX_SYMBOLS = 1, + MODE_TX_SYMBOLS = 2, + MODE_TX_TEST = 3, + MODE_SPECAN = 4, + MODE_RANGE_TEST = 5, + MODE_REPEATER = 6 +}; + +enum modulations { + MOD_BT_BASIC_RATE = 0, + MOD_BT_LOW_ENERGY = 1, + MOD_80211_FHSS = 2 +}; + +typedef struct { + u8 valid; + u8 request_pa; + u8 request_num; + u8 reply_pa; + u8 reply_num; +} rangetest_result; + +rangetest_result rr; + +volatile u32 mode = MODE_IDLE; +volatile u32 requested_mode = MODE_IDLE; +volatile u32 modulation = MOD_BT_BASIC_RATE; +volatile u16 channel = 2441; +volatile u16 low_freq = 2400; +volatile u16 high_freq = 2483; + +/* DMA linked list items */ +typedef struct { + u32 src; + u32 dest; + u32 next_lli; + u32 control; +} dma_lli; + +dma_lli rx_dma_lli1; +dma_lli rx_dma_lli2; + +/* rx terminal count and error interrupt counters */ +volatile u32 rx_tc; +volatile u32 rx_err; + +/* number of rx USB packets to send */ +volatile u32 rx_pkts = 0; + +/* status information byte */ +volatile u8 status = 0; + +#define DMA_OVERFLOW 0x01 +#define DMA_ERROR 0x02 +#define FIFO_OVERFLOW 0x04 + +/* + * USB packet for Bluetooth RX (64 total bytes) + */ +typedef struct { + u8 pkt_type; + u8 status; + u8 channel; + u8 clkn_high; + u32 clk100ns; + u8 reserved[6]; + u8 data[DMA_SIZE]; +} usb_pkt_rx; + +/* + * This is supposed to be a lock-free ring buffer, but I haven't verified + * atomicity of the operations on head and tail. + */ + +usb_pkt_rx fifo[128]; + +volatile u32 head = 0; +volatile u32 tail = 0; + +void queue_init() +{ + head = 0; + tail = 0; +} + +int enqueue(u8 *buf) +{ + int i; + u8 h = head & 0x7F; + u8 t = tail & 0x7F; + u8 n = (t + 1) & 0x7F; + + /* fail if queue is full */ + if (h == n) + return 0; + + fifo[t].clkn_high = clkn_high; + fifo[t].clk100ns = CLK100NS; + + USRLED_SET; + for (i = 0; i < DMA_SIZE; i++) + fifo[t].data[i] = buf[i]; + fifo[t].status = status; + status = 0; + ++tail; + + return 1; +} + +int dequeue() +{ + u8 h = head & 0x7F; + u8 t = tail & 0x7F; + + /* fail if queue is empty */ + if (h == t) { + USRLED_CLR; + return 0; + } + + USBHwEPWrite(BULK_IN_EP, (u8 *)&fifo[h], sizeof(usb_pkt_rx)); + ++head; + + return 1; +} + +static const u8 abDescriptors[] = { + +/* Device descriptor */ + 0x12, + DESC_DEVICE, + LE_WORD(0x0200), // bcdUSB + 0xFF, // bDeviceClass + 0x00, // bDeviceSubClass + 0x00, // bDeviceProtocol + MAX_PACKET_SIZE0, // bMaxPacketSize + LE_WORD(0xFFFF), // idVendor + LE_WORD(0x0004), // idProduct + LE_WORD(0x0100), // bcdDevice + 0x01, // iManufacturer + 0x02, // iProduct + 0x03, // iSerialNumber + 0x01, // bNumConfigurations + +// configuration + 0x09, + DESC_CONFIGURATION, + LE_WORD(0x20), // wTotalLength + 0x01, // bNumInterfaces + 0x01, // bConfigurationValue + 0x00, // iConfiguration + 0x80, // bmAttributes + 0x32, // bMaxPower + +// interface + 0x09, + DESC_INTERFACE, + 0x00, // bInterfaceNumber + 0x00, // bAlternateSetting + 0x02, // bNumEndPoints + 0xFF, // bInterfaceClass + 0x00, // bInterfaceSubClass + 0x00, // bInterfaceProtocol + 0x00, // iInterface + +// bulk in + 0x07, + DESC_ENDPOINT, + BULK_IN_EP, // bEndpointAddress + 0x02, // bmAttributes = BULK + LE_WORD(MAX_PACKET_SIZE),// wMaxPacketSize + 0, // bInterval + +// bulk out + 0x07, + DESC_ENDPOINT, + BULK_OUT_EP, // bEndpointAddress + 0x02, // bmAttributes = BULK + LE_WORD(MAX_PACKET_SIZE),// wMaxPacketSize + 0, // bInterval + +// string descriptors + 0x04, + DESC_STRING, + LE_WORD(0x0409), + + // manufacturer string + 0x44, + DESC_STRING, + 'h', 0, 't', 0, 't', 0, 'p', 0, ':', 0, '/', 0, '/', 0, 'u', 0, + 'b', 0, 'e', 0, 'r', 0, 't', 0, 'o', 0, 'o', 0, 't', 0, 'h', 0, + '.', 0, 's', 0, 'o', 0, 'u', 0, 'r', 0, 'c', 0, 'e', 0, 'f', 0, + 'o', 0, 'r', 0, 'g', 0, 'e', 0, '.', 0, 'n', 0, 'e', 0, 't', 0, + '/', 0, + + // product string + 0x30, + DESC_STRING, + 'u', 0, 'b', 0, 'e', 0, 'r', 0, 't', 0, 'o', 0, 'o', 0, 't', 0, + 'h', 0, ' ', 0, 'a', 0, 's', 0, 's', 0, 'e', 0, 'm', 0, 'b', 0, + 'l', 0, 'y', 0, '_', 0, 't', 0, 'e', 0, 's', 0, 't', 0, + + // serial number string + 0x12, + DESC_STRING, + '0', 0, '0', 0, '0', 0, '0', 0, '0', 0, '0', 0, '0', 0, '1', 0, + + // terminator + 0 +}; + +static u8 abVendorReqData[17]; + +static void usb_bulk_in_handler(u8 bEP, u8 bEPStatus) +{ + if (!(bEPStatus & EP_STATUS_DATA)) + dequeue(); +} + +static void usb_bulk_out_handler(u8 bEP, u8 bEPStatus) +{ +} + +static BOOL usb_vendor_request_handler(TSetupPacket *pSetup, int *piLen, u8 **ppbData) +{ + u8 *pbData = *ppbData; + u32 command[5]; + u32 result[5]; + + switch (pSetup->bRequest) { + + case UBERTOOTH_PING: + *piLen = 0; + break; + + case UBERTOOTH_RX_SYMBOLS: + rx_pkts += pSetup->wValue; + if (rx_pkts == 0) + rx_pkts = 0xFFFFFFFF; + *piLen = 0; + break; + + case UBERTOOTH_GET_USRLED: + pbData[0] = (USRLED) ? 1 : 0; + *piLen = 1; + break; + + case UBERTOOTH_SET_USRLED: + if (pSetup->wValue) + USRLED_SET; + else + USRLED_CLR; + break; + + case UBERTOOTH_GET_RXLED: + pbData[0] = (RXLED) ? 1 : 0; + *piLen = 1; + break; + + case UBERTOOTH_SET_RXLED: + if (pSetup->wValue) + RXLED_SET; + else + RXLED_CLR; + break; + + case UBERTOOTH_GET_TXLED: + pbData[0] = (TXLED) ? 1 : 0; + *piLen = 1; + break; + + case UBERTOOTH_SET_TXLED: + if (pSetup->wValue) + TXLED_SET; + else + TXLED_CLR; + break; + + case UBERTOOTH_GET_1V8: + pbData[0] = (CC1V8) ? 1 : 0; + *piLen = 1; + break; + + case UBERTOOTH_SET_1V8: + if (pSetup->wValue) + CC1V8_SET; + else + CC1V8_CLR; + break; + + case UBERTOOTH_GET_PARTNUM: + command[0] = 54; /* read part number */ + iap_entry(command, result); + pbData[0] = result[0] & 0xFF; /* status */ + pbData[1] = result[1] & 0xFF; + pbData[2] = (result[1] >> 8) & 0xFF; + pbData[3] = (result[1] >> 16) & 0xFF; + pbData[4] = (result[1] >> 24) & 0xFF; + *piLen = 5; + break; + + case UBERTOOTH_RESET: + reset(); + break; + + case UBERTOOTH_GET_SERIAL: + command[0] = 58; /* read device serial number */ + iap_entry(command, result); + pbData[0] = result[0] & 0xFF; /* status */ + pbData[1] = result[1] & 0xFF; + pbData[2] = (result[1] >> 8) & 0xFF; + pbData[3] = (result[1] >> 16) & 0xFF; + pbData[4] = (result[1] >> 24) & 0xFF; + pbData[5] = result[2] & 0xFF; + pbData[6] = (result[2] >> 8) & 0xFF; + pbData[7] = (result[2] >> 16) & 0xFF; + pbData[8] = (result[2] >> 24) & 0xFF; + pbData[9] = result[3] & 0xFF; + pbData[10] = (result[3] >> 8) & 0xFF; + pbData[11] = (result[3] >> 16) & 0xFF; + pbData[12] = (result[3] >> 24) & 0xFF; + pbData[13] = result[4] & 0xFF; + pbData[14] = (result[4] >> 8) & 0xFF; + pbData[15] = (result[4] >> 16) & 0xFF; + pbData[16] = (result[4] >> 24) & 0xFF; + *piLen = 17; + break; + +#ifdef UBERTOOTH_ONE + case UBERTOOTH_GET_PAEN: + pbData[0] = (PAEN) ? 1 : 0; + *piLen = 1; + break; + + case UBERTOOTH_SET_PAEN: + if (pSetup->wValue) + PAEN_SET; + else + PAEN_CLR; + break; + + case UBERTOOTH_GET_HGM: + pbData[0] = (HGM) ? 1 : 0; + *piLen = 1; + break; + + case UBERTOOTH_SET_HGM: + if (pSetup->wValue) + HGM_SET; + else + HGM_CLR; + break; +#endif + +#ifdef TX_ENABLE + case UBERTOOTH_TX_TEST: + requested_mode = MODE_TX_TEST; + break; + + case UBERTOOTH_GET_PALEVEL: + pbData[0] = cc2400_get(FREND) & 0x7; + *piLen = 1; + break; + + case UBERTOOTH_SET_PALEVEL: + if( pSetup->wValue < 8 ) { + cc2400_set(FREND, 8 | pSetup->wValue); + } else { + return FALSE; + } + break; + + case UBERTOOTH_RANGE_TEST: + requested_mode = MODE_RANGE_TEST; + break; + + case UBERTOOTH_REPEATER: + requested_mode = MODE_REPEATER; + break; +#endif + + case UBERTOOTH_RANGE_CHECK: + pbData[0] = rr.valid; + pbData[1] = rr.request_pa; + pbData[2] = rr.request_num; + pbData[3] = rr.reply_pa; + pbData[4] = rr.reply_num; + *piLen = 5; + break; + + case UBERTOOTH_STOP: + requested_mode = MODE_IDLE; + break; + + case UBERTOOTH_GET_MOD: + pbData[0] = modulation; + *piLen = 1; + break; + + case UBERTOOTH_SET_MOD: + modulation = pSetup->wValue; + break; + + case UBERTOOTH_GET_CHANNEL: + pbData[0] = channel & 0xFF; + pbData[1] = (channel >> 8) & 0xFF; + *piLen = 2; + break; + + case UBERTOOTH_SET_CHANNEL: + channel = pSetup->wValue; + channel = MAX(channel, MIN_FREQ); + channel = MIN(channel, MAX_FREQ); + break; + + case UBERTOOTH_SET_ISP: + command[0] = 57; + iap_entry(command, result); + *piLen = 0; /* should never return */ + break; + + case UBERTOOTH_FLASH: + bootloader_ctrl = DFU_MODE; + reset(); + break; + + case UBERTOOTH_SPECAN: + if (pSetup->wValue < 2049 || pSetup->wValue > 3072 || + pSetup->wIndex < 2049 || pSetup->wIndex > 3072 || + pSetup->wIndex < pSetup->wValue) + return FALSE; + low_freq = pSetup->wValue; + high_freq = pSetup->wIndex; + requested_mode = MODE_SPECAN; + *piLen = 0; + break; + + case UBERTOOTH_GET_REV_NUM: + pbData[0] = SVN_REV_NUM & 0xFF; + pbData[1] = (SVN_REV_NUM >> 8) & 0xFF; + *piLen = 2; + break; + + default: + return FALSE; + } + return TRUE; +} + +int ubertooth_usb_init() +{ + // initialise stack + USBInit(); + + // register device descriptors + USBRegisterDescriptors(abDescriptors); + + // override standard request handler + USBRegisterRequestHandler(REQTYPE_TYPE_VENDOR, usb_vendor_request_handler, abVendorReqData); + + // register endpoints + //USBHwRegisterEPIntHandler(BULK_IN_EP, usb_bulk_in_handler); + //USBHwRegisterEPIntHandler(BULK_OUT_EP, usb_bulk_out_handler); + + // enable USB interrupts + //ISER0 |= ISER0_ISE_USB; + + // connect to bus + USBHwConnect(TRUE); + + return 0; +} + +static void clkn_init() +{ + /* + * Because these are reset defaults, we're assuming TIMER0 is powered on + * and in timer mode. The TIMER0 peripheral clock should have been set to + * cclk/2 (50 MHz) by clock_start(). + */ + + /* stop and reset the timer to zero */ + T0TCR = TCR_Counter_Reset; + clkn_high = 0; + + /* + * The peripheral clock has a period of 20ns. 5 pclk periods makes one + * CLK100NS period (100ns). CLK100NS resets every 2^15 * 10^5 (3276800000) + * steps, roughly 5.5 minutes. + */ + T0PR = 4; + T0MR0 = 3276799999; + T0MCR = TMCR_MR0R | TMCR_MR0I; + ISER0 |= ISER0_ISE_TIMER0; + + /* start timer */ + T0TCR = TCR_Counter_Enable; +} + +/* clkn_high is incremented each time CLK100NS rolls over */ +void TIMER0_IRQHandler() +{ + if (T0IR & TIR_MR0_Interrupt) { + ++clkn_high; + T0IR |= TIR_MR0_Interrupt; + } +} + +static void dma_init() +{ + /* power up GPDMA controller */ + PCONP |= PCONP_PCGPDMA; + + /* zero out channel configs and clear interrupts */ + DMACC0Config = 0; + DMACC1Config = 0; + DMACC2Config = 0; + DMACC3Config = 0; + DMACC4Config = 0; + DMACC5Config = 0; + DMACC6Config = 0; + DMACC7Config = 0; + DMACIntTCClear = 0xFF; + DMACIntErrClr = 0xFF; + + /* DMA linked lists */ + rx_dma_lli1.src = (u32)&(DIO_SSP_DR); + rx_dma_lli1.dest = (u32)&rxbuf1[0]; + rx_dma_lli1.next_lli = (u32)&rx_dma_lli2; + rx_dma_lli1.control = (DMA_SIZE) | + (1 << 12) | /* source burst size = 4 */ + (1 << 15) | /* destination burst size = 4 */ + (0 << 18) | /* source width 8 bits */ + (0 << 21) | /* destination width 8 bits */ + DMACCxControl_DI | /* destination increment */ + DMACCxControl_I; /* terminal count interrupt enable */ + + rx_dma_lli2.src = (u32)&(DIO_SSP_DR); + rx_dma_lli2.dest = (u32)&rxbuf2[0]; + rx_dma_lli2.next_lli = (u32)&rx_dma_lli1; + rx_dma_lli2.control = (DMA_SIZE) | + (1 << 12) | /* source burst size = 4 */ + (1 << 15) | /* destination burst size = 4 */ + (0 << 18) | /* source width 8 bits */ + (0 << 21) | /* destination width 8 bits */ + DMACCxControl_DI | /* destination increment */ + DMACCxControl_I; /* terminal count interrupt enable */ + + /* disable DMA interrupts */ + ISER0 &= ~ISER0_ISE_DMA; + + /* enable DMA globally */ + DMACConfig = DMACConfig_E; + while (!(DMACConfig & DMACConfig_E)); + + /* configure DMA channel 1 */ + DMACC0SrcAddr = rx_dma_lli1.src; + DMACC0DestAddr = rx_dma_lli1.dest; + DMACC0LLI = rx_dma_lli1.next_lli; + DMACC0Control = rx_dma_lli1.control; + DMACC0Config = + DIO_SSP_SRC | + (0x2 << 11) | /* peripheral to memory */ + DMACCxConfig_IE | /* allow error interrupts */ + DMACCxConfig_ITC; /* allow terminal count interrupts */ + + /* reset interrupt counters */ + rx_tc = 0; + rx_err = 0; +} + +void DMA_IRQHandler() +{ + /* interrupt on channel 0 */ + if (DMACIntStat & (1 << 0)) { + if (DMACIntTCStat & (1 << 0)) { + DMACIntTCClear |= (1 << 0); + ++rx_tc; + } + if (DMACIntErrStat & (1 << 0)) { + DMACIntErrClr |= (1 << 0); + ++rx_err; + } + } +} + +static void dio_ssp_start() +{ + /* make sure the (active low) slave select signal is not active */ + DIO_SSEL_SET; + + /* enable rx DMA on DIO_SSP */ + DIO_SSP_DMACR |= SSPDMACR_RXDMAE; + DIO_SSP_CR1 |= SSPCR1_SSE; + + /* enable DMA */ + DMACC0Config |= DMACCxConfig_E; + ISER0 |= ISER0_ISE_DMA; + + /* activate slave select pin */ + DIO_SSEL_CLR; +} + +/* start un-buffered rx */ +void cc2400_rx() +{ + if (modulation == MOD_BT_BASIC_RATE) { + cc2400_set(MANAND, 0x7fff); + cc2400_set(LMTST, 0x2b22); + cc2400_set(MDMTST0, 0x134b); // without PRNG + cc2400_set(GRMDM, 0x0101); // un-buffered mode, GFSK + cc2400_set(FSDIV, channel - 1); // 1 MHz IF + cc2400_set(MDMCTRL, 0x0029); // 160 kHz frequency deviation + } else if (modulation == MOD_BT_LOW_ENERGY) { + cc2400_set(MANAND, 0x7fff); + cc2400_set(LMTST, 0x2b22); + cc2400_set(MDMTST0, 0x134b); // without PRNG + cc2400_set(GRMDM, 0x0101); // un-buffered mode, GFSK + cc2400_set(FSDIV, channel - 1); // 1 MHz IF + cc2400_set(MDMCTRL, 0x0040); // 250 kHz frequency deviation + } else { + /* oops */ + return; + } + while (!(cc2400_status() & XOSC16M_STABLE)); + cc2400_strobe(SFSON); + while (!(cc2400_status() & FS_LOCK)); + cc2400_strobe(SRX); +#ifdef UBERTOOTH_ONE + PAEN_SET; + HGM_SET; +#endif +} + +void cc2400_txtest() +{ +#ifdef TX_ENABLE + if (modulation == MOD_BT_BASIC_RATE) { + cc2400_set(MANAND, 0x7fff); + cc2400_set(LMTST, 0x2b22); + cc2400_set(MDMTST0, 0x334b); // with PRNG + cc2400_set(FSDIV, channel); + cc2400_set(MDMCTRL, 0x0029); // 160 kHz frequency deviation + } else if (modulation == MOD_BT_LOW_ENERGY) { + cc2400_set(MANAND, 0x7fff); + cc2400_set(LMTST, 0x2b22); + cc2400_set(MDMTST0, 0x334b); // with PRNG + cc2400_set(FSDIV, channel); + cc2400_set(MDMCTRL, 0x0040); // 250 kHz frequency deviation + } else { + /* oops */ + return; + } + while (!(cc2400_status() & XOSC16M_STABLE)); + cc2400_strobe(SFSON); + while (!(cc2400_status() & FS_LOCK)); + TXLED_SET; + cc2400_strobe(STX); +#ifdef UBERTOOTH_ONE + PAEN_SET; +#endif + mode = MODE_TX_TEST; +#endif +} + +/* + * This range test transmits a Bluetooth-like (but not Bluetooth compatible) + * packet to a repeater and then receives the repeated packet. It is only + * useful if another device is running cc2400_repeater() some distance away. + * + * The outgoing packet is transmitted at each power amplifier (PA) level from + * lowest to highest. It is sent several times at each level. The repeater + * takes the first packet to be received correctly and repeats it in a similar + * manner. The result should indicate the lowest successful PA level in each + * direction. + * + * The range test packet consists of: + * preamble: 4 bytes + * sync word: 4 bytes + * payload: + * length: 1 byte (21) + * packet type: 1 byte (0 = request; 1 = reply) + * LPC17xx serial number: 16 bytes + * request pa: 1 byte + * request number: 1 byte + * reply pa: 1 byte + * reply number: 1 byte + * crc: 2 bytes + */ + +void cc2400_rangetest() +{ +#ifdef TX_ENABLE + u32 command[5]; + u32 result[5]; + int i; + int j; + u8 len = 22; + u8 pa = 0; + u8 txbuf[len]; + u8 rxbuf[len]; + + mode = MODE_RANGE_TEST; + + txbuf[0] = len - 1; // length of data (rest of payload) + txbuf[1] = 0; // request + + // read device serial number + command[0] = 58; + iap_entry(command, result); + if ((result[0] & 0xFF) != 0) //status check + return; + txbuf[2] = (result[1] >> 24) & 0xFF; + txbuf[3] = (result[1] >> 16) & 0xFF; + txbuf[4] = (result[1] >> 8) & 0xFF; + txbuf[5] = result[1] & 0xFF; + txbuf[6] = (result[2] >> 24) & 0xFF; + txbuf[7] = (result[2] >> 16) & 0xFF; + txbuf[8] = (result[2] >> 8) & 0xFF; + txbuf[9] = result[2] & 0xFF; + txbuf[10] = (result[3] >> 24) & 0xFF; + txbuf[11] = (result[3] >> 16) & 0xFF; + txbuf[12] = (result[3] >> 8) & 0xFF; + txbuf[13] = result[3] & 0xFF; + txbuf[14] = (result[4] >> 24) & 0xFF; + txbuf[15] = (result[4] >> 16) & 0xFF; + txbuf[16] = (result[4] >> 8) & 0xFF; + txbuf[17] = result[4] & 0xFF; + + txbuf[18] = pa; // request pa + txbuf[19] = 0; // request number + txbuf[20] = 0xff; // reply pa + txbuf[21] = 0xff; // reply number + + // Bluetooth-like modulation + cc2400_set(MANAND, 0x7fff); + cc2400_set(LMTST, 0x2b22); + cc2400_set(MDMTST0, 0x134b); + cc2400_set(FSDIV, channel); + cc2400_set(SYNCH, 0xf9ae); + cc2400_set(SYNCL, 0x1584); + cc2400_set(FREND, 8 | pa); + cc2400_set(MDMCTRL, 0x0029); + while (!(cc2400_status() & XOSC16M_STABLE)); + cc2400_strobe(SFSON); + while (!(cc2400_status() & FS_LOCK)); + TXLED_SET; +#ifdef UBERTOOTH_ONE + PAEN_SET; +#endif + for (pa = 0; pa < 8; pa++) { + cc2400_set(FREND, 8 | pa); + txbuf[18] = pa; + for (i = 0; i < 16; i++) { + txbuf[19] = i; + while ((cc2400_get(FSMSTATE) & 0x1f) != STATE_STROBE_FS_ON); + // transmit a packet + for (j = 0; j < len; j++) + cc2400_set8(FIFOREG, txbuf[j]); + cc2400_strobe(STX); + } + } + // sent packet, now look for repeated packet + while ((cc2400_get(FSMSTATE) & 0x1f) != STATE_STROBE_FS_ON); + TXLED_CLR; + cc2400_strobe(SRFOFF); + while ((cc2400_status() & FS_LOCK)); + cc2400_set(FSDIV, channel - 1); + while (!(cc2400_status() & XOSC16M_STABLE)); + cc2400_strobe(SFSON); + while (!(cc2400_status() & FS_LOCK)); + RXLED_SET; + while (1) { + while ((cc2400_get(FSMSTATE) & 0x1f) != STATE_STROBE_FS_ON); + cc2400_strobe(SRX); + while (!(cc2400_status() & SYNC_RECEIVED)); + USRLED_SET; + for (j = 0; j < len; j++) + rxbuf[j] = cc2400_get8(FIFOREG); + if (cc2400_status() & STATUS_CRC_OK) + break; + USRLED_CLR; + } + + // done + while ((cc2400_get(FSMSTATE) & 0x1f) != STATE_STROBE_FS_ON); + cc2400_strobe(SRFOFF); + while ((cc2400_status() & FS_LOCK)); +#ifdef UBERTOOTH_ONE + PAEN_CLR; +#endif + RXLED_CLR; + + // get test result + rr.valid = 1; + rr.request_pa = rxbuf[18]; + rr.request_num = rxbuf[19]; + rr.reply_pa = rxbuf[20]; + rr.reply_num = rxbuf[21]; + + // make sure rx packet is as expected + txbuf[1] = 1; // expected value in rxbuf + for (i = 0; i < 18; i++) + if (rxbuf[i] != txbuf[i]) + rr.valid = 0; + + USRLED_CLR; + mode = MODE_IDLE; + if (requested_mode == MODE_RANGE_TEST) + requested_mode = MODE_IDLE; +#endif +} + +/* This is the repeater implementation to be used with cc2400_rangetest(). */ +void cc2400_repeater() +{ +#ifdef TX_ENABLE + int i; + int j; + u8 len = 22; + u8 pa = 0; + u8 buf[len]; + + mode = MODE_REPEATER; + + //FIXME allow to be turned off + while (1) { + cc2400_set(MANAND, 0x7fff); + cc2400_set(LMTST, 0x2b22); + cc2400_set(MDMTST0, 0x134b); + cc2400_set(FSDIV, channel - 1); + cc2400_set(SYNCH, 0xf9ae); + cc2400_set(SYNCL, 0x1584); + cc2400_set(FREND, 0x0008); // minimum tx power + cc2400_set(MDMCTRL, 0x0029); // 160 kHz frequency deviation + while (!(cc2400_status() & XOSC16M_STABLE)); + cc2400_strobe(SFSON); + while (!(cc2400_status() & FS_LOCK)); + RXLED_SET; + TXLED_CLR; + USRLED_CLR; +#ifdef UBERTOOTH_ONE + PAEN_SET; +#endif + while (1) { + while ((cc2400_get(FSMSTATE) & 0x1f) != STATE_STROBE_FS_ON); + USRLED_CLR; + cc2400_strobe(SRX); + while (!(cc2400_status() & SYNC_RECEIVED)); + USRLED_SET; + for (i = 0; i < len; i++) + buf[i] = cc2400_get8(FIFOREG); + if (cc2400_status() & STATUS_CRC_OK) + break; + } + // got packet, now repeat it + i = 2000000; while (--i); // allow time for requester to switch to rx + USRLED_CLR; + RXLED_CLR; + cc2400_strobe(SRFOFF); + while ((cc2400_status() & FS_LOCK)); + while (!(cc2400_status() & XOSC16M_STABLE)); + cc2400_set(FSDIV, channel); + while (!(cc2400_status() & XOSC16M_STABLE)); + cc2400_strobe(SFSON); + TXLED_SET; + buf[0] = len - 1; // length of data (rest of payload) + buf[1] = 1; // reply + for (pa = 0; pa < 8; pa++) { + cc2400_set(FREND, 8 | pa); + buf[20] = pa; + for (i = 0; i < 16; i++) { + buf[21] = i; + while ((cc2400_get(FSMSTATE) & 0x1f) != STATE_STROBE_FS_ON); + for (j = 0; j < len; j++) + cc2400_set8(FIFOREG, buf[j]); + cc2400_strobe(STX); + } + } + TXLED_CLR; + cc2400_strobe(SRFOFF); + while ((cc2400_status() & FS_LOCK)); + } +#endif +} + +void bt_stream_rx() +{ + u8 *tmp = NULL; + u8 epstat; + int i; + + RXLED_SET; + + queue_init(); + dio_ssp_init(); + dma_init(); + dio_ssp_start(); + cc2400_rx(); + + while (rx_pkts) { + /* wait for DMA transfer */ + while ((rx_tc == 0) && (rx_err == 0)); + if (rx_tc % 2) { + /* swap buffers */ + tmp = active_rxbuf; + active_rxbuf = idle_rxbuf; + idle_rxbuf = tmp; + } + if (rx_err) + status |= DMA_ERROR; + if (rx_tc) { + if (rx_tc > 1) + status |= DMA_OVERFLOW; + if (enqueue(idle_rxbuf)) + --rx_pkts; + else + status |= FIFO_OVERFLOW; + } + + /* send via USB */ + epstat = USBHwEPGetStatus(BULK_IN_EP); + if (!(epstat & EPSTAT_B1FULL)) + dequeue(); + if (!(epstat & EPSTAT_B2FULL)) + dequeue(); + USBHwISR(); + + rx_tc = 0; + rx_err = 0; + } + //FIXME turn off rx + RXLED_CLR; +} + +/* spectrum analysis */ +void specan() +{ + u8 epstat; + u16 f; + u8 i = 0; + u8 buf[DMA_SIZE]; + + RXLED_SET; + + queue_init(); + +#ifdef UBERTOOTH_ONE + PAEN_SET; + //HGM_SET; +#endif + cc2400_set(MANAND, 0x7fff); + cc2400_set(LMTST, 0x2b22); + cc2400_set(MDMTST0, 0x134b); // without PRNG + cc2400_set(GRMDM, 0x0101); // un-buffered mode, GFSK + cc2400_set(MDMCTRL, 0x0029); // 160 kHz frequency deviation + //FIXME maybe set RSSI.RSSI_FILT + while (!(cc2400_status() & XOSC16M_STABLE)); + while ((cc2400_status() & FS_LOCK)); + + while (requested_mode == MODE_SPECAN) { + for (f = low_freq; f < high_freq + 1; f++) { + cc2400_set(FSDIV, f - 1); + cc2400_strobe(SFSON); + while (!(cc2400_status() & FS_LOCK)); + cc2400_strobe(SRX); + + //u32 j = 100; while (--j); //FIXME crude delay + buf[3 * i] = (f >> 8) & 0xFF; + buf[(3 * i) + 1] = f & 0xFF; + buf[(3 * i) + 2] = cc2400_get(RSSI) >> 8; + i++; + if (i == 16) { + //FIXME ought to use different packet type + enqueue(buf); + i = 0; + /* send via USB */ + epstat = USBHwEPGetStatus(BULK_IN_EP); + if (!(epstat & EPSTAT_B1FULL)) + dequeue(); + if (!(epstat & EPSTAT_B2FULL)) + dequeue(); + USBHwISR(); + } + + cc2400_strobe(SRFOFF); + while ((cc2400_status() & FS_LOCK)); + } + } + mode = MODE_IDLE; + RXLED_CLR; +} + +/* an ugly but effective way to identify a GIAC (inquiry packet) */ +int find_giac(u8 *buf) +{ + int i, j; + const uint8_t giac[8][7] = { + {0x47, 0x5c, 0x58, 0xcc, 0x73, 0x34, 0x5e}, + {0x8e, 0xb8, 0xb1, 0x98, 0xe6, 0x68, 0xbc}, + {0x11, 0xd7, 0x16, 0x33, 0x1c, 0xcd, 0x17}, + {0x23, 0xae, 0x2c, 0x66, 0x39, 0x9a, 0x2f}, + {0x75, 0xc5, 0x8c, 0xc7, 0x33, 0x45, 0xe7}, + {0xeb, 0x8b, 0x19, 0x8e, 0x66, 0x8b, 0xce}, + {0x1d, 0x71, 0x63, 0x31, 0xcc, 0xd1, 0x79}, + {0x3a, 0xe2, 0xc6, 0x63, 0x99, 0xa2, 0xf3}}; + + for (i = 0; i < (DMA_SIZE - 6); i++) + for (j = 0; j < 8; j++) + if (buf[i] == giac[j][0] + && buf[i + 1] == giac[j][1] + && buf[i + 2] == giac[j][2] + && buf[i + 3] == giac[j][3] + && buf[i + 4] == giac[j][4] + && buf[i + 5] == giac[j][5] + && buf[i + 6] == giac[j][6]) + return 1; + + return 0; +} + +void bt_test_rx() +{ + u8 *tmp = NULL; + int i; + int countdown = 0; + int num_giacs = 0; + + dio_ssp_init(); + dma_init(); + dio_ssp_start(); + cc2400_rx(); + + while (num_giacs < 20) { + /* wait for DMA transfer */ + while ((rx_tc == 0) && (rx_err == 0)); + if (rx_tc % 2) { + /* swap buffers */ + tmp = active_rxbuf; + active_rxbuf = idle_rxbuf; + idle_rxbuf = tmp; + } + if (rx_err) + RXLED_CLR; + if (rx_tc) { + if (rx_tc > 1) + TXLED_CLR; + if (find_giac(idle_rxbuf)) { + USRLED_SET; + countdown = 100; + num_giacs++; + } else { + if (countdown == 0) { + /* win if more than 32 GIACs seen during this countdown */ + //if (num_giacs > 32) + //break; + USRLED_CLR; + num_giacs = 0; + } else { + --countdown; + } + } + } + + rx_tc = 0; + rx_err = 0; + } + //FIXME turn off rx +} + +/* delay a number of milliseconds while on internal oscillator (4 MHz) */ +void waitms(u8 ms) +{ + u32 i = 400 * ms; + while (--i); +} + +int main() +{ + int i; + + gpio_init(); + + /* blinky */ + for (i = 0; i < 2; i++) { + TXLED_SET; + RXLED_SET; + USRLED_SET; + waitms(200); + TXLED_CLR; + RXLED_CLR; + USRLED_CLR; + waitms(200); + } + + /* cc2400_test */ + cc2400_init(); + TXLED_SET; + waitms(200); + TXLED_CLR; + waitms(200); + cc2400_reset(); + TXLED_SET; + waitms(200); + TXLED_CLR; + waitms(200); + if (cc2400_get(AGCCTRL) != 0xf700) + while(1); + TXLED_SET; + waitms(200); + + /* clock_test */ + clock_start(); + for (i = 0; i < 4; i++) { + RXLED_SET; + wait(2); + RXLED_CLR; + wait(2); + } + RXLED_SET; + + clkn_init(); + bt_test_rx(); + USRLED_SET; + + /* + * Now we function like bluetooth_rxtx so that the USB interface can be + * tested. + */ + ubertooth_usb_init(); + + while (1) { + USBHwISR(); + if (rx_pkts) + bt_stream_rx(); + else if (requested_mode == MODE_TX_TEST && mode != MODE_TX_TEST) + cc2400_txtest(); + else if (requested_mode == MODE_RANGE_TEST && mode != MODE_RANGE_TEST) + cc2400_rangetest(); + else if (requested_mode == MODE_REPEATER && mode != MODE_REPEATER) + cc2400_repeater(); + else if (requested_mode == MODE_SPECAN && mode != MODE_SPECAN) + specan(); + //FIXME do other modes like this + } +} diff --git a/firmware/bluetooth_rxtx/bluetooth_rxtx.c b/firmware/bluetooth_rxtx/bluetooth_rxtx.c index 08bcc1f..b86e57c 100644 --- a/firmware/bluetooth_rxtx/bluetooth_rxtx.c +++ b/firmware/bluetooth_rxtx/bluetooth_rxtx.c @@ -306,27 +306,6 @@ static const u8 abDescriptors[] = { LE_WORD(MAX_PACKET_SIZE),// wMaxPacketSize 0, // bInterval -/* commented due to compile fail -// interface - 0x09, - DESC_INTERFACE, - 0x01, // bInterfaceNumber - 0x00, // bAlternateSetting - 0x00, // bNumEndPoints - 0xFE, // bInterfaceClass - 0x01, // bInterfaceSubClass - 0x01, // bInterfaceProtocol - 0x00, // iInterface - -// DFU Functional Descriptor - 0x09, - DESC_DFU_FUNCTIONAL, - DFU_CAN_DNLOAD, // bmAttributes - LE_WORD(0xFFFF), // wDetachTimeOut - LE_WORD(0x0400), // wTransferSize - LE_WORD(0x0101), // bcdDFUVersion -*/ - // string descriptors 0x04, DESC_STRING, diff --git a/firmware/common.mk b/firmware/common.mk index b302b10..f0da1f4 100644 --- a/firmware/common.mk +++ b/firmware/common.mk @@ -104,7 +104,7 @@ OPT = 0 DEBUG = dwarf-2 -g3 # Linker Script for the current MCU -LINKER_SCRIPT = LPC17xx_Linker_Script_with_bootloader.ld +LINKER_SCRIPT ?= LPC17xx_Linker_Script_with_bootloader.ld # List any extra directories to look for include files here. # Each directory must be seperated by a space. diff --git a/web/content/hardware/build.html b/web/content/hardware/build.html index 45df237..062ce61 100644 --- a/web/content/hardware/build.html +++ b/web/content/hardware/build.html @@ -161,8 +161,8 @@ situation, and go back to step 8. <p>If you are building a Pogoprog, you should make sure that an FTDI USB serial adapter has been detected by your host operating system. If so, you can try using it to <a href="../program">program</a> an Ubertooth board. If you are -making an Ubertooth board, you should try programming it with the blinky -firmware and then continue the process described in firmware/README.</p> +making an Ubertooth board, you should follow the procedure in +firmware/assembly_test/README.</p> <h2>step 12: boast</h2> |